Skip to content

Commit

Permalink
feat(syscall/fs): handle non-cwd fd {open,chdir}
Browse files Browse the repository at this point in the history
* Handle non-AT_FDCWD file descriptors for {open,chdir} system calls.
  The updated signature and behaviour has also been updated in the mlibc
  patches.

Signed-off-by: Anhad Singh <[email protected]>
  • Loading branch information
Andy-Python-Programmer committed Apr 10, 2024
1 parent 126af76 commit 9105725
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 24 deletions.
55 changes: 55 additions & 0 deletions patches/mlibc/jinx-working-patch.patch
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,58 @@ index 3474615..d06f130 100644
}

char **backtrace_symbols(void *const *, int) {
diff --git mlibc-clean/sysdeps/aero/generic/aero.cpp mlibc-workdir/sysdeps/aero/generic/aero.cpp
index 80f9c6f..897986d 100644
--- mlibc-clean/sysdeps/aero/generic/aero.cpp
+++ mlibc-workdir/sysdeps/aero/generic/aero.cpp
@@ -200,14 +200,19 @@ int sys_getcwd(char *buffer, size_t size) {
return 0;
}

-int sys_chdir(const char *path) {
- auto result = syscall(SYS_CHDIR, path, strlen(path));
+static int sys_chdir_impl(int fd, const char *path) {
+ auto ret = syscall(SYS_CHDIR, fd, path, strlen(path));
+ if(int e = sc_error(ret); e)
+ return e;
+ return 0;
+}

- if (result < 0) {
- return -result;
- }
+int sys_chdir(const char *path) {
+ return sys_chdir_impl(AT_FDCWD, path);
+}

- return 0;
+int sys_fchdir(int fd) {
+ return sys_chdir_impl(fd, "");
}

int sys_gethostname(char *buffer, size_t bufsize) {
diff --git mlibc-clean/sysdeps/aero/generic/filesystem.cpp mlibc-workdir/sysdeps/aero/generic/filesystem.cpp
index 95c49b9..9416be7 100644
--- mlibc-clean/sysdeps/aero/generic/filesystem.cpp
+++ mlibc-workdir/sysdeps/aero/generic/filesystem.cpp
@@ -69,13 +69,14 @@ int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) {
}

int sys_open(const char *filename, int flags, mode_t mode, int *fd) {
- auto result = syscall(SYS_OPEN, 0, filename, strlen(filename), flags);
-
- if (result < 0) {
- return -result;
- }
+ return sys_openat(AT_FDCWD, filename, flags, mode, fd);
+}

- *fd = result;
+int sys_openat(int dirfd, const char *path, int flags, mode_t mode, int *fd) {
+ auto ret = syscall(SYS_OPEN, dirfd, path, strlen(path), flags, mode);
+ if (int e = sc_error(ret); e)
+ return e;
+ *fd = ret;
return 0;
}

53 changes: 31 additions & 22 deletions src/aero_kernel/src/syscall/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,19 @@ pub fn read(fd: FileDescriptor, buffer: &mut [u8]) -> Result<usize, SyscallError
}

#[syscall]
pub fn open(fd: usize, path: &Path, mode: usize) -> Result<usize, SyscallError> {
let dir = match fd as isize {
0 => {
if !path.is_absolute() {
scheduler::get_scheduler().current_task().cwd_dirent()
} else {
crate::fs::root_dir().clone()
}
}

_ => {
todo!()
pub fn open(fd: usize, path: &Path, flags: usize, _mode: usize) -> Result<usize, SyscallError> {
let current_thread = scheduler::current_thread();
let at = match fd as isize {
AT_FDCWD if !path.is_absolute() => current_thread.cwd_dirent(),
_ if !path.is_absolute() => {
let ent = FileDescriptor::from_usize(fd).handle()?.inode.clone();
assert!(ent.inode().metadata()?.is_directory());
ent
}
_ => fs::root_dir().clone(),
};

let mut flags = OpenFlags::from_bits(mode).ok_or(SyscallError::EINVAL)?;
let mut flags = OpenFlags::from_bits(flags).ok_or(SyscallError::EINVAL)?;

if !flags.intersects(OpenFlags::O_RDONLY | OpenFlags::O_RDWR | OpenFlags::O_WRONLY) {
flags.insert(OpenFlags::O_RDONLY);
Expand All @@ -129,7 +126,7 @@ pub fn open(fd: usize, path: &Path, mode: usize) -> Result<usize, SyscallError>
lookup_mode = LookupMode::Create;
}

let inode = fs::lookup_path_with(dir, path, lookup_mode, true)?;
let inode = fs::lookup_path_with(at, path, lookup_mode, true)?;

if flags.contains(OpenFlags::O_DIRECTORY) && !inode.inode().metadata()?.is_directory() {
return Err(SyscallError::ENOTDIR);
Expand All @@ -139,9 +136,7 @@ pub fn open(fd: usize, path: &Path, mode: usize) -> Result<usize, SyscallError>
inode.inode().truncate(0)?;
}

Ok(scheduler::current_thread()
.file_table
.open_file(inode.clone(), flags)?)
Ok(current_thread.file_table.open_file(inode.clone(), flags)?)
}

#[syscall]
Expand Down Expand Up @@ -183,15 +178,29 @@ pub fn close(fd: FileDescriptor) -> Result<usize, SyscallError> {
}

#[syscall]
pub fn chdir(path: &str) -> Result<usize, SyscallError> {
let inode = fs::lookup_path(Path::new(path))?;
pub fn chdir(fd: usize, path: &Path) -> Result<usize, SyscallError> {
let current_thread = scheduler::current_thread();
let at = match fd as isize {
AT_FDCWD if !path.is_absolute() => current_thread.cwd_dirent(),
_ if !path.is_absolute() => {
let ent = FileDescriptor::from_usize(fd).handle()?.inode.clone();
assert!(ent.inode().metadata()?.is_directory());
ent
}
_ => fs::root_dir().clone(),
};

if !inode.inode().metadata()?.is_directory() {
// A component of path is not a directory.
if path.is_empty() {
current_thread.set_cwd(at);
return Ok(0);
}

let ent = fs::lookup_path_with(at, path, LookupMode::None, true)?;
if !ent.inode().metadata()?.is_directory() {
return Err(SyscallError::ENOTDIR);
}

scheduler::get_scheduler().current_task().set_cwd(inode);
current_thread.set_cwd(ent);
Ok(0)
}

Expand Down
4 changes: 2 additions & 2 deletions src/aero_kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,12 @@ pub fn generic_do_syscall(
SYS_GETPGID => process::getpgid(b),

SYS_READ => fs::read(b, c, d),
SYS_OPEN => fs::open(b, c, d, e),
SYS_OPEN => fs::open(b, c, d, e, f),
SYS_CLOSE => fs::close(b),
SYS_WRITE => fs::write(b, c, d),
SYS_GETDENTS => fs::getdents(b, c, d),
SYS_GETCWD => fs::getcwd(b, c),
SYS_CHDIR => fs::chdir(b, c),
SYS_CHDIR => fs::chdir(b, c, d),
SYS_MKDIR_AT => fs::mkdirat(b, c, d),
SYS_RMDIR => fs::rmdir(b, c),
SYS_IOCTL => fs::ioctl(b, c, d),
Expand Down

0 comments on commit 9105725

Please sign in to comment.