Add syscall mknod

Signed-off-by: Zhenchen Wang <m202372036@hust.edu.cn>
This commit is contained in:
Zhenchen Wang
2024-06-02 19:41:00 +08:00
committed by Tate, Hongliang Tian
parent 0cf954801d
commit d8389da797
9 changed files with 108 additions and 7 deletions

View File

@ -153,7 +153,9 @@ provided by Linux on x86-64 architecture.
| 130 | rt_sigsuspend | ✅ |
| 131 | sigaltstack | ✅ |
| 132 | utime | ✅ |
| 133 | mknod | |
| 133 | mknod | |
| 132 | utime | ❌ |
| 133 | mknod | ✅ |
| 134 | uselib | ❌ |
| 135 | personality | ❌ |
| 136 | ustat | ❌ |
@ -279,7 +281,7 @@ provided by Linux on x86-64 architecture.
| 256 | migrate_pages | ❌ |
| 257 | openat | ✅ |
| 258 | mkdirat | ✅ |
| 259 | mknodat | |
| 259 | mknodat | |
| 260 | fchownat | ✅ |
| 261 | futimesat | ✅ |
| 262 | newfstatat | ✅ |

View File

@ -47,3 +47,20 @@ pub fn init() -> Result<()> {
pty::init()?;
Ok(())
}
pub fn get_device(dev: usize) -> Result<Arc<dyn Device>> {
if dev == 0 {
return_errno_with_message!(Errno::EPERM, "whiteout device")
}
let major = ((dev >> 32) & 0xffff_f000 | (dev >> 8) & 0x0000_0fff) as u32;
let minor = ((dev >> 12) & 0xffff_ff00 | dev & 0x0000_00ff) as u32;
match (major, minor) {
(1, 3) => Ok(Arc::new(null::Null)),
(1, 5) => Ok(Arc::new(zero::Zero)),
(5, 0) => Ok(Arc::new(tty::TtyDevice)),
(1, 8) => Ok(Arc::new(random::Random)),
(1, 9) => Ok(Arc::new(urandom::Urandom)),
_ => return_errno_with_message!(Errno::EINVAL, "unsupported device"),
}
}

View File

@ -55,6 +55,7 @@ use crate::syscall::{
lseek::sys_lseek,
madvise::sys_madvise,
mkdir::{sys_mkdir, sys_mkdirat},
mknod::{sys_mknod, sys_mknodat},
mmap::sys_mmap,
mount::sys_mount,
mprotect::sys_mprotect,
@ -236,6 +237,7 @@ impl_syscall_nums_and_dispatch_fn! {
SYS_RT_SIGSUSPEND = 130 => sys_rt_sigsuspend(args[..2]);
SYS_SIGALTSTACK = 131 => sys_sigaltstack(args[..2]);
SYS_UTIME = 132 => sys_utime(args[..2]);
SYS_MKNOD = 133 => sys_mknod(args[..3]);
SYS_STATFS = 137 => sys_statfs(args[..2]);
SYS_FSTATFS = 138 => sys_fstatfs(args[..2]);
SYS_GET_PRIORITY = 140 => sys_get_priority(args[..2]);
@ -267,6 +269,7 @@ impl_syscall_nums_and_dispatch_fn! {
SYS_WAITID = 247 => sys_waitid(args[..5]);
SYS_OPENAT = 257 => sys_openat(args[..4]);
SYS_MKDIRAT = 258 => sys_mkdirat(args[..3]);
SYS_MKNODAT = 259 => sys_mknodat(args[..4]);
SYS_FCHOWNAT = 260 => sys_fchownat(args[..5]);
SYS_FUTIMESAT = 261 => sys_futimesat(args[..3]);
SYS_FSTATAT = 262 => sys_fstatat(args[..4]);

View File

@ -0,0 +1,62 @@
// SPDX-License-Identifier: MPL-2.0
use super::SyscallReturn;
use crate::{
device::get_device,
fs::{
file_table::FileDesc,
fs_resolver::{FsPath, AT_FDCWD},
utils::{InodeMode, InodeType},
},
prelude::*,
syscall::{constants::MAX_FILENAME_LEN, stat::FileTypeFlags},
util::read_cstring_from_user,
};
pub fn sys_mknodat(
dirfd: FileDesc,
path_addr: Vaddr,
mode: u16,
dev: usize,
) -> Result<SyscallReturn> {
let path = read_cstring_from_user(path_addr, MAX_FILENAME_LEN)?;
let current = current!();
let inode_mode = {
let mask_mode = mode & !current.umask().read().get();
InodeMode::from_bits_truncate(mask_mode)
};
let file_type = FileTypeFlags::from_bits_truncate(mode);
debug!(
"dirfd = {}, path = {:?}, inode_mode = {:?}, file_type = {:?}, dev = {}",
dirfd, path, inode_mode, file_type, dev
);
let (dir_dentry, name) = {
let path = path.to_string_lossy();
if path.is_empty() {
return_errno_with_message!(Errno::ENOENT, "path is empty");
}
let fs_path = FsPath::new(dirfd, path.as_ref())?;
current.fs().read().lookup_dir_and_base_name(&fs_path)?
};
if file_type.contains(FileTypeFlags::S_IFREG) || file_type.is_empty() {
let _ = dir_dentry.new_fs_child(name.trim_end_matches('/'), InodeType::File, inode_mode)?;
} else if file_type.contains(FileTypeFlags::S_IFCHR)
|| file_type.contains(FileTypeFlags::S_IFBLK)
{
let _ = dir_dentry.mknod(name.trim_end_matches('/'), inode_mode, get_device(dev)?)?;
} else if file_type.contains(FileTypeFlags::S_IFIFO)
|| file_type.contains(FileTypeFlags::S_IFSOCK)
{
return_errno_with_message!(Errno::EINVAL, "unsupported file type flag");
} else {
return_errno_with_message!(Errno::EPERM, "unimplemented types");
}
Ok(SyscallReturn::Return(0))
}
pub fn sys_mknod(path_addr: Vaddr, mode: u16, dev: usize) -> Result<SyscallReturn> {
self::sys_mknodat(AT_FDCWD, path_addr, mode, dev)
}

View File

@ -62,6 +62,7 @@ mod listen;
mod lseek;
mod madvise;
mod mkdir;
mod mknod;
mod mmap;
mod mount;
mod mprotect;

View File

@ -77,11 +77,19 @@ pub fn sys_fstatat(
Ok(SyscallReturn::Return(0))
}
pub const S_IFMT: u32 = 0o170000;
pub const S_IFCHR: u32 = 0o020000;
pub const S_IFDIR: u32 = 0o040000;
pub const S_IFREG: u32 = 0o100000;
pub const S_IFLNK: u32 = 0o120000;
bitflags! {
/// File type.
pub struct FileTypeFlags: u16 {
const S_IFMT = 0o170000; // File type mask.
const S_IFSOCK = 0o140000; // Socket.
const S_IFCHR = 0o020000; // Character device.
const S_IFBLK = 0o060000; // Block device.
const S_IFDIR = 0o040000; // Directory.
const S_IFIFO = 0o010000; // FIFO (named pipe).
const S_IFREG = 0o100000; // Regular file.
const S_IFLNK = 0o120000; // Symbolic link.
}
}
/// File Stat
#[derive(Debug, Clone, Copy, Pod, Default)]

View File

@ -20,6 +20,7 @@ TESTS ?= \
link_test \
lseek_test \
mkdir_test \
mknod_test \
mmap_test \
mount_test \
open_create_test \

View File

@ -0,0 +1 @@
MknodTest.RegularFilePermissions

View File

@ -0,0 +1,6 @@
MknodTest.MknodAtFIFO
MknodTest.MknodOnExistingPathFails
MknodTest.Socket
MknodTest.Fifo
MknodTest.FifoOtrunc
MknodTest.FifoTruncNoOp