diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index 68aed39d1dcdf..99b0b502f4492 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -54,14 +54,6 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> { ignore_notfound(fs::remove_dir(path)) } -pub fn exists(path: &Path) -> io::Result { - match fs::metadata(path) { - Ok(_) => Ok(true), - Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), - Err(error) => Err(error), - } -} - pub struct Dir { path: PathBuf, } diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index d29ea81c67e6d..09177e82eae2e 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -10,7 +10,7 @@ use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Raw use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::sys::fd::FileDesc; -pub use crate::sys::fs::common::{Dir, copy, exists}; +pub use crate::sys::fs::common::{Dir, copy}; use crate::sys::helpers::run_path_with_cstr; use crate::sys::time::SystemTime; use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, cvt, unsupported, unsupported_err}; @@ -234,9 +234,7 @@ impl DirEntry { } pub fn metadata(&self) -> io::Result { - let mut path = self.path(); - path.set_file_name(self.file_name_os_str()); - lstat(&path) + run_path_with_cstr(&self.path(), &lstat) } pub fn file_type(&self) -> io::Result { @@ -554,66 +552,70 @@ pub fn readdir(path: &Path) -> io::Result { Ok(ReadDir::new(InnerReadDir::new(root, vec))) } -pub fn unlink(path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::unlink(path.as_ptr()) }).map(|_| ())) +pub fn unlink(path: &CStr) -> io::Result<()> { + cvt(unsafe { hermit_abi::unlink(path.as_ptr()) }).map(|_| ()) } -pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { +pub fn rename(_old: &CStr, _new: &CStr) -> io::Result<()> { unsupported() } -pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { +pub fn set_perm(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { Err(Error::from_raw_os_error(22)) } -pub fn set_perm_nofollow(_p: &Path, _perm: FilePermissions) -> io::Result<()> { +pub fn set_perm_nofollow(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { unsupported() } -pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_times(_p: &CStr, _times: FileTimes) -> io::Result<()> { Err(Error::from_raw_os_error(22)) } -pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_times_nofollow(_p: &CStr, _times: FileTimes) -> io::Result<()> { Err(Error::from_raw_os_error(22)) } -pub fn rmdir(path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::rmdir(path.as_ptr()) }).map(|_| ())) +pub fn rmdir(path: &CStr) -> io::Result<()> { + cvt(unsafe { hermit_abi::rmdir(path.as_ptr()) }).map(|_| ()) +} + +pub fn exists(path: &CStr) -> io::Result { + match stat(path) { + Ok(_) => Ok(true), + Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), + Err(error) => Err(error), + } } pub fn remove_dir_all(_path: &Path) -> io::Result<()> { unsupported() } -pub fn readlink(_p: &Path) -> io::Result { +pub fn readlink(_p: &CStr) -> io::Result { unsupported() } -pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> { +pub fn symlink(_original: &CStr, _link: &CStr) -> io::Result<()> { unsupported() } -pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { +pub fn link(_original: &CStr, _link: &CStr) -> io::Result<()> { unsupported() } -pub fn stat(path: &Path) -> io::Result { - run_path_with_cstr(path, &|path| { - let mut stat_val: stat_struct = unsafe { mem::zeroed() }; - cvt(unsafe { hermit_abi::stat(path.as_ptr(), &mut stat_val) })?; - Ok(FileAttr::from_stat(stat_val)) - }) +pub fn stat(path: &CStr) -> io::Result { + let mut stat_val: stat_struct = unsafe { mem::zeroed() }; + cvt(unsafe { hermit_abi::stat(path.as_ptr(), &mut stat_val) })?; + Ok(FileAttr::from_stat(stat_val)) } -pub fn lstat(path: &Path) -> io::Result { - run_path_with_cstr(path, &|path| { - let mut stat_val: stat_struct = unsafe { mem::zeroed() }; - cvt(unsafe { hermit_abi::lstat(path.as_ptr(), &mut stat_val) })?; - Ok(FileAttr::from_stat(stat_val)) - }) +pub fn lstat(path: &CStr) -> io::Result { + let mut stat_val: stat_struct = unsafe { mem::zeroed() }; + cvt(unsafe { hermit_abi::lstat(path.as_ptr(), &mut stat_val) })?; + Ok(FileAttr::from_stat(stat_val)) } -pub fn canonicalize(_p: &Path) -> io::Result { +pub fn canonicalize(_p: &CStr) -> io::Result { unsupported() } diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index b5a5fa93fd491..903be20640e2c 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -28,36 +28,35 @@ cfg_select! { target_os = "hermit" => { mod hermit; use hermit as imp; + use crate::sys::helpers::run_path_with_cstr as with_native_path; } target_os = "motor" => { mod motor; use motor as imp; + use crate::sys::path::with_native_path; } target_os = "solid_asp3" => { mod solid; use solid as imp; + use crate::sys::path::with_native_path; } target_os = "uefi" => { mod uefi; use uefi as imp; + use crate::sys::path::with_native_path; } target_os = "vexos" => { mod vexos; use vexos as imp; + use crate::sys::helpers::run_path_with_cstr as with_native_path; } _ => { mod unsupported; use unsupported as imp; + use unsupported::with_native_path; } } -// FIXME: Replace this with platform-specific path conversion functions. -#[cfg(not(any(target_family = "unix", target_os = "windows", target_os = "wasi")))] -#[inline] -pub fn with_native_path(path: &Path, f: &dyn Fn(&Path) -> io::Result) -> io::Result { - f(path) -} - pub use imp::{ Dir, DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions, ReadDir, @@ -137,10 +136,6 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { } pub fn exists(path: &Path) -> io::Result { - // FIXME: use with_native_path on all platforms - #[cfg(not(windows))] - return imp::exists(path); - #[cfg(windows)] with_native_path(path, &imp::exists) } diff --git a/library/std/src/sys/fs/motor.rs b/library/std/src/sys/fs/motor.rs index a76f64a47c24a..c2776f003387c 100644 --- a/library/std/src/sys/fs/motor.rs +++ b/library/std/src/sys/fs/motor.rs @@ -4,7 +4,7 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::path::{Path, PathBuf}; use crate::sys::fd::FileDesc; -pub use crate::sys::fs::common::{Dir, exists}; +pub use crate::sys::fs::common::Dir; use crate::sys::time::SystemTime; use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, map_motor_error, unsupported}; @@ -297,69 +297,70 @@ impl DirBuilder { } } -pub fn unlink(path: &Path) -> io::Result<()> { - let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; +pub fn unlink(path: &str) -> io::Result<()> { moto_rt::fs::unlink(path).map_err(map_motor_error) } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let old = old.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; - let new = new.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; +pub fn rename(old: &str, new: &str) -> io::Result<()> { moto_rt::fs::rename(old, new).map_err(map_motor_error) } -pub fn rmdir(path: &Path) -> io::Result<()> { - let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; +pub fn rmdir(path: &str) -> io::Result<()> { moto_rt::fs::rmdir(path).map_err(map_motor_error) } +pub fn exists(path: &str) -> io::Result { + match stat(path) { + Ok(_) => Ok(true), + Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), + Err(error) => Err(error), + } +} + pub fn remove_dir_all(path: &Path) -> io::Result<()> { let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; moto_rt::fs::rmdir_all(path).map_err(map_motor_error) } -pub fn set_perm(path: &Path, perm: FilePermissions) -> io::Result<()> { +pub fn set_perm(path: &str, perm: FilePermissions) -> io::Result<()> { // Motor does not support symlinks set_perm_nofollow(path, perm) } -pub fn set_perm_nofollow(path: &Path, perm: FilePermissions) -> io::Result<()> { - let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; +pub fn set_perm_nofollow(path: &str, perm: FilePermissions) -> io::Result<()> { moto_rt::fs::set_perm(path, perm.rt_perm).map_err(map_motor_error) } -pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_times(_p: &str, _times: FileTimes) -> io::Result<()> { unsupported() } -pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_times_nofollow(_p: &str, _times: FileTimes) -> io::Result<()> { unsupported() } -pub fn readlink(_p: &Path) -> io::Result { +pub fn readlink(_p: &str) -> io::Result { unsupported() } -pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> { +pub fn symlink(_original: &str, _link: &str) -> io::Result<()> { unsupported() } -pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { +pub fn link(_src: &str, _dst: &str) -> io::Result<()> { unsupported() } -pub fn stat(path: &Path) -> io::Result { - let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; +pub fn stat(path: &str) -> io::Result { let inner = moto_rt::fs::stat(path).map_err(map_motor_error)?; Ok(FileAttr { inner }) } -pub fn lstat(path: &Path) -> io::Result { +pub fn lstat(path: &str) -> io::Result { stat(path) } -pub fn canonicalize(path: &Path) -> io::Result { - let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; +pub fn canonicalize(path: &str) -> io::Result { let path = moto_rt::fs::canonicalize(path).map_err(map_motor_error)?; Ok(path.into()) } diff --git a/library/std/src/sys/fs/solid.rs b/library/std/src/sys/fs/solid.rs index bd963b1d2f038..b21b009e2978f 100644 --- a/library/std/src/sys/fs/solid.rs +++ b/library/std/src/sys/fs/solid.rs @@ -9,7 +9,7 @@ use crate::os::raw::{c_int, c_short}; use crate::os::solid::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sync::Arc; -pub use crate::sys::fs::common::{Dir, exists}; +pub use crate::sys::fs::common::Dir; use crate::sys::helpers::ignore_notfound; use crate::sys::pal::{abi, error}; use crate::sys::time::SystemTime; @@ -206,7 +206,8 @@ impl DirEntry { } pub fn metadata(&self) -> io::Result { - lstat(&self.path()) + let cstr = cstr(&self.path())?; + lstat(&cstr) } pub fn file_type(&self) -> io::Result { @@ -216,7 +217,7 @@ impl DirEntry { abi::DT_REG => Ok(FileType(abi::S_IFREG)), abi::DT_DIR => Ok(FileType(abi::S_IFDIR)), abi::DT_BLK => Ok(FileType(abi::S_IFBLK)), - _ => lstat(&self.path()).map(|m| m.file_type()), + _ => lstat(&cstr(&self.path())?).map(|m| m.file_type()), } } } @@ -296,7 +297,7 @@ impl OpenOptions { } } -fn cstr(path: &Path) -> io::Result { +pub fn cstr(path: &Path) -> io::Result { let path = path.as_os_str().as_bytes(); if !path.starts_with(br"\") { @@ -512,48 +513,44 @@ impl fmt::Debug for File { } } -pub fn unlink(p: &Path) -> io::Result<()> { +pub fn unlink(p: &CStr) -> io::Result<()> { if stat(p)?.file_type().is_dir() { Err(io::const_error!(io::ErrorKind::IsADirectory, "is a directory")) } else { - error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(cstr(p)?.as_ptr()) }) + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(p.as_ptr()) }) .map_err(|e| e.as_io_error())?; Ok(()) } } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - error::SolidError::err_if_negative(unsafe { - abi::SOLID_FS_Rename(cstr(old)?.as_ptr(), cstr(new)?.as_ptr()) - }) - .map_err(|e| e.as_io_error())?; +pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> { + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Rename(old.as_ptr(), new.as_ptr()) }) + .map_err(|e| e.as_io_error())?; Ok(()) } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { +pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> { // Solid does not support symlinks set_perm_nofollow(p, perm) } -pub fn set_perm_nofollow(p: &Path, perm: FilePermissions) -> io::Result<()> { - error::SolidError::err_if_negative(unsafe { - abi::SOLID_FS_Chmod(cstr(p)?.as_ptr(), perm.0.into()) - }) - .map_err(|e| e.as_io_error())?; +pub fn set_perm_nofollow(p: &CStr, perm: FilePermissions) -> io::Result<()> { + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Chmod(p.as_ptr(), perm.0.into()) }) + .map_err(|e| e.as_io_error())?; Ok(()) } -pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_times(_p: &CStr, _times: FileTimes) -> io::Result<()> { unsupported() } -pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_times_nofollow(_p: &CStr, _times: FileTimes) -> io::Result<()> { unsupported() } -pub fn rmdir(p: &Path) -> io::Result<()> { +pub fn rmdir(p: &CStr) -> io::Result<()> { if stat(p)?.file_type().is_dir() { - error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(cstr(p)?.as_ptr()) }) + error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(p.as_ptr()) }) .map_err(|e| e.as_io_error())?; Ok(()) } else { @@ -561,6 +558,14 @@ pub fn rmdir(p: &Path) -> io::Result<()> { } } +pub fn exists(path: &CStr) -> io::Result { + match stat(path) { + Ok(_) => Ok(true), + Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), + Err(error) => Err(error), + } +} + pub fn remove_dir_all(path: &Path) -> io::Result<()> { for child in readdir(path)? { let result: io::Result<()> = try { @@ -569,7 +574,7 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { if child_type.is_dir() { remove_dir_all(&child.path())?; } else { - unlink(&child.path())?; + unlink(&cstr(&child.path())?)?; } }; // ignore internal NotFound errors @@ -579,43 +584,40 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { return result; } } - ignore_notfound(rmdir(path)) + ignore_notfound(rmdir(&cstr(path)?)) } -pub fn readlink(p: &Path) -> io::Result { +pub fn readlink(p: &CStr) -> io::Result { // This target doesn't support symlinks stat(p)?; Err(io::const_error!(io::ErrorKind::InvalidInput, "not a symbolic link")) } -pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> { +pub fn symlink(_original: &CStr, _link: &CStr) -> io::Result<()> { // This target doesn't support symlinks unsupported() } -pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { +pub fn link(_src: &CStr, _dst: &CStr) -> io::Result<()> { // This target doesn't support symlinks unsupported() } -pub fn stat(p: &Path) -> io::Result { +pub fn stat(p: &CStr) -> io::Result { // This target doesn't support symlinks lstat(p) } -pub fn lstat(p: &Path) -> io::Result { +pub fn lstat(p: &CStr) -> io::Result { unsafe { let mut out_stat = MaybeUninit::uninit(); - error::SolidError::err_if_negative(abi::SOLID_FS_Stat( - cstr(p)?.as_ptr(), - out_stat.as_mut_ptr(), - )) - .map_err(|e| e.as_io_error())?; + error::SolidError::err_if_negative(abi::SOLID_FS_Stat(p.as_ptr(), out_stat.as_mut_ptr())) + .map_err(|e| e.as_io_error())?; Ok(FileAttr { stat: out_stat.assume_init() }) } } -pub fn canonicalize(_p: &Path) -> io::Result { +pub fn canonicalize(_p: &CStr) -> io::Result { unsupported() } diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 1a0da329ce1a3..3be532714c647 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -263,10 +263,12 @@ impl File { return Err(io::const_error!(io::ErrorKind::InvalidInput, "Invalid open options")); } - if opts.create_new && exists(path)? { + if opts.create_new && exists(crate::path::absolute(path)?)? { return Err(io::const_error!(io::ErrorKind::AlreadyExists, "File already exists")); } + let path = crate::path::absolute(path)?; + let f = uefi_fs::File::from_path(path, opts.mode, 0).map(Self)?; if opts.truncate { @@ -417,7 +419,7 @@ impl fmt::Debug for File { pub fn readdir(p: &Path) -> io::Result { let path = crate::path::absolute(p)?; - let f = uefi_fs::File::from_path(&path, file::MODE_READ, 0)?; + let f = uefi_fs::File::from_path(path, file::MODE_READ, 0)?; let file_info = f.file_info()?; let file_attr = FileAttr::from_uefi(file_info); @@ -428,7 +430,7 @@ pub fn readdir(p: &Path) -> io::Result { } } -pub fn unlink(p: &Path) -> io::Result<()> { +pub fn unlink(p: PathBuf) -> io::Result<()> { let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?; let file_info = f.file_info()?; let file_attr = FileAttr::from_uefi(file_info); @@ -448,12 +450,9 @@ pub fn unlink(p: &Path) -> io::Result<()> { /// 2. Check that both lie in the same disk. /// 3. Construct the target path relative to the current disk root. /// 4. Set this target path as the file_name in the file_info structure. -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let old_absolute = crate::path::absolute(old)?; - let new_absolute = crate::path::absolute(new)?; - - let mut old_components = old_absolute.components(); - let mut new_components = new_absolute.components(); +pub fn rename(old: PathBuf, new: PathBuf) -> io::Result<()> { + let mut old_components = old.components(); + let mut new_components = new.components(); let Some(old_disk) = old_components.next() else { return Err(io::const_error!(io::ErrorKind::InvalidInput, "Old path is not valid")); @@ -479,27 +478,27 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { f.set_file_info(new_info) } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { +pub fn set_perm(p: PathBuf, perm: FilePermissions) -> io::Result<()> { // UEFI does not support symlinks set_perm_nofollow(p, perm) } -pub fn set_perm_nofollow(p: &Path, perm: FilePermissions) -> io::Result<()> { +pub fn set_perm_nofollow(p: PathBuf, perm: FilePermissions) -> io::Result<()> { let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?; set_perm_inner(&f, perm) } -pub fn set_times(p: &Path, times: FileTimes) -> io::Result<()> { +pub fn set_times(p: PathBuf, times: FileTimes) -> io::Result<()> { // UEFI does not support symlinks set_times_nofollow(p, times) } -pub fn set_times_nofollow(p: &Path, times: FileTimes) -> io::Result<()> { +pub fn set_times_nofollow(p: PathBuf, times: FileTimes) -> io::Result<()> { let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?; set_times_inner(&f, times) } -pub fn rmdir(p: &Path) -> io::Result<()> { +pub fn rmdir(p: PathBuf) -> io::Result<()> { let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?; let file_info = f.file_info()?; let file_attr = FileAttr::from_uefi(file_info); @@ -511,7 +510,7 @@ pub fn rmdir(p: &Path) -> io::Result<()> { } } -pub fn exists(path: &Path) -> io::Result { +pub fn exists(path: PathBuf) -> io::Result { let f = uefi_fs::File::from_path(path, r_efi::protocols::file::MODE_READ, 0); match f { Ok(_) => Ok(true), @@ -520,30 +519,30 @@ pub fn exists(path: &Path) -> io::Result { } } -pub fn readlink(_p: &Path) -> io::Result { +pub fn readlink(_p: PathBuf) -> io::Result { unsupported() } -pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> { +pub fn symlink(_original: PathBuf, _link: PathBuf) -> io::Result<()> { unsupported() } -pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { +pub fn link(_src: PathBuf, _dst: PathBuf) -> io::Result<()> { unsupported() } -pub fn stat(p: &Path) -> io::Result { +pub fn stat(p: PathBuf) -> io::Result { let f = uefi_fs::File::from_path(p, r_efi::protocols::file::MODE_READ, 0)?; let inf = f.file_info()?; Ok(FileAttr::from_uefi(inf)) } -pub fn lstat(p: &Path) -> io::Result { +pub fn lstat(p: PathBuf) -> io::Result { stat(p) } -pub fn canonicalize(p: &Path) -> io::Result { - crate::path::absolute(p) +pub fn canonicalize(p: PathBuf) -> io::Result { + Ok(p) } fn set_perm_inner(f: &uefi_fs::File, perm: FilePermissions) -> io::Result<()> { @@ -582,7 +581,7 @@ mod uefi_fs { use crate::ffi::OsString; use crate::io; use crate::os::uefi::ffi::OsStringExt; - use crate::path::Path; + use crate::path::{Path, PathBuf}; use crate::ptr::NonNull; use crate::sys::pal::helpers::{self, UefiBox}; use crate::sys::pal::system_time; @@ -599,14 +598,12 @@ mod uefi_fs { unsafe impl Send for File {} impl File { - pub(crate) fn from_path(path: &Path, open_mode: u64, attr: u64) -> io::Result { - let absolute = crate::path::absolute(path)?; - - let p = helpers::OwnedDevicePath::from_text(absolute.as_os_str())?; + pub(crate) fn from_path(path: PathBuf, open_mode: u64, attr: u64) -> io::Result { + let p = helpers::OwnedDevicePath::from_text(path.as_os_str())?; let (vol, mut path_remaining) = Self::open_volume_from_device_path(p.borrow())?; let protocol = Self::open(vol, &mut path_remaining, open_mode, attr)?; - Ok(Self { protocol, path: absolute }) + Ok(Self { protocol, path }) } /// Open Filesystem volume given a devicepath to the volume, or a file/directory in the diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 147234f345f45..51309743017da 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -92,7 +92,6 @@ use crate::os::wasi::prelude::*; use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::sys::fd::FileDesc; -pub use crate::sys::fs::common::exists; use crate::sys::helpers::run_path_with_cstr; use crate::sys::time::SystemTime; #[cfg(all(target_os = "linux", target_env = "gnu"))] @@ -2073,6 +2072,14 @@ pub fn rmdir(p: &CStr) -> io::Result<()> { cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()) } +pub fn exists(path: &CStr) -> io::Result { + match stat(path) { + Ok(_) => Ok(true), + Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), + Err(error) => Err(error), + } +} + pub fn readlink(c_path: &CStr) -> io::Result { let p = c_path.as_ptr(); diff --git a/library/std/src/sys/fs/unsupported.rs b/library/std/src/sys/fs/unsupported.rs index 512af27401dfe..39d2831347e98 100644 --- a/library/std/src/sys/fs/unsupported.rs +++ b/library/std/src/sys/fs/unsupported.rs @@ -8,6 +8,11 @@ pub use crate::sys::fs::common::Dir; use crate::sys::time::SystemTime; use crate::sys::unsupported; +#[inline] +pub fn with_native_path(path: &Path, f: &dyn Fn(&Path) -> io::Result) -> io::Result { + f(path) +} + pub struct File(!); pub struct FileAttr(!); diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs index 1357787c44c77..d97ad5998736d 100644 --- a/library/std/src/sys/fs/vexos.rs +++ b/library/std/src/sys/fs/vexos.rs @@ -1,4 +1,4 @@ -use crate::ffi::{OsString, c_char}; +use crate::ffi::{CStr, OsString, c_char}; use crate::fmt; use crate::fs::TryLockError; use crate::hash::Hash; @@ -11,10 +11,7 @@ use crate::sys::{unsupported, unsupported_err}; #[expect(dead_code)] #[path = "unsupported.rs"] mod unsupported_fs; -pub use unsupported_fs::{ - Dir, DirBuilder, FileTimes, canonicalize, link, readlink, remove_dir_all, rename, rmdir, - symlink, unlink, -}; +pub use unsupported_fs::{Dir, DirBuilder, FileTimes}; /// VEXos file descriptor. /// @@ -149,7 +146,7 @@ impl DirEntry { } pub fn metadata(&self) -> io::Result { - stat(&self.path) + run_path_with_cstr(&self.path(), &stat) } pub fn file_type(&self) -> io::Result { @@ -488,51 +485,91 @@ pub fn readdir(_p: &Path) -> io::Result { unsupported() } -pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { +pub fn unlink(_p: &CStr) -> io::Result<()> { unsupported() } -pub fn set_perm_nofollow(_p: &Path, _perm: FilePermissions) -> io::Result<()> { +pub fn rename(_old: &CStr, _new: &CStr) -> io::Result<()> { unsupported() } -pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_perm(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { unsupported() } -pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { +pub fn set_perm_nofollow(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { unsupported() } -pub fn exists(path: &Path) -> io::Result { - run_path_with_cstr(path, &|path| Ok(unsafe { vex_sdk::vexFileStatus(path.as_ptr()) } != 0)) +pub fn set_times(_p: &CStr, _times: FileTimes) -> io::Result<()> { + unsupported() +} + +pub fn set_times_nofollow(_p: &CStr, _times: FileTimes) -> io::Result<()> { + unsupported() +} + +pub fn rmdir(_p: &CStr) -> io::Result<()> { + unsupported() } -pub fn stat(p: &Path) -> io::Result { +pub fn remove_dir_all(_path: &Path) -> io::Result<()> { + unsupported() +} + +pub fn exists(path: &CStr) -> io::Result { + Ok(unsafe { vex_sdk::vexFileStatus(path.as_ptr()) } != 0) +} + +pub fn readlink(_p: &CStr) -> io::Result { + unsupported() +} + +pub fn symlink(_original: &CStr, _link: &CStr) -> io::Result<()> { + unsupported() +} + +pub fn link(_src: &CStr, _dst: &CStr) -> io::Result<()> { + unsupported() +} + +pub fn stat(p: &CStr) -> io::Result { // `vexFileStatus` returns 3 if the given path is a directory, 1 if the path is a // file, or 0 if no such path exists. const FILE_STATUS_DIR: u32 = 3; + let file_type = unsafe { vex_sdk::vexFileStatus(p.as_ptr()) }; - run_path_with_cstr(p, &|c_path| { - let file_type = unsafe { vex_sdk::vexFileStatus(c_path.as_ptr()) }; + // We can't get the size if its a directory because we cant open it as a file + if file_type == FILE_STATUS_DIR { + Ok(FileAttr::Dir) + } else { + let file = unsafe { vex_sdk::vexFileOpen(p.as_ptr(), c"".as_ptr()) }; - // We can't get the size if its a directory because we cant open it as a file - if file_type == FILE_STATUS_DIR { - Ok(FileAttr::Dir) + if file.is_null() { + Err(io::const_error!(io::ErrorKind::NotFound, "could not open file")) } else { - let mut opts = OpenOptions::new(); - opts.read(true); - let file = File::open(p, &opts)?; - file.file_attr() + // `vexFileSize` returns -1 upon error, so u64::try_from will fail on error. + if let Ok(size) = u64::try_from(unsafe { + // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime. + vex_sdk::vexFileSize(file) + }) { + Ok(FileAttr::File { size }) + } else { + Err(io::const_error!(io::ErrorKind::InvalidData, "failed to get file size")) + } } - }) + } } -pub fn lstat(p: &Path) -> io::Result { +pub fn lstat(p: &CStr) -> io::Result { // Symlinks aren't supported in this filesystem stat(p) } +pub fn canonicalize(_p: &CStr) -> io::Result { + unsupported() +} + // Cannot use `copy` from `common` here, since `File::set_permissions` is unsupported on this target. pub fn copy(from: &Path, to: &Path) -> io::Result { use crate::fs::File; diff --git a/library/std/src/sys/path/unix.rs b/library/std/src/sys/path/common.rs similarity index 100% rename from library/std/src/sys/path/unix.rs rename to library/std/src/sys/path/common.rs diff --git a/library/std/src/sys/path/mod.rs b/library/std/src/sys/path/mod.rs index bbb7577e186ae..1bff884369465 100644 --- a/library/std/src/sys/path/mod.rs +++ b/library/std/src/sys/path/mod.rs @@ -28,8 +28,8 @@ cfg_select! { pub use sgx::*; } target_os = "solid_asp3" => { - mod unsupported_backslash; - pub use unsupported_backslash::*; + mod solid; + pub use solid::*; } target_os = "uefi" => { mod uefi; @@ -40,8 +40,18 @@ cfg_select! { mod windows_prefix; pub use cygwin::*; } + target_os = "motor" => { + mod common; + mod motor; + pub use common::*; + pub use motor::*; + } + target_family = "unix" => { + mod common; + pub use common::*; + } _ => { - mod unix; - pub use unix::*; + mod common; + pub use common::*; } } diff --git a/library/std/src/sys/path/motor.rs b/library/std/src/sys/path/motor.rs new file mode 100644 index 0000000000000..a144943650b5c --- /dev/null +++ b/library/std/src/sys/path/motor.rs @@ -0,0 +1,7 @@ +use crate::io; +use crate::path::Path; + +pub fn with_native_path(path: &Path, f: &dyn Fn(&str) -> io::Result) -> io::Result { + let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?; + f(path) +} diff --git a/library/std/src/sys/path/unsupported_backslash.rs b/library/std/src/sys/path/solid.rs similarity index 69% rename from library/std/src/sys/path/unsupported_backslash.rs rename to library/std/src/sys/path/solid.rs index ce1851e938395..c7481f44a5c09 100644 --- a/library/std/src/sys/path/unsupported_backslash.rs +++ b/library/std/src/sys/path/solid.rs @@ -1,8 +1,8 @@ #![forbid(unsafe_op_in_unsafe_fn)] -use crate::ffi::OsStr; +use crate::ffi::{CStr, OsStr}; use crate::io; use crate::path::{Path, PathBuf, Prefix}; -use crate::sys::unsupported; +use crate::sys::{cstr, unsupported}; path_separator_bytes!(b'\\'); @@ -17,6 +17,12 @@ pub fn parse_prefix(_: &OsStr) -> Option> { pub const HAS_PREFIXES: bool = true; +#[inline] +pub fn with_native_path(path: &Path, f: &dyn Fn(&CStr) -> io::Result) -> io::Result { + let path = cstr(path)?; + f(&path) +} + pub(crate) fn absolute(_path: &Path) -> io::Result { unsupported() } diff --git a/library/std/src/sys/path/uefi.rs b/library/std/src/sys/path/uefi.rs index 8c911ee5f9c53..a536505222cb6 100644 --- a/library/std/src/sys/path/uefi.rs +++ b/library/std/src/sys/path/uefi.rs @@ -21,6 +21,12 @@ pub fn parse_prefix(_: &OsStr) -> Option> { pub const HAS_PREFIXES: bool = true; +#[inline] +pub fn with_native_path(path: &Path, f: &dyn Fn(PathBuf) -> io::Result) -> io::Result { + let path = absolute(path)?; + f(path) +} + /// UEFI paths can be of 4 types: /// /// 1. Absolute Shell Path: Uses shell mappings (eg: `FS0:`). Does not exist if UEFI shell not present.