about summary refs log tree commit diff
path: root/library/std
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2022-03-09 17:05:16 -0800
committerJosh Stone <jistone@redhat.com>2022-05-06 08:50:53 -0700
commitfec4818fdb40c82679f57fa7f26fcddc1a874c13 (patch)
tree4c06a6e5b385e327257f7f7fe8f8746f422622d1 /library/std
parent97b49a0cc5bea5845dc89c1598a32d7f9fea985a (diff)
downloadrust-fec4818fdb40c82679f57fa7f26fcddc1a874c13.tar.gz
rust-fec4818fdb40c82679f57fa7f26fcddc1a874c13.zip
Use statx's 64-bit times on 32-bit linux-gnu
Diffstat (limited to 'library/std')
-rw-r--r--library/std/src/os/linux/fs.rs21
-rw-r--r--library/std/src/sys/unix/fs.rs109
-rw-r--r--library/std/src/sys/unix/time.rs8
3 files changed, 97 insertions, 41 deletions
diff --git a/library/std/src/os/linux/fs.rs b/library/std/src/os/linux/fs.rs
index 9d18ccbeb24..23267c44685 100644
--- a/library/std/src/os/linux/fs.rs
+++ b/library/std/src/os/linux/fs.rs
@@ -356,19 +356,34 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_size as u64
     }
     fn st_atime(&self) -> i64 {
-        self.as_inner().as_inner().st_atime as i64
+        let file_attr = self.as_inner();
+        #[cfg(all(target_env = "gnu", target_pointer_width = "32"))]
+        if let Some(atime) = file_attr.stx_atime() {
+            return atime.tv_sec;
+        }
+        file_attr.as_inner().st_atime as i64
     }
     fn st_atime_nsec(&self) -> i64 {
         self.as_inner().as_inner().st_atime_nsec as i64
     }
     fn st_mtime(&self) -> i64 {
-        self.as_inner().as_inner().st_mtime as i64
+        let file_attr = self.as_inner();
+        #[cfg(all(target_env = "gnu", target_pointer_width = "32"))]
+        if let Some(mtime) = file_attr.stx_mtime() {
+            return mtime.tv_sec;
+        }
+        file_attr.as_inner().st_mtime as i64
     }
     fn st_mtime_nsec(&self) -> i64 {
         self.as_inner().as_inner().st_mtime_nsec as i64
     }
     fn st_ctime(&self) -> i64 {
-        self.as_inner().as_inner().st_ctime as i64
+        let file_attr = self.as_inner();
+        #[cfg(all(target_env = "gnu", target_pointer_width = "32"))]
+        if let Some(ctime) = file_attr.stx_ctime() {
+            return ctime.tv_sec;
+        }
+        file_attr.as_inner().st_ctime as i64
     }
     fn st_ctime_nsec(&self) -> i64 {
         self.as_inner().as_inner().st_ctime_nsec as i64
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 27fc7accdae..61fb2814018 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -113,10 +113,19 @@ cfg_has_statx! {{
         // This is needed to check if btime is supported by the filesystem.
         stx_mask: u32,
         stx_btime: libc::statx_timestamp,
+        // With statx, we can overcome 32-bit `time_t` too.
+        #[cfg(target_pointer_width = "32")]
+        stx_atime: libc::statx_timestamp,
+        #[cfg(target_pointer_width = "32")]
+        stx_ctime: libc::statx_timestamp,
+        #[cfg(target_pointer_width = "32")]
+        stx_mtime: libc::statx_timestamp,
+
     }
 
-    // We prefer `statx` on Linux if available, which contains file creation time.
-    // Default `stat64` contains no creation time.
+    // We prefer `statx` on Linux if available, which contains file creation time,
+    // as well as 64-bit timestamps of all kinds.
+    // Default `stat64` contains no creation time and may have 32-bit `time_t`.
     unsafe fn try_statx(
         fd: c_int,
         path: *const c_char,
@@ -192,6 +201,13 @@ cfg_has_statx! {{
         let extra = StatxExtraFields {
             stx_mask: buf.stx_mask,
             stx_btime: buf.stx_btime,
+            // Store full times to avoid 32-bit `time_t` truncation.
+            #[cfg(target_pointer_width = "32")]
+            stx_atime: buf.stx_atime,
+            #[cfg(target_pointer_width = "32")]
+            stx_ctime: buf.stx_ctime,
+            #[cfg(target_pointer_width = "32")]
+            stx_mtime: buf.stx_mtime,
         };
 
         Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) }))
@@ -310,6 +326,36 @@ cfg_has_statx! {{
         fn from_stat64(stat: stat64) -> Self {
             Self { stat, statx_extra_fields: None }
         }
+
+        #[cfg(target_pointer_width = "32")]
+        pub fn stx_mtime(&self) -> Option<&libc::statx_timestamp> {
+            if let Some(ext) = &self.statx_extra_fields {
+                if (ext.stx_mask & libc::STATX_MTIME) != 0 {
+                    return Some(&ext.stx_mtime);
+                }
+            }
+            None
+        }
+
+        #[cfg(target_pointer_width = "32")]
+        pub fn stx_atime(&self) -> Option<&libc::statx_timestamp> {
+            if let Some(ext) = &self.statx_extra_fields {
+                if (ext.stx_mask & libc::STATX_ATIME) != 0 {
+                    return Some(&ext.stx_atime);
+                }
+            }
+            None
+        }
+
+        #[cfg(target_pointer_width = "32")]
+        pub fn stx_ctime(&self) -> Option<&libc::statx_timestamp> {
+            if let Some(ext) = &self.statx_extra_fields {
+                if (ext.stx_mask & libc::STATX_CTIME) != 0 {
+                    return Some(&ext.stx_ctime);
+                }
+            }
+            None
+        }
     }
 } else {
     impl FileAttr {
@@ -335,24 +381,15 @@ impl FileAttr {
 #[cfg(target_os = "netbsd")]
 impl FileAttr {
     pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_mtime as libc::time_t,
-            tv_nsec: self.stat.st_mtimensec as libc::c_long,
-        }))
+        Ok(SystemTime::new(self.stat.st_mtime as i64, self.stat.st_mtimensec as i64))
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_atime as libc::time_t,
-            tv_nsec: self.stat.st_atimensec as libc::c_long,
-        }))
+        Ok(SystemTime::new(self.stat.st_atime as i64, self.stat.st_atimensec as i64))
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_birthtime as libc::time_t,
-            tv_nsec: self.stat.st_birthtimensec as libc::c_long,
-        }))
+        Ok(SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtimensec as i64))
     }
 }
 
@@ -360,34 +397,36 @@ impl FileAttr {
 impl FileAttr {
     #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
     pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_mtime as libc::time_t,
-            tv_nsec: self.stat.st_mtime_nsec as _,
-        }))
+        #[cfg(target_pointer_width = "32")]
+        cfg_has_statx! {
+            if let Some(mtime) = self.stx_mtime() {
+                return Ok(SystemTime::new(mtime.tv_sec, mtime.tv_nsec as i64));
+            }
+        }
+
+        Ok(SystemTime::new(self.stat.st_mtime as i64, self.stat.st_mtime_nsec as i64))
     }
 
     #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
     pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_mtime as libc::time_t,
-            tv_nsec: 0,
-        }))
+        Ok(SystemTime::new(self.stat.st_mtime as i64, 0))
     }
 
     #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_atime as libc::time_t,
-            tv_nsec: self.stat.st_atime_nsec as _,
-        }))
+        #[cfg(target_pointer_width = "32")]
+        cfg_has_statx! {
+            if let Some(atime) = self.stx_atime() {
+                return Ok(SystemTime::new(atime.tv_sec, atime.tv_nsec as i64));
+            }
+        }
+
+        Ok(SystemTime::new(self.stat.st_atime as i64, self.stat.st_atime_nsec as i64))
     }
 
     #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_atime as libc::time_t,
-            tv_nsec: 0,
-        }))
+        Ok(SystemTime::new(self.stat.st_atime as i64, 0))
     }
 
     #[cfg(any(
@@ -397,10 +436,7 @@ impl FileAttr {
         target_os = "ios"
     ))]
     pub fn created(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(libc::timespec {
-            tv_sec: self.stat.st_birthtime as libc::time_t,
-            tv_nsec: self.stat.st_birthtime_nsec as libc::c_long,
-        }))
+        Ok(SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtime_nsec as i64))
     }
 
     #[cfg(not(any(
@@ -413,10 +449,7 @@ impl FileAttr {
         cfg_has_statx! {
             if let Some(ext) = &self.statx_extra_fields {
                 return if (ext.stx_mask & libc::STATX_BTIME) != 0 {
-                    Ok(SystemTime::from(libc::timespec {
-                        tv_sec: ext.stx_btime.tv_sec as libc::time_t,
-                        tv_nsec: ext.stx_btime.tv_nsec as _,
-                    }))
+                    Ok(SystemTime::new(ext.stx_btime.tv_sec, ext.stx_btime.tv_nsec as i64))
                 } else {
                     Err(io::const_io_error!(
                         io::ErrorKind::Uncategorized,
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index 20d061206be..5000e7d890b 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -144,6 +144,10 @@ mod inner {
     }
 
     impl SystemTime {
+        pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
+            SystemTime { t: Timespec::new(tv_sec, tv_nsec) }
+        }
+
         pub fn now() -> SystemTime {
             use crate::ptr;
 
@@ -294,6 +298,10 @@ mod inner {
     }
 
     impl SystemTime {
+        pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
+            SystemTime { t: Timespec::new(tv_sec, tv_nsec) }
+        }
+
         pub fn now() -> SystemTime {
             SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
         }