@@ -20,7 +20,13 @@ use crate::sys::time::SystemTime;
20
20
use crate :: sys:: { cvt, cvt_r} ;
21
21
use crate :: sys_common:: { AsInner , AsInnerMut , FromInner , IntoInner } ;
22
22
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" ) ]
24
30
use crate :: sys:: weak:: syscall;
25
31
#[ cfg( any( target_os = "android" , target_os = "macos" , target_os = "solaris" ) ) ]
26
32
use crate :: sys:: weak:: weak;
@@ -29,7 +35,6 @@ use libc::{c_int, mode_t};
29
35
30
36
#[ cfg( any(
31
37
target_os = "solaris" ,
32
- all( target_os = "linux" , target_env = "gnu" ) ,
33
38
target_vendor = "apple" ,
34
39
) ) ]
35
40
use libc:: c_char;
@@ -138,14 +143,14 @@ cfg_has_statx! {{
138
143
struct StatxExtraFields {
139
144
// This is needed to check if btime is supported by the filesystem.
140
145
stx_mask: u32 ,
141
- stx_btime: libc :: statx_timestamp ,
146
+ stx_btime: StatxTimestamp ,
142
147
// With statx, we can overcome 32-bit `time_t` too.
143
148
#[ cfg( target_pointer_width = "32" ) ]
144
- stx_atime: libc :: statx_timestamp ,
149
+ stx_atime: StatxTimestamp ,
145
150
#[ cfg( target_pointer_width = "32" ) ]
146
- stx_ctime: libc :: statx_timestamp ,
151
+ stx_ctime: StatxTimestamp ,
147
152
#[ cfg( target_pointer_width = "32" ) ]
148
- stx_mtime: libc :: statx_timestamp ,
153
+ stx_mtime: StatxTimestamp ,
149
154
150
155
}
151
156
@@ -154,61 +159,16 @@ cfg_has_statx! {{
154
159
// Default `stat64` contains no creation time and may have 32-bit `time_t`.
155
160
unsafe fn try_statx(
156
161
fd: c_int,
157
- path: * const c_char ,
158
- flags: i32 ,
159
- mask: u32 ,
162
+ path: & CStr ,
163
+ flags: AtFlags ,
164
+ mask: StatxFlags ,
160
165
) -> 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
+ } ;
212
172
213
173
// We cannot fill `stat64` exhaustively because of private padding fields.
214
174
let mut stat: stat64 = mem:: zeroed( ) ;
@@ -895,21 +855,21 @@ impl DirEntry {
895
855
) ) ]
896
856
pub fn metadata ( & self ) -> io:: Result < FileAttr > {
897
857
let fd = cvt ( unsafe { dirfd ( self . dir . dirp . 0 ) } ) ?;
898
- let name = self . name_cstr ( ) . as_ptr ( ) ;
858
+ let name = self . name_cstr ( ) ;
899
859
900
860
cfg_has_statx ! {
901
861
if let Some ( ret) = unsafe { try_statx(
902
862
fd,
903
863
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 ,
906
866
) } {
907
867
return ret;
908
868
}
909
869
}
910
870
911
871
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 ) } ) ?;
913
873
Ok ( FileAttr :: from_stat64 ( stat) )
914
874
}
915
875
@@ -1172,13 +1132,12 @@ impl File {
1172
1132
1173
1133
pub fn file_attr ( & self ) -> io:: Result < FileAttr > {
1174
1134
let fd = self . as_raw_fd ( ) ;
1175
-
1176
1135
cfg_has_statx ! {
1177
1136
if let Some ( ret) = unsafe { try_statx(
1178
1137
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 ,
1182
1141
) } {
1183
1142
return ret;
1184
1143
}
@@ -1782,9 +1741,9 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
1782
1741
cfg_has_statx ! {
1783
1742
if let Some ( ret) = unsafe { try_statx(
1784
1743
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 ,
1788
1747
) } {
1789
1748
return ret;
1790
1749
}
@@ -1801,9 +1760,9 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
1801
1760
cfg_has_statx ! {
1802
1761
if let Some ( ret) = unsafe { try_statx(
1803
1762
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 ,
1807
1766
) } {
1808
1767
return ret;
1809
1768
}
0 commit comments