Browse Source

[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
pull/779/head
Jakub Konka 5 years ago
committed by GitHub
parent
commit
06be4b1495
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      crates/wasi-common/src/helpers.rs
  2. 3
      crates/wasi-common/src/hostcalls_impl/fs.rs
  3. 10
      crates/wasi-common/src/old/snapshot_0/helpers.rs
  4. 3
      crates/wasi-common/src/old/snapshot_0/hostcalls_impl/fs.rs
  5. 17
      crates/wasi-common/src/old/snapshot_0/sys/unix/host_impl.rs
  6. 49
      crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs
  7. 59
      crates/wasi-common/src/old/snapshot_0/sys/windows/host_impl.rs
  8. 57
      crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/fs.rs
  9. 1
      crates/wasi-common/src/old/snapshot_0/sys/windows/hostcalls_impl/misc.rs
  10. 17
      crates/wasi-common/src/sys/unix/host_impl.rs
  11. 49
      crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs
  12. 59
      crates/wasi-common/src/sys/windows/host_impl.rs
  13. 57
      crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs
  14. 1
      crates/wasi-common/src/sys/windows/hostcalls_impl/misc.rs
  15. 7
      crates/wasi-common/yanix/src/file.rs

10
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<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.
///

3
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);

10
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<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.
///

3
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);

17
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<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,

49
crates/wasi-common/src/old/snapshot_0/sys/unix/hostcalls_impl/fs.rs

@ -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(

59
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<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,

57
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<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
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;

17
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<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,

49
crates/wasi-common/src/sys/unix/hostcalls_impl/fs.rs

@ -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(

59
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<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,

57
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<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
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;

7
crates/wasi-common/yanix/src/file.rs

@ -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;

Loading…
Cancel
Save