diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index b850da01ef..05e427571f 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -5,7 +5,7 @@ use crate::{ arch::*, auxv_defs::*, read_proc_meta, - sys::{open, proc_call, thread_call}, + sys::{fstat, open, proc_call, thread_call}, }; use redox_protocols::protocol::{ProcCall, ThreadCall}; @@ -798,7 +798,7 @@ impl FdGuard { #[inline] pub fn fstat(&self, stat: &mut syscall::Stat) -> Result { - syscall::fstat(self.fd, stat) + fstat(self.fd, stat) } #[inline] diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 37dc909845..60b6fd282c 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -6,7 +6,7 @@ use core::{ use ioslice::IoSlice; use syscall::{ - CallFlags, EINVAL, ERESTART, TimeSpec, + CallFlags, EINVAL, ERESTART, StdFsCallKind, TimeSpec, data::StdFsCallMeta, error::{self, EINTR, ENODEV, ESRCH, Error, Result}, }; @@ -527,3 +527,6 @@ pub fn std_fs_call_wo(fd: usize, payload: &[u8], metadata: &StdFsCallMeta) -> Re pub fn std_fs_call_rw(fd: usize, payload: &mut [u8], metadata: &StdFsCallMeta) -> Result { sys_call_rw(fd, payload, CallFlags::STD_FS, metadata) } +pub fn fstat(fd: usize, stat: &mut syscall::Stat) -> Result { + std_fs_call_ro(fd, stat, &StdFsCallMeta::new(StdFsCallKind::Fstat, 0, 0)) +} diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index f39a083b7c..da0a0d9087 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -94,7 +94,7 @@ pub fn execve( // executable memory. let mut stat = Stat::default(); - syscall::fstat(*image_file as usize, &mut stat)?; + redox_rt::sys::fstat(*image_file as usize, &mut stat)?; let Resugid { ruid, rgid, .. } = redox_rt::sys::posix_getresugid(); let mode = if ruid == stat.st_uid { diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 81abae875b..591423ed0e 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -1,10 +1,14 @@ -use core::{slice, str}; +use core::{mem, slice, str}; use alloc::vec::Vec; use ioslice::IoSlice; use redox_protocols::protocol::{ProcKillTarget, SocketCall, WaitFlags}; -use redox_rt::sys::{WaitpidTarget, posix_read, posix_write}; -use syscall::{EMFILE, Error, Result}; +use redox_rt::sys::{WaitpidTarget, posix_read, posix_write, std_fs_call_ro, std_fs_call_wo}; +use syscall::{ + EMFILE, ENAMETOOLONG, ENOSYS, EOPNOTSUPP, Error, Result, StdFsCallKind, + data::StdFsCallMeta, + dirent::{DirentHeader, DirentKind}, +}; use crate::{ header::{ @@ -46,84 +50,30 @@ pub fn openat(dirfd: c_int, path: &str, oflag: c_int, mode: mode_t) -> Result Result<()> { - let mut redox_buf: syscall::Stat = Default::default(); - syscall::fstat(fd, &mut redox_buf)?; - - if let Some(buf) = unsafe { buf.as_mut() } { - buf.st_dev = redox_buf.st_dev as dev_t; - buf.st_ino = redox_buf.st_ino as ino_t; - buf.st_nlink = redox_buf.st_nlink as nlink_t; - buf.st_mode = redox_buf.st_mode as mode_t; - buf.st_uid = redox_buf.st_uid as uid_t; - buf.st_gid = redox_buf.st_gid as gid_t; - // TODO st_rdev - buf.st_rdev = 0; - buf.st_size = redox_buf.st_size as off_t; - buf.st_blksize = redox_buf.st_blksize as blksize_t; - buf.st_blocks = redox_buf.st_blocks as blkcnt_t; - buf.st_atim = timespec { - tv_sec: redox_buf.st_atime as time_t, - tv_nsec: redox_buf.st_atime_nsec as c_long, - }; - buf.st_mtim = timespec { - tv_sec: redox_buf.st_mtime as time_t, - tv_nsec: redox_buf.st_mtime_nsec as c_long, - }; - buf.st_ctim = timespec { - tv_sec: redox_buf.st_ctime as time_t, - tv_nsec: redox_buf.st_ctime_nsec as c_long, - }; - } +pub fn fchmod(fd: usize, new_mode: u16) -> Result<()> { + std_fs_call_wo( + fd, + &[], + &StdFsCallMeta::new(StdFsCallKind::Fchmod, new_mode as u64, 0), + )?; Ok(()) } -pub unsafe fn fstatvfs( - fd: usize, - buf: *mut crate::header::sys_statvfs::statvfs, -) -> syscall::Result<()> { - let mut kbuf: syscall::StatVfs = Default::default(); - syscall::fstatvfs(fd, &mut kbuf)?; - - if !buf.is_null() { - unsafe { - (*buf).f_bsize = kbuf.f_bsize as c_ulong; - (*buf).f_frsize = kbuf.f_bsize as c_ulong; - (*buf).f_blocks = kbuf.f_blocks as c_ulong; - (*buf).f_bfree = kbuf.f_bfree as c_ulong; - (*buf).f_bavail = kbuf.f_bavail as c_ulong; - //TODO - (*buf).f_files = 0; - (*buf).f_ffree = 0; - (*buf).f_favail = 0; - (*buf).f_fsid = 0; - (*buf).f_flag = 0; - (*buf).f_namemax = 0; - } - } +pub fn fchown(fd: usize, new_uid: u32, new_gid: u32) -> Result<()> { + /* std_fs_call + Error::mux(std_fs_call_wo( + fd, + &[], + &StdFsCallMeta::new( + StdFsCallKind::Fchmod, + (new_uid as u64) | ((new_gid as u64) << 32), + 0, + ), + )) + */ + syscall::fchown(fd, new_uid, new_gid)?; Ok(()) } -pub unsafe fn futimens(fd: usize, times: *const timespec) -> syscall::Result<()> { - let times = if times.is_null() { - // null means set to current time using special UTIME_NOW value (tv_sec is ignored in that case) - [ - syscall::TimeSpec { - tv_sec: 0, - tv_nsec: UTIME_NOW as c_int, - }, - syscall::TimeSpec { - tv_sec: 0, - tv_nsec: UTIME_NOW as c_int, - }, - ] - } else { - unsafe { times.cast::<[timespec; 2]>().read() }.map(|ts| syscall::TimeSpec::from(&ts)) - }; - syscall::futimens(fd as usize, ×)?; - Ok(()) -} -/* std_fs_call -pub fn std_fs_call_getdents(fd: usize, buf: &mut [u8], opaque: u64) -> Result { +pub fn getdents(fd: usize, buf: &mut [u8], opaque: u64) -> Result { //println!("GETDENTS {} into ({:p}+{})", fd, buf.as_ptr(), buf.len()); const HEADER_SIZE: usize = mem::size_of::(); @@ -177,13 +127,9 @@ pub fn std_fs_call_getdents(fd: usize, buf: &mut [u8], opaque: u64) -> Result Result<()> { +pub unsafe fn fstat(fd: usize, buf: *mut crate::header::sys_stat::stat) -> Result<()> { let mut redox_buf: syscall::Stat = Default::default(); - std_fs_call_ro( - fd, - &mut redox_buf, - &StdFsCallMeta::new(StdFsCallKind::Fstat, 0, 0), - )?; + redox_rt::sys::fstat(fd, &mut redox_buf)?; if let Some(buf) = unsafe { buf.as_mut() } { buf.st_dev = redox_buf.st_dev as dev_t; @@ -212,10 +158,7 @@ pub unsafe fn std_fs_call_fstat(fd: usize, buf: *mut crate::header::sys_stat::st } Ok(()) } -pub unsafe fn std_fs_call_fstatvfs( - fd: usize, - buf: *mut crate::header::sys_statvfs::statvfs, -) -> Result<()> { +pub unsafe fn fstatvfs(fd: usize, buf: *mut crate::header::sys_statvfs::statvfs) -> Result<()> { let mut kbuf: syscall::StatVfs = Default::default(); std_fs_call_ro( fd, @@ -241,7 +184,19 @@ pub unsafe fn std_fs_call_fstatvfs( } Ok(()) } -pub unsafe fn std_fs_call_futimens(fd: usize, times: *const timespec) -> Result<()> { +pub fn fsync(fd: usize) -> Result<()> { + std_fs_call_wo(fd, &[], &StdFsCallMeta::new(StdFsCallKind::Fsync, 0, 0))?; + Ok(()) +} +pub fn ftruncate(fd: usize, len: usize) -> Result<()> { + std_fs_call_wo( + fd, + &[], + &StdFsCallMeta::new(StdFsCallKind::Ftruncate, len as u64, 0), + )?; + Ok(()) +} +pub unsafe fn futimens(fd: usize, times: *const timespec) -> Result<()> { let times = if times.is_null() { // null means set to current time using special UTIME_NOW value (tv_sec is ignored in that case) [ @@ -270,7 +225,6 @@ pub unsafe fn std_fs_call_futimens(fd: usize, times: *const timespec) -> Result< )?; Ok(()) } -*/ pub fn clock_gettime(clock: usize, mut tp: Out) -> Result<()> { let mut redox_tp = syscall::TimeSpec::default(); syscall::clock_gettime(clock as usize, &mut redox_tp)?; @@ -344,29 +298,11 @@ pub unsafe extern "C" fn redox_write_v1( } #[unsafe(no_mangle)] pub unsafe extern "C" fn redox_fchmod_v1(fd: usize, new_mode: u16) -> RawResult { - /* std_fs_call - Error::mux(std_fs_call_wo( - fd, - &[], - &StdFsCallMeta::new(StdFsCallKind::Fchmod, new_mode as u64, 0), - )) - */ - Error::mux(syscall::fchmod(fd, new_mode)) + Error::mux(fchmod(fd, new_mode).map(|()| 0)) } #[unsafe(no_mangle)] pub unsafe extern "C" fn redox_fchown_v1(fd: usize, new_uid: u32, new_gid: u32) -> RawResult { - /* std_fs_call - Error::mux(std_fs_call_wo( - fd, - &[], - &StdFsCallMeta::new( - StdFsCallKind::Fchmod, - (new_uid as u64) | ((new_gid as u64) << 32), - 0, - ), - )) - */ - Error::mux(syscall::fchown(fd, new_uid, new_gid)) + Error::mux(fchown(fd, new_uid, new_gid).map(|()| 0)) } #[unsafe(no_mangle)] pub unsafe extern "C" fn redox_getdents_v0( @@ -400,37 +336,16 @@ pub unsafe extern "C" fn redox_fstatvfs_v1( } #[unsafe(no_mangle)] pub unsafe extern "C" fn redox_fsync_v1(fd: usize) -> RawResult { - /* std_fs_call - Error::mux(std_fs_call_wo( - fd, - &[], - &StdFsCallMeta::new(StdFsCallKind::Fsync, 0, 0), - )) - */ - Error::mux(syscall::fsync(fd)) + Error::mux(fsync(fd).map(|()| 0)) } #[unsafe(no_mangle)] pub unsafe extern "C" fn redox_fdatasync_v1(fd: usize) -> RawResult { - /* std_fs_call - Error::mux(std_fs_call_wo( - fd, - &[], - &StdFsCallMeta::new(StdFsCallKind::Fsync, 0, 0), - )) - */ // TODO - Error::mux(syscall::fsync(fd)) + Error::mux(fsync(fd).map(|()| 0)) } #[unsafe(no_mangle)] pub unsafe extern "C" fn redox_ftruncate_v0(fd: usize, len: usize) -> RawResult { - /* std_fs_call - Error::mux(std_fs_call_wo( - fd, - &[], - &StdFsCallMeta::new(StdFsCallKind::Ftruncate, len as u64, 0), - )) - */ - Error::mux(syscall::ftruncate(fd as usize, len as usize)) + Error::mux(ftruncate(fd, len).map(|()| 0)) } #[unsafe(no_mangle)] pub unsafe extern "C" fn redox_futimens_v1(fd: usize, times: *const timespec) -> RawResult { diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 5f527cfaa3..3c0d90ac03 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -13,7 +13,7 @@ use redox_rt::{ use syscall::{ self, EILSEQ, ESRCH, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta, data::{Map, TimeSpec as redox_timespec}, - dirent::{DirentHeader, DirentKind}, + dirent::DirentHeader, }; use self::{ @@ -270,7 +270,7 @@ impl Pal for Sys { } fn fchmod(fd: c_int, mode: mode_t) -> Result<()> { - syscall::fchmod(fd as usize, mode as u16)?; + libredox::fchmod(fd as usize, mode as u16)?; Ok(()) } @@ -283,12 +283,12 @@ impl Pal for Sys { .and_then(|cs| str::from_utf8(cs.to_bytes()).ok()) .ok_or(Errno(ENOENT))?; let file = openat2(dirfd, path, flags, 0)?; - syscall::fchmod(*file as usize, mode as u16)?; + libredox::fchmod(*file as usize, mode as u16)?; Ok(()) } fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> Result<()> { - syscall::fchown(fd as usize, owner as u32, group as u32)?; + libredox::fchown(fd as usize, owner as u32, group as u32)?; Ok(()) } @@ -484,12 +484,12 @@ impl Pal for Sys { } fn fsync(fd: c_int) -> Result<()> { - syscall::fsync(fd as usize)?; + libredox::fsync(fd as usize)?; Ok(()) } fn ftruncate(fd: c_int, len: off_t) -> Result<()> { - syscall::ftruncate(fd as usize, len as usize)?; + libredox::ftruncate(fd as usize, len as usize)?; Ok(()) } @@ -523,63 +523,7 @@ impl Pal for Sys { } fn getdents(fd: c_int, buf: &mut [u8], opaque: u64) -> Result { - //println!("GETDENTS {} into ({:p}+{})", fd, buf.as_ptr(), buf.len()); - - const HEADER_SIZE: usize = size_of::(); - - // Use syscall if it exists. - match unsafe { - syscall::syscall5( - syscall::SYS_GETDENTS, - fd as usize, - buf.as_mut_ptr() as usize, - buf.len(), - HEADER_SIZE, - opaque as usize, - ) - } { - Err(Error { - errno: EOPNOTSUPP | ENOSYS, - }) => (), - other => { - //println!("REAL GETDENTS {:?}", other); - return Ok(other?); - } - } - - // Otherwise, for legacy schemes, assume the buffer is pre-arranged (all schemes do this in - // practice), and just read the name. If multiple names appear, pretend it didn't happen - // and just use the first entry. - - let (header, name) = buf.split_at_mut(size_of::()); - - let bytes_read = Sys::pread(fd, name, opaque as i64)? as usize; - if bytes_read == 0 { - return Ok(0); - } - - let (name_len, advance) = match name[..bytes_read].iter().position(|c| *c == b'\n') { - Some(idx) => (idx, idx + 1), - - // Insufficient space for NUL byte, or entire entry was not read. Indicate we need a - // larger buffer. - None if bytes_read == name.len() => return Err(Errno(EINVAL)), - - None => (bytes_read, name.len()), - }; - name[name_len] = b'\0'; - - let record_len = u16::try_from(size_of::() + name_len + 1) - .map_err(|_| Error::new(ENAMETOOLONG))?; - header.copy_from_slice(&DirentHeader { - inode: 0, - next_opaque_id: opaque + advance as u64, - record_len, - kind: DirentKind::Unspecified as u8, - }); - //println!("EMULATED GETDENTS"); - - Ok(record_len.into()) + Ok(libredox::getdents(fd as usize, buf, opaque)?) } fn dir_seek(_fd: c_int, _off: u64) -> Result<()> { @@ -1041,17 +985,18 @@ impl Pal for Sys { let length = length.get(); let total_offset = offset.checked_add(length).ok_or(Errno(EFBIG))?; - let mut stat = syscall::Stat::default(); - syscall::fstat(fd as usize, &mut stat)?; + let mut stat: stat = unsafe { mem::zeroed() }; + unsafe { libredox::fstat(fd as usize, &mut stat)? }; + let st_size = stat.st_size as u64; // The difference between total_offset and the file size is the number of bytes to // allocate. So, if it's negative then the file is already large enough and we don't // need to do any extra work. if let Some(total_len) = total_offset - .checked_sub(stat.st_size) - .and_then(|diff| stat.st_size.checked_add(diff)) + .checked_sub(st_size) + .and_then(|diff| st_size.checked_add(diff)) { let total_len: usize = total_len.try_into().map_err(|_| Errno(EFBIG))?; - syscall::ftruncate(fd as usize, total_len)?; + libredox::ftruncate(fd as usize, total_len)?; } Ok(())