Add a typesafe enum for file type

This commit is contained in:
Marcin Mielniczuk
2019-10-03 15:21:43 +02:00
committed by Jakub Konka
parent 5dad532a43
commit 968fb19f17
4 changed files with 49 additions and 28 deletions

View File

@@ -1062,3 +1062,23 @@ pub(crate) unsafe fn fd_prestat_dir_name(
enc_slice_of(memory, path.as_bytes(), path_ptr) enc_slice_of(memory, path.as_bytes(), path_ptr)
}) })
} }
#[allow(dead_code)] // trouble with sockets
#[derive(Clone, Copy, Debug)]
#[repr(u8)]
pub(crate) enum FileType {
Unknown = host::__WASI_FILETYPE_UNKNOWN,
BlockDevice = host::__WASI_FILETYPE_BLOCK_DEVICE,
CharacterDevice = host::__WASI_FILETYPE_CHARACTER_DEVICE,
Directory = host::__WASI_FILETYPE_DIRECTORY,
RegularFile = host::__WASI_FILETYPE_REGULAR_FILE,
SocketDgram = host::__WASI_FILETYPE_SOCKET_DGRAM,
SocketStream = host::__WASI_FILETYPE_SOCKET_STREAM,
Symlink = host::__WASI_FILETYPE_SYMBOLIC_LINK,
}
impl FileType {
pub(crate) fn to_wasi(&self) -> host::__wasi_filetype_t {
*self as host::__wasi_filetype_t
}
}

View File

@@ -2,6 +2,7 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(dead_code)] #![allow(dead_code)]
use crate::hostcalls_impl::FileType;
use crate::{host, memory, Error, Result}; use crate::{host, memory, Error, Result};
use log::warn; use log::warn;
use std::ffi::OsStr; use std::ffi::OsStr;
@@ -156,22 +157,22 @@ pub(crate) fn nix_from_oflags(oflags: host::__wasi_oflags_t) -> nix::fcntl::OFla
nix_flags nix_flags
} }
pub(crate) fn filetype_from_nix(sflags: nix::sys::stat::SFlag) -> host::__wasi_filetype_t { pub(crate) fn filetype_from_nix(sflags: nix::sys::stat::SFlag) -> FileType {
use nix::sys::stat::SFlag; use nix::sys::stat::SFlag;
if sflags.contains(SFlag::S_IFCHR) { if sflags.contains(SFlag::S_IFCHR) {
host::__WASI_FILETYPE_CHARACTER_DEVICE FileType::CharacterDevice
} else if sflags.contains(SFlag::S_IFBLK) { } else if sflags.contains(SFlag::S_IFBLK) {
host::__WASI_FILETYPE_BLOCK_DEVICE FileType::BlockDevice
} else if sflags.contains(SFlag::S_IFSOCK) { } else if sflags.contains(SFlag::S_IFSOCK) {
host::__WASI_FILETYPE_SOCKET_STREAM FileType::SocketStream
} else if sflags.contains(SFlag::S_IFDIR) { } else if sflags.contains(SFlag::S_IFDIR) {
host::__WASI_FILETYPE_DIRECTORY FileType::Directory
} else if sflags.contains(SFlag::S_IFREG) { } else if sflags.contains(SFlag::S_IFREG) {
host::__WASI_FILETYPE_REGULAR_FILE FileType::RegularFile
} else if sflags.contains(SFlag::S_IFLNK) { } else if sflags.contains(SFlag::S_IFLNK) {
host::__WASI_FILETYPE_SYMBOLIC_LINK FileType::Symlink
} else { } else {
host::__WASI_FILETYPE_UNKNOWN FileType::Unknown
} }
} }
@@ -200,7 +201,7 @@ pub(crate) fn filestat_from_nix(
st_atim, st_atim,
st_ctim, st_ctim,
st_mtim, st_mtim,
st_filetype: filetype_from_nix(filetype), st_filetype: filetype_from_nix(filetype).to_wasi(),
}) })
} }

View File

@@ -2,7 +2,7 @@
#![allow(unused_unsafe)] #![allow(unused_unsafe)]
use super::fs_helpers::*; use super::fs_helpers::*;
use crate::helpers::systemtime_to_timestamp; use crate::helpers::systemtime_to_timestamp;
use crate::hostcalls_impl::PathGet; use crate::hostcalls_impl::{FileType, PathGet};
use crate::sys::host_impl; use crate::sys::host_impl;
use crate::{host, Error, Result}; use crate::{host, Error, Result};
use nix::libc; use nix::libc;
@@ -219,35 +219,35 @@ pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<host::__wasi_
st_atim: systemtime_to_timestamp(metadata.accessed()?)?, st_atim: systemtime_to_timestamp(metadata.accessed()?)?,
st_ctim: metadata.ctime().try_into()?, // i64 doesn't fit into u64 st_ctim: metadata.ctime().try_into()?, // i64 doesn't fit into u64
st_mtim: systemtime_to_timestamp(metadata.modified()?)?, st_mtim: systemtime_to_timestamp(metadata.modified()?)?,
st_filetype: filetype(file, &metadata)?, st_filetype: filetype(file, &metadata)?.to_wasi(),
}) })
} }
fn filetype(file: &File, metadata: &Metadata) -> Result<host::__wasi_filetype_t> { fn filetype(file: &File, metadata: &Metadata) -> Result<FileType> {
use nix::sys::socket::{self, SockType}; use nix::sys::socket::{self, SockType};
use std::os::unix::fs::FileTypeExt; use std::os::unix::fs::FileTypeExt;
let ftype = metadata.file_type(); let ftype = metadata.file_type();
if ftype.is_file() { if ftype.is_file() {
Ok(host::__WASI_FILETYPE_REGULAR_FILE) Ok(FileType::RegularFile)
} else if ftype.is_dir() { } else if ftype.is_dir() {
Ok(host::__WASI_FILETYPE_DIRECTORY) Ok(FileType::Directory)
} else if ftype.is_symlink() { } else if ftype.is_symlink() {
Ok(host::__WASI_FILETYPE_SYMBOLIC_LINK) Ok(FileType::Symlink)
} else if ftype.is_char_device() { } else if ftype.is_char_device() {
Ok(host::__WASI_FILETYPE_CHARACTER_DEVICE) Ok(FileType::CharacterDevice)
} else if ftype.is_block_device() { } else if ftype.is_block_device() {
Ok(host::__WASI_FILETYPE_BLOCK_DEVICE) Ok(FileType::BlockDevice)
} else if ftype.is_socket() { } else if ftype.is_socket() {
match socket::getsockopt(file.as_raw_fd(), socket::sockopt::SockType) match socket::getsockopt(file.as_raw_fd(), socket::sockopt::SockType)
.map_err(|err| err.as_errno().unwrap()) .map_err(|err| err.as_errno().unwrap())
.map_err(host_impl::errno_from_nix)? .map_err(host_impl::errno_from_nix)?
{ {
SockType::Datagram => Ok(host::__WASI_FILETYPE_SOCKET_DGRAM), SockType::Datagram => Ok(FileType::SocketDgram),
SockType::Stream => Ok(host::__WASI_FILETYPE_SOCKET_STREAM), SockType::Stream => Ok(FileType::SocketStream),
_ => Ok(host::__WASI_FILETYPE_UNKNOWN), _ => Ok(FileType::Unknown),
} }
} else { } else {
Ok(host::__WASI_FILETYPE_UNKNOWN) Ok(FileType::Unknown)
} }
} }

View File

@@ -4,7 +4,7 @@ use super::fs_helpers::*;
use crate::ctx::WasiCtx; use crate::ctx::WasiCtx;
use crate::fdentry::FdEntry; use crate::fdentry::FdEntry;
use crate::helpers::systemtime_to_timestamp; use crate::helpers::systemtime_to_timestamp;
use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet}; use crate::hostcalls_impl::{fd_filestat_set_times_impl, FileType, PathGet};
use crate::sys::fdentry_impl::{determine_type_rights, OsFile}; use crate::sys::fdentry_impl::{determine_type_rights, OsFile};
use crate::sys::host_impl; use crate::sys::host_impl;
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt; use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
@@ -286,20 +286,20 @@ pub(crate) fn fd_filestat_get_impl(file: &std::fs::File) -> Result<host::__wasi_
st_atim: systemtime_to_timestamp(metadata.accessed()?)?, st_atim: systemtime_to_timestamp(metadata.accessed()?)?,
st_ctim: change_time(file, &metadata)?.try_into()?, // i64 doesn't fit into u64 st_ctim: change_time(file, &metadata)?.try_into()?, // i64 doesn't fit into u64
st_mtim: systemtime_to_timestamp(metadata.modified()?)?, st_mtim: systemtime_to_timestamp(metadata.modified()?)?,
st_filetype: filetype(file, &metadata)?, st_filetype: filetype(file, &metadata)?.to_wasi(),
}) })
} }
fn filetype(_file: &File, metadata: &Metadata) -> Result<host::__wasi_filetype_t> { fn filetype(_file: &File, metadata: &Metadata) -> Result<FileType> {
let ftype = metadata.file_type(); let ftype = metadata.file_type();
let ret = if ftype.is_file() { let ret = if ftype.is_file() {
host::__WASI_FILETYPE_REGULAR_FILE FileType::RegularFile
} else if ftype.is_dir() { } else if ftype.is_dir() {
host::__WASI_FILETYPE_DIRECTORY FileType::Directory
} else if ftype.is_symlink() { } else if ftype.is_symlink() {
host::__WASI_FILETYPE_SYMBOLIC_LINK FileType::Symlink
} else { } else {
host::__WASI_FILETYPE_UNKNOWN FileType::Unknown
}; };
Ok(ret) Ok(ret)