From 06be4b14956061a4231771912f85a98904b70cec Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 8 Jan 2020 16:34:38 +0100 Subject: [PATCH] [wasi-common] Clean up fd_filestat_get implementation (#757) * Clean up fd_filestat_get implementation This commit does 4 things: * Adds `yanix::file::fstat`, a wrapper around `libc::fstat`. * It essentially reverts 89fbde2 for Unix hosts -- in other words, it brings back the use of `fstat` to obtain `libc::stat` from a file descriptor, rather than relying on `std::fs::Metadata`. This way, we reuse `host_impl::filestat_from_nix` in `hostcalls_impl::fd_filestat_get` implementation rather than unnecessarily duplicate code for converting filestats into `__wasi_filestat_t`. * Moves `crate::helpers::systemtime_to_timestamp` to Windows `host_impl` module. It does the same thing with helpers which assist in converting `std::fs::Metadata` into `__wasi_filestat_t`. This should retain symmetry between *nix and Windows impls. * Makes timestamp conversions in `host_impl::filestat_from_nix` fallible. * Backport changes to snapshot0 * Signal no overflow with `from` rather than `as` cast --- crates/wasi-common/src/helpers.rs | 10 ---- crates/wasi-common/src/hostcalls_impl/fs.rs | 3 +- .../wasi-common/src/old/snapshot_0/helpers.rs | 10 ---- .../src/old/snapshot_0/hostcalls_impl/fs.rs | 3 +- .../src/old/snapshot_0/sys/unix/host_impl.rs | 17 +++++- .../snapshot_0/sys/unix/hostcalls_impl/fs.rs | 49 +++------------ .../old/snapshot_0/sys/windows/host_impl.rs | 59 +++++++++++++++++++ .../sys/windows/hostcalls_impl/fs.rs | 57 +++--------------- .../sys/windows/hostcalls_impl/misc.rs | 1 - crates/wasi-common/src/sys/unix/host_impl.rs | 17 +++++- .../src/sys/unix/hostcalls_impl/fs.rs | 49 +++------------ .../wasi-common/src/sys/windows/host_impl.rs | 59 +++++++++++++++++++ .../src/sys/windows/hostcalls_impl/fs.rs | 57 +++--------------- .../src/sys/windows/hostcalls_impl/misc.rs | 1 - crates/wasi-common/yanix/src/file.rs | 7 +++ 15 files changed, 183 insertions(+), 216 deletions(-) diff --git a/crates/wasi-common/src/helpers.rs b/crates/wasi-common/src/helpers.rs index 057540261e..f176b8d1fe 100644 --- a/crates/wasi-common/src/helpers.rs +++ b/crates/wasi-common/src/helpers.rs @@ -1,15 +1,5 @@ use crate::{Error, Result}; -use std::convert::TryInto; use std::str; -use std::time::{SystemTime, UNIX_EPOCH}; - -pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result { - st.duration_since(UNIX_EPOCH) - .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH - .as_nanos() - .try_into() - .map_err(Into::into) // u128 doesn't fit into u64 -} /// Creates not-owned WASI path from byte slice. /// diff --git a/crates/wasi-common/src/hostcalls_impl/fs.rs b/crates/wasi-common/src/hostcalls_impl/fs.rs index d59668a9ab..7f93fbc27d 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/hostcalls_impl/fs.rs @@ -710,8 +710,7 @@ pub(crate) unsafe fn fd_filestat_get( ); let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?; - - let host_filestat = hostcalls_impl::fd_filestat_get_impl(fd)?; + let host_filestat = hostcalls_impl::fd_filestat_get(fd)?; trace!(" | *filestat_ptr={:?}", host_filestat); diff --git a/crates/wasi-common/src/old/snapshot_0/helpers.rs b/crates/wasi-common/src/old/snapshot_0/helpers.rs index 48bd5fd3a2..f540eb8f12 100644 --- a/crates/wasi-common/src/old/snapshot_0/helpers.rs +++ b/crates/wasi-common/src/old/snapshot_0/helpers.rs @@ -1,15 +1,5 @@ use crate::old::snapshot_0::{Error, Result}; -use std::convert::TryInto; use std::str; -use std::time::{SystemTime, UNIX_EPOCH}; - -pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result { - st.duration_since(UNIX_EPOCH) - .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH - .as_nanos() - .try_into() - .map_err(Into::into) // u128 doesn't fit into u64 -} /// Creates not-owned WASI path from byte slice. /// diff --git a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs index 002e9d6749..8bbe5c223d 100644 --- a/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs @@ -693,8 +693,7 @@ pub(crate) unsafe fn fd_filestat_get( ); let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?; - - let host_filestat = hostcalls_impl::fd_filestat_get_impl(fd)?; + let host_filestat = hostcalls_impl::fd_filestat_get(fd)?; trace!(" | *filestat_ptr={:?}", host_filestat); diff --git a/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs index eb0bf33689..ac74fd3e83 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs @@ -168,6 +168,8 @@ pub(crate) fn filetype_from_nix(sflags: SFlag) -> FileType { } pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result { + use std::convert::TryInto; + fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result { secs.checked_mul(1_000_000_000) .and_then(|sec_nsec| sec_nsec.checked_add(nsecs)) @@ -177,9 +179,18 @@ pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result Result Ok(copy_len) } -pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result { - use std::os::unix::fs::MetadataExt; - - let metadata = file.metadata()?; - Ok(wasi::__wasi_filestat_t { - dev: metadata.dev(), - ino: metadata.ino(), - nlink: metadata.nlink().try_into()?, // u64 doesn't fit into u32 - size: metadata.len(), - atim: systemtime_to_timestamp(metadata.accessed()?)?, - ctim: metadata.ctime().try_into()?, // i64 doesn't fit into u64 - mtim: systemtime_to_timestamp(metadata.modified()?)?, - filetype: filetype(file, &metadata)?.to_wasi(), - }) -} - -fn filetype(file: &File, metadata: &Metadata) -> Result { - use std::os::unix::fs::FileTypeExt; - use yanix::socket::{get_socket_type, SockType}; - let ftype = metadata.file_type(); - if ftype.is_file() { - Ok(FileType::RegularFile) - } else if ftype.is_dir() { - Ok(FileType::Directory) - } else if ftype.is_symlink() { - Ok(FileType::Symlink) - } else if ftype.is_char_device() { - Ok(FileType::CharacterDevice) - } else if ftype.is_block_device() { - Ok(FileType::BlockDevice) - } else if ftype.is_socket() { - match unsafe { get_socket_type(file.as_raw_fd())? } { - SockType::Datagram => Ok(FileType::SocketDgram), - SockType::Stream => Ok(FileType::SocketStream), - _ => Ok(FileType::Unknown), - } - } else { - Ok(FileType::Unknown) - } +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { + use yanix::file::fstat; + unsafe { fstat(file.as_raw_fd()) } + .map_err(Into::into) + .and_then(host_impl::filestat_from_nix) } pub(crate) fn path_filestat_get( diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs index ddb1f35f5d..e5b80e2193 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs @@ -2,11 +2,16 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(unused)] +use crate::old::snapshot_0::host::FileType; use crate::old::snapshot_0::{wasi, Error, Result}; +use std::convert::TryInto; use std::ffi::OsStr; use std::fs::OpenOptions; +use std::fs::{self, File}; +use std::io; use std::os::windows::ffi::OsStrExt; use std::os::windows::fs::OpenOptionsExt; +use std::time::{SystemTime, UNIX_EPOCH}; use winx::file::{AccessMode, Attributes, CreationDisposition, Flags}; pub(crate) fn errno_from_win(error: winx::winerror::WinError) -> wasi::__wasi_errno_t { @@ -98,6 +103,60 @@ pub(crate) fn win_from_oflags(oflags: wasi::__wasi_oflags_t) -> CreationDisposit } } +pub(crate) fn filetype_from_std(ftype: &fs::FileType) -> FileType { + if ftype.is_file() { + FileType::RegularFile + } else if ftype.is_dir() { + FileType::Directory + } else if ftype.is_symlink() { + FileType::Symlink + } else { + FileType::Unknown + } +} + +fn num_hardlinks(file: &File) -> io::Result { + Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into()) +} + +fn device_id(file: &File) -> io::Result { + Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into()) +} + +pub(crate) fn file_serial_no(file: &File) -> io::Result { + let info = winx::file::get_fileinfo(file)?; + let high = info.nFileIndexHigh; + let low = info.nFileIndexLow; + let no = (u64::from(high) << 32) | u64::from(low); + Ok(no) +} + +fn change_time(file: &File) -> io::Result { + winx::file::change_time(file) +} + +fn systemtime_to_timestamp(st: SystemTime) -> Result { + st.duration_since(UNIX_EPOCH) + .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH + .as_nanos() + .try_into() + .map_err(Into::into) // u128 doesn't fit into u64 +} + +pub(crate) fn filestat_from_win(file: &File) -> Result { + let metadata = file.metadata()?; + Ok(wasi::__wasi_filestat_t { + dev: device_id(file)?, + ino: file_serial_no(file)?, + nlink: num_hardlinks(file)?.try_into()?, // u64 doesn't fit into u32 + size: metadata.len(), + atim: systemtime_to_timestamp(metadata.accessed()?)?, + ctim: change_time(file)?.try_into()?, // i64 doesn't fit into u64 + mtim: systemtime_to_timestamp(metadata.modified()?)?, + filetype: filetype_from_std(&metadata.file_type()).to_wasi(), + }) +} + /// Creates owned WASI path from OS string. /// /// NB WASI spec requires OS string to be valid UTF-8. Otherwise, diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs index 84228c28d9..173b8aa2b2 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs @@ -3,7 +3,6 @@ use super::fs_helpers::*; use crate::old::snapshot_0::ctx::WasiCtx; use crate::old::snapshot_0::fdentry::FdEntry; -use crate::old::snapshot_0::helpers::systemtime_to_timestamp; use crate::old::snapshot_0::host::{Dirent, FileType}; use crate::old::snapshot_0::hostcalls_impl::{fd_filestat_set_times_impl, PathGet}; use crate::old::snapshot_0::sys::fdentry_impl::determine_type_rights; @@ -249,10 +248,10 @@ fn dirent_from_path>( .open(path)?; let ty = file.metadata()?.file_type(); Ok(Dirent { - ftype: filetype_from_std(&ty), + ftype: host_impl::filetype_from_std(&ty), name: name.to_owned(), cookie, - ino: file_serial_no(&file)?, + ino: host_impl::file_serial_no(&file)?, }) } @@ -305,8 +304,8 @@ pub(crate) fn fd_readdir( Ok(Dirent { name: path_from_host(dir.file_name())?, - ftype: filetype_from_std(&dir.file_type()?), - ino: File::open(dir.path()).and_then(|f| file_serial_no(&f))?, + ftype: host_impl::filetype_from_std(&dir.file_type()?), + ino: File::open(dir.path()).and_then(|f| host_impl::file_serial_no(&f))?, cookie: no, }) }); @@ -429,50 +428,8 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul }) } -pub(crate) fn num_hardlinks(file: &File, _metadata: &Metadata) -> io::Result { - Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into()) -} - -pub(crate) fn device_id(file: &File, _metadata: &Metadata) -> io::Result { - Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into()) -} - -pub(crate) fn file_serial_no(file: &File) -> io::Result { - let info = winx::file::get_fileinfo(file)?; - let high = info.nFileIndexHigh; - let low = info.nFileIndexLow; - let no = ((high as u64) << 32) | (low as u64); - Ok(no) -} - -pub(crate) fn change_time(file: &File, _metadata: &Metadata) -> io::Result { - winx::file::change_time(file) -} - -pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result { - let metadata = file.metadata()?; - Ok(wasi::__wasi_filestat_t { - dev: device_id(file, &metadata)?, - ino: file_serial_no(file)?, - nlink: num_hardlinks(file, &metadata)?.try_into()?, // u64 doesn't fit into u32 - size: metadata.len(), - atim: systemtime_to_timestamp(metadata.accessed()?)?, - ctim: change_time(file, &metadata)?.try_into()?, // i64 doesn't fit into u64 - mtim: systemtime_to_timestamp(metadata.modified()?)?, - filetype: filetype_from_std(&metadata.file_type()).to_wasi(), - }) -} - -pub(crate) fn filetype_from_std(ftype: &std::fs::FileType) -> FileType { - if ftype.is_file() { - FileType::RegularFile - } else if ftype.is_dir() { - FileType::Directory - } else if ftype.is_symlink() { - FileType::Symlink - } else { - FileType::Unknown - } +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { + host_impl::filestat_from_win(file) } pub(crate) fn path_filestat_get( @@ -481,7 +438,7 @@ pub(crate) fn path_filestat_get( ) -> Result { let path = resolved.concatenate()?; let file = File::open(path)?; - fd_filestat_get_impl(&file) + host_impl::filestat_from_win(&file) } pub(crate) fn path_filestat_set_times( diff --git a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs index b6ed4df11e..bf8df626cd 100644 --- a/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs @@ -1,7 +1,6 @@ #![allow(non_camel_case_types)] #![allow(unused_unsafe)] #![allow(unused)] -use crate::old::snapshot_0::helpers::systemtime_to_timestamp; use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData}; use crate::old::snapshot_0::memory::*; use crate::old::snapshot_0::sys::host_impl; diff --git a/crates/wasi-common/src/sys/unix/host_impl.rs b/crates/wasi-common/src/sys/unix/host_impl.rs index 34ca49a1f4..e74c2bcc7f 100644 --- a/crates/wasi-common/src/sys/unix/host_impl.rs +++ b/crates/wasi-common/src/sys/unix/host_impl.rs @@ -168,6 +168,8 @@ pub(crate) fn filetype_from_nix(sflags: SFlag) -> FileType { } pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result { + use std::convert::TryInto; + fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result { secs.checked_mul(1_000_000_000) .and_then(|sec_nsec| sec_nsec.checked_add(nsecs)) @@ -177,9 +179,18 @@ pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result Result Ok(copy_len) } -pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result { - use std::os::unix::fs::MetadataExt; - - let metadata = file.metadata()?; - Ok(wasi::__wasi_filestat_t { - dev: metadata.dev(), - ino: metadata.ino(), - nlink: metadata.nlink().try_into()?, // u64 doesn't fit into u32 - size: metadata.len(), - atim: systemtime_to_timestamp(metadata.accessed()?)?, - ctim: metadata.ctime().try_into()?, // i64 doesn't fit into u64 - mtim: systemtime_to_timestamp(metadata.modified()?)?, - filetype: filetype(file, &metadata)?.to_wasi(), - }) -} - -fn filetype(file: &File, metadata: &Metadata) -> Result { - use std::os::unix::fs::FileTypeExt; - use yanix::socket::{get_socket_type, SockType}; - let ftype = metadata.file_type(); - if ftype.is_file() { - Ok(FileType::RegularFile) - } else if ftype.is_dir() { - Ok(FileType::Directory) - } else if ftype.is_symlink() { - Ok(FileType::Symlink) - } else if ftype.is_char_device() { - Ok(FileType::CharacterDevice) - } else if ftype.is_block_device() { - Ok(FileType::BlockDevice) - } else if ftype.is_socket() { - match unsafe { get_socket_type(file.as_raw_fd())? } { - SockType::Datagram => Ok(FileType::SocketDgram), - SockType::Stream => Ok(FileType::SocketStream), - _ => Ok(FileType::Unknown), - } - } else { - Ok(FileType::Unknown) - } +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { + use yanix::file::fstat; + unsafe { fstat(file.as_raw_fd()) } + .map_err(Into::into) + .and_then(host_impl::filestat_from_nix) } pub(crate) fn path_filestat_get( diff --git a/crates/wasi-common/src/sys/windows/host_impl.rs b/crates/wasi-common/src/sys/windows/host_impl.rs index 2816bcd66b..71d7ef0332 100644 --- a/crates/wasi-common/src/sys/windows/host_impl.rs +++ b/crates/wasi-common/src/sys/windows/host_impl.rs @@ -1,7 +1,12 @@ //! WASI host types specific to Windows host. +use crate::host::FileType; use crate::{wasi, Error, Result}; +use std::convert::TryInto; use std::ffi::OsStr; +use std::fs::{self, File}; +use std::io; use std::os::windows::ffi::OsStrExt; +use std::time::{SystemTime, UNIX_EPOCH}; pub(crate) fn errno_from_win(error: winx::winerror::WinError) -> wasi::__wasi_errno_t { // TODO: implement error mapping between Windows and WASI @@ -34,6 +39,60 @@ pub(crate) fn errno_from_win(error: winx::winerror::WinError) -> wasi::__wasi_er } } +pub(crate) fn filetype_from_std(ftype: &fs::FileType) -> FileType { + if ftype.is_file() { + FileType::RegularFile + } else if ftype.is_dir() { + FileType::Directory + } else if ftype.is_symlink() { + FileType::Symlink + } else { + FileType::Unknown + } +} + +fn num_hardlinks(file: &File) -> io::Result { + Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into()) +} + +fn device_id(file: &File) -> io::Result { + Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into()) +} + +pub(crate) fn file_serial_no(file: &File) -> io::Result { + let info = winx::file::get_fileinfo(file)?; + let high = info.nFileIndexHigh; + let low = info.nFileIndexLow; + let no = (u64::from(high) << 32) | u64::from(low); + Ok(no) +} + +fn change_time(file: &File) -> io::Result { + winx::file::change_time(file) +} + +fn systemtime_to_timestamp(st: SystemTime) -> Result { + st.duration_since(UNIX_EPOCH) + .map_err(|_| Error::EINVAL)? // date earlier than UNIX_EPOCH + .as_nanos() + .try_into() + .map_err(Into::into) // u128 doesn't fit into u64 +} + +pub(crate) fn filestat_from_win(file: &File) -> Result { + let metadata = file.metadata()?; + Ok(wasi::__wasi_filestat_t { + dev: device_id(file)?, + ino: file_serial_no(file)?, + nlink: num_hardlinks(file)?.try_into()?, // u64 doesn't fit into u32 + size: metadata.len(), + atim: systemtime_to_timestamp(metadata.accessed()?)?, + ctim: change_time(file)?.try_into()?, // i64 doesn't fit into u64 + mtim: systemtime_to_timestamp(metadata.modified()?)?, + filetype: filetype_from_std(&metadata.file_type()).to_wasi(), + }) +} + /// Creates owned WASI path from OS string. /// /// NB WASI spec requires OS string to be valid UTF-8. Otherwise, diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs index 4f5d3c8783..654a475b2d 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs @@ -3,7 +3,6 @@ use super::fs_helpers::*; use crate::ctx::WasiCtx; use crate::fdentry::FdEntry; -use crate::helpers::systemtime_to_timestamp; use crate::host::{Dirent, FileType}; use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet}; use crate::sys::fdentry_impl::determine_type_rights; @@ -249,10 +248,10 @@ fn dirent_from_path>( .open(path)?; let ty = file.metadata()?.file_type(); Ok(Dirent { - ftype: filetype_from_std(&ty), + ftype: host_impl::filetype_from_std(&ty), name: name.to_owned(), cookie, - ino: file_serial_no(&file)?, + ino: host_impl::file_serial_no(&file)?, }) } @@ -305,8 +304,8 @@ pub(crate) fn fd_readdir( Ok(Dirent { name: path_from_host(dir.file_name())?, - ftype: filetype_from_std(&dir.file_type()?), - ino: File::open(dir.path()).and_then(|f| file_serial_no(&f))?, + ftype: host_impl::filetype_from_std(&dir.file_type()?), + ino: File::open(dir.path()).and_then(|f| host_impl::file_serial_no(&f))?, cookie: no, }) }); @@ -429,50 +428,8 @@ pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Resul }) } -pub(crate) fn num_hardlinks(file: &File, _metadata: &Metadata) -> io::Result { - Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into()) -} - -pub(crate) fn device_id(file: &File, _metadata: &Metadata) -> io::Result { - Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into()) -} - -pub(crate) fn file_serial_no(file: &File) -> io::Result { - let info = winx::file::get_fileinfo(file)?; - let high = info.nFileIndexHigh; - let low = info.nFileIndexLow; - let no = ((high as u64) << 32) | (low as u64); - Ok(no) -} - -pub(crate) fn change_time(file: &File, _metadata: &Metadata) -> io::Result { - winx::file::change_time(file) -} - -pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result { - let metadata = file.metadata()?; - Ok(wasi::__wasi_filestat_t { - dev: device_id(file, &metadata)?, - ino: file_serial_no(file)?, - nlink: num_hardlinks(file, &metadata)?.try_into()?, // u64 doesn't fit into u32 - size: metadata.len(), - atim: systemtime_to_timestamp(metadata.accessed()?)?, - ctim: change_time(file, &metadata)?.try_into()?, // i64 doesn't fit into u64 - mtim: systemtime_to_timestamp(metadata.modified()?)?, - filetype: filetype_from_std(&metadata.file_type()).to_wasi(), - }) -} - -pub(crate) fn filetype_from_std(ftype: &std::fs::FileType) -> FileType { - if ftype.is_file() { - FileType::RegularFile - } else if ftype.is_dir() { - FileType::Directory - } else if ftype.is_symlink() { - FileType::Symlink - } else { - FileType::Unknown - } +pub(crate) fn fd_filestat_get(file: &std::fs::File) -> Result { + host_impl::filestat_from_win(file) } pub(crate) fn path_filestat_get( @@ -481,7 +438,7 @@ pub(crate) fn path_filestat_get( ) -> Result { let path = resolved.concatenate()?; let file = File::open(path)?; - fd_filestat_get_impl(&file) + host_impl::filestat_from_win(&file) } pub(crate) fn path_filestat_set_times( diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs index 28d1408de1..d781409093 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs @@ -1,7 +1,6 @@ #![allow(non_camel_case_types)] #![allow(unused_unsafe)] #![allow(unused)] -use crate::helpers::systemtime_to_timestamp; use crate::hostcalls_impl::{ClockEventData, FdEventData}; use crate::memory::*; use crate::sys::host_impl; diff --git a/crates/wasi-common/yanix/src/file.rs b/crates/wasi-common/yanix/src/file.rs index 36f12141a1..397cc8bd30 100644 --- a/crates/wasi-common/yanix/src/file.rs +++ b/crates/wasi-common/yanix/src/file.rs @@ -190,6 +190,13 @@ pub unsafe fn fstatat>(dirfd: RawFd, path: P, flags: AtFlag) -> Ok(filestat.assume_init()) } +pub unsafe fn fstat(fd: RawFd) -> Result { + use std::mem::MaybeUninit; + let mut filestat = MaybeUninit::::uninit(); + Errno::from_result(libc::fstat(fd, filestat.as_mut_ptr()))?; + Ok(filestat.assume_init()) +} + /// `fionread()` function, equivalent to `ioctl(fd, FIONREAD, *bytes)`. pub unsafe fn fionread(fd: RawFd) -> Result { let mut nread: libc::c_int = 0;