diff --git a/crates/wasi-common/yanix/src/file.rs b/crates/wasi-common/yanix/src/file.rs index 10f4aa6a05..1764d29120 100644 --- a/crates/wasi-common/yanix/src/file.rs +++ b/crates/wasi-common/yanix/src/file.rs @@ -1,4 +1,4 @@ -use crate::{from_result, from_success_code}; +use crate::{cstr, from_result, from_success_code}; use bitflags::bitflags; use cfg_if::cfg_if; #[cfg(unix)] @@ -7,8 +7,9 @@ use std::os::unix::prelude::*; use std::os::wasi::prelude::*; use std::{ convert::TryInto, - ffi::{CString, OsStr, OsString}, + ffi::{OsStr, OsString}, io::Result, + path::Path, }; pub use crate::sys::file::*; @@ -157,13 +158,13 @@ impl FileType { } } -pub unsafe fn openat>( +pub unsafe fn openat>( dirfd: RawFd, path: P, oflag: OFlags, mode: Mode, ) -> Result { - let path = CString::new(path.as_ref().as_bytes())?; + let path = cstr(path)?; from_result(libc::openat( dirfd, path.as_ptr(), @@ -172,8 +173,8 @@ pub unsafe fn openat>( )) } -pub unsafe fn readlinkat>(dirfd: RawFd, path: P) -> Result { - let path = CString::new(path.as_ref().as_bytes())?; +pub unsafe fn readlinkat>(dirfd: RawFd, path: P) -> Result { + let path = cstr(path)?; let buffer = &mut [0u8; libc::PATH_MAX as usize + 1]; let nread = from_result(libc::readlinkat( dirfd, @@ -189,20 +190,20 @@ pub unsafe fn readlinkat>(dirfd: RawFd, path: P) -> Result>(dirfd: RawFd, path: P, mode: Mode) -> Result<()> { - let path = CString::new(path.as_ref().as_bytes())?; +pub unsafe fn mkdirat>(dirfd: RawFd, path: P, mode: Mode) -> Result<()> { + let path = cstr(path)?; from_success_code(libc::mkdirat(dirfd, path.as_ptr(), mode.bits())) } -pub unsafe fn linkat, Q: AsRef>( +pub unsafe fn linkat, Q: AsRef>( old_dirfd: RawFd, old_path: P, new_dirfd: RawFd, new_path: Q, flags: AtFlags, ) -> Result<()> { - let old_path = CString::new(old_path.as_ref().as_bytes())?; - let new_path = CString::new(new_path.as_ref().as_bytes())?; + let old_path = cstr(old_path)?; + let new_path = cstr(new_path)?; from_success_code(libc::linkat( old_dirfd, old_path.as_ptr(), @@ -212,19 +213,19 @@ pub unsafe fn linkat, Q: AsRef>( )) } -pub unsafe fn unlinkat>(dirfd: RawFd, path: P, flags: AtFlags) -> Result<()> { - let path = CString::new(path.as_ref().as_bytes())?; +pub unsafe fn unlinkat>(dirfd: RawFd, path: P, flags: AtFlags) -> Result<()> { + let path = cstr(path)?; from_success_code(libc::unlinkat(dirfd, path.as_ptr(), flags.bits())) } -pub unsafe fn renameat, Q: AsRef>( +pub unsafe fn renameat, Q: AsRef>( old_dirfd: RawFd, old_path: P, new_dirfd: RawFd, new_path: Q, ) -> Result<()> { - let old_path = CString::new(old_path.as_ref().as_bytes())?; - let new_path = CString::new(new_path.as_ref().as_bytes())?; + let old_path = cstr(old_path)?; + let new_path = cstr(new_path)?; from_success_code(libc::renameat( old_dirfd, old_path.as_ptr(), @@ -233,13 +234,13 @@ pub unsafe fn renameat, Q: AsRef>( )) } -pub unsafe fn symlinkat, Q: AsRef>( +pub unsafe fn symlinkat, Q: AsRef>( old_path: P, new_dirfd: RawFd, new_path: Q, ) -> Result<()> { - let old_path = CString::new(old_path.as_ref().as_bytes())?; - let new_path = CString::new(new_path.as_ref().as_bytes())?; + let old_path = cstr(old_path)?; + let new_path = cstr(new_path)?; from_success_code(libc::symlinkat( old_path.as_ptr(), new_dirfd, @@ -247,13 +248,9 @@ pub unsafe fn symlinkat, Q: AsRef>( )) } -pub unsafe fn fstatat>( - dirfd: RawFd, - path: P, - flags: AtFlags, -) -> Result { +pub unsafe fn fstatat>(dirfd: RawFd, path: P, flags: AtFlags) -> Result { use std::mem::MaybeUninit; - let path = CString::new(path.as_ref().as_bytes())?; + let path = cstr(path)?; let mut filestat = MaybeUninit::::uninit(); from_result(libc::fstatat( dirfd, diff --git a/crates/wasi-common/yanix/src/lib.rs b/crates/wasi-common/yanix/src/lib.rs index 2b742c4e97..141ac0281a 100644 --- a/crates/wasi-common/yanix/src/lib.rs +++ b/crates/wasi-common/yanix/src/lib.rs @@ -26,7 +26,9 @@ pub mod fadvise { pub use super::sys::fadvise::*; } +use std::ffi::CString; use std::io::{Error, Result}; +use std::path::Path; fn from_success_code(t: T) -> Result<()> { if t.is_zero() { @@ -71,3 +73,17 @@ macro_rules! impl_is_minus_one { } impl_is_minus_one! { i32 i64 isize } + +/// Convert an `AsRef` into a `CString`. +fn cstr>(path: P) -> Result { + #[cfg(target_os = "hermit")] + use std::os::hermit::ext::ffi::OsStrExt; + #[cfg(unix)] + use std::os::unix::ffi::OsStrExt; + #[cfg(target_os = "vxworks")] + use std::os::vxworks::ext::ffi::OsStrExt; + #[cfg(target_os = "wasi")] + use std::os::wasi::ffi::OsStrExt; + + Ok(CString::new(path.as_ref().as_os_str().as_bytes())?) +} diff --git a/crates/wasi-common/yanix/src/sys/bsd/filetime.rs b/crates/wasi-common/yanix/src/sys/bsd/filetime.rs index 63a7f58830..d0c62fc486 100644 --- a/crates/wasi-common/yanix/src/sys/bsd/filetime.rs +++ b/crates/wasi-common/yanix/src/sys/bsd/filetime.rs @@ -1,7 +1,7 @@ //! This module consists of helper types and functions for dealing //! with setting the file times specific to BSD-style *nixes. use crate::filetime::FileTime; -use crate::from_success_code; +use crate::{cstr, from_success_code}; use std::ffi::CStr; use std::fs::File; use std::io::Result; @@ -21,7 +21,6 @@ pub fn utimensat( symlink_nofollow: bool, ) -> Result<()> { use crate::filetime::to_timespec; - use std::ffi::CString; use std::os::unix::prelude::*; // Attempt to use the `utimensat` syscall, but if it's not supported by the @@ -33,10 +32,10 @@ pub fn utimensat( 0 }; - let p = CString::new(path.as_bytes())?; + let path = cstr(path)?; let times = [to_timespec(&atime)?, to_timespec(&mtime)?]; return from_success_code(unsafe { - func(dirfd.as_raw_fd(), p.as_ptr(), times.as_ptr(), flags) + func(dirfd.as_raw_fd(), path.as_ptr(), times.as_ptr(), flags) }); } diff --git a/crates/wasi-common/yanix/src/sys/emscripten/filetime.rs b/crates/wasi-common/yanix/src/sys/emscripten/filetime.rs index 0d7336b591..771247896a 100644 --- a/crates/wasi-common/yanix/src/sys/emscripten/filetime.rs +++ b/crates/wasi-common/yanix/src/sys/emscripten/filetime.rs @@ -1,7 +1,7 @@ //! This module consists of helper types and functions for dealing //! with setting the file times specific to Emscripten. use crate::filetime::FileTime; -use crate::from_success_code; +use crate::{cstr, from_success_code}; use std::fs::File; use std::io::Result; @@ -15,7 +15,6 @@ pub fn utimensat( symlink_nofollow: bool, ) -> Result<()> { use crate::filetime::to_timespec; - use std::ffi::CString; use std::os::unix::prelude::*; let flags = if symlink_nofollow { @@ -23,9 +22,9 @@ pub fn utimensat( } else { 0 }; - let p = CString::new(path.as_bytes())?; + let path = cstr(path)?; let times = [to_timespec(&atime)?, to_timespec(&mtime)?]; from_success_code(unsafe { - libc::utimensat(dirfd.as_raw_fd(), p.as_ptr(), times.as_ptr(), flags) + libc::utimensat(dirfd.as_raw_fd(), path.as_ptr(), times.as_ptr(), flags) }) } diff --git a/crates/wasi-common/yanix/src/sys/linux/filetime.rs b/crates/wasi-common/yanix/src/sys/linux/filetime.rs index 243aa46eef..3c4cdfa9f6 100644 --- a/crates/wasi-common/yanix/src/sys/linux/filetime.rs +++ b/crates/wasi-common/yanix/src/sys/linux/filetime.rs @@ -1,7 +1,7 @@ //! This module consists of helper types and functions for dealing //! with setting the file times specific to Linux. use crate::filetime::FileTime; -use crate::from_success_code; +use crate::{cstr, from_success_code}; use std::fs::File; use std::io::Result; use std::sync::atomic::{AtomicBool, Ordering::Relaxed}; @@ -20,7 +20,6 @@ pub fn utimensat( symlink_nofollow: bool, ) -> Result<()> { use crate::filetime::to_timespec; - use std::ffi::CString; use std::os::unix::prelude::*; let flags = if symlink_nofollow { @@ -33,13 +32,13 @@ pub fn utimensat( // current kernel then fall back to an older syscall. static INVALID: AtomicBool = AtomicBool::new(false); if !INVALID.load(Relaxed) { - let p = CString::new(path.as_bytes())?; + let path = cstr(path)?; let times = [to_timespec(&atime)?, to_timespec(&mtime)?]; let res = from_success_code(unsafe { libc::syscall( libc::SYS_utimensat, dirfd.as_raw_fd(), - p.as_ptr(), + path.as_ptr(), times.as_ptr(), flags, ) diff --git a/crates/wasi-common/yanix/src/sys/linux/utimesat.rs b/crates/wasi-common/yanix/src/sys/linux/utimesat.rs index 396c19b359..3ed9b5c68c 100644 --- a/crates/wasi-common/yanix/src/sys/linux/utimesat.rs +++ b/crates/wasi-common/yanix/src/sys/linux/utimesat.rs @@ -1,6 +1,6 @@ use crate::filetime::FileTime; use crate::filetime::FileTimeExt; -use crate::from_success_code; +use crate::{cstr, from_success_code}; use std::fs; use std::io::Result; @@ -15,16 +15,15 @@ pub fn utimesat( mtime: FileTime, symlink_nofollow: bool, ) -> Result<()> { - use std::ffi::CString; use std::os::unix::prelude::*; // emulate *at syscall by reading the path from a combination of // (fd, path) - let p = CString::new(path.as_bytes())?; + let path = cstr(path)?; let mut flags = libc::O_RDWR; if symlink_nofollow { flags |= libc::O_NOFOLLOW; } - let fd = unsafe { libc::openat(dirfd.as_raw_fd(), p.as_ptr(), flags) }; + let fd = unsafe { libc::openat(dirfd.as_raw_fd(), path.as_ptr(), flags) }; let f = unsafe { fs::File::from_raw_fd(fd) }; let (atime, mtime) = get_times(atime, mtime, || f.metadata().map_err(Into::into))?; let times = [to_timeval(atime)?, to_timeval(mtime)?];