|
|
@@ -1,12 +1,12 @@
|
|
|
+use super::FromSyscallArg;
|
|
|
use crate::kernel::constants::{
|
|
|
- AT_FDCWD, AT_STATX_SYNC_AS_STAT, AT_STATX_SYNC_TYPE, AT_SYMLINK_NOFOLLOW, EBADF, ENOTDIR,
|
|
|
- SEEK_CUR, SEEK_END, SEEK_SET, S_IFBLK, S_IFCHR,
|
|
|
+ EBADF, EFAULT, EINVAL, ENOENT, ENOTDIR, SEEK_CUR, SEEK_END, SEEK_SET, S_IFBLK, S_IFCHR,
|
|
|
};
|
|
|
use crate::kernel::task::Thread;
|
|
|
+use crate::kernel::vfs::filearray::FD;
|
|
|
use crate::{
|
|
|
io::{Buffer, BufferFill},
|
|
|
kernel::{
|
|
|
- constants::{AT_EMPTY_PATH, EFAULT, EINVAL, ENOENT},
|
|
|
user::{
|
|
|
dataflow::{CheckedUserPointer, UserBuffer, UserString},
|
|
|
UserPointer, UserPointerMut,
|
|
|
@@ -22,20 +22,32 @@ use crate::{
|
|
|
use alloc::sync::Arc;
|
|
|
use core::mem::MaybeUninit;
|
|
|
use eonix_runtime::task::Task;
|
|
|
+use posix_types::open::{AtFlags, OpenFlags};
|
|
|
use posix_types::stat::{Stat, StatX};
|
|
|
use posix_types::syscall_no::*;
|
|
|
|
|
|
+impl FromSyscallArg for OpenFlags {
|
|
|
+ fn from_arg(value: usize) -> Self {
|
|
|
+ OpenFlags::from_bits_retain(value as u32)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl FromSyscallArg for AtFlags {
|
|
|
+ fn from_arg(value: usize) -> Self {
|
|
|
+ AtFlags::from_bits_retain(value as u32)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
fn dentry_from(
|
|
|
thread: &Thread,
|
|
|
- dirfd: u32,
|
|
|
+ dirfd: FD,
|
|
|
pathname: *const u8,
|
|
|
follow_symlink: bool,
|
|
|
) -> KResult<Arc<Dentry>> {
|
|
|
- const _AT_FDCWD: u32 = AT_FDCWD as u32;
|
|
|
let path = UserString::new(pathname)?;
|
|
|
|
|
|
match (path.as_cstr().to_bytes_with_nul()[0], dirfd) {
|
|
|
- (b'/', _) | (_, _AT_FDCWD) => {
|
|
|
+ (b'/', _) | (_, FD::AT_FDCWD) => {
|
|
|
let path = Path::new(path.as_cstr().to_bytes())?;
|
|
|
Dentry::open(&thread.fs_context, path, follow_symlink)
|
|
|
}
|
|
|
@@ -54,49 +66,50 @@ fn dentry_from(
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_READ)]
|
|
|
-fn read(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
+fn read(fd: FD, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
let mut buffer = UserBuffer::new(buffer, bufsize)?;
|
|
|
|
|
|
Task::block_on(thread.files.get(fd).ok_or(EBADF)?.read(&mut buffer))
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_WRITE)]
|
|
|
-fn write(fd: u32, buffer: *const u8, count: usize) -> KResult<usize> {
|
|
|
+fn write(fd: FD, buffer: *const u8, count: usize) -> KResult<usize> {
|
|
|
let data = unsafe { core::slice::from_raw_parts(buffer, count) };
|
|
|
|
|
|
Task::block_on(thread.files.get(fd).ok_or(EBADF)?.write(data))
|
|
|
}
|
|
|
|
|
|
+#[eonix_macros::define_syscall(SYS_OPENAT)]
|
|
|
+fn openat(dirfd: FD, pathname: *const u8, flags: OpenFlags, mode: u32) -> KResult<FD> {
|
|
|
+ let dentry = dentry_from(thread, dirfd, pathname, flags.follow_symlink())?;
|
|
|
+ thread.files.open(&dentry, flags, mode)
|
|
|
+}
|
|
|
+
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_OPEN)]
|
|
|
-fn open(path: *const u8, flags: u32, mode: u32) -> KResult<u32> {
|
|
|
- let path = UserString::new(path)?;
|
|
|
- let path = Path::new(path.as_cstr().to_bytes())?;
|
|
|
-
|
|
|
- let mode = mode & !*thread.fs_context.umask.lock();
|
|
|
-
|
|
|
- thread.files.open(&thread.fs_context, path, flags, mode)
|
|
|
+fn open(path: *const u8, flags: OpenFlags, mode: u32) -> KResult<FD> {
|
|
|
+ sys_openat(thread, FD::AT_FDCWD, path, flags, mode)
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_CLOSE)]
|
|
|
-fn close(fd: u32) -> KResult<()> {
|
|
|
+fn close(fd: FD) -> KResult<()> {
|
|
|
thread.files.close(fd)
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_DUP)]
|
|
|
-fn dup(fd: u32) -> KResult<u32> {
|
|
|
+fn dup(fd: FD) -> KResult<FD> {
|
|
|
thread.files.dup(fd)
|
|
|
}
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_DUP2)]
|
|
|
-fn dup2(old_fd: u32, new_fd: u32) -> KResult<u32> {
|
|
|
- thread.files.dup_to(old_fd, new_fd, 0)
|
|
|
+fn dup2(old_fd: FD, new_fd: FD) -> KResult<FD> {
|
|
|
+ thread.files.dup_to(old_fd, new_fd, OpenFlags::empty())
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_PIPE2)]
|
|
|
-fn pipe2(pipe_fd: *mut [u32; 2], flags: u32) -> KResult<()> {
|
|
|
- let mut buffer = UserBuffer::new(pipe_fd as *mut u8, core::mem::size_of::<[u32; 2]>())?;
|
|
|
+fn pipe2(pipe_fd: *mut [FD; 2], flags: OpenFlags) -> KResult<()> {
|
|
|
+ let mut buffer = UserBuffer::new(pipe_fd as *mut u8, core::mem::size_of::<[FD; 2]>())?;
|
|
|
let (read_fd, write_fd) = thread.files.pipe(flags)?;
|
|
|
|
|
|
buffer.copy(&[read_fd, write_fd])?.ok_or(EFAULT)
|
|
|
@@ -104,13 +117,13 @@ fn pipe2(pipe_fd: *mut [u32; 2], flags: u32) -> KResult<()> {
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_PIPE)]
|
|
|
-fn pipe(pipe_fd: *mut [u32; 2]) -> KResult<()> {
|
|
|
- sys_pipe2(thread, pipe_fd, 0)
|
|
|
+fn pipe(pipe_fd: *mut [FD; 2]) -> KResult<()> {
|
|
|
+ sys_pipe2(thread, pipe_fd, OpenFlags::empty())
|
|
|
}
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_GETDENTS)]
|
|
|
-fn getdents(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
+fn getdents(fd: FD, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
let mut buffer = UserBuffer::new(buffer, bufsize)?;
|
|
|
|
|
|
thread.files.get(fd).ok_or(EBADF)?.getdents(&mut buffer)?;
|
|
|
@@ -118,7 +131,7 @@ fn getdents(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_GETDENTS64)]
|
|
|
-fn getdents64(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
+fn getdents64(fd: FD, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
let mut buffer = UserBuffer::new(buffer, bufsize)?;
|
|
|
|
|
|
thread.files.get(fd).ok_or(EBADF)?.getdents64(&mut buffer)?;
|
|
|
@@ -127,13 +140,12 @@ fn getdents64(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
|
|
|
#[cfg(not(target_arch = "x86_64"))]
|
|
|
#[eonix_macros::define_syscall(SYS_NEWFSTATAT)]
|
|
|
-fn newfstatat(dirfd: u32, pathname: *const u8, statbuf: *mut Stat, flags: u32) -> KResult<()> {
|
|
|
- let dentry = if (flags & AT_EMPTY_PATH) != 0 {
|
|
|
+fn newfstatat(dirfd: FD, pathname: *const u8, statbuf: *mut Stat, flags: AtFlags) -> KResult<()> {
|
|
|
+ let dentry = if flags.at_empty_path() {
|
|
|
let file = thread.files.get(dirfd).ok_or(EBADF)?;
|
|
|
file.as_path().ok_or(EBADF)?.clone()
|
|
|
} else {
|
|
|
- let follow_symlink = (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW;
|
|
|
- dentry_from(thread, dirfd, pathname, follow_symlink)?
|
|
|
+ dentry_from(thread, dirfd, pathname, !flags.no_follow())?
|
|
|
};
|
|
|
|
|
|
let statbuf = UserPointerMut::new(statbuf)?;
|
|
|
@@ -147,46 +159,35 @@ fn newfstatat(dirfd: u32, pathname: *const u8, statbuf: *mut Stat, flags: u32) -
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_STATX)]
|
|
|
-fn statx(dirfd: u32, path: *const u8, flags: u32, mask: u32, buffer: *mut u8) -> KResult<()> {
|
|
|
- if (flags & AT_STATX_SYNC_TYPE) != AT_STATX_SYNC_AS_STAT {
|
|
|
- unimplemented!("AT_STATX_SYNC_TYPE={:x}", flags & AT_STATX_SYNC_TYPE);
|
|
|
+fn statx(
|
|
|
+ dirfd: FD,
|
|
|
+ pathname: *const u8,
|
|
|
+ flags: AtFlags,
|
|
|
+ mask: u32,
|
|
|
+ buffer: *mut StatX,
|
|
|
+) -> KResult<()> {
|
|
|
+ if !flags.statx_default_sync() {
|
|
|
+ unimplemented!("statx with no default sync flags: {:?}", flags);
|
|
|
}
|
|
|
|
|
|
- let mut stat: StatX = unsafe { MaybeUninit::zeroed().assume_init() };
|
|
|
- let mut buffer = UserBuffer::new(buffer, core::mem::size_of::<StatX>())?;
|
|
|
+ let mut statx = StatX::default();
|
|
|
+ let buffer = UserPointerMut::new(buffer)?;
|
|
|
|
|
|
- if (flags & AT_EMPTY_PATH) != 0 {
|
|
|
+ let dentry = if flags.at_empty_path() {
|
|
|
let file = thread.files.get(dirfd).ok_or(EBADF)?;
|
|
|
- file.statx(&mut stat, mask)?;
|
|
|
+ file.as_path().ok_or(EBADF)?.clone()
|
|
|
} else {
|
|
|
- let path = UserString::new(path)?;
|
|
|
- let path = Path::new(path.as_cstr().to_bytes())?;
|
|
|
-
|
|
|
- let file;
|
|
|
- if dirfd != AT_FDCWD as u32 && !path.is_absolute() {
|
|
|
- let at = thread.files.get(dirfd).ok_or(EBADF)?;
|
|
|
- file = Dentry::open_at(
|
|
|
- &thread.fs_context,
|
|
|
- at.as_path().ok_or(EBADF)?,
|
|
|
- path,
|
|
|
- (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW,
|
|
|
- )?;
|
|
|
- } else {
|
|
|
- file = Dentry::open(
|
|
|
- &thread.fs_context,
|
|
|
- path,
|
|
|
- (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW,
|
|
|
- )?;
|
|
|
- }
|
|
|
+ dentry_from(thread, dirfd, pathname, !flags.no_follow())?
|
|
|
+ };
|
|
|
|
|
|
- file.statx(&mut stat, mask)?;
|
|
|
- }
|
|
|
+ dentry.statx(&mut statx, mask)?;
|
|
|
+ buffer.write(statx)?;
|
|
|
|
|
|
- buffer.copy(&stat)?.ok_or(EFAULT)
|
|
|
+ Ok(())
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_MKDIRAT)]
|
|
|
-fn mkdirat(dirfd: u32, pathname: *const u8, mode: u32) -> KResult<()> {
|
|
|
+fn mkdirat(dirfd: FD, pathname: *const u8, mode: u32) -> KResult<()> {
|
|
|
let umask = *thread.fs_context.umask.lock();
|
|
|
let mode = mode & !umask & 0o777;
|
|
|
|
|
|
@@ -197,7 +198,7 @@ fn mkdirat(dirfd: u32, pathname: *const u8, mode: u32) -> KResult<()> {
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_MKDIR)]
|
|
|
fn mkdir(pathname: *const u8, mode: u32) -> KResult<()> {
|
|
|
- sys_mkdirat(thread, AT_FDCWD as u32, pathname, mode)
|
|
|
+ sys_mkdirat(thread, FD::AT_FDCWD, pathname, mode)
|
|
|
}
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
@@ -212,18 +213,18 @@ fn truncate(pathname: *const u8, length: usize) -> KResult<()> {
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_UNLINKAT)]
|
|
|
-fn unlinkat(dirfd: u32, pathname: *const u8) -> KResult<()> {
|
|
|
+fn unlinkat(dirfd: FD, pathname: *const u8) -> KResult<()> {
|
|
|
dentry_from(thread, dirfd, pathname, false)?.unlink()
|
|
|
}
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_UNLINK)]
|
|
|
fn unlink(pathname: *const u8) -> KResult<()> {
|
|
|
- sys_unlinkat(thread, AT_FDCWD as u32, pathname)
|
|
|
+ sys_unlinkat(thread, FD::AT_FDCWD, pathname)
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_SYMLINKAT)]
|
|
|
-fn symlinkat(dirfd: u32, target: *const u8, linkpath: *const u8) -> KResult<()> {
|
|
|
+fn symlinkat(dirfd: FD, target: *const u8, linkpath: *const u8) -> KResult<()> {
|
|
|
let target = UserString::new(target)?;
|
|
|
let dentry = dentry_from(thread, dirfd, linkpath, false)?;
|
|
|
|
|
|
@@ -233,11 +234,11 @@ fn symlinkat(dirfd: u32, target: *const u8, linkpath: *const u8) -> KResult<()>
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_SYMLINK)]
|
|
|
fn symlink(target: *const u8, linkpath: *const u8) -> KResult<()> {
|
|
|
- sys_symlinkat(thread, AT_FDCWD as u32, target, linkpath)
|
|
|
+ sys_symlinkat(thread, FD::AT_FDCWD, target, linkpath)
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_MKNODAT)]
|
|
|
-fn mknodat(dirfd: u32, pathname: *const u8, mode: u32, dev: u32) -> KResult<()> {
|
|
|
+fn mknodat(dirfd: FD, pathname: *const u8, mode: u32, dev: u32) -> KResult<()> {
|
|
|
let dentry = dentry_from(thread, dirfd, pathname, true)?;
|
|
|
|
|
|
let umask = *thread.fs_context.umask.lock();
|
|
|
@@ -249,11 +250,11 @@ fn mknodat(dirfd: u32, pathname: *const u8, mode: u32, dev: u32) -> KResult<()>
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_MKNOD)]
|
|
|
fn mknod(pathname: *const u8, mode: u32, dev: u32) -> KResult<()> {
|
|
|
- sys_mknodat(thread, AT_FDCWD as u32, pathname, mode, dev)
|
|
|
+ sys_mknodat(thread, FD::AT_FDCWD, pathname, mode, dev)
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_READLINKAT)]
|
|
|
-fn readlinkat(dirfd: u32, pathname: *const u8, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
+fn readlinkat(dirfd: FD, pathname: *const u8, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
let dentry = dentry_from(thread, dirfd, pathname, false)?;
|
|
|
let mut buffer = UserBuffer::new(buffer, bufsize)?;
|
|
|
|
|
|
@@ -263,18 +264,12 @@ fn readlinkat(dirfd: u32, pathname: *const u8, buffer: *mut u8, bufsize: usize)
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_READLINK)]
|
|
|
fn readlink(pathname: *const u8, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
|
|
|
- sys_readlinkat(thread, AT_FDCWD as u32, pathname, buffer, bufsize)
|
|
|
+ sys_readlinkat(thread, FD::AT_FDCWD, pathname, buffer, bufsize)
|
|
|
}
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
#[eonix_macros::define_syscall(SYS_LLSEEK)]
|
|
|
-fn llseek(
|
|
|
- fd: u32,
|
|
|
- offset_high: u32,
|
|
|
- offset_low: u32,
|
|
|
- result: *mut u64,
|
|
|
- whence: u32,
|
|
|
-) -> KResult<()> {
|
|
|
+fn llseek(fd: FD, offset_high: u32, offset_low: u32, result: *mut u64, whence: u32) -> KResult<()> {
|
|
|
let mut result = UserBuffer::new(result as *mut u8, core::mem::size_of::<u64>())?;
|
|
|
let file = thread.files.get(fd).ok_or(EBADF)?;
|
|
|
|
|
|
@@ -298,7 +293,7 @@ struct IoVec32 {
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_READV)]
|
|
|
-fn readv(fd: u32, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
|
|
|
+fn readv(fd: FD, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
|
|
|
let file = thread.files.get(fd).ok_or(EBADF)?;
|
|
|
|
|
|
let mut iov_user = UserPointer::new(iov_user as *mut IoVec32)?;
|
|
|
@@ -330,7 +325,7 @@ fn readv(fd: u32, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_WRITEV)]
|
|
|
-fn writev(fd: u32, iov_user: *const u8, iovcnt: u32) -> KResult<usize> {
|
|
|
+fn writev(fd: FD, iov_user: *const u8, iovcnt: u32) -> KResult<usize> {
|
|
|
let file = thread.files.get(fd).ok_or(EBADF)?;
|
|
|
|
|
|
// TODO: Rewrite this with `UserPointer`.
|
|
|
@@ -390,7 +385,7 @@ fn access(pathname: *const u8, _mode: u32) -> KResult<()> {
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_SENDFILE64)]
|
|
|
-fn sendfile64(out_fd: u32, in_fd: u32, offset: *mut u8, count: usize) -> KResult<usize> {
|
|
|
+fn sendfile64(out_fd: FD, in_fd: FD, offset: *mut u8, count: usize) -> KResult<usize> {
|
|
|
let in_file = thread.files.get(in_fd).ok_or(EBADF)?;
|
|
|
let out_file = thread.files.get(out_fd).ok_or(EBADF)?;
|
|
|
|
|
|
@@ -402,21 +397,21 @@ fn sendfile64(out_fd: u32, in_fd: u32, offset: *mut u8, count: usize) -> KResult
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_IOCTL)]
|
|
|
-fn ioctl(fd: u32, request: usize, arg3: usize) -> KResult<usize> {
|
|
|
+fn ioctl(fd: FD, request: usize, arg3: usize) -> KResult<usize> {
|
|
|
let file = thread.files.get(fd).ok_or(EBADF)?;
|
|
|
|
|
|
file.ioctl(request, arg3)
|
|
|
}
|
|
|
|
|
|
#[eonix_macros::define_syscall(SYS_FCNTL64)]
|
|
|
-fn fcntl64(fd: u32, cmd: u32, arg: usize) -> KResult<usize> {
|
|
|
+fn fcntl64(fd: FD, cmd: u32, arg: usize) -> KResult<usize> {
|
|
|
thread.files.fcntl(fd, cmd, arg)
|
|
|
}
|
|
|
|
|
|
#[repr(C)]
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
struct UserPollFd {
|
|
|
- fd: u32,
|
|
|
+ fd: FD,
|
|
|
events: u16,
|
|
|
revents: u16,
|
|
|
}
|