[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
This commit is contained in:
@@ -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<u64> {
|
||||
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.
|
||||
///
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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<u64> {
|
||||
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.
|
||||
///
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -168,6 +168,8 @@ pub(crate) fn filetype_from_nix(sflags: SFlag) -> FileType {
|
||||
}
|
||||
|
||||
pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result<wasi::__wasi_filestat_t> {
|
||||
use std::convert::TryInto;
|
||||
|
||||
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<wasi::__wasi_timestamp_t> {
|
||||
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<wasi::__wasi_fil
|
||||
let filetype = SFlag::from_bits_truncate(filestat.st_mode);
|
||||
let dev = stdev_from_nix(filestat.st_dev)?;
|
||||
let ino = stino_from_nix(filestat.st_ino)?;
|
||||
let atim = filestat_to_timestamp(filestat.st_atime as u64, filestat.st_atime_nsec as u64)?;
|
||||
let ctim = filestat_to_timestamp(filestat.st_ctime as u64, filestat.st_ctime_nsec as u64)?;
|
||||
let mtim = filestat_to_timestamp(filestat.st_mtime as u64, filestat.st_mtime_nsec as u64)?;
|
||||
let atim = filestat_to_timestamp(
|
||||
filestat.st_atime.try_into()?,
|
||||
filestat.st_atime_nsec.try_into()?,
|
||||
)?;
|
||||
let ctim = filestat_to_timestamp(
|
||||
filestat.st_ctime.try_into()?,
|
||||
filestat.st_ctime_nsec.try_into()?,
|
||||
)?;
|
||||
let mtim = filestat_to_timestamp(
|
||||
filestat.st_mtime.try_into()?,
|
||||
filestat.st_mtime_nsec.try_into()?,
|
||||
)?;
|
||||
|
||||
Ok(wasi::__wasi_filestat_t {
|
||||
dev,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(unused_unsafe)]
|
||||
use crate::old::snapshot_0::helpers::systemtime_to_timestamp;
|
||||
use crate::old::snapshot_0::host::{Dirent, FileType};
|
||||
use crate::old::snapshot_0::host::Dirent;
|
||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
||||
use crate::old::snapshot_0::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl};
|
||||
use crate::old::snapshot_0::{wasi, Error, Result};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{File, Metadata};
|
||||
use std::fs::File;
|
||||
use std::os::unix::fs::FileExt;
|
||||
use std::os::unix::prelude::{AsRawFd, FromRawFd};
|
||||
|
||||
@@ -198,45 +197,11 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
|
||||
Ok(copy_len)
|
||||
}
|
||||
|
||||
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
|
||||
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<FileType> {
|
||||
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<wasi::__wasi_filestat_t> {
|
||||
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(
|
||||
|
||||
@@ -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<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into())
|
||||
}
|
||||
|
||||
fn device_id(file: &File) -> io::Result<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into())
|
||||
}
|
||||
|
||||
pub(crate) fn file_serial_no(file: &File) -> io::Result<u64> {
|
||||
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<i64> {
|
||||
winx::file::change_time(file)
|
||||
}
|
||||
|
||||
fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
|
||||
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<wasi::__wasi_filestat_t> {
|
||||
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,
|
||||
|
||||
@@ -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<P: AsRef<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<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into())
|
||||
}
|
||||
|
||||
pub(crate) fn device_id(file: &File, _metadata: &Metadata) -> io::Result<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into())
|
||||
}
|
||||
|
||||
pub(crate) fn file_serial_no(file: &File) -> io::Result<u64> {
|
||||
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<i64> {
|
||||
winx::file::change_time(file)
|
||||
}
|
||||
|
||||
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
|
||||
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<wasi::__wasi_filestat_t> {
|
||||
host_impl::filestat_from_win(file)
|
||||
}
|
||||
|
||||
pub(crate) fn path_filestat_get(
|
||||
@@ -481,7 +438,7 @@ pub(crate) fn path_filestat_get(
|
||||
) -> Result<wasi::__wasi_filestat_t> {
|
||||
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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -168,6 +168,8 @@ pub(crate) fn filetype_from_nix(sflags: SFlag) -> FileType {
|
||||
}
|
||||
|
||||
pub(crate) fn filestat_from_nix(filestat: libc::stat) -> Result<wasi::__wasi_filestat_t> {
|
||||
use std::convert::TryInto;
|
||||
|
||||
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<wasi::__wasi_timestamp_t> {
|
||||
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<wasi::__wasi_fil
|
||||
let filetype = SFlag::from_bits_truncate(filestat.st_mode);
|
||||
let dev = stdev_from_nix(filestat.st_dev)?;
|
||||
let ino = stino_from_nix(filestat.st_ino)?;
|
||||
let atim = filestat_to_timestamp(filestat.st_atime as u64, filestat.st_atime_nsec as u64)?;
|
||||
let ctim = filestat_to_timestamp(filestat.st_ctime as u64, filestat.st_ctime_nsec as u64)?;
|
||||
let mtim = filestat_to_timestamp(filestat.st_mtime as u64, filestat.st_mtime_nsec as u64)?;
|
||||
let atim = filestat_to_timestamp(
|
||||
filestat.st_atime.try_into()?,
|
||||
filestat.st_atime_nsec.try_into()?,
|
||||
)?;
|
||||
let ctim = filestat_to_timestamp(
|
||||
filestat.st_ctime.try_into()?,
|
||||
filestat.st_ctime_nsec.try_into()?,
|
||||
)?;
|
||||
let mtim = filestat_to_timestamp(
|
||||
filestat.st_mtime.try_into()?,
|
||||
filestat.st_mtime_nsec.try_into()?,
|
||||
)?;
|
||||
|
||||
Ok(wasi::__wasi_filestat_t {
|
||||
dev,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(unused_unsafe)]
|
||||
use crate::helpers::systemtime_to_timestamp;
|
||||
use crate::host::{Dirent, FileType};
|
||||
use crate::host::Dirent;
|
||||
use crate::hostcalls_impl::PathGet;
|
||||
use crate::sys::{fdentry_impl::OsHandle, host_impl, unix::sys_impl};
|
||||
use crate::{wasi, Error, Result};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{File, Metadata};
|
||||
use std::fs::File;
|
||||
use std::os::unix::fs::FileExt;
|
||||
use std::os::unix::prelude::{AsRawFd, FromRawFd};
|
||||
|
||||
@@ -198,45 +197,11 @@ pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result<usize>
|
||||
Ok(copy_len)
|
||||
}
|
||||
|
||||
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
|
||||
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<FileType> {
|
||||
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<wasi::__wasi_filestat_t> {
|
||||
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(
|
||||
|
||||
@@ -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<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into())
|
||||
}
|
||||
|
||||
fn device_id(file: &File) -> io::Result<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into())
|
||||
}
|
||||
|
||||
pub(crate) fn file_serial_no(file: &File) -> io::Result<u64> {
|
||||
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<i64> {
|
||||
winx::file::change_time(file)
|
||||
}
|
||||
|
||||
fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
|
||||
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<wasi::__wasi_filestat_t> {
|
||||
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,
|
||||
|
||||
@@ -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<P: AsRef<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<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.nNumberOfLinks.into())
|
||||
}
|
||||
|
||||
pub(crate) fn device_id(file: &File, _metadata: &Metadata) -> io::Result<u64> {
|
||||
Ok(winx::file::get_fileinfo(file)?.dwVolumeSerialNumber.into())
|
||||
}
|
||||
|
||||
pub(crate) fn file_serial_no(file: &File) -> io::Result<u64> {
|
||||
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<i64> {
|
||||
winx::file::change_time(file)
|
||||
}
|
||||
|
||||
pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<wasi::__wasi_filestat_t> {
|
||||
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<wasi::__wasi_filestat_t> {
|
||||
host_impl::filestat_from_win(file)
|
||||
}
|
||||
|
||||
pub(crate) fn path_filestat_get(
|
||||
@@ -481,7 +438,7 @@ pub(crate) fn path_filestat_get(
|
||||
) -> Result<wasi::__wasi_filestat_t> {
|
||||
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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -190,6 +190,13 @@ pub unsafe fn fstatat<P: AsRef<OsStr>>(dirfd: RawFd, path: P, flags: AtFlag) ->
|
||||
Ok(filestat.assume_init())
|
||||
}
|
||||
|
||||
pub unsafe fn fstat(fd: RawFd) -> Result<libc::stat> {
|
||||
use std::mem::MaybeUninit;
|
||||
let mut filestat = MaybeUninit::<libc::stat>::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<usize> {
|
||||
let mut nread: libc::c_int = 0;
|
||||
|
||||
Reference in New Issue
Block a user