Skip to content

Commit 5081e77

Browse files
committed
Use rustix to call statx on Linux.
1 parent 20ba13c commit 5081e77

File tree

4 files changed

+75
-74
lines changed

4 files changed

+75
-74
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,10 @@ name = "bitflags"
355355
version = "2.5.0"
356356
source = "registry+https://github.com/rust-lang/crates.io-index"
357357
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
358+
dependencies = [
359+
"compiler_builtins",
360+
"rustc-std-workspace-core",
361+
]
358362

359363
[[package]]
360364
name = "block-buffer"
@@ -2249,6 +2253,10 @@ name = "linux-raw-sys"
22492253
version = "0.4.14"
22502254
source = "registry+https://github.com/rust-lang/crates.io-index"
22512255
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
2256+
dependencies = [
2257+
"compiler_builtins",
2258+
"rustc-std-workspace-core",
2259+
]
22522260

22532261
[[package]]
22542262
name = "litemap"
@@ -5042,9 +5050,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
50425050
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
50435051
dependencies = [
50445052
"bitflags 2.5.0",
5053+
"compiler_builtins",
50455054
"errno",
50465055
"libc",
50475056
"linux-raw-sys",
5057+
"rustc-std-workspace-alloc",
5058+
"rustc-std-workspace-core",
50485059
"windows-sys 0.52.0",
50495060
]
50505061

@@ -5358,6 +5369,7 @@ dependencies = [
53585369
"rand",
53595370
"rand_xorshift",
53605371
"rustc-demangle",
5372+
"rustix",
53615373
"std_detect",
53625374
"unwind",
53635375
"wasi",

library/std/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ std_detect = { path = "../stdarch/crates/std_detect", default-features = false,
2626
# Dependencies of the `backtrace` crate
2727
rustc-demangle = { version = "0.1.24", features = ['rustc-dep-of-std'] }
2828

29+
[target.'cfg(all(target_os = "linux", target_env = "gnu"))'.dependencies]
30+
rustix = { version = "0.38.34", default-features = false, features = ['rustc-dep-of-std', 'fs'] }
31+
2932
[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies]
3033
miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
3134
addr2line = { version = "0.22.0", optional = true, default-features = false }

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

Lines changed: 33 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ use crate::sys::time::SystemTime;
2020
use crate::sys::{cvt, cvt_r};
2121
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
2222

23-
#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]
23+
#[cfg(all(target_os = "linux", target_env = "gnu"))]
24+
use rustix::{
25+
fs::{AtFlags, StatxFlags, StatxTimestamp},
26+
io::Errno,
27+
};
28+
29+
#[cfg(target_vendor = "apple")]
2430
use crate::sys::weak::syscall;
2531
#[cfg(any(target_os = "android", target_os = "macos", target_os = "solaris"))]
2632
use crate::sys::weak::weak;
@@ -29,7 +35,6 @@ use libc::{c_int, mode_t};
2935

3036
#[cfg(any(
3137
target_os = "solaris",
32-
all(target_os = "linux", target_env = "gnu"),
3338
target_vendor = "apple",
3439
))]
3540
use libc::c_char;
@@ -138,14 +143,14 @@ cfg_has_statx! {{
138143
struct StatxExtraFields {
139144
// This is needed to check if btime is supported by the filesystem.
140145
stx_mask: u32,
141-
stx_btime: libc::statx_timestamp,
146+
stx_btime: StatxTimestamp,
142147
// With statx, we can overcome 32-bit `time_t` too.
143148
#[cfg(target_pointer_width = "32")]
144-
stx_atime: libc::statx_timestamp,
149+
stx_atime: StatxTimestamp,
145150
#[cfg(target_pointer_width = "32")]
146-
stx_ctime: libc::statx_timestamp,
151+
stx_ctime: StatxTimestamp,
147152
#[cfg(target_pointer_width = "32")]
148-
stx_mtime: libc::statx_timestamp,
153+
stx_mtime: StatxTimestamp,
149154

150155
}
151156

@@ -154,61 +159,16 @@ cfg_has_statx! {{
154159
// Default `stat64` contains no creation time and may have 32-bit `time_t`.
155160
unsafe fn try_statx(
156161
fd: c_int,
157-
path: *const c_char,
158-
flags: i32,
159-
mask: u32,
162+
path: &CStr,
163+
flags: AtFlags,
164+
mask: StatxFlags,
160165
) -> Option<io::Result<FileAttr>> {
161-
use crate::sync::atomic::{AtomicU8, Ordering};
162-
163-
// Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx`.
164-
// We check for it on first failure and remember availability to avoid having to
165-
// do it again.
166-
#[repr(u8)]
167-
enum STATX_STATE{ Unknown = 0, Present, Unavailable }
168-
static STATX_SAVED_STATE: AtomicU8 = AtomicU8::new(STATX_STATE::Unknown as u8);
169-
170-
syscall! {
171-
fn statx(
172-
fd: c_int,
173-
pathname: *const c_char,
174-
flags: c_int,
175-
mask: libc::c_uint,
176-
statxbuf: *mut libc::statx
177-
) -> c_int
178-
}
179-
180-
if STATX_SAVED_STATE.load(Ordering::Relaxed) == STATX_STATE::Unavailable as u8 {
181-
return None;
182-
}
183-
184-
let mut buf: libc::statx = mem::zeroed();
185-
if let Err(err) = cvt(statx(fd, path, flags, mask, &mut buf)) {
186-
if STATX_SAVED_STATE.load(Ordering::Relaxed) == STATX_STATE::Present as u8 {
187-
return Some(Err(err));
188-
}
189-
190-
// We're not yet entirely sure whether `statx` is usable on this kernel
191-
// or not. Syscalls can return errors from things other than the kernel
192-
// per se, e.g. `EPERM` can be returned if seccomp is used to block the
193-
// syscall, or `ENOSYS` might be returned from a faulty FUSE driver.
194-
//
195-
// Availability is checked by performing a call which expects `EFAULT`
196-
// if the syscall is usable.
197-
//
198-
// See: https://github.com/rust-lang/rust/issues/65662
199-
//
200-
// FIXME what about transient conditions like `ENOMEM`?
201-
let err2 = cvt(statx(0, ptr::null(), 0, libc::STATX_ALL, ptr::null_mut()))
202-
.err()
203-
.and_then(|e| e.raw_os_error());
204-
if err2 == Some(libc::EFAULT) {
205-
STATX_SAVED_STATE.store(STATX_STATE::Present as u8, Ordering::Relaxed);
206-
return Some(Err(err));
207-
} else {
208-
STATX_SAVED_STATE.store(STATX_STATE::Unavailable as u8, Ordering::Relaxed);
209-
return None;
210-
}
211-
}
166+
let fd = rustix::fd::BorrowedFd::borrow_raw(fd);
167+
let buf = match rustix::fs::statx(fd, path, flags, mask) {
168+
Ok(buf) => buf,
169+
Err(Errno::NOSYS) => return None,
170+
Err(err) => return Some(Err(io::Error::from_raw_os_error(err.raw_os_error()))),
171+
};
212172

213173
// We cannot fill `stat64` exhaustively because of private padding fields.
214174
let mut stat: stat64 = mem::zeroed();
@@ -895,21 +855,21 @@ impl DirEntry {
895855
))]
896856
pub fn metadata(&self) -> io::Result<FileAttr> {
897857
let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?;
898-
let name = self.name_cstr().as_ptr();
858+
let name = self.name_cstr();
899859

900860
cfg_has_statx! {
901861
if let Some(ret) = unsafe { try_statx(
902862
fd,
903863
name,
904-
libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
905-
libc::STATX_ALL,
864+
AtFlags::SYMLINK_NOFOLLOW | AtFlags::STATX_SYNC_AS_STAT,
865+
StatxFlags::ALL,
906866
) } {
907867
return ret;
908868
}
909869
}
910870

911871
let mut stat: stat64 = unsafe { mem::zeroed() };
912-
cvt(unsafe { fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?;
872+
cvt(unsafe { fstatat64(fd, name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?;
913873
Ok(FileAttr::from_stat64(stat))
914874
}
915875

@@ -1172,13 +1132,12 @@ impl File {
11721132

11731133
pub fn file_attr(&self) -> io::Result<FileAttr> {
11741134
let fd = self.as_raw_fd();
1175-
11761135
cfg_has_statx! {
11771136
if let Some(ret) = unsafe { try_statx(
11781137
fd,
1179-
c"".as_ptr() as *const c_char,
1180-
libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT,
1181-
libc::STATX_ALL,
1138+
c"",
1139+
AtFlags::EMPTY_PATH | AtFlags::STATX_SYNC_AS_STAT,
1140+
StatxFlags::ALL,
11821141
) } {
11831142
return ret;
11841143
}
@@ -1782,9 +1741,9 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
17821741
cfg_has_statx! {
17831742
if let Some(ret) = unsafe { try_statx(
17841743
libc::AT_FDCWD,
1785-
p.as_ptr(),
1786-
libc::AT_STATX_SYNC_AS_STAT,
1787-
libc::STATX_ALL,
1744+
p,
1745+
AtFlags::STATX_SYNC_AS_STAT,
1746+
StatxFlags::ALL,
17881747
) } {
17891748
return ret;
17901749
}
@@ -1801,9 +1760,9 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
18011760
cfg_has_statx! {
18021761
if let Some(ret) = unsafe { try_statx(
18031762
libc::AT_FDCWD,
1804-
p.as_ptr(),
1805-
libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
1806-
libc::STATX_ALL,
1763+
p,
1764+
AtFlags::SYMLINK_NOFOLLOW | AtFlags::STATX_SYNC_AS_STAT,
1765+
StatxFlags::ALL,
18071766
) } {
18081767
return ret;
18091768
}

src/bootstrap/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,33 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
9292
(Some(Mode::Std), "no_global_oom_handling", None),
9393
(Some(Mode::Std), "no_rc", None),
9494
(Some(Mode::Std), "no_sync", None),
95+
(Some(Mode::Std), "netbsd10", None),
96+
(Some(Mode::Std), "backtrace_in_libstd", None),
97+
// `cfg`s that rustix uses.
98+
(Some(Mode::Std), "libc", None),
99+
(Some(Mode::Std), "linux_raw", None),
100+
(Some(Mode::Std), "linux_kernel", None),
101+
(Some(Mode::Std), "linux_like", None),
102+
(Some(Mode::Std), "apple", None),
103+
(Some(Mode::Std), "bsd", None),
104+
(Some(Mode::Std), "solarish", None),
105+
(Some(Mode::Std), "netbsdlike", None),
106+
(Some(Mode::Std), "freebsdlike", None),
107+
(Some(Mode::Std), "thumb_mode", None),
108+
(Some(Mode::Std), "fix_y2038", None),
109+
(Some(Mode::Std), "rustc_attrs", None),
110+
(Some(Mode::Std), "doc_cfg", None),
111+
(Some(Mode::Std), "core_ffi_c", None),
112+
(Some(Mode::Std), "core_c_str", None),
113+
(Some(Mode::Std), "core_intrinsics", None),
114+
(Some(Mode::Std), "asm_experimental_arch", None),
115+
(Some(Mode::Std), "static_assertions", None),
116+
(Some(Mode::Std), "alloc_c_string", None),
117+
(Some(Mode::Std), "alloc_ffi", None),
118+
(Some(Mode::Std), "wasi", None),
119+
(Some(Mode::Std), "wasi_ext", None),
120+
(Some(Mode::Std), "staged_api", None),
121+
(Some(Mode::Std), "backtrace_in_libstd", None),
95122
/* Extra values not defined in the built-in targets yet, but used in std */
96123
(Some(Mode::Std), "target_env", Some(&["libnx", "p2"])),
97124
(Some(Mode::Std), "target_os", Some(&["visionos"])),

0 commit comments

Comments
 (0)