diff --git a/Cargo.toml b/Cargo.toml index 5cf5f8b083..5651c7ec5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,12 @@ mman = [] ## [hermit-c]: https://github.com/hermit-os/hermit-c newlib = [] +## Enable stubbing result values for some system calls. +## +## For some system calls related to system options in which Hermit does not implement all possible options, +## return 0 (success) instead of an error when the option is unknown ; or return a convincing fake value. +syscall-fake-values = [] + #! ### Platform Features ## Enables [Uhyve] support. diff --git a/src/fs/mem.rs b/src/fs/mem.rs index 61002da066..14715dacc6 100644 --- a/src/fs/mem.rs +++ b/src/fs/mem.rs @@ -8,6 +8,8 @@ use alloc::sync::Arc; use alloc::vec::Vec; use core::marker::PhantomData; use core::mem::MaybeUninit; +#[cfg(feature = "syscall-fake-values")] +use core::sync::atomic::{AtomicU64, Ordering}; use core::{mem, ptr}; use align_address::Align; @@ -36,6 +38,9 @@ impl RomFileInner { } } +#[cfg(feature = "syscall-fake-values")] +static VFS_INO_NUM: AtomicU64 = AtomicU64::new(10_000); + pub struct RomFileInterface { /// Position within the file pos: Mutex, @@ -306,6 +311,8 @@ impl RomFile { st_atim: t, st_mtim: t, st_ctim: t, + #[cfg(feature = "syscall-fake-values")] + st_ino: VFS_INO_NUM.fetch_add(1, Ordering::AcqRel), ..Default::default() }; @@ -361,6 +368,12 @@ impl RamFile { st_atim: t, st_mtim: t, st_ctim: t, + #[cfg(feature = "syscall-fake-values")] + st_nlink: 1, + #[cfg(feature = "syscall-fake-values")] + st_blksize: 4096, + #[cfg(feature = "syscall-fake-values")] + st_ino: VFS_INO_NUM.fetch_add(1, Ordering::AcqRel), ..Default::default() }; @@ -614,15 +627,17 @@ impl VfsNode for MemDirectory { block_on( async { let (component, rest) = path.split_once("/").unwrap_or((path, "")); + let inner = self.inner.read().await; + let node = inner.get(component).ok_or(Errno::Badf)?; if !rest.is_empty() { - let inner = self.inner.read().await; - let directory = inner.get(component).ok_or(Errno::Badf)?; - return directory.traverse_lstat(rest); + if node.get_kind() == NodeKind::File { + Err(Errno::Notdir)?; + } + + return node.traverse_lstat(rest); } - let inner = self.inner.read().await; - let node = inner.get(component).ok_or(Errno::Badf)?; node.get_file_attributes() }, None, @@ -633,15 +648,17 @@ impl VfsNode for MemDirectory { block_on( async { let (component, rest) = path.split_once("/").unwrap_or((path, "")); + let inner = self.inner.read().await; + let node = inner.get(component).ok_or(Errno::Badf)?; if !rest.is_empty() { - let inner = self.inner.read().await; - let directory = inner.get(component).ok_or(Errno::Badf)?; - return directory.traverse_stat(rest); + if node.get_kind() == NodeKind::File { + Err(Errno::Notdir)?; + } + + return node.traverse_stat(rest); } - let inner = self.inner.read().await; - let node = inner.get(component).ok_or(Errno::Badf)?; node.get_file_attributes() }, None, diff --git a/src/syscalls/mod.rs b/src/syscalls/mod.rs index 53c0490422..58719fee06 100644 --- a/src/syscalls/mod.rs +++ b/src/syscalls/mod.rs @@ -482,10 +482,6 @@ pub unsafe extern "C" fn sys_access(name: *const c_char, flags: i32) -> i32 { return -i32::from(Errno::Inval); }; - if access_option.contains(AccessOption::F_OK) && access_option != AccessOption::F_OK { - return -i32::from(Errno::Inval); - } - let Ok(name) = unsafe { CStr::from_ptr(name) }.to_str() else { return -i32::from(Errno::Inval); }; @@ -684,6 +680,7 @@ pub unsafe extern "C" fn sys_ioctl(fd: RawFd, cmd: i32, argp: *mut core::ffi::c_ #[hermit_macro::system(errno)] #[unsafe(no_mangle)] pub extern "C" fn sys_fcntl(fd: i32, cmd: i32, arg: i32) -> i32 { + const F_GETFD: i32 = 1; const F_SETFD: i32 = 2; const F_GETFL: i32 = 3; const F_SETFL: i32 = 4; @@ -691,6 +688,9 @@ pub extern "C" fn sys_fcntl(fd: i32, cmd: i32, arg: i32) -> i32 { if cmd == F_SETFD && arg == FD_CLOEXEC { 0 + } else if cmd == F_GETFD { + // Only the FD_CLOEXEC flag is defined, and it has no effect in hermit, so always return 0 + 0 } else if cmd == F_GETFL { let obj = get_object(fd); obj.map_or_else( @@ -717,6 +717,9 @@ pub extern "C" fn sys_fcntl(fd: i32, cmd: i32, arg: i32) -> i32 { .map_or_else(|e| -i32::from(e), |()| 0) }, ) + } else if cfg!(feature = "syscall-fake-values") { + warn!("[syscall-fake-values] Unknown fcntl flag {cmd} {arg}, returning 0"); + 0 } else { -i32::from(Errno::Inval) }