@@ -147,52 +147,48 @@ fn stat(f: &File) -> io::Result<libc::stat64> {
147147}
148148
149149fn statx ( f : & File ) -> io:: Result < ( libc:: stat64 , u64 ) > {
150- let mut stx = MaybeUninit :: < libc:: statx > :: zeroed ( ) ;
150+ use rustix:: fd:: BorrowedFd ;
151+ use rustix:: fs:: { statx, AtFlags , StatxFlags } ;
151152
152153 // Safe because this is a constant value and a valid C string.
153154 let pathname = unsafe { CStr :: from_bytes_with_nul_unchecked ( EMPTY_CSTR ) } ;
155+ let dirfd = unsafe { BorrowedFd :: borrow_raw ( f. as_raw_fd ( ) ) } ;
154156
155157 // Safe because the kernel will only write data in `st` and we check the return
156158 // value.
157- let res = unsafe {
158- libc:: statx (
159- f. as_raw_fd ( ) ,
160- pathname. as_ptr ( ) ,
161- libc:: AT_EMPTY_PATH | libc:: AT_SYMLINK_NOFOLLOW ,
162- libc:: STATX_BASIC_STATS | libc:: STATX_MNT_ID ,
163- stx. as_mut_ptr ( ) ,
164- )
165- } ;
166- if res >= 0 {
167- // Safe because the kernel guarantees that the struct is now fully initialized.
168- let stx = unsafe { stx. assume_init ( ) } ;
169-
170- // Unfortunately, we cannot use an initializer to create the stat64 object,
171- // because it may contain padding and reserved fields (depending on the
172- // architecture), and it does not implement the Default trait.
173- // So we take a zeroed struct and set what we can. (Zero in all fields is
174- // wrong, but safe.)
175- let mut st = unsafe { MaybeUninit :: < libc:: stat64 > :: zeroed ( ) . assume_init ( ) } ;
176-
177- st. st_dev = libc:: makedev ( stx. stx_dev_major , stx. stx_dev_minor ) ;
178- st. st_ino = stx. stx_ino ;
179- st. st_mode = stx. stx_mode as _ ;
180- st. st_nlink = stx. stx_nlink as _ ;
181- st. st_uid = stx. stx_uid ;
182- st. st_gid = stx. stx_gid ;
183- st. st_rdev = libc:: makedev ( stx. stx_rdev_major , stx. stx_rdev_minor ) ;
184- st. st_size = stx. stx_size as _ ;
185- st. st_blksize = stx. stx_blksize as _ ;
186- st. st_blocks = stx. stx_blocks as _ ;
187- st. st_atime = stx. stx_atime . tv_sec ;
188- st. st_atime_nsec = stx. stx_atime . tv_nsec as _ ;
189- st. st_mtime = stx. stx_mtime . tv_sec ;
190- st. st_mtime_nsec = stx. stx_mtime . tv_nsec as _ ;
191- st. st_ctime = stx. stx_ctime . tv_sec ;
192- st. st_ctime_nsec = stx. stx_ctime . tv_nsec as _ ;
193- Ok ( ( st, stx. stx_mnt_id ) )
194- } else {
195- Err ( io:: Error :: last_os_error ( ) )
159+ match statx (
160+ dirfd,
161+ pathname,
162+ AtFlags :: EMPTY_PATH | AtFlags :: SYMLINK_NOFOLLOW ,
163+ StatxFlags :: BASIC_STATS | StatxFlags :: MNT_ID ,
164+ ) {
165+ Ok ( stx) => {
166+ // Unfortunately, we cannot use an initializer to create the stat64 object,
167+ // because it may contain padding and reserved fields (depending on the
168+ // architecture), and it does not implement the Default trait.
169+ // So we take a zeroed struct and set what we can. (Zero in all fields is
170+ // wrong, but safe.)
171+ let mut st = unsafe { MaybeUninit :: < libc:: stat64 > :: zeroed ( ) . assume_init ( ) } ;
172+
173+ st. st_dev = libc:: makedev ( stx. stx_dev_major , stx. stx_dev_minor ) ;
174+ st. st_ino = stx. stx_ino ;
175+ st. st_mode = stx. stx_mode as _ ;
176+ st. st_nlink = stx. stx_nlink as _ ;
177+ st. st_uid = stx. stx_uid ;
178+ st. st_gid = stx. stx_gid ;
179+ st. st_rdev = libc:: makedev ( stx. stx_rdev_major , stx. stx_rdev_minor ) ;
180+ st. st_size = stx. stx_size as _ ;
181+ st. st_blksize = stx. stx_blksize as _ ;
182+ st. st_blocks = stx. stx_blocks as _ ;
183+ st. st_atime = stx. stx_atime . tv_sec ;
184+ st. st_atime_nsec = stx. stx_atime . tv_nsec as _ ;
185+ st. st_mtime = stx. stx_mtime . tv_sec ;
186+ st. st_mtime_nsec = stx. stx_mtime . tv_nsec as _ ;
187+ st. st_ctime = stx. stx_ctime . tv_sec ;
188+ st. st_ctime_nsec = stx. stx_ctime . tv_nsec as _ ;
189+ Ok ( ( st, stx. stx_mnt_id ) )
190+ }
191+ Err ( e) => Err ( e. into ( ) ) ,
196192 }
197193}
198194
0 commit comments