[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:
Jakub Konka
2020-01-08 16:34:38 +01:00
committed by GitHub
parent b46f26361f
commit 06be4b1495
15 changed files with 183 additions and 216 deletions

View File

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