diff --git a/src/helpers.rs b/src/helpers.rs index 4d99b96093..34044b47f2 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,5 +1,6 @@ use crate::{Error, Result}; use std::convert::TryInto; +use std::ffi::CString; use std::time::{SystemTime, UNIX_EPOCH}; pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result { @@ -9,3 +10,7 @@ pub(crate) fn systemtime_to_timestamp(st: SystemTime) -> Result { .try_into() .map_err(Into::into) // u128 doesn't fit into u64 } + +pub(crate) fn str_to_cstring(s: &str) -> Result { + CString::new(s.as_bytes()).map_err(|_| Error::EILSEQ) +} diff --git a/src/hostcalls_impl/fs_helpers.rs b/src/hostcalls_impl/fs_helpers.rs index e9af4c0375..24cc0d0ab1 100644 --- a/src/hostcalls_impl/fs_helpers.rs +++ b/src/hostcalls_impl/fs_helpers.rs @@ -1,7 +1,9 @@ #![allow(non_camel_case_types)] +use crate::helpers::str_to_cstring; use crate::sys::host_impl; use crate::sys::hostcalls_impl::fs_helpers::*; use crate::{host, Error, Result}; +use std::ffi::CString; use std::fs::File; use std::path::{Component, Path}; @@ -19,6 +21,10 @@ impl PathGet { pub(crate) fn path(&self) -> &str { &self.path } + + pub(crate) fn path_cstring(&self) -> Result { + str_to_cstring(&self.path) + } } /// Normalizes a path to ensure that the target path is located under the directory provided. diff --git a/src/sys/unix/bsd/hostcalls_impl.rs b/src/sys/unix/bsd/hostcalls_impl.rs index 5e1738a87c..ce583b1384 100644 --- a/src/sys/unix/bsd/hostcalls_impl.rs +++ b/src/sys/unix/bsd/hostcalls_impl.rs @@ -1,10 +1,10 @@ use super::osfile::OsFile; +use crate::helpers::str_to_cstring; use crate::hostcalls_impl::PathGet; use crate::sys::host_impl; use crate::{host, Error, Result}; use nix::libc::{self, c_long, c_void}; use std::convert::TryInto; -use std::ffi::CString; use std::fs::File; use std::os::unix::prelude::AsRawFd; @@ -12,7 +12,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { use nix::errno; use nix::libc::unlinkat; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let path_cstr = resolved.path_cstring()?; // nix doesn't expose unlinkat() yet match unsafe { unlinkat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0) } { @@ -52,8 +52,8 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { use nix::{errno::Errno, fcntl::AtFlags, libc::symlinkat, sys::stat::fstatat}; - let old_path_cstr = CString::new(old_path.as_bytes()).map_err(|_| Error::EILSEQ)?; - let new_path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let old_path_cstr = str_to_cstring(old_path)?; + let new_path_cstr = resolved.path_cstring()?; log::debug!("path_symlink old_path = {:?}", old_path); log::debug!("path_symlink resolved = {:?}", resolved); @@ -93,8 +93,8 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { use nix::{errno::Errno, fcntl::AtFlags, libc::renameat, sys::stat::fstatat}; - let old_path_cstr = CString::new(resolved_old.path().as_bytes()).map_err(|_| Error::EILSEQ)?; - let new_path_cstr = CString::new(resolved_new.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let old_path_cstr = resolved_old.path_cstring()?; + let new_path_cstr = resolved_new.path_cstring()?; let res = unsafe { renameat( diff --git a/src/sys/unix/hostcalls_impl/fs.rs b/src/sys/unix/hostcalls_impl/fs.rs index 3dca957283..dec8562dce 100644 --- a/src/sys/unix/hostcalls_impl/fs.rs +++ b/src/sys/unix/hostcalls_impl/fs.rs @@ -7,7 +7,6 @@ use crate::sys::host_impl; use crate::{host, Error, Result}; use nix::libc; use std::convert::TryInto; -use std::ffi::CString; use std::fs::{File, Metadata}; use std::os::unix::fs::FileExt; use std::os::unix::prelude::{AsRawFd, FromRawFd}; @@ -58,7 +57,7 @@ pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: host::__wasi_fdflags_t) -> pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { use nix::libc::mkdirat; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let path_cstr = resolved.path_cstring()?; // nix doesn't expose mkdirat() yet match unsafe { mkdirat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0o777) } { 0 => Ok(()), @@ -68,8 +67,8 @@ pub(crate) fn path_create_directory(resolved: PathGet) -> Result<()> { pub(crate) fn path_link(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { use nix::libc::linkat; - let old_path_cstr = CString::new(resolved_old.path().as_bytes()).map_err(|_| Error::EILSEQ)?; - let new_path_cstr = CString::new(resolved_new.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let old_path_cstr = resolved_old.path_cstring()?; + let new_path_cstr = resolved_new.path_cstring()?; // Not setting AT_SYMLINK_FOLLOW fails on most filesystems let atflags = libc::AT_SYMLINK_FOLLOW; @@ -184,7 +183,7 @@ pub(crate) fn path_open( pub(crate) fn path_readlink(resolved: PathGet, buf: &mut [u8]) -> Result { use nix::errno::Errno; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let path_cstr = resolved.path_cstring()?; // Linux requires that the buffer size is positive, whereas POSIX does not. // Use a fake buffer to store the results if the size is zero. @@ -341,7 +340,7 @@ pub(crate) fn path_remove_directory(resolved: PathGet) -> Result<()> { use nix::errno; use nix::libc::{unlinkat, AT_REMOVEDIR}; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let path_cstr = resolved.path_cstring()?; // nix doesn't expose unlinkat() yet match unsafe { diff --git a/src/sys/unix/linux/hostcalls_impl.rs b/src/sys/unix/linux/hostcalls_impl.rs index 6ce5b4b411..835b210d14 100644 --- a/src/sys/unix/linux/hostcalls_impl.rs +++ b/src/sys/unix/linux/hostcalls_impl.rs @@ -1,4 +1,5 @@ use super::osfile::OsFile; +use crate::helpers::str_to_cstring; use crate::hostcalls_impl::PathGet; use crate::sys::host_impl; use crate::{host, Error, Result}; @@ -13,7 +14,7 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { use nix::errno; use nix::libc::unlinkat; - let path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let path_cstr = resolved.path_cstring()?; // nix doesn't expose unlinkat() yet let res = unsafe { unlinkat(resolved.dirfd().as_raw_fd(), path_cstr.as_ptr(), 0) }; @@ -27,8 +28,8 @@ pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> { pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { use nix::{errno::Errno, libc::symlinkat}; - let old_path_cstr = CString::new(old_path.as_bytes()).map_err(|_| Error::EILSEQ)?; - let new_path_cstr = CString::new(resolved.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let old_path_cstr = str_to_cstring(old_path)?; + let new_path_cstr = resolved.path_cstring()?; log::debug!("path_symlink old_path = {:?}", old_path); log::debug!("path_symlink resolved = {:?}", resolved); @@ -49,8 +50,8 @@ pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> { pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> { use nix::libc::renameat; - let old_path_cstr = CString::new(resolved_old.path().as_bytes()).map_err(|_| Error::EILSEQ)?; - let new_path_cstr = CString::new(resolved_new.path().as_bytes()).map_err(|_| Error::EILSEQ)?; + let old_path_cstr = resolved_old.path_cstring()?; + let new_path_cstr = resolved_new.path_cstring()?; let res = unsafe { renameat( diff --git a/src/sys/windows/hostcalls_impl/misc.rs b/src/sys/windows/hostcalls_impl/misc.rs index f19941a612..57022ce22b 100644 --- a/src/sys/windows/hostcalls_impl/misc.rs +++ b/src/sys/windows/hostcalls_impl/misc.rs @@ -14,7 +14,6 @@ lazy_static! { static ref START_MONOTONIC: Instant = Instant::now(); } - pub(crate) fn clock_res_get(clock_id: host::__wasi_clockid_t) -> Result { unimplemented!("clock_res_get") }