summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/unix/fs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/unix/fs.rs')
-rw-r--r--library/std/src/sys/unix/fs.rs96
1 files changed, 74 insertions, 22 deletions
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index abef170dd..09e9ae272 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -349,6 +349,8 @@ pub struct FilePermissions {
pub struct FileTimes {
accessed: Option<SystemTime>,
modified: Option<SystemTime>,
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ created: Option<SystemTime>,
}
#[derive(Copy, Clone, Eq, Debug)]
@@ -447,7 +449,12 @@ impl FileAttr {
#[cfg(not(any(target_os = "netbsd", target_os = "nto")))]
impl FileAttr {
- #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
+ #[cfg(not(any(
+ target_os = "vxworks",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "vita"
+ )))]
pub fn modified(&self) -> io::Result<SystemTime> {
#[cfg(target_pointer_width = "32")]
cfg_has_statx! {
@@ -459,7 +466,7 @@ impl FileAttr {
Ok(SystemTime::new(self.stat.st_mtime as i64, self.stat.st_mtime_nsec as i64))
}
- #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
+ #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))]
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_mtime as i64, 0))
}
@@ -469,7 +476,12 @@ impl FileAttr {
Ok(SystemTime::from(self.stat.st_mtim))
}
- #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
+ #[cfg(not(any(
+ target_os = "vxworks",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "vita"
+ )))]
pub fn accessed(&self) -> io::Result<SystemTime> {
#[cfg(target_pointer_width = "32")]
cfg_has_statx! {
@@ -481,7 +493,7 @@ impl FileAttr {
Ok(SystemTime::new(self.stat.st_atime as i64, self.stat.st_atime_nsec as i64))
}
- #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
+ #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))]
pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_atime as i64, 0))
}
@@ -547,6 +559,7 @@ impl FileAttr {
}
impl AsInner<stat64> for FileAttr {
+ #[inline]
fn as_inner(&self) -> &stat64 {
&self.stat
}
@@ -580,6 +593,11 @@ impl FileTimes {
pub fn set_modified(&mut self, t: SystemTime) {
self.modified = Some(t);
}
+
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ pub fn set_created(&mut self, t: SystemTime) {
+ self.created = Some(t);
+ }
}
impl FileType {
@@ -865,6 +883,7 @@ impl DirEntry {
target_os = "vxworks",
target_os = "espidf",
target_os = "horizon",
+ target_os = "vita",
target_os = "nto",
))]
pub fn ino(&self) -> u64 {
@@ -1193,37 +1212,51 @@ impl File {
None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }),
}
};
- #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))]
- let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
cfg_if::cfg_if! {
if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] {
// Redox doesn't appear to support `UTIME_OMIT`.
// ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
// the same as for Redox.
- drop(times);
+ let _ = times;
Err(io::const_io_error!(
io::ErrorKind::Unsupported,
"setting file times not supported",
))
- } else if #[cfg(any(target_os = "android", target_os = "macos"))] {
- // futimens requires macOS 10.13, and Android API level 19
+ } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
+ let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
+ let mut num_times = 0;
+ let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
+ attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT;
+ if times.created.is_some() {
+ buf[num_times].write(to_timespec(times.created)?);
+ num_times += 1;
+ attrlist.commonattr |= libc::ATTR_CMN_CRTIME;
+ }
+ if times.modified.is_some() {
+ buf[num_times].write(to_timespec(times.modified)?);
+ num_times += 1;
+ attrlist.commonattr |= libc::ATTR_CMN_MODTIME;
+ }
+ if times.accessed.is_some() {
+ buf[num_times].write(to_timespec(times.accessed)?);
+ num_times += 1;
+ attrlist.commonattr |= libc::ATTR_CMN_ACCTIME;
+ }
+ cvt(unsafe { libc::fsetattrlist(
+ self.as_raw_fd(),
+ (&attrlist as *const libc::attrlist).cast::<libc::c_void>().cast_mut(),
+ buf.as_ptr().cast::<libc::c_void>().cast_mut(),
+ num_times * mem::size_of::<libc::timespec>(),
+ 0
+ ) })?;
+ Ok(())
+ } else if #[cfg(target_os = "android")] {
+ let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
+ // futimens requires Android API level 19
cvt(unsafe {
weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
match futimens.get() {
Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
- #[cfg(target_os = "macos")]
- None => {
- fn ts_to_tv(ts: &libc::timespec) -> libc::timeval {
- libc::timeval {
- tv_sec: ts.tv_sec,
- tv_usec: (ts.tv_nsec / 1000) as _
- }
- }
- let timevals = [ts_to_tv(&times[0]), ts_to_tv(&times[1])];
- libc::futimes(self.as_raw_fd(), timevals.as_ptr())
- }
- // futimes requires even newer Android.
- #[cfg(target_os = "android")]
None => return Err(io::const_io_error!(
io::ErrorKind::Unsupported,
"setting file times requires Android API level >= 19",
@@ -1232,6 +1265,22 @@ impl File {
})?;
Ok(())
} else {
+ #[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))]
+ {
+ use crate::sys::{time::__timespec64, weak::weak};
+
+ // Added in glibc 2.34
+ weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int);
+
+ if let Some(futimens64) = __futimens64.get() {
+ let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64())
+ .unwrap_or(__timespec64::new(0, libc::UTIME_OMIT as _));
+ let times = [to_timespec(times.accessed), to_timespec(times.modified)];
+ cvt(unsafe { futimens64(self.as_raw_fd(), times.as_ptr()) })?;
+ return Ok(());
+ }
+ }
+ let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
cvt(unsafe { libc::futimens(self.as_raw_fd(), times.as_ptr()) })?;
Ok(())
}
@@ -1254,12 +1303,14 @@ impl DirBuilder {
}
impl AsInner<FileDesc> for File {
+ #[inline]
fn as_inner(&self) -> &FileDesc {
&self.0
}
}
impl AsInnerMut<FileDesc> for File {
+ #[inline]
fn as_inner_mut(&mut self) -> &mut FileDesc {
&mut self.0
}
@@ -1284,6 +1335,7 @@ impl AsFd for File {
}
impl AsRawFd for File {
+ #[inline]
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}