[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,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(
|
||||
|
||||
Reference in New Issue
Block a user