Skip to content

Commit 10d0c2f

Browse files
committed
Unix implementation of NativePath
1 parent bf9e946 commit 10d0c2f

File tree

6 files changed

+116
-9
lines changed

6 files changed

+116
-9
lines changed

library/std/src/os/unix/ffi/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,24 @@
3838

3939
mod os_str;
4040

41+
use crate::ffi::CStr;
42+
use crate::path::NativePath;
43+
4144
#[stable(feature = "rust1", since = "1.0.0")]
4245
pub use self::os_str::{OsStrExt, OsStringExt};
46+
47+
#[unstable(feature = "fs_native_path", issue = "108979")]
48+
pub trait NativePathExt: crate::sealed::Sealed {
49+
fn from_cstr(cstr: &CStr) -> &NativePath;
50+
fn into_cstr(&self) -> &CStr;
51+
}
52+
53+
#[unstable(feature = "fs_native_path", issue = "108979")]
54+
impl NativePathExt for NativePath {
55+
fn from_cstr(cstr: &CStr) -> &NativePath {
56+
unsafe { &*(cstr as *const CStr as *const NativePath) }
57+
}
58+
fn into_cstr(&self) -> &CStr {
59+
unsafe { &*(self as *const Self as *const CStr) }
60+
}
61+
}

library/std/src/os/unix/fs.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use super::platform::fs::MetadataExt as _;
88
use crate::fs::{self, OpenOptions, Permissions};
99
use crate::io;
1010
use crate::os::unix::io::{AsFd, AsRawFd};
11-
use crate::path::Path;
11+
use crate::path::{AsPath, Path};
1212
use crate::sys;
1313
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
1414
// Used for `File::read` on intra-doc links
@@ -954,8 +954,8 @@ impl DirEntryExt2 for fs::DirEntry {
954954
/// }
955955
/// ```
956956
#[stable(feature = "symlink", since = "1.1.0")]
957-
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
958-
sys::fs::symlink(original.as_ref(), link.as_ref())
957+
pub fn symlink<P: AsPath, Q: AsPath>(original: P, link: Q) -> io::Result<()> {
958+
sys::fs::fs_imp::soft_link(original, link)
959959
}
960960

961961
/// Unix-specific extensions to [`fs::DirBuilder`].

library/std/src/sys/pal/unix/fs.rs

+55-5
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,60 @@ use libc::{dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, st
109109

110110
pub use crate::sys_common::fs::try_exists;
111111

112+
pub(crate) mod fs_imp {
113+
use crate::io;
114+
use crate::path::AsPath;
115+
use crate::path::PathBuf;
116+
use crate::sys::fs;
117+
pub(crate) use crate::sys::fs::{
118+
DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
119+
ReadDir,
120+
};
121+
122+
pub(crate) fn remove_file<P: AsPath>(path: P) -> io::Result<()> {
123+
path.with_path(fs::unlink)
124+
}
125+
pub(crate) fn symlink_metadata<P: AsPath>(path: P) -> io::Result<FileAttr> {
126+
path.with_path(|path| fs::lstat(path))
127+
}
128+
pub(crate) fn metadata<P: AsPath>(path: P) -> io::Result<FileAttr> {
129+
path.with_path(|path| fs::stat(path))
130+
}
131+
pub(crate) fn rename<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<()> {
132+
from.with_path(|from| to.with_path(|to| fs::rename(from, to)))
133+
}
134+
pub(crate) fn hard_link<P: AsPath, Q: AsPath>(original: P, link: Q) -> io::Result<()> {
135+
original.with_path(|original| link.with_path(|link| fs::link(original, link)))
136+
}
137+
pub(crate) fn soft_link<P: AsPath, Q: AsPath>(original: P, link: Q) -> io::Result<()> {
138+
original.with_path(|original| link.with_path(|link| fs::symlink(original, link)))
139+
}
140+
pub(crate) fn remove_dir<P: AsPath>(path: P) -> io::Result<()> {
141+
path.with_path(fs::rmdir)
142+
}
143+
pub(crate) fn read_dir<P: AsPath>(path: P) -> io::Result<ReadDir> {
144+
path.with_path(fs::readdir)
145+
}
146+
pub(crate) fn set_permissions<P: AsPath>(path: P, perms: FilePermissions) -> io::Result<()> {
147+
path.with_path(|path| fs::set_perm(path, perms))
148+
}
149+
pub(crate) fn copy<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<u64> {
150+
from.with_path(|from| to.with_path(|to| fs::copy(from, to)))
151+
}
152+
pub(crate) fn canonicalize<P: AsPath>(path: P) -> io::Result<PathBuf> {
153+
path.with_path(fs::canonicalize)
154+
}
155+
pub(crate) fn remove_dir_all<P: AsPath>(path: P) -> io::Result<()> {
156+
path.with_path(fs::remove_dir_all)
157+
}
158+
pub(crate) fn read_link<P: AsPath>(path: P) -> io::Result<PathBuf> {
159+
path.with_path(fs::readlink)
160+
}
161+
pub(crate) fn try_exists<P: AsPath>(path: P) -> io::Result<bool> {
162+
path.with_path(fs::try_exists)
163+
}
164+
}
165+
112166
pub struct File(FileDesc);
113167

114168
// FIXME: This should be available on Linux with all `target_env`.
@@ -1117,11 +1171,7 @@ impl OpenOptions {
11171171
}
11181172

11191173
impl File {
1120-
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
1121-
run_path_with_cstr(path, &|path| File::open_c(path, opts))
1122-
}
1123-
1124-
pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
1174+
pub fn open_native(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
11251175
let flags = libc::O_CLOEXEC
11261176
| opts.get_access_mode()?
11271177
| opts.get_creation_mode()?

library/std/src/sys/pal/unix/process/process_common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ impl Stdio {
481481
let mut opts = OpenOptions::new();
482482
opts.read(readable);
483483
opts.write(!readable);
484-
let fd = File::open_c(DEV_NULL, &opts)?;
484+
let fd = File::open_native(DEV_NULL, &opts)?;
485485
Ok((ChildStdio::Owned(fd.into_inner()), None))
486486
}
487487

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use crate::ffi::CStr;
2+
use crate::io;
3+
use crate::mem;
4+
use crate::path::{AsPath, Path};
5+
use crate::sys::common::small_c_string::run_path_with_cstr;
6+
7+
pub type NativePath = CStr;
8+
9+
#[unstable(feature = "fs_native_path_internals", issue = "none")]
10+
impl<P: AsRef<Path>> AsPath for P {
11+
fn with_path<T, F: FnOnce(&Path) -> io::Result<T>>(self, f: F) -> io::Result<T> {
12+
f(self.as_ref())
13+
}
14+
fn with_native_path<T, F: Fn(&NativePath) -> io::Result<T>>(self, f: F) -> io::Result<T> {
15+
run_path_with_cstr(self.as_ref(), &f)
16+
}
17+
}
18+
19+
#[unstable(feature = "fs_native_path_internals", issue = "none")]
20+
impl AsPath for &crate::path::NativePath {
21+
fn with_path<T, F: FnOnce(&Path) -> io::Result<T>>(self, f: F) -> io::Result<T> {
22+
// SAFETY: OsStr is a byte slice on platforms with CStr paths.
23+
// Note: We can't use os::unix::OsStrExt because that isn't necessarily
24+
// available for all platforms that use CStr paths.
25+
let osstr: &Path = unsafe { mem::transmute(self.0.to_bytes()) };
26+
f(osstr)
27+
}
28+
fn with_native_path<T, F: Fn(&NativePath) -> io::Result<T>>(self, f: F) -> io::Result<T> {
29+
f(&self.0)
30+
}
31+
}

library/std/src/sys/path/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
cfg_if::cfg_if! {
2+
if #[cfg(not(target_os = "windows"))] {
3+
mod cstr_native;
4+
pub use cstr_native::NativePath;
5+
}
6+
}
7+
18
cfg_if::cfg_if! {
29
if #[cfg(target_os = "windows")] {
310
mod windows;

0 commit comments

Comments
 (0)