path: return Unknown for remoteness check on illumos

Part of #12410
This commit is contained in:
Liam Snow
2026-02-03 18:23:46 +00:00
committed by Johannes Altmanninger
parent dadec16661
commit 9750d8c3ad

View File

@@ -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<P: AsRef<std::path::Path>>(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
}
}
}
}
}