From 18485eafbb4087fb4bb9ed4c31c2b74923bda300 Mon Sep 17 00:00:00 2001 From: weitengchen Date: Fri, 17 Apr 2026 22:30:42 +0000 Subject: [PATCH] support mknodat --- litebox_common_linux/src/lib.rs | 14 ++++++++ litebox_shim_linux/src/lib.rs | 8 +++++ litebox_shim_linux/src/syscalls/file.rs | 43 +++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/litebox_common_linux/src/lib.rs b/litebox_common_linux/src/lib.rs index 3929df6a5..357c88ab5 100644 --- a/litebox_common_linux/src/lib.rs +++ b/litebox_common_linux/src/lib.rs @@ -219,6 +219,7 @@ bitflags::bitflags! { } #[repr(u32)] +#[derive(IntEnum)] pub enum InodeType { /// FIFO (named pipe) NamedPipe = 0o010000, @@ -2136,6 +2137,12 @@ pub enum SyscallRequest { fd: i32, length: usize, }, + Mknodat { + dirfd: i32, + pathname: Platform::RawConstPointer, + mode_and_type: u32, + dev: u32, + }, Unlinkat { dirfd: i32, pathname: Platform::RawConstPointer, @@ -2723,6 +2730,13 @@ impl SyscallRequest { mode: ctx.sys_req_arg(2), } } + Sysno::mknodat => sys_req!(Mknodat { dirfd,pathname:*,mode_and_type,dev }), + Sysno::mknod => SyscallRequest::Mknodat { + dirfd: AT_FDCWD, + pathname: ctx.sys_req_ptr(0), + mode_and_type: ctx.sys_req_arg(1), + dev: ctx.sys_req_arg(2), + }, Sysno::unlinkat => sys_req!(Unlinkat { dirfd,pathname:*,flags }), Sysno::unlink => { // unlink is equivalent to unlinkat with dirfd AT_FDCWD and flags 0 diff --git a/litebox_shim_linux/src/lib.rs b/litebox_shim_linux/src/lib.rs index 2834f7b72..62d1e4ad8 100644 --- a/litebox_shim_linux/src/lib.rs +++ b/litebox_shim_linux/src/lib.rs @@ -861,6 +861,14 @@ impl Task { syscall!(sys_openat(dirfd, path, flags, mode)) }), SyscallRequest::Ftruncate { fd, length } => syscall!(sys_ftruncate(fd, length)), + SyscallRequest::Mknodat { + dirfd, + pathname, + mode_and_type, + dev, + } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { + syscall!(sys_mknodat(dirfd, path, mode_and_type, dev)) + }), SyscallRequest::Unlinkat { dirfd, pathname, diff --git a/litebox_shim_linux/src/syscalls/file.rs b/litebox_shim_linux/src/syscalls/file.rs index 46971a4cf..dd02f2bc2 100644 --- a/litebox_shim_linux/src/syscalls/file.rs +++ b/litebox_shim_linux/src/syscalls/file.rs @@ -17,8 +17,8 @@ use litebox::{ utils::{ReinterpretSignedExt as _, ReinterpretUnsignedExt as _, TruncateExt as _}, }; use litebox_common_linux::{ - AtFlags, EfdFlags, EpollCreateFlags, FcntlArg, FileDescriptorFlags, FileStat, IoReadVec, - IoWriteVec, IoctlArg, TimeParam, errno::Errno, + AtFlags, EfdFlags, EpollCreateFlags, FcntlArg, FileDescriptorFlags, FileStat, InodeType, + IoReadVec, IoWriteVec, IoctlArg, TimeParam, errno::Errno, }; use litebox_platform_multiplex::Platform; @@ -258,6 +258,45 @@ impl Task { .flatten() } + /// Handle syscall `mknodat` — create a filesystem node. + pub(crate) fn sys_mknodat( + &self, + dirfd: i32, + pathname: impl path::Arg, + mode_and_type: u32, + _dev: u32, + ) -> Result<(), Errno> { + const FILE_TYPE_MASK: u32 = 0o170000; + + let file_type = mode_and_type & FILE_TYPE_MASK; + let file_type = if file_type == 0 { + // zero translates to S_IFREG + InodeType::File + } else { + InodeType::try_from(file_type).map_err(|_| Errno::EINVAL)? + }; + match file_type { + InodeType::File => { + let mode = Mode::from_bits_truncate(mode_and_type & !FILE_TYPE_MASK); + let fd = self.sys_openat( + dirfd, + pathname, + OFlags::CREAT | OFlags::EXCL | OFlags::WRONLY, + mode, + )?; + self.sys_close(fd.cast_signed())?; + } + // TODO: Named pipe, socket, block and char files are not supported + InodeType::NamedPipe + | InodeType::Socket + | InodeType::BlockDevice + | InodeType::CharDevice + | InodeType::Dir => return Err(Errno::EPERM), + InodeType::SymLink => return Err(Errno::EINVAL), + } + Ok(()) + } + /// Handle syscall `unlinkat` pub(crate) fn sys_unlinkat( &self,