diff --git a/src/path.rs b/src/path.rs index 461b72efb..8c6b832db 100644 --- a/src/path.rs +++ b/src/path.rs @@ -14,7 +14,6 @@ use nix::unistd::AccessFlags; use std::ffi::OsStr; use std::io::ErrorKind; -use std::mem::MaybeUninit; use std::os::unix::prelude::*; use std::sync::LazyLock; @@ -629,69 +628,78 @@ fn create_dir_all_with_mode>(path: P, mode: u32) -> st /// Return whether the given path is on a remote filesystem. pub fn path_remoteness(path: &wstr) -> DirRemoteness { - let narrow = wcs2zstring(path); cfg_if! { - if #[cfg(any(target_os = "linux", cygwin))] { - let mut buf = MaybeUninit::uninit(); - if unsafe { libc::statfs(narrow.as_ptr(), buf.as_mut_ptr()) } < 0 { - return DirRemoteness::Unknown; - } - let buf = unsafe { buf.assume_init() }; - // Linux has constants for these like NFS_SUPER_MAGIC, SMB_SUPER_MAGIC, CIFS_MAGIC_NUMBER but - // these are in varying headers. Simply hard code them. - // Note that we treat FUSE filesystems as remote, which means we lock less on such filesystems. - // NOTE: The cast is necessary for 32-bit systems because of the 4-byte CIFS_MAGIC_NUMBER - match buf.f_type as usize { - 0x5346414F | // AFS_SUPER_MAGIC - Andrew File System - 0x6B414653 | // AFS_FS_MAGIC - Kernel AFS and AuriStorFS - 0x73757245 | // CODA_SUPER_MAGIC - Coda File System - 0x47504653 | // GPFS - General Parallel File System - 0x564c | // NCP_SUPER_MAGIC - Novell NetWare - 0x6969 | // NFS_SUPER_MAGIC - 0x7461636f | // OCFS2_SUPER_MAGIC - Oracle Cluster File System - 0x61636673 | // ACFS - Oracle ACFS. Undocumented magic number. - 0x517B | // SMB_SUPER_MAGIC - 0xFE534D42 | // SMB2_MAGIC_NUMBER - 0xFF534D42 | // CIFS_MAGIC_NUMBER - 0x01021997 | // V9FS_MAGIC - 0x19830326 | // fhgfs / BeeGFS. Undocumented magic number. - 0x013111A7 | 0x013111A8 | // IBRIX. Undocumented. - 0x65735546 | // FUSE_SUPER_MAGIC - 0xA501FCF5 // VXFS_SUPER_MAGIC - => DirRemoteness::Remote, - _ => { - DirRemoteness::Unknown - } - } - } else if #[cfg(target_os = "netbsd")] { - // NetBSD doesn't have statfs, but MNT_LOCAL works for statvfs. - let mut buf = MaybeUninit::uninit(); - if unsafe { libc::statvfs(narrow.as_ptr(), buf.as_mut_ptr()) } < 0 { - return DirRemoteness::Unknown; - } - let buf = unsafe { buf.assume_init() }; - #[allow(clippy::useless_conversion)] - let flags = buf.f_flag as u64; - #[allow(clippy::unnecessary_cast)] - if flags & (libc::MNT_LOCAL as u64) != 0 { - DirRemoteness::Local - } else { - DirRemoteness::Remote - } + // illumos doesn't have statfs and MNT_LOCAL doesn't work for statvfs + // we _could_ use statvfs to match against known filesystems but that is fragile + if #[cfg(target_os = "illumos")] { + DirRemoteness::Unknown } else { - let mut buf = MaybeUninit::uninit(); - if unsafe { libc::statfs(narrow.as_ptr(), buf.as_mut_ptr()) } < 0 { - return DirRemoteness::Unknown; - } - let buf = unsafe { buf.assume_init() }; - // statfs::f_flags types differ. - #[allow(clippy::useless_conversion)] - let flags = buf.f_flags as u64; - #[allow(clippy::unnecessary_cast)] - if flags & (libc::MNT_LOCAL as u64) != 0 { - DirRemoteness::Local - } else { - DirRemoteness::Remote + let narrow = wcs2zstring(path); + use std::mem::MaybeUninit; + cfg_if! { + if #[cfg(any(target_os = "linux", cygwin))] { + let mut buf = MaybeUninit::uninit(); + if unsafe { libc::statfs(narrow.as_ptr(), buf.as_mut_ptr()) } < 0 { + return DirRemoteness::Unknown; + } + let buf = unsafe { buf.assume_init() }; + // Linux has constants for these like NFS_SUPER_MAGIC, SMB_SUPER_MAGIC, CIFS_MAGIC_NUMBER but + // these are in varying headers. Simply hard code them. + // Note that we treat FUSE filesystems as remote, which means we lock less on such filesystems. + // NOTE: The cast is necessary for 32-bit systems because of the 4-byte CIFS_MAGIC_NUMBER + match buf.f_type as usize { + 0x5346414F | // AFS_SUPER_MAGIC - Andrew File System + 0x6B414653 | // AFS_FS_MAGIC - Kernel AFS and AuriStorFS + 0x73757245 | // CODA_SUPER_MAGIC - Coda File System + 0x47504653 | // GPFS - General Parallel File System + 0x564c | // NCP_SUPER_MAGIC - Novell NetWare + 0x6969 | // NFS_SUPER_MAGIC + 0x7461636f | // OCFS2_SUPER_MAGIC - Oracle Cluster File System + 0x61636673 | // ACFS - Oracle ACFS. Undocumented magic number. + 0x517B | // SMB_SUPER_MAGIC + 0xFE534D42 | // SMB2_MAGIC_NUMBER + 0xFF534D42 | // CIFS_MAGIC_NUMBER + 0x01021997 | // V9FS_MAGIC + 0x19830326 | // fhgfs / BeeGFS. Undocumented magic number. + 0x013111A7 | 0x013111A8 | // IBRIX. Undocumented. + 0x65735546 | // FUSE_SUPER_MAGIC + 0xA501FCF5 // VXFS_SUPER_MAGIC + => DirRemoteness::Remote, + _ => { + DirRemoteness::Unknown + } + } + } else if #[cfg(target_os = "netbsd")] { + // NetBSD doesn't have statfs, but MNT_LOCAL works for statvfs. + let mut buf = MaybeUninit::uninit(); + if unsafe { libc::statvfs(narrow.as_ptr(), buf.as_mut_ptr()) } < 0 { + return DirRemoteness::Unknown; + } + let buf = unsafe { buf.assume_init() }; + #[allow(clippy::useless_conversion)] + let flags = buf.f_flag as u64; + #[allow(clippy::unnecessary_cast)] + if flags & (libc::MNT_LOCAL as u64) != 0 { + DirRemoteness::Local + } else { + DirRemoteness::Remote + } + } else { + let mut buf = MaybeUninit::uninit(); + if unsafe { libc::statfs(narrow.as_ptr(), buf.as_mut_ptr()) } < 0 { + return DirRemoteness::Unknown; + } + let buf = unsafe { buf.assume_init() }; + // statfs::f_flags types differ. + #[allow(clippy::useless_conversion)] + let flags = buf.f_flags as u64; + #[allow(clippy::unnecessary_cast)] + if flags & (libc::MNT_LOCAL as u64) != 0 { + DirRemoteness::Local + } else { + DirRemoteness::Remote + } + } } } }