about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authoroxalica <oxalicc@pm.me>2019-10-23 02:43:45 +0800
committeroxalica <oxalicc@pm.me>2019-10-23 02:43:45 +0800
commit10f1bc77b3c404ebc1d386fc14453b6b32cf02bb (patch)
tree2891ce79bc1be691a802f5155dbd88cba073538c /src/libstd
parentc787fe3c70bdb84d0c82d6c592080ca2f1d7902f (diff)
downloadrust-10f1bc77b3c404ebc1d386fc14453b6b32cf02bb.tar.gz
rust-10f1bc77b3c404ebc1d386fc14453b6b32cf02bb.zip
Some tweaks
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/sys/unix/fs.rs93
1 files changed, 44 insertions, 49 deletions
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 54b2aee9400..5e1f10c03ce 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -124,64 +124,59 @@ cfg_has_statx! {{
         }
 
         match STATX_STATE.load(Ordering::Relaxed) {
-            // For the first time, we try to call on current working directory
-            // to check if it is available.
             0 => {
-                let mut buf: libc::statx = mem::zeroed();
-                let err = cvt(statx(
-                    libc::AT_FDCWD,
-                    b".\0".as_ptr().cast(),
-                    0,
-                    libc::STATX_ALL,
-                    &mut buf,
-                ))
+                // It is a trick to call `statx` with NULL pointers to check if the syscall
+                // is available. According to the manual, it is expected to fail with EFAULT.
+                // We do this mainly for performance, since it is nearly hundreds times
+                // faster than a normal successfull call.
+                let err = cvt(statx(0, ptr::null(), 0, libc::STATX_ALL, ptr::null_mut()))
                     .err()
                     .and_then(|e| e.raw_os_error());
-                // `seccomp` will emit `EPERM` on denied syscall.
+                // We don't check `err == Some(libc::ENOSYS)` because the syscall may be limited
+                // and returns `EPERM`. Listing all possible errors seems not a good idea.
                 // See: https://github.com/rust-lang/rust/issues/65662
-                if err == Some(libc::ENOSYS) || err == Some(libc::EPERM) {
+                if err != Some(libc::EFAULT) {
                     STATX_STATE.store(1, Ordering::Relaxed);
-                } else {
-                    STATX_STATE.store(2, Ordering::Relaxed);
+                    return None;
                 }
-                try_statx(fd, path, flags, mask)
+                STATX_STATE.store(2, Ordering::Relaxed);
             }
-            1 => None,
-            _ => {
-                let mut buf: libc::statx = mem::zeroed();
-                if let Err(err) = cvt(statx(fd, path, flags, mask, &mut buf)) {
-                    return Some(Err(err));
-                }
-
-                // We cannot fill `stat64` exhaustively because of private padding fields.
-                let mut stat: stat64 = mem::zeroed();
-                // `c_ulong` on gnu-mips, `dev_t` otherwise
-                stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor) as _;
-                stat.st_ino = buf.stx_ino as libc::ino64_t;
-                stat.st_nlink = buf.stx_nlink as libc::nlink_t;
-                stat.st_mode = buf.stx_mode as libc::mode_t;
-                stat.st_uid = buf.stx_uid as libc::uid_t;
-                stat.st_gid = buf.stx_gid as libc::gid_t;
-                stat.st_rdev = libc::makedev(buf.stx_rdev_major, buf.stx_rdev_minor) as _;
-                stat.st_size = buf.stx_size as off64_t;
-                stat.st_blksize = buf.stx_blksize as libc::blksize_t;
-                stat.st_blocks = buf.stx_blocks as libc::blkcnt64_t;
-                stat.st_atime = buf.stx_atime.tv_sec as libc::time_t;
-                // `i64` on gnu-x86_64-x32, `c_ulong` otherwise.
-                stat.st_atime_nsec = buf.stx_atime.tv_nsec as _;
-                stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t;
-                stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as _;
-                stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t;
-                stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as _;
-
-                let extra = StatxExtraFields {
-                    stx_mask: buf.stx_mask,
-                    stx_btime: buf.stx_btime,
-                };
+            1 => return None,
+            _ => {}
+        }
 
-                Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) }))
-            }
+        let mut buf: libc::statx = mem::zeroed();
+        if let Err(err) = cvt(statx(fd, path, flags, mask, &mut buf)) {
+            return Some(Err(err));
         }
+
+        // We cannot fill `stat64` exhaustively because of private padding fields.
+        let mut stat: stat64 = mem::zeroed();
+        // `c_ulong` on gnu-mips, `dev_t` otherwise
+        stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor) as _;
+        stat.st_ino = buf.stx_ino as libc::ino64_t;
+        stat.st_nlink = buf.stx_nlink as libc::nlink_t;
+        stat.st_mode = buf.stx_mode as libc::mode_t;
+        stat.st_uid = buf.stx_uid as libc::uid_t;
+        stat.st_gid = buf.stx_gid as libc::gid_t;
+        stat.st_rdev = libc::makedev(buf.stx_rdev_major, buf.stx_rdev_minor) as _;
+        stat.st_size = buf.stx_size as off64_t;
+        stat.st_blksize = buf.stx_blksize as libc::blksize_t;
+        stat.st_blocks = buf.stx_blocks as libc::blkcnt64_t;
+        stat.st_atime = buf.stx_atime.tv_sec as libc::time_t;
+        // `i64` on gnu-x86_64-x32, `c_ulong` otherwise.
+        stat.st_atime_nsec = buf.stx_atime.tv_nsec as _;
+        stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t;
+        stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as _;
+        stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t;
+        stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as _;
+
+        let extra = StatxExtraFields {
+            stx_mask: buf.stx_mask,
+            stx_btime: buf.stx_btime,
+        };
+
+        Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) }))
     }
 
 } else {