diff --git a/core/ksyscall/Cargo.toml b/core/ksyscall/Cargo.toml index 9f96f8977b4dbc173d3768a19f037065a9d908b6..fa772789b3ea742edfab45c9c3f8ae9287bf487c 100644 --- a/core/ksyscall/Cargo.toml +++ b/core/ksyscall/Cargo.toml @@ -20,7 +20,6 @@ tee = [ kservices = { workspace = true } kbuild_config = { workspace = true } kerrno.workspace = true -fs-ng-vfs.workspace = true kfs.workspace = true khal.workspace = true kio.workspace = true diff --git a/core/ksyscall/src/dispatch.rs b/core/ksyscall/src/dispatch.rs index 98873e80ffe294de0b47c7a42cb6e6250aaf3e03..978573be66a232b4c756e00c5a85aff37953404b 100644 --- a/core/ksyscall/src/dispatch.rs +++ b/core/ksyscall/src/dispatch.rs @@ -42,44 +42,44 @@ pub fn dispatch_irq_syscall(uctx: &mut UserContext) { let result = match sysno { // fs ctl Sysno::ioctl => sys_ioctl(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), - Sysno::chdir => sys_chdir(uctx.arg0() as _), + Sysno::chdir => sys_chdir(uctx.arg0().into()), Sysno::fchdir => sys_fchdir(uctx.arg0() as _), - Sysno::chroot => sys_chroot(uctx.arg0() as _), + Sysno::chroot => sys_chroot(uctx.arg0().into()), #[cfg(target_arch = "x86_64")] - Sysno::mkdir => sys_mkdir(uctx.arg0() as _, uctx.arg1() as _), - Sysno::mkdirat => sys_mkdirat(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), - Sysno::getdents64 => sys_getdents64(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), + Sysno::mkdir => sys_mkdir(uctx.arg0().into(), uctx.arg1() as _), + Sysno::mkdirat => sys_mkdirat(uctx.arg0() as _, uctx.arg1().into(), uctx.arg2() as _), + Sysno::getdents64 => sys_getdents64(uctx.arg0() as _, uctx.arg1().into(), uctx.arg2() as _), #[cfg(target_arch = "x86_64")] - Sysno::link => sys_link(uctx.arg0() as _, uctx.arg1() as _), + Sysno::link => sys_link(uctx.arg0().into(), uctx.arg1().into()), Sysno::linkat => sys_linkat( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, - uctx.arg3() as _, + uctx.arg3().into(), uctx.arg4() as _, ), #[cfg(target_arch = "x86_64")] - Sysno::rmdir => sys_rmdir(uctx.arg0() as _), + Sysno::rmdir => sys_rmdir(uctx.arg0().into()), #[cfg(target_arch = "x86_64")] - Sysno::unlink => sys_unlink(uctx.arg0() as _), - Sysno::unlinkat => sys_unlinkat(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), - Sysno::getcwd => sys_getcwd(uctx.arg0() as _, uctx.arg1() as _), + Sysno::unlink => sys_unlink(uctx.arg0().into()), + Sysno::unlinkat => sys_unlinkat(uctx.arg0() as _, uctx.arg1().into(), uctx.arg2() as _), + Sysno::getcwd => sys_getcwd(uctx.arg0().into(), uctx.arg1() as _), #[cfg(target_arch = "x86_64")] - Sysno::symlink => sys_symlink(uctx.arg0() as _, uctx.arg1() as _), - Sysno::symlinkat => sys_symlinkat(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), + Sysno::symlink => sys_symlink(uctx.arg0().into(), uctx.arg1().into()), + Sysno::symlinkat => sys_symlinkat(uctx.arg0().into(), uctx.arg1() as _, uctx.arg2().into()), #[cfg(target_arch = "x86_64")] - Sysno::rename => sys_rename(uctx.arg0() as _, uctx.arg1() as _), + Sysno::rename => sys_rename(uctx.arg0().into(), uctx.arg1().into()), Sysno::renameat => sys_renameat( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, - uctx.arg3() as _, + uctx.arg3().into(), ), Sysno::renameat2 => sys_renameat2( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, - uctx.arg3() as _, + uctx.arg3().into(), uctx.arg4() as _, ), Sysno::sync => sys_sync(), @@ -87,42 +87,42 @@ pub fn dispatch_irq_syscall(uctx: &mut UserContext) { // file ops #[cfg(target_arch = "x86_64")] - Sysno::chown => sys_chown(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), + Sysno::chown => sys_chown(uctx.arg0().into(), uctx.arg1() as _, uctx.arg2() as _), #[cfg(target_arch = "x86_64")] - Sysno::lchown => sys_lchown(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), + Sysno::lchown => sys_lchown(uctx.arg0().into(), uctx.arg1() as _, uctx.arg2() as _), Sysno::fchown => sys_fchown(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), Sysno::fchownat => sys_fchownat( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, uctx.arg4() as _, ), #[cfg(target_arch = "x86_64")] - Sysno::chmod => sys_chmod(uctx.arg0() as _, uctx.arg1() as _), + Sysno::chmod => sys_chmod(uctx.arg0().into(), uctx.arg1() as _), Sysno::fchmod => sys_fchmod(uctx.arg0() as _, uctx.arg1() as _), Sysno::fchmodat | Sysno::fchmodat2 => sys_fchmodat( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, ), #[cfg(target_arch = "x86_64")] - Sysno::readlink => sys_readlink(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), + Sysno::readlink => sys_readlink(uctx.arg0().into(), uctx.arg1().into(), uctx.arg2() as _), Sysno::readlinkat => sys_readlinkat( uctx.arg0() as _, - uctx.arg1() as _, - uctx.arg2() as _, + uctx.arg1().into(), + uctx.arg2().into(), uctx.arg3() as _, ), #[cfg(target_arch = "x86_64")] - Sysno::utime => sys_utime(uctx.arg0() as _, uctx.arg1() as _), + Sysno::utime => sys_utime(uctx.arg0().into(), uctx.arg1().into()), #[cfg(target_arch = "x86_64")] - Sysno::utimes => sys_utimes(uctx.arg0() as _, uctx.arg1() as _), + Sysno::utimes => sys_utimes(uctx.arg0().into(), uctx.arg1().into()), Sysno::utimensat => sys_utimensat( uctx.arg0() as _, - uctx.arg1() as _, - uctx.arg2() as _, + uctx.arg1().into(), + uctx.arg2().into(), uctx.arg3() as _, ), @@ -145,10 +145,10 @@ pub fn dispatch_irq_syscall(uctx: &mut UserContext) { Sysno::flock => sys_flock(uctx.arg0() as _, uctx.arg1() as _), // io - Sysno::read => sys_read(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), - Sysno::readv => sys_readv(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), - Sysno::write => sys_write(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), - Sysno::writev => sys_writev(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), + Sysno::read => sys_read(uctx.arg0() as _, uctx.arg1().into(), uctx.arg2() as _), + Sysno::readv => sys_readv(uctx.arg0() as _, uctx.arg1().into(), uctx.arg2() as _), + Sysno::write => sys_write(uctx.arg0() as _, uctx.arg1().into(), uctx.arg2() as _), + Sysno::writev => sys_writev(uctx.arg0() as _, uctx.arg1().into(), uctx.arg2() as _), Sysno::lseek => sys_lseek(uctx.arg0() as _, uctx.arg1() as _, uctx.arg2() as _), Sysno::truncate => sys_truncate(uctx.arg0().into(), uctx.arg1() as _), Sysno::ftruncate => sys_ftruncate(uctx.arg0() as _, uctx.arg1() as _), @@ -168,38 +168,38 @@ pub fn dispatch_irq_syscall(uctx: &mut UserContext) { ), Sysno::pread64 => sys_pread64( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, ), Sysno::pwrite64 => sys_pwrite64( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, ), Sysno::preadv => sys_preadv( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, ), Sysno::pwritev => sys_pwritev( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, ), Sysno::preadv2 => sys_preadv2( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, uctx.arg4() as _, ), Sysno::pwritev2 => sys_pwritev2( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, uctx.arg3() as _, uctx.arg4() as _, @@ -207,22 +207,22 @@ pub fn dispatch_irq_syscall(uctx: &mut UserContext) { Sysno::sendfile => sys_sendfile( uctx.arg0() as _, uctx.arg1() as _, - uctx.arg2() as _, + uctx.arg2().into(), uctx.arg3() as _, ), Sysno::copy_file_range => sys_copy_file_range( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, - uctx.arg3() as _, + uctx.arg3().into(), uctx.arg4() as _, uctx.arg5() as _, ), Sysno::splice => sys_splice( uctx.arg0() as _, - uctx.arg1() as _, + uctx.arg1().into(), uctx.arg2() as _, - uctx.arg3() as _, + uctx.arg3().into(), uctx.arg4() as _, uctx.arg5() as _, ), @@ -288,9 +288,9 @@ pub fn dispatch_irq_syscall(uctx: &mut UserContext) { Sysno::umount2 => sys_umount2(uctx.arg0().into(), uctx.arg1() as _) as _, // pipe - Sysno::pipe2 => sys_pipe2(uctx.arg0() as _, uctx.arg1() as _), + Sysno::pipe2 => sys_pipe2(uctx.arg0().into(), uctx.arg1() as _), #[cfg(target_arch = "x86_64")] - Sysno::pipe => sys_pipe2(uctx.arg0() as _, 0), + Sysno::pipe => sys_pipe2(uctx.arg0().into(), 0), // event Sysno::eventfd2 => sys_eventfd2(uctx.arg0() as _, uctx.arg1() as _), diff --git a/core/ksyscall/src/fs/mod.rs b/core/ksyscall/src/fs/mod.rs index 9402b70346b6f3ea4eb83ff3a960245defb88240..e7b82c5932cbcc70eb32e888ac91ab92e334d1b8 100644 --- a/core/ksyscall/src/fs/mod.rs +++ b/core/ksyscall/src/fs/mod.rs @@ -4,23 +4,15 @@ //! File system related syscalls. //! -//! This module implements various file system operations including: -//! - File I/O (read, write, seek, etc.) -//! - Directory operations (mkdir, rmdir, chdir, etc.) -//! - File descriptor operations (open, close, dup, etc.) -//! - File metadata and statistics (stat, fstat, etc.) -//! - File control (ioctl, fcntl, etc.) -//! - Special files (pipes, fifos, device files, etc.) +//! This module keeps fd-backed syscalls whose primary ABI semantics are not +//! filesystem operations, while re-exporting filesystem ABI implementations +//! from `posix_fs`. -mod ctl; mod event; -mod fd_ops; -mod io; mod pidfd; -mod pipe; mod signalfd; mod timerfd; pub use posix_fs::*; -pub use self::{ctl::*, event::*, fd_ops::*, io::*, pidfd::*, pipe::*, signalfd::*, timerfd::*}; +pub use self::{event::*, pidfd::*, signalfd::*, timerfd::*}; diff --git a/posix/fs/Cargo.toml b/posix/fs/Cargo.toml index 670330fac8e948e772798ac71ddeaef0626c96a0..af0923fe5d108507902cdcbed52536aecf78ff3b 100644 --- a/posix/fs/Cargo.toml +++ b/posix/fs/Cargo.toml @@ -16,11 +16,15 @@ bitflags.workspace = true kcore.workspace = true kerrno.workspace = true kfs.workspace = true +khal.workspace = true +kio.workspace = true klogger.workspace = true +kpoll.workspace = true kservices.workspace = true ktask.workspace = true fs-ng-vfs.workspace = true linux-raw-sys = { workspace = true, features = ["ioctl", "loop_device"] } +linux_sysno.workspace = true osvm.workspace = true posix-types.workspace = true unittest.workspace = true diff --git a/core/ksyscall/src/fs/ctl.rs b/posix/fs/src/ctl.rs similarity index 80% rename from core/ksyscall/src/fs/ctl.rs rename to posix/fs/src/ctl.rs index f3386c1205792ddfeca99e0e1e0399a34d39e742..015974667dbf17d2f33576bdc804097ff9d8b71f 100644 --- a/core/ksyscall/src/fs/ctl.rs +++ b/posix/fs/src/ctl.rs @@ -24,16 +24,16 @@ use kcore::task::AsThread; use kerrno::{KError, KResult}; use kfs::{FS_CONTEXT, FsContext}; use khal::time::wall_time; -use kservices::mm::vm_load_string; +use kservices::file::{Directory, FileLike, get_file_like}; use ktask::current; use linux_raw_sys::{ general::*, ioctl::{FIONBIO, TIOCGWINSZ}, }; -use osvm::{VirtPtr, write_vm_mem}; -use posix_types::TimeValueLike; +use osvm::VirtPtr; +use posix_types::{TimeValueLike, UserConstPtr, UserPtr}; -use crate::file::{Directory, FileLike, get_file_like, resolve_at, with_fs}; +use crate::path::{resolve_at, with_fs}; /// The ioctl() system call manipulates the underlying device parameters /// of special files. @@ -63,8 +63,8 @@ pub fn sys_ioctl(fd: i32, cmd: u32, arg: usize) -> KResult { } /// Changes the current working directory. -pub fn sys_chdir(path: *const c_char) -> KResult { - let path = vm_load_string(path)?; +pub fn sys_chdir(path: UserConstPtr) -> KResult { + let path = path.load_string()?; debug!("sys_chdir <= path: {path}"); let mut fs = FS_CONTEXT.lock(); @@ -83,13 +83,13 @@ pub fn sys_fchdir(dirfd: i32) -> KResult { } #[cfg(target_arch = "x86_64")] -pub fn sys_mkdir(path: *const c_char, mode: u32) -> KResult { +pub fn sys_mkdir(path: UserConstPtr, mode: u32) -> KResult { sys_mkdirat(AT_FDCWD, path, mode) } /// Changes the root directory of the calling process. -pub fn sys_chroot(path: *const c_char) -> KResult { - let path = vm_load_string(path)?; +pub fn sys_chroot(path: UserConstPtr) -> KResult { + let path = path.load_string()?; debug!("sys_chroot <= path: {path}"); let mut fs = FS_CONTEXT.lock(); @@ -102,8 +102,8 @@ pub fn sys_chroot(path: *const c_char) -> KResult { } /// Creates a directory relative to a directory file descriptor. -pub fn sys_mkdirat(dirfd: i32, path: *const c_char, mode: u32) -> KResult { - let path = vm_load_string(path)?; +pub fn sys_mkdirat(dirfd: i32, path: UserConstPtr, mode: u32) -> KResult { + let path = path.load_string()?; debug!("sys_mkdirat <= dirfd: {dirfd}, path: {path}, mode: {mode}"); let mode = mode & !current().as_thread().proc_data.umask(); @@ -171,8 +171,11 @@ impl DirBuffer { } /// Reads directory entries in linux_dirent64 format. -pub fn sys_getdents64(fd: i32, buf: *mut u8, len: usize) -> KResult { - debug!("sys_getdents64 <= fd: {fd}, buf: {buf:?}, len: {len}"); +pub fn sys_getdents64(fd: i32, buf: UserPtr, len: usize) -> KResult { + debug!( + "sys_getdents64 <= fd: {fd}, buf: {:?}, len: {len}", + buf.as_ptr() + ); let mut buffer = DirBuffer::new(len); @@ -195,7 +198,7 @@ pub fn sys_getdents64(fd: i32, buf: *mut u8, len: usize) -> KResult { return Err(KError::InvalidInput); } - write_vm_mem(buf, &buffer.buf)?; + buf.write_vm_slice(&buffer.buf)?; Ok(buffer.offset as _) } @@ -208,13 +211,16 @@ pub fn sys_getdents64(fd: i32, buf: *mut u8, len: usize) -> KResult { /// Creates a hard link to an existing file. pub fn sys_linkat( old_dirfd: c_int, - old_path: *const c_char, + old_path: UserConstPtr, new_dirfd: c_int, - new_path: *const c_char, + new_path: UserConstPtr, flags: u32, ) -> KResult { - let old_path = old_path.check_non_null().map(vm_load_string).transpose()?; - let new_path = vm_load_string(new_path)?; + let old_path = old_path + .check_non_null() + .map(UserConstPtr::load_string) + .transpose()?; + let new_path = new_path.load_string()?; debug!( "sys_linkat <= old_dirfd: {old_dirfd}, old_path: {old_path:?}, new_dirfd: {new_dirfd}, \ new_path: {new_path}, flags: {flags}" @@ -238,7 +244,7 @@ pub fn sys_linkat( } #[cfg(target_arch = "x86_64")] -pub fn sys_link(old_path: *const c_char, new_path: *const c_char) -> KResult { +pub fn sys_link(old_path: UserConstPtr, new_path: UserConstPtr) -> KResult { sys_linkat(AT_FDCWD, old_path, AT_FDCWD, new_path, 0) } @@ -248,8 +254,8 @@ pub fn sys_link(old_path: *const c_char, new_path: *const c_char) -> KResult KResult { - let path = vm_load_string(path)?; +pub fn sys_unlinkat(dirfd: i32, path: UserConstPtr, flags: usize) -> KResult { + let path = path.load_string()?; debug!("sys_unlinkat <= dirfd: {dirfd}, path: {path:?}, flags: {flags}"); @@ -264,17 +270,17 @@ pub fn sys_unlinkat(dirfd: i32, path: *const c_char, flags: usize) -> KResult KResult { +pub fn sys_rmdir(path: UserConstPtr) -> KResult { sys_unlinkat(AT_FDCWD, path, AT_REMOVEDIR as usize) } #[cfg(target_arch = "x86_64")] -pub fn sys_unlink(path: *const c_char) -> KResult { +pub fn sys_unlink(path: UserConstPtr) -> KResult { sys_unlinkat(AT_FDCWD, path, 0) } /// Gets the current working directory path. -pub fn sys_getcwd(buf: *mut u8, size: isize) -> KResult { +pub fn sys_getcwd(buf: UserPtr, size: isize) -> KResult { let size: usize = size.try_into().map_err(|_| KError::BadAddress)?; if buf.is_null() { return Ok(0); @@ -287,7 +293,7 @@ pub fn sys_getcwd(buf: *mut u8, size: isize) -> KResult { let cwd = cwd.as_bytes_with_nul(); if cwd.len() <= size { - write_vm_mem(buf, cwd)?; + buf.write_vm_slice(cwd)?; // FIXME: it is said that this should return 0 Ok(buf.as_ptr() as _) } else { @@ -296,18 +302,18 @@ pub fn sys_getcwd(buf: *mut u8, size: isize) -> KResult { } #[cfg(target_arch = "x86_64")] -pub fn sys_symlink(target: *const c_char, linkpath: *const c_char) -> KResult { +pub fn sys_symlink(target: UserConstPtr, linkpath: UserConstPtr) -> KResult { sys_symlinkat(target, AT_FDCWD, linkpath) } /// Creates a symbolic link relative to a directory file descriptor. pub fn sys_symlinkat( - target: *const c_char, + target: UserConstPtr, new_dirfd: i32, - linkpath: *const c_char, + linkpath: UserConstPtr, ) -> KResult { - let target = vm_load_string(target)?; - let linkpath = vm_load_string(linkpath)?; + let target = target.load_string()?; + let linkpath = linkpath.load_string()?; debug!("sys_symlinkat <= target: {target:?}, new_dirfd: {new_dirfd}, linkpath: {linkpath:?}"); with_fs(new_dirfd, |fs| { @@ -317,18 +323,18 @@ pub fn sys_symlinkat( } #[cfg(target_arch = "x86_64")] -pub fn sys_readlink(path: *const c_char, buf: *mut u8, size: usize) -> KResult { +pub fn sys_readlink(path: UserConstPtr, buf: UserPtr, size: usize) -> KResult { sys_readlinkat(AT_FDCWD, path, buf, size) } /// Reads the target of a symbolic link. pub fn sys_readlinkat( dirfd: i32, - path: *const c_char, - buf: *mut u8, + path: UserConstPtr, + buf: UserPtr, size: usize, ) -> KResult { - let path = vm_load_string(path)?; + let path = path.load_string()?; debug!("sys_readlinkat <= dirfd: {dirfd}, path: {path:?}"); @@ -336,35 +342,38 @@ pub fn sys_readlinkat( let entry = fs.resolve_no_follow(path)?; let link = entry.read_link()?; let read = size.min(link.len()); - write_vm_mem(buf, &link.as_bytes()[..read])?; + buf.write_vm_slice(&link.as_bytes()[..read])?; Ok(read as isize) }) } #[cfg(target_arch = "x86_64")] -pub fn sys_chown(path: *const c_char, uid: i32, gid: i32) -> KResult { +pub fn sys_chown(path: UserConstPtr, uid: i32, gid: i32) -> KResult { sys_fchownat(AT_FDCWD, path, uid, gid, 0) } #[cfg(target_arch = "x86_64")] -pub fn sys_lchown(path: *const c_char, uid: i32, gid: i32) -> KResult { +pub fn sys_lchown(path: UserConstPtr, uid: i32, gid: i32) -> KResult { use linux_raw_sys::general::AT_SYMLINK_NOFOLLOW; sys_fchownat(AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW) } pub fn sys_fchown(fd: i32, uid: i32, gid: i32) -> KResult { - sys_fchownat(fd, core::ptr::null(), uid, gid, AT_EMPTY_PATH) + sys_fchownat(fd, UserConstPtr::default(), uid, gid, AT_EMPTY_PATH) } /// Changes file ownership relative to a directory file descriptor. pub fn sys_fchownat( dirfd: i32, - path: *const c_char, + path: UserConstPtr, uid: i32, gid: i32, flags: u32, ) -> KResult { - let path = path.check_non_null().map(vm_load_string).transpose()?; + let path = path + .check_non_null() + .map(UserConstPtr::load_string) + .transpose()?; let loc = resolve_at(dirfd, path.as_deref(), flags)? .into_file() .ok_or(KError::BadFileDescriptor)?; @@ -389,18 +398,26 @@ pub fn sys_fchownat( } #[cfg(target_arch = "x86_64")] -pub fn sys_chmod(path: *const c_char, mode: u32) -> KResult { +pub fn sys_chmod(path: UserConstPtr, mode: u32) -> KResult { sys_fchmodat(AT_FDCWD, path, mode, 0) } /// Changes file permissions by file descriptor. pub fn sys_fchmod(fd: i32, mode: u32) -> KResult { - sys_fchmodat(fd, core::ptr::null(), mode, AT_EMPTY_PATH) + sys_fchmodat(fd, UserConstPtr::default(), mode, AT_EMPTY_PATH) } /// Changes file permissions relative to a directory file descriptor. -pub fn sys_fchmodat(dirfd: i32, path: *const c_char, mode: u32, flags: u32) -> KResult { - let path = path.check_non_null().map(vm_load_string).transpose()?; +pub fn sys_fchmodat( + dirfd: i32, + path: UserConstPtr, + mode: u32, + flags: u32, +) -> KResult { + let path = path + .check_non_null() + .map(UserConstPtr::load_string) + .transpose()?; resolve_at(dirfd, path.as_deref(), flags)? .into_file() .ok_or(KError::BadFileDescriptor)? @@ -413,12 +430,15 @@ pub fn sys_fchmodat(dirfd: i32, path: *const c_char, mode: u32, flags: u32) -> K fn update_times( dirfd: i32, - path: *const c_char, + path: UserConstPtr, atime: Option, mtime: Option, flags: u32, ) -> KResult<()> { - let path = path.check_non_null().map(vm_load_string).transpose()?; + let path = path + .check_non_null() + .map(UserConstPtr::load_string) + .transpose()?; resolve_at(dirfd, path.as_deref(), flags)? .into_file() .ok_or(KError::BadFileDescriptor)? @@ -439,7 +459,7 @@ pub struct utimbuf { } #[cfg(target_arch = "x86_64")] -pub fn sys_utime(path: *const c_char, times: *const utimbuf) -> KResult { +pub fn sys_utime(path: UserConstPtr, times: UserConstPtr) -> KResult { let (atime, mtime) = if let Some(times) = times.check_non_null() { // FIXME: AnyBitPattern let times = unsafe { times.read_uninit()?.assume_init() }; @@ -457,8 +477,8 @@ pub fn sys_utime(path: *const c_char, times: *const utimbuf) -> KResult { #[cfg(target_arch = "x86_64")] pub fn sys_utimes( - path: *const c_char, - times: *const [linux_raw_sys::general::timeval; 2], + path: UserConstPtr, + times: UserConstPtr<[linux_raw_sys::general::timeval; 2]>, ) -> KResult { let (atime, mtime) = if let Some(times) = times.check_non_null() { // FIXME: AnyBitPattern @@ -474,8 +494,8 @@ pub fn sys_utimes( pub fn sys_utimensat( dirfd: i32, - path: *const c_char, - times: *const [timespec; 2], + path: UserConstPtr, + times: UserConstPtr<[timespec; 2]>, mut flags: u32, ) -> KResult { if path.is_null() { @@ -509,28 +529,31 @@ pub fn sys_utimensat( } #[cfg(target_arch = "x86_64")] -pub fn sys_rename(old_path: *const c_char, new_path: *const c_char) -> KResult { +pub fn sys_rename( + old_path: UserConstPtr, + new_path: UserConstPtr, +) -> KResult { sys_renameat(AT_FDCWD, old_path, AT_FDCWD, new_path) } pub fn sys_renameat( old_dirfd: i32, - old_path: *const c_char, + old_path: UserConstPtr, new_dirfd: i32, - new_path: *const c_char, + new_path: UserConstPtr, ) -> KResult { sys_renameat2(old_dirfd, old_path, new_dirfd, new_path, 0) } pub fn sys_renameat2( old_dirfd: i32, - old_path: *const c_char, + old_path: UserConstPtr, new_dirfd: i32, - new_path: *const c_char, + new_path: UserConstPtr, flags: u32, ) -> KResult { - let old_path = vm_load_string(old_path)?; - let new_path = vm_load_string(new_path)?; + let old_path = old_path.load_string()?; + let new_path = new_path.load_string()?; debug!( "sys_renameat2 <= old_dirfd: {old_dirfd}, old_path: {old_path:?}, new_dirfd: {new_dirfd}, \ new_path: {new_path}, flags: {flags}" diff --git a/core/ksyscall/src/fs/fd_ops.rs b/posix/fs/src/fd_ops.rs similarity index 94% rename from core/ksyscall/src/fs/fd_ops.rs rename to posix/fs/src/fd_ops.rs index 0c5b81cb21dab624bd5ca48b7ee5f5fe3a777bcf..cf4793b5d95fb93fcbefabc05d1a2f03b2dd9340 100644 --- a/core/ksyscall/src/fs/fd_ops.rs +++ b/posix/fs/src/fd_ops.rs @@ -18,11 +18,11 @@ use core::{ use bitflags::bitflags; use kcore::task::AsThread; use kerrno::{KError, KResult}; -use kservices::{file::FileLike, mm::UserPtr}; +use kservices::file::{FD_TABLE, FileLike, Pipe, add_file_like, close_file_like, get_file_like}; use ktask::current; use linux_raw_sys::general::*; - -use crate::file::{FD_TABLE, Pipe, add_file_like, close_file_like, get_file_like}; +use osvm::{VirtMutPtr, VirtPtr}; +use posix_types::UserPtr; /// Closes the specified file descriptor. pub fn sys_close(fd: c_int) -> KResult { @@ -137,7 +137,9 @@ pub fn sys_fcntl(fd: c_int, cmd: c_int, arg: usize) -> KResult { F_OFD_SETLK | F_OFD_SETLKW => Ok(0), F_GETLK | F_OFD_GETLK => { let arg = UserPtr::::from(arg); - arg.get_as_mut()?.l_type = F_UNLCK as _; + let mut lock = unsafe { arg.read_uninit()?.assume_init() }; + lock.l_type = F_UNLCK as _; + arg.write_vm(lock)?; Ok(0) } F_SETFL => { diff --git a/core/ksyscall/src/fs/io.rs b/posix/fs/src/io.rs similarity index 90% rename from core/ksyscall/src/fs/io.rs rename to posix/fs/src/io.rs index b547422ce8692326241e2c4e9094f0c5c6a6cbb1..4342be57f9c23dace0887c3b1f9c64ce5410689e 100644 --- a/core/ksyscall/src/fs/io.rs +++ b/posix/fs/src/io.rs @@ -21,16 +21,16 @@ use kerrno::{KError, KResult, LinuxError}; use kfs::{FS_CONTEXT, FileFlags, OpenOptions}; use kio::{Seek, SeekFrom}; use kpoll::{IoEvents, Pollable}; -use kservices::mm::{UserConstPtr, VmBytes, VmBytesMut}; +use kservices::{ + file::{Directory, File, FileLike, Pipe, get_file_like}, + io::{IoVec, IoVectorBuf}, + mm::{VmBytes, VmBytesMut}, +}; use ktask::current; use linux_raw_sys::general::__kernel_off_t; use linux_sysno::Sysno; use osvm::{VirtMutPtr, VirtPtr}; - -use crate::{ - file::{Directory, File, FileLike, Pipe, get_file_like}, - io::{IoVec, IoVectorBuf}, -}; +use posix_types::{UserConstPtr, UserPtr}; struct DummyFd; impl FileLike for DummyFd { @@ -82,35 +82,35 @@ pub fn sys_dummy_fd(sysno: Sysno) -> KResult { /// Read data from the file indicated by `fd`. /// /// Return the read size if success. -pub fn sys_read(fd: i32, buf: *mut u8, len: usize) -> KResult { - debug!("sys_read <= fd: {fd}, buf: {buf:p}, len: {len}"); +pub fn sys_read(fd: i32, buf: UserPtr, len: usize) -> KResult { + debug!("sys_read <= fd: {fd}, buf: {:p}, len: {len}", buf.as_ptr()); // Get the file object and perform the read operation into the user buffer - Ok(get_file_like(fd)?.read(&mut VmBytesMut::new(buf, len))? as _) + Ok(get_file_like(fd)?.read(&mut VmBytesMut::new(buf.as_ptr().cast_mut(), len))? as _) } /// Vectored read into multiple buffers. -pub fn sys_readv(fd: i32, iov: *const IoVec, iovcnt: usize) -> KResult { +pub fn sys_readv(fd: i32, iov: UserConstPtr, iovcnt: usize) -> KResult { debug!("sys_readv <= fd: {fd}, iovcnt: {iovcnt}"); // Vectored read - read data into multiple buffers in a single operation let f = get_file_like(fd)?; - f.read(&mut IoVectorBuf::new(iov, iovcnt)?.into_io()) + f.read(&mut IoVectorBuf::new(iov.as_ptr(), iovcnt)?.into_io()) .map(|n| n as _) } /// Write data to the file indicated by `fd`. /// /// Return the written size if success. -pub fn sys_write(fd: i32, buf: *mut u8, len: usize) -> KResult { - debug!("sys_write <= fd: {fd}, buf: {buf:p}, len: {len}"); - Ok(get_file_like(fd)?.write(&mut VmBytes::new(buf, len))? as _) +pub fn sys_write(fd: i32, buf: UserConstPtr, len: usize) -> KResult { + debug!("sys_write <= fd: {fd}, buf: {:p}, len: {len}", buf.as_ptr()); + Ok(get_file_like(fd)?.write(&mut VmBytes::new(buf.as_ptr(), len))? as _) } /// Vectored write from multiple buffers. -pub fn sys_writev(fd: i32, iov: *const IoVec, iovcnt: usize) -> KResult { +pub fn sys_writev(fd: i32, iov: UserConstPtr, iovcnt: usize) -> KResult { debug!("sys_writev <= fd: {fd}, iovcnt: {iovcnt}"); // Vectored write - write data from multiple buffers in a single operation let f = get_file_like(fd)?; - f.write(&mut IoVectorBuf::new(iov, iovcnt)?.into_io()) + f.write(&mut IoVectorBuf::new(iov.as_ptr(), iovcnt)?.into_io()) .map(|n| n as _) } @@ -153,7 +153,7 @@ pub fn sys_lseek(fd: c_int, offset: __kernel_off_t, whence: c_int) -> KResult, length: __kernel_off_t) -> KResult { - let path = path.get_as_str()?; + let path = path.load_string()?; debug!("sys_truncate <= {path:?} {length}"); // Truncate file to specified length - opens file by path if length < 0 { @@ -322,11 +322,11 @@ pub fn sys_fallocate( pub fn sys_fsync(fd: c_int) -> KResult { debug!("sys_fsync <= {fd}"); // Synchronize file to disk - syncs both data and metadata - let any_file = crate::file::get_file_like(fd)?; + let any_file = kservices::file::get_file_like(fd)?; if let Ok(f) = any_file.clone().downcast_arc::() { f.inner().sync(false)?; return Ok(0); - } else if let Ok(d) = any_file.downcast_arc::() { + } else if let Ok(d) = any_file.downcast_arc::() { d.inner().sync(false)?; return Ok(0); } @@ -337,11 +337,11 @@ pub fn sys_fsync(fd: c_int) -> KResult { pub fn sys_fdatasync(fd: c_int) -> KResult { debug!("sys_fdatasync <= {fd}"); // Synchronize file data to disk - only syncs data, not metadata - let any_file = crate::file::get_file_like(fd)?; + let any_file = kservices::file::get_file_like(fd)?; if let Ok(f) = any_file.clone().downcast_arc::() { f.inner().sync(true)?; return Ok(0); - } else if let Ok(d) = any_file.downcast_arc::() { + } else if let Ok(d) = any_file.downcast_arc::() { d.inner().sync(true)?; return Ok(0); } @@ -368,20 +368,27 @@ pub fn sys_fadvise64( } /// Reads from a file at a given offset without changing the file position. -pub fn sys_pread64(fd: c_int, buf: *mut u8, len: usize, offset: __kernel_off_t) -> KResult { +pub fn sys_pread64( + fd: c_int, + buf: UserPtr, + len: usize, + offset: __kernel_off_t, +) -> KResult { // Read from file at specific offset without changing file position let f = File::from_fd(fd)?; if offset < 0 { return Err(KError::InvalidInput); } - let read = f.inner().read_at(VmBytesMut::new(buf, len), offset as _)?; + let read = f + .inner() + .read_at(VmBytesMut::new(buf.as_ptr().cast_mut(), len), offset as _)?; Ok(read as _) } /// Writes to a file at a given offset without changing the file position. pub fn sys_pwrite64( fd: c_int, - buf: *const u8, + buf: UserConstPtr, len: usize, offset: __kernel_off_t, ) -> KResult { @@ -390,14 +397,16 @@ pub fn sys_pwrite64( return Ok(0); } let f = File::from_fd(fd)?; - let write = f.inner().write_at(VmBytes::new(buf, len), offset as _)?; + let write = f + .inner() + .write_at(VmBytes::new(buf.as_ptr(), len), offset as _)?; Ok(write as _) } /// Vectored read at a given offset. pub fn sys_preadv( fd: c_int, - iov: *const IoVec, + iov: UserConstPtr, iovcnt: usize, offset: __kernel_off_t, ) -> KResult { @@ -408,7 +417,7 @@ pub fn sys_preadv( /// Vectored write at a given offset. pub fn sys_pwritev( fd: c_int, - iov: *const IoVec, + iov: UserConstPtr, iovcnt: usize, offset: __kernel_off_t, ) -> KResult { @@ -419,7 +428,7 @@ pub fn sys_pwritev( /// Vectored read at a given offset with flags. pub fn sys_preadv2( fd: c_int, - iov: *const IoVec, + iov: UserConstPtr, iovcnt: usize, offset: __kernel_off_t, _flags: u32, @@ -428,14 +437,17 @@ pub fn sys_preadv2( // Vectored read at specific offset with optional flags let f = File::from_fd(fd)?; f.inner() - .read_at(IoVectorBuf::new(iov, iovcnt)?.into_io(), offset as _) + .read_at( + IoVectorBuf::new(iov.as_ptr(), iovcnt)?.into_io(), + offset as _, + ) .map(|n| n as _) } /// Vectored write at a given offset with flags. pub fn sys_pwritev2( fd: c_int, - iov: *const IoVec, + iov: UserConstPtr, iovcnt: usize, offset: __kernel_off_t, _flags: u32, @@ -444,15 +456,18 @@ pub fn sys_pwritev2( // Vectored write at specific offset with optional flags. let f = File::from_fd(fd)?; f.inner() - .write_at(IoVectorBuf::new(iov, iovcnt)?.into_io(), offset as _) + .write_at( + IoVectorBuf::new(iov.as_ptr(), iovcnt)?.into_io(), + offset as _, + ) .map(|n| n as _) } /// Helper for sendfile and copy_file_range operations /// Abstracts both fixed position (via offset pointer) and current position reads/writes enum SendFile { - Direct(Arc), // Use current file position - Offset(Arc, *mut u64), // Use fixed offset from user space + Direct(Arc), // Use current file position + Offset(Arc, UserPtr), // Use fixed offset from user space } impl SendFile { @@ -532,7 +547,12 @@ fn do_send(mut src: SendFile, mut dst: SendFile, len: usize) -> KResult { /// Efficiently transfer data from in_fd to out_fd without going through user space /// Transfers data from one file descriptor to another. -pub fn sys_sendfile(out_fd: c_int, in_fd: c_int, offset: *mut u64, len: usize) -> KResult { +pub fn sys_sendfile( + out_fd: c_int, + in_fd: c_int, + offset: UserPtr, + len: usize, +) -> KResult { debug!( "sys_sendfile <= out_fd: {}, in_fd: {}, offset: {}, len: {}", out_fd, @@ -562,9 +582,9 @@ pub fn sys_sendfile(out_fd: c_int, in_fd: c_int, offset: *mut u64, len: usize) - /// Copies a range of bytes between two file descriptors. pub fn sys_copy_file_range( fd_in: c_int, - off_in: *mut u64, + off_in: UserPtr, fd_out: c_int, - off_out: *mut u64, + off_out: UserPtr, len: usize, _flags: u32, ) -> KResult { @@ -603,9 +623,9 @@ pub fn sys_copy_file_range( /// Splice can connect pipes to regular files or between pipes without user-space buffering pub fn sys_splice( fd_in: c_int, - off_in: *mut i64, + off_in: UserPtr, fd_out: c_int, - off_out: *mut i64, + off_out: UserPtr, len: usize, _flags: u32, ) -> KResult { diff --git a/posix/fs/src/lib.rs b/posix/fs/src/lib.rs index 1742a84917629e46a7271478b44788decba04208..72b27730ac7a0cbfd10fb3ae62764dede6d15471 100644 --- a/posix/fs/src/lib.rs +++ b/posix/fs/src/lib.rs @@ -11,9 +11,13 @@ extern crate alloc; #[macro_use] extern crate klogger; +mod ctl; +mod fd_ops; +mod io; mod mount; mod open; mod path; +mod pipe; mod stat; -pub use self::{mount::*, open::*, path::*, stat::*}; +pub use self::{ctl::*, fd_ops::*, io::*, mount::*, open::*, path::*, pipe::*, stat::*}; diff --git a/core/ksyscall/src/fs/pipe.rs b/posix/fs/src/pipe.rs similarity index 94% rename from core/ksyscall/src/fs/pipe.rs rename to posix/fs/src/pipe.rs index 856e7ee78f28682ffa74ee1e36752e867406a8ca..d33255f06a374fd987453504cf535a14f06e00b8 100644 --- a/core/ksyscall/src/fs/pipe.rs +++ b/posix/fs/src/pipe.rs @@ -15,6 +15,7 @@ use kerrno::KResult; use kservices::file::{FileLike, Pipe, close_file_like}; use linux_raw_sys::general::{O_CLOEXEC, O_NONBLOCK}; use osvm::VirtMutPtr; +use posix_types::UserPtr; bitflags! { /// Flags for the `pipe2` syscall. @@ -28,7 +29,7 @@ bitflags! { } /// Creates a pipe and returns the read/write file descriptors. -pub fn sys_pipe2(fds: *mut [c_int; 2], flags: u32) -> KResult { +pub fn sys_pipe2(fds: UserPtr<[c_int; 2]>, flags: u32) -> KResult { let flags = { let new_flags = PipeFlags::from_bits_truncate(flags); if new_flags.bits() != flags {