@@ -124,64 +124,59 @@ cfg_has_statx! {{
124124        } 
125125
126126        match  STATX_STATE . load( Ordering :: Relaxed )  { 
127-             // For the first time, we try to call on current working directory 
128-             // to check if it is available. 
129127            0  => { 
130-                 let  mut  buf:  libc:: statx = mem:: zeroed( ) ; 
131-                 let  err = cvt( statx( 
132-                     libc:: AT_FDCWD , 
133-                     b".\0 " . as_ptr( ) . cast( ) , 
134-                     0 , 
135-                     libc:: STATX_ALL , 
136-                     & mut  buf, 
137-                 ) ) 
128+                 // It is a trick to call `statx` with NULL pointers to check if the syscall 
129+                 // is available. According to the manual, it is expected to fail with EFAULT. 
130+                 // We do this mainly for performance, since it is nearly hundreds times 
131+                 // faster than a normal successfull call. 
132+                 let  err = cvt( statx( 0 ,  ptr:: null( ) ,  0 ,  libc:: STATX_ALL ,  ptr:: null_mut( ) ) ) 
138133                    . err( ) 
139134                    . and_then( |e| e. raw_os_error( ) ) ; 
140-                 // `seccomp` will emit `EPERM` on denied syscall. 
135+                 // We don't check `err == Some(libc::ENOSYS)` because the syscall may be limited 
136+                 // and returns `EPERM`. Listing all possible errors seems not a good idea. 
141137                // See: https://github.com/rust-lang/rust/issues/65662 
142-                 if  err ==  Some ( libc:: ENOSYS )  || err ==  Some ( libc :: EPERM )  { 
138+                 if  err !=  Some ( libc:: EFAULT )  { 
143139                    STATX_STATE . store( 1 ,  Ordering :: Relaxed ) ; 
144-                 }  else { 
145-                     STATX_STATE . store( 2 ,  Ordering :: Relaxed ) ; 
140+                     return  None ; 
146141                } 
147-                 try_statx ( fd ,  path ,  flags ,  mask ) 
142+                 STATX_STATE . store ( 2 ,   Ordering :: Relaxed ) ; 
148143            } 
149-             1  => None , 
150-             _ => { 
151-                 let  mut  buf:  libc:: statx = mem:: zeroed( ) ; 
152-                 if  let  Err ( err)  = cvt( statx( fd,  path,  flags,  mask,  & mut  buf) )  { 
153-                     return  Some ( Err ( err) ) ; 
154-                 } 
155- 
156-                 // We cannot fill `stat64` exhaustively because of private padding fields. 
157-                 let  mut  stat:  stat64 = mem:: zeroed( ) ; 
158-                 // `c_ulong` on gnu-mips, `dev_t` otherwise 
159-                 stat. st_dev = libc:: makedev( buf. stx_dev_major,  buf. stx_dev_minor)  as  _; 
160-                 stat. st_ino = buf. stx_ino as  libc:: ino64_t; 
161-                 stat. st_nlink = buf. stx_nlink as  libc:: nlink_t; 
162-                 stat. st_mode = buf. stx_mode as  libc:: mode_t; 
163-                 stat. st_uid = buf. stx_uid as  libc:: uid_t; 
164-                 stat. st_gid = buf. stx_gid as  libc:: gid_t; 
165-                 stat. st_rdev = libc:: makedev( buf. stx_rdev_major,  buf. stx_rdev_minor)  as  _; 
166-                 stat. st_size = buf. stx_size as  off64_t; 
167-                 stat. st_blksize = buf. stx_blksize as  libc:: blksize_t; 
168-                 stat. st_blocks = buf. stx_blocks as  libc:: blkcnt64_t; 
169-                 stat. st_atime = buf. stx_atime. tv_sec as  libc:: time_t; 
170-                 // `i64` on gnu-x86_64-x32, `c_ulong` otherwise. 
171-                 stat. st_atime_nsec = buf. stx_atime. tv_nsec as  _; 
172-                 stat. st_mtime = buf. stx_mtime. tv_sec as  libc:: time_t; 
173-                 stat. st_mtime_nsec = buf. stx_mtime. tv_nsec as  _; 
174-                 stat. st_ctime = buf. stx_ctime. tv_sec as  libc:: time_t; 
175-                 stat. st_ctime_nsec = buf. stx_ctime. tv_nsec as  _; 
176- 
177-                 let  extra = StatxExtraFields  { 
178-                     stx_mask:  buf. stx_mask, 
179-                     stx_btime:  buf. stx_btime, 
180-                 } ; 
144+             1  => return  None , 
145+             _ => { } 
146+         } 
181147
182-                 Some ( Ok ( FileAttr  {  stat,  statx_extra_fields:  Some ( extra)  } ) ) 
183-             } 
148+         let  mut  buf:  libc:: statx = mem:: zeroed( ) ; 
149+         if  let  Err ( err)  = cvt( statx( fd,  path,  flags,  mask,  & mut  buf) )  { 
150+             return  Some ( Err ( err) ) ; 
184151        } 
152+ 
153+         // We cannot fill `stat64` exhaustively because of private padding fields. 
154+         let  mut  stat:  stat64 = mem:: zeroed( ) ; 
155+         // `c_ulong` on gnu-mips, `dev_t` otherwise 
156+         stat. st_dev = libc:: makedev( buf. stx_dev_major,  buf. stx_dev_minor)  as  _; 
157+         stat. st_ino = buf. stx_ino as  libc:: ino64_t; 
158+         stat. st_nlink = buf. stx_nlink as  libc:: nlink_t; 
159+         stat. st_mode = buf. stx_mode as  libc:: mode_t; 
160+         stat. st_uid = buf. stx_uid as  libc:: uid_t; 
161+         stat. st_gid = buf. stx_gid as  libc:: gid_t; 
162+         stat. st_rdev = libc:: makedev( buf. stx_rdev_major,  buf. stx_rdev_minor)  as  _; 
163+         stat. st_size = buf. stx_size as  off64_t; 
164+         stat. st_blksize = buf. stx_blksize as  libc:: blksize_t; 
165+         stat. st_blocks = buf. stx_blocks as  libc:: blkcnt64_t; 
166+         stat. st_atime = buf. stx_atime. tv_sec as  libc:: time_t; 
167+         // `i64` on gnu-x86_64-x32, `c_ulong` otherwise. 
168+         stat. st_atime_nsec = buf. stx_atime. tv_nsec as  _; 
169+         stat. st_mtime = buf. stx_mtime. tv_sec as  libc:: time_t; 
170+         stat. st_mtime_nsec = buf. stx_mtime. tv_nsec as  _; 
171+         stat. st_ctime = buf. stx_ctime. tv_sec as  libc:: time_t; 
172+         stat. st_ctime_nsec = buf. stx_ctime. tv_nsec as  _; 
173+ 
174+         let  extra = StatxExtraFields  { 
175+             stx_mask:  buf. stx_mask, 
176+             stx_btime:  buf. stx_btime, 
177+         } ; 
178+ 
179+         Some ( Ok ( FileAttr  {  stat,  statx_extra_fields:  Some ( extra)  } ) ) 
185180    } 
186181
187182}  else { 
0 commit comments