diff options
| author | oxalica <oxalicc@pm.me> | 2019-10-14 07:17:15 +0800 |
|---|---|---|
| committer | oxalica <oxalicc@pm.me> | 2019-10-18 10:32:27 +0800 |
| commit | 15cb3e08e31660b94305abe5cc3abc8b79662c0f (patch) | |
| tree | 8c53be388c57f689fcd3502723a511d61c30af3c /src/libstd/sys | |
| parent | 43f398be6d0faaf119150c950133ba4aa0ff42b3 (diff) | |
| download | rust-15cb3e08e31660b94305abe5cc3abc8b79662c0f.tar.gz rust-15cb3e08e31660b94305abe5cc3abc8b79662c0f.zip | |
Fix cfgs for current libc
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/unix/fs.rs | 228 |
1 files changed, 139 insertions, 89 deletions
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 8113fe38165..fee6eecf864 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -41,88 +41,137 @@ pub use crate::sys_common::fs::remove_dir_all; pub struct File(FileDesc); -#[derive(Clone)] -pub struct FileAttr { - stat: stat64, - #[cfg(target_os = "linux")] - statx_extra_fields: Option<StatxExtraFields>, -} - -#[cfg(target_os = "linux")] -#[derive(Clone)] -struct StatxExtraFields { - // This is needed to check if btime is supported by the filesystem. - stx_mask: u32, - stx_btime: libc::statx_timestamp, +// FIXME: This should be available on Linux with all `target_arch` and `target_env`. +// https://github.com/rust-lang/libc/issues/1545 +macro_rules! cfg_has_statx { + ({ $($then_tt:tt)* } else { $($else_tt:tt)* }) => { + cfg_if::cfg_if! { + if #[cfg(all(target_os = "linux", target_env = "gnu", any( + target_arch = "x86", + target_arch = "arm", + // target_arch = "mips", + target_arch = "powerpc", + target_arch = "x86_64", + // target_arch = "aarch64", + target_arch = "powerpc64", + // target_arch = "mips64", + // target_arch = "s390x", + target_arch = "sparc64", + )))] { + $($then_tt)* + } else { + $($else_tt)* + } + } + }; + ($($block_inner:tt)*) => { + #[cfg(all(target_os = "linux", target_env = "gnu", any( + target_arch = "x86", + target_arch = "arm", + // target_arch = "mips", + target_arch = "powerpc", + target_arch = "x86_64", + // target_arch = "aarch64", + target_arch = "powerpc64", + // target_arch = "mips64", + // target_arch = "s390x", + target_arch = "sparc64", + )))] + { + $($block_inner)* + } + }; } -// We prefer `statx` on Linux if available, which contains file creation time. -// Default `stat64` contains no creation time. -#[cfg(target_os = "linux")] -unsafe fn try_statx( - fd: c_int, - path: *const libc::c_char, - flags: i32, - mask: u32, -) -> Option<io::Result<FileAttr>> { - use crate::sync::atomic::{AtomicBool, Ordering}; +cfg_has_statx! {{ + #[derive(Clone)] + pub struct FileAttr { + stat: stat64, + statx_extra_fields: Option<StatxExtraFields>, + } + + #[derive(Clone)] + struct StatxExtraFields { + // This is needed to check if btime is supported by the filesystem. + stx_mask: u32, + stx_btime: libc::statx_timestamp, + } + + // We prefer `statx` on Linux if available, which contains file creation time. + // Default `stat64` contains no creation time. + unsafe fn try_statx( + fd: c_int, + path: *const libc::c_char, + flags: i32, + mask: u32, + ) -> Option<io::Result<FileAttr>> { + use crate::sync::atomic::{AtomicBool, Ordering}; + + // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx` + // We store the availability in a global to avoid unnecessary syscalls + static HAS_STATX: AtomicBool = AtomicBool::new(true); + syscall! { + fn statx( + fd: c_int, + pathname: *const libc::c_char, + flags: c_int, + mask: libc::c_uint, + statxbuf: *mut libc::statx + ) -> c_int + } - // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx` - // We store the availability in a global to avoid unnecessary syscalls - static HAS_STATX: AtomicBool = AtomicBool::new(true); - syscall! { - fn statx( - fd: c_int, - pathname: *const libc::c_char, - flags: c_int, - mask: libc::c_uint, - statxbuf: *mut libc::statx - ) -> c_int - } + if !HAS_STATX.load(Ordering::Relaxed) { + return None; + } - if !HAS_STATX.load(Ordering::Relaxed) { - return None; - } + let mut buf: libc::statx = mem::zeroed(); + let ret = cvt(statx(fd, path, flags, mask, &mut buf)); + match ret { + Err(err) => match err.raw_os_error() { + Some(libc::ENOSYS) => { + HAS_STATX.store(false, Ordering::Relaxed); + return None; + } + _ => return Some(Err(err)), + } + Ok(_) => { + // 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, + }; - let mut buf: libc::statx = mem::zeroed(); - let ret = cvt(statx(fd, path, flags, mask, &mut buf)); - match ret { - Err(err) => match err.raw_os_error() { - Some(libc::ENOSYS) => { - HAS_STATX.store(false, Ordering::Relaxed); - return None; + Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) })) } - _ => return Some(Err(err)), } - Ok(_) => { - // We cannot fill `stat64` exhaustively because of private padding fields. - let mut stat: stat64 = mem::zeroed(); - stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor); - 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); - 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; - stat.st_atime_nsec = buf.stx_atime.tv_nsec as libc::c_long; - stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t; - stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as libc::c_long; - stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t; - stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as libc::c_long; - - let extra = StatxExtraFields { - stx_mask: buf.stx_mask, - stx_btime: buf.stx_btime, - }; + } - Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) })) - } +} else { + #[derive(Clone)] + pub struct FileAttr { + stat: stat64, } -} +}} // all DirEntry's will have a reference to this struct struct InnerReadDir { @@ -175,15 +224,21 @@ pub struct FileType { mode: mode_t } #[derive(Debug)] pub struct DirBuilder { mode: mode_t } -impl FileAttr { - fn from_stat64(stat: stat64) -> Self { - Self { - stat, - #[cfg(target_os = "linux")] - statx_extra_fields: None, +cfg_has_statx! {{ + impl FileAttr { + fn from_stat64(stat: stat64) -> Self { + Self { stat, statx_extra_fields: None } } } +} else { + impl FileAttr { + fn from_stat64(stat: stat64) -> Self { + Self { stat } + } + } +}} +impl FileAttr { pub fn size(&self) -> u64 { self.stat.st_size as u64 } pub fn perm(&self) -> FilePermissions { FilePermissions { mode: (self.stat.st_mode as mode_t) } @@ -250,8 +305,7 @@ impl FileAttr { target_os = "macos", target_os = "ios")))] pub fn created(&self) -> io::Result<SystemTime> { - #[cfg(target_os = "linux")] - { + 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 { @@ -412,8 +466,7 @@ impl DirEntry { let fd = cvt(unsafe { dirfd(self.dir.inner.dirp.0) })?; let name = self.entry.d_name.as_ptr(); - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, name, @@ -636,8 +689,7 @@ impl File { pub fn file_attr(&self) -> io::Result<FileAttr> { let fd = self.0.raw(); - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, b"\0" as *const _ as *const libc::c_char, @@ -930,8 +982,7 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { pub fn stat(p: &Path) -> io::Result<FileAttr> { let p = cstr(p)?; - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( libc::AT_FDCWD, p.as_ptr(), @@ -952,8 +1003,7 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> { pub fn lstat(p: &Path) -> io::Result<FileAttr> { let p = cstr(p)?; - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( libc::AT_FDCWD, p.as_ptr(), |
