Skip to content

Commit e62bc9d

Browse files
sys_getdents: read one directory entry at a time
Unfortunately, the sys_read_entries sysdep in libc is required to read one directory entry at a time but the Aero getdents syscall reads as much it can into the provided in the buffer and we dont know the size of the buffer since we dont know the size of the name aswell. We cannot also assign an aribiray size to the name since the syscall will bail out if the size of the buffer is too small to fit in the name. :^) * We need a way to retrieve the chopped off name. * We need to null terminate the string since rust strings are not null terminated and this could possibally cause issues. Signed-off-by: Andy-Python-Programmer <[email protected]>
1 parent cd157ce commit e62bc9d

File tree

4 files changed

+63
-79
lines changed

4 files changed

+63
-79
lines changed

patches/mlibc/mlibc.patch

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
From ef88dca94b8e13b78bdd0dc71df8b6062009c6f0 Mon Sep 17 00:00:00 2001
1+
From d92b4e7afe56d401b465f3dcdf12c60d9b414b6b Mon Sep 17 00:00:00 2001
22
From: unknown <[email protected]>
33
Date: Sun, 6 Jun 2021 16:37:54 +1000
44
Subject: [PATCH] targets: add aero target port
@@ -15,7 +15,7 @@ Signed-off-by: Andy-Python-Programmer <[email protected]>
1515
sysdeps/aero/crt-x86_64/crt0.S | 8 +
1616
sysdeps/aero/generic/aero.cc | 276 ++++++++++++++++++++
1717
sysdeps/aero/generic/entry.cc | 32 +++
18-
sysdeps/aero/generic/filesystem.cc | 266 +++++++++++++++++++
18+
sysdeps/aero/generic/filesystem.cc | 262 +++++++++++++++++++
1919
sysdeps/aero/generic/signals.S | 7 +
2020
sysdeps/aero/generic/signals.cc | 43 +++
2121
sysdeps/aero/generic/sockets.cc | 0
@@ -51,7 +51,7 @@ Signed-off-by: Andy-Python-Programmer <[email protected]>
5151
sysdeps/aero/meson.build | 67 +++++
5252
sysdeps/dripos/generic/generic.cpp | 3 +
5353
sysdeps/lemon/generic/signals.S | 7 +
54-
46 files changed, 1025 insertions(+), 11 deletions(-)
54+
46 files changed, 1021 insertions(+), 11 deletions(-)
5555
create mode 100644 abis/aero/auxv.h
5656
create mode 100644 sysdeps/aero/crt-x86_64/crt0.S
5757
create mode 100644 sysdeps/aero/generic/aero.cc
@@ -567,10 +567,10 @@ index 0000000..265ab56
567567
+}
568568
diff --git a/sysdeps/aero/generic/filesystem.cc b/sysdeps/aero/generic/filesystem.cc
569569
new file mode 100644
570-
index 0000000..a944402
570+
index 0000000..421e2d6
571571
--- /dev/null
572572
+++ b/sysdeps/aero/generic/filesystem.cc
573-
@@ -0,0 +1,266 @@
573+
@@ -0,0 +1,262 @@
574574
+#include <aero/syscall.h>
575575
+
576576
+#include <sys/types.h>
@@ -740,8 +740,7 @@ index 0000000..a944402
740740
+} __attribute__((packed));
741741
+
742742
+int sys_read_entries(int handle, void *buffer, size_t max_size, size_t *bytes_read) {
743-
+ struct aero_dir_entry entry;
744-
+ auto result = syscall(SYS_GETDENTS, handle, &entry, sizeof(struct aero_dir_entry));
743+
+ auto result = syscall(SYS_GETDENTS, handle, buffer, max_size);
745744
+
746745
+ // Check if we got an error.
747746
+ if (result < 0) {
@@ -755,26 +754,23 @@ index 0000000..a944402
755754
+ return 0;
756755
+ }
757756
+
758-
+ // Check if we have enough space.
759-
+ __ensure(max_size >= entry.reclen);
757+
+ auto entry = (struct aero_dir_entry*)buffer;
760758
+
761-
+ struct dirent *dirent = (struct dirent *)buffer;
762-
+
763-
+ dirent->d_ino = entry.inode;
764-
+ dirent->d_off = entry.offset;
765-
+ dirent->d_reclen = entry.reclen;
766-
+ dirent->d_type = entry.filetyp;
759+
+ struct dirent dirent = {
760+
+ .d_ino = entry->inode,
761+
+ .d_off = entry->offset,
762+
+ .d_reclen = entry->reclen,
763+
+ .d_type = entry->filetyp,
764+
+ };
767765
+
768766
+ // The reclen is the size of the dirent struct, plus the size of the name.
769-
+ auto name_size = entry.reclen - sizeof(struct aero_dir_entry);
770-
+
771-
+ if (name_size > 255) {
772-
+ name_size = 255;
773-
+ }
767+
+ auto name_size = entry->reclen - sizeof(struct aero_dir_entry);
768+
+ __ensure(name_size < 255);
774769
+
775-
+ memcpy(dirent->d_name, entry.name, name_size);
776-
+ *bytes_read = entry.reclen;
770+
+ memcpy(&dirent.d_name, entry->name, name_size);
771+
+ *bytes_read = entry->reclen;
777772
+
773+
+ memcpy(buffer, &dirent, sizeof(struct dirent));
778774
+ return 0;
779775
+}
780776
+

src/aero_kernel/src/fs/file_table.rs

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -125,57 +125,49 @@ impl FileHandle {
125125
Ok(new)
126126
}
127127

128-
pub fn get_dents(&self, mut buffer: &mut [u8]) -> super::Result<usize> {
129-
let mut offset = 0x00usize;
130-
131-
loop {
132-
let inode = self
133-
.inode
134-
.inode()
135-
.dirent(self.inode.clone(), self.offset.load(Ordering::SeqCst))?;
136-
137-
if let Some(entry) = inode {
138-
let reclen = core::mem::size_of::<SysDirEntry>() + entry.name().len();
139-
let dir_offset = offset + reclen;
140-
141-
let file_type = entry.inode().metadata()?.file_type();
142-
let file_type: aero_syscall::SysFileType = file_type.into();
143-
144-
let sysd = SysDirEntry {
145-
inode: entry.inode().metadata()?.id(),
146-
offset: dir_offset,
147-
reclen,
148-
file_type: file_type as usize,
149-
name: [], // will be filled in later
150-
};
151-
152-
if buffer.len() < sysd.reclen {
153-
break Ok(offset);
154-
}
128+
pub fn get_dents(&self, buffer: &mut [u8]) -> super::Result<usize> {
129+
let inode = self
130+
.inode
131+
.inode()
132+
.dirent(self.inode.clone(), self.offset.load(Ordering::SeqCst))?;
155133

156-
self.offset.fetch_add(1, Ordering::SeqCst);
134+
// We are allowed to chop off the name of the entry though not the header
135+
// itself.
136+
if buffer.len() < core::mem::size_of::<SysDirEntry>() {
137+
return Err(FileSystemError::TooSmall);
138+
}
157139

158-
unsafe {
159-
let sysd_ref = &mut *(buffer.as_mut_ptr() as *mut SysDirEntry);
140+
if let Some(entry) = inode {
141+
let mut reclen = core::mem::size_of::<SysDirEntry>() + entry.name().len();
160142

161-
// Copy the directory entry info into the provided buffer.
162-
buffer.as_mut_ptr().copy_from(
163-
&sysd as *const _ as *const u8,
164-
core::mem::size_of::<SysDirEntry>(),
165-
);
143+
if reclen > buffer.len() {
144+
reclen = buffer.len();
145+
}
166146

167-
// Copy over the name of the inode.
168-
sysd_ref
169-
.name
170-
.as_mut_ptr()
171-
.copy_from(entry.name().as_ptr(), entry.name().len());
172-
}
147+
let name_size = reclen - core::mem::size_of::<SysDirEntry>();
173148

174-
offset += sysd.reclen;
175-
buffer = &mut buffer[sysd.reclen..];
176-
} else {
177-
break Ok(offset);
149+
let file_type = entry.inode().metadata()?.file_type();
150+
let file_type: aero_syscall::SysFileType = file_type.into();
151+
152+
let sysd = unsafe { &mut *(buffer.as_mut_ptr() as *mut SysDirEntry) };
153+
154+
sysd.inode = entry.inode().metadata()?.id();
155+
sysd.offset = reclen;
156+
sysd.reclen = reclen;
157+
sysd.file_type = file_type as usize;
158+
159+
unsafe {
160+
// Copy over the name of the inode.
161+
sysd.name
162+
.as_mut_ptr()
163+
.copy_from(entry.name().as_ptr(), name_size);
178164
}
165+
166+
self.offset.fetch_add(1, Ordering::SeqCst);
167+
Ok(reclen)
168+
} else {
169+
// nothin to read
170+
Ok(0)
179171
}
180172
}
181173
}

src/aero_kernel/src/fs/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub enum FileSystemError {
128128
NotDirectory,
129129
IsPipe,
130130
Interrupted,
131+
TooSmall,
131132
}
132133

133134
impl From<FileSystemError> for AeroSyscallError {
@@ -140,6 +141,7 @@ impl From<FileSystemError> for AeroSyscallError {
140141
FileSystemError::NotDirectory => AeroSyscallError::ENOTDIR,
141142
FileSystemError::IsPipe => AeroSyscallError::ESPIPE,
142143
FileSystemError::Interrupted => AeroSyscallError::EINTR,
144+
FileSystemError::TooSmall => AeroSyscallError::E2BIG,
143145
}
144146
}
145147
}

userland/aero_shell/src/main.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ fn list_directory(path: &str) -> Result<(), AeroSyscallError> {
231231
let dir_fd = sys_open(path, OpenFlags::O_DIRECTORY)?;
232232

233233
loop {
234-
let mut offset = 0;
235234
let mut dir_ents_buffer = [0; 1024];
236235

237236
let size = sys_getdents(dir_fd, &mut dir_ents_buffer)?;
@@ -240,20 +239,15 @@ fn list_directory(path: &str) -> Result<(), AeroSyscallError> {
240239
break;
241240
}
242241

243-
while offset < size {
244-
let dir_entry =
245-
unsafe { &*(dir_ents_buffer.as_ptr().add(offset) as *const SysDirEntry) };
242+
let dir_entry = unsafe { &*(dir_ents_buffer.as_ptr() as *const SysDirEntry) };
246243

247-
let name_start = offset + core::mem::size_of::<SysDirEntry>();
248-
let name_end = offset + dir_entry.reclen;
244+
let name_start = core::mem::size_of::<SysDirEntry>();
245+
let name_end = dir_entry.reclen;
249246

250-
let name =
251-
unsafe { core::str::from_utf8_unchecked(&dir_ents_buffer[name_start..name_end]) };
247+
let name =
248+
unsafe { core::str::from_utf8_unchecked(&dir_ents_buffer[name_start..name_end]) };
252249

253-
offset += dir_entry.reclen;
254-
255-
print!("{} ", name);
256-
}
250+
print!("{} ", name);
257251
}
258252

259253
println!();

0 commit comments

Comments
 (0)