From d19e5508d7b406da6813edb9d0a6909094d20e5a Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Mon, 5 Aug 2024 13:09:24 +0200 Subject: [PATCH] Remove non-portable use of fstatat Part of #10634 --- src/libc.c | 13 +++++++++++++ src/libc.rs | 35 ++++++++++++++++++++++++++++++++++- src/wutil/dir_iter.rs | 11 +++++------ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/libc.c b/src/libc.c index 2da58fd89..deb6addc5 100644 --- a/src/libc.c +++ b/src/libc.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include #include #include @@ -198,3 +200,14 @@ bool C_portable_readdir(DIR* dirp, const char** d_name, size_t* d_name_len, uint *d_type = dent->d_type; return true; } + +bool C_portable_fstatat(int dirfd, const char* file, int flag, uint64_t* st_dev, uint64_t* st_ino, mode_t* st_mode) { + struct stat buf; + if (fstatat(dirfd, file, &buf, flag) == -1) { + return false; + } + *st_dev = buf.st_dev; + *st_ino = buf.st_ino; + *st_mode = buf.st_mode; + return true; +} diff --git a/src/libc.rs b/src/libc.rs index 962235e4e..28f649891 100644 --- a/src/libc.rs +++ b/src/libc.rs @@ -1,4 +1,4 @@ -use std::sync::atomic::AtomicPtr; +use std::{ffi::CStr, sync::atomic::AtomicPtr}; use libc::{c_char, c_int}; use once_cell::sync::Lazy; @@ -79,3 +79,36 @@ extern "C" { d_type: *mut u8, ) -> bool; } + +pub(crate) fn portable_fstatat( + dirfd: c_int, + file: &CStr, + flag: c_int, +) -> Option<(u64, u64, libc::mode_t)> { + let mut st_dev = unsafe { std::mem::zeroed() }; + let mut st_ino = unsafe { std::mem::zeroed() }; + let mut st_mode = unsafe { std::mem::zeroed() }; + if !unsafe { + C_portable_fstatat( + dirfd, + file.as_ptr(), + flag, + &mut st_dev, + &mut st_ino, + &mut st_mode, + ) + } { + return None; + } + Some((st_dev, st_ino, st_mode)) +} +extern "C" { + fn C_portable_fstatat( + dirfd: c_int, + file: *const c_char, + flag: c_int, + st_dev: *mut u64, + st_ino: *mut u64, + st_mode: *mut libc::mode_t, + ) -> bool; +} diff --git a/src/wutil/dir_iter.rs b/src/wutil/dir_iter.rs index b25018357..e99273c19 100644 --- a/src/wutil/dir_iter.rs +++ b/src/wutil/dir_iter.rs @@ -1,6 +1,6 @@ use super::wopendir; use crate::common::{cstr2wcstring, wcs2zstring}; -use crate::libc::portable_readdir; +use crate::libc::{portable_fstatat, portable_readdir}; use crate::wchar::{wstr, WString}; use crate::wutil::DevInode; use libc::{ @@ -104,14 +104,13 @@ impl DirEntry { return; } let narrow = wcs2zstring(&self.name); - let mut s: libc::stat = unsafe { std::mem::zeroed() }; - if unsafe { libc::fstatat(fd, narrow.as_ptr(), &mut s, 0) } == 0 { + if let Some((st_dev, st_ino, st_mode)) = portable_fstatat(fd, &narrow, 0) { let dev_inode = DevInode { - device: s.st_dev as u64, - inode: s.st_ino as u64, + device: st_dev, + inode: st_ino, }; self.dev_inode.set(Some(dev_inode)); - self.typ.set(stat_mode_to_entry_type(s.st_mode)); + self.typ.set(stat_mode_to_entry_type(st_mode)); } else { match errno::errno().0 { ELOOP => {