use std::path::Path;
pub fn is_network_fs(path: &Path) -> bool {
imp::is_network_fs(path)
}
#[cfg(any(
target_os = "macos",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly",
))]
mod imp {
use std::ffi::CString;
use std::mem::MaybeUninit;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
const NETWORK_FS_NAMES: &[&[u8]] = &[
b"nfs", b"smbfs", b"cifs", b"afpfs", b"webdav", b"ftp",
b"fuse", b"fusefs", b"osxfuse", b"macfuse", ];
pub fn is_network_fs(path: &Path) -> bool {
let Ok(c_path) = CString::new(path.as_os_str().as_bytes()) else {
return false;
};
let mut buf: MaybeUninit<libc::statfs> = MaybeUninit::uninit();
let rc = unsafe { libc::statfs(c_path.as_ptr(), buf.as_mut_ptr()) };
if rc != 0 {
return false;
}
let buf = unsafe { buf.assume_init() };
let bytes: &[u8] = unsafe {
std::slice::from_raw_parts(
buf.f_fstypename.as_ptr().cast::<u8>(),
buf.f_fstypename.len(),
)
};
let nul = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
let fs_name = &bytes[..nul];
NETWORK_FS_NAMES.contains(&fs_name)
}
}
#[cfg(target_os = "linux")]
mod imp {
use std::ffi::CString;
use std::mem::MaybeUninit;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
const NFS_SUPER_MAGIC: i64 = 0x6969;
const CIFS_MAGIC_NUMBER: i64 = 0xff53_4d42;
const SMB_SUPER_MAGIC: i64 = 0x517B;
const SMB2_MAGIC_NUMBER: i64 = 0xfe53_4d42;
const AFS_SUPER_MAGIC: i64 = 0x5346_414f;
const CODA_SUPER_MAGIC: i64 = 0x7375_7245;
const NCP_SUPER_MAGIC: i64 = 0x564c;
const FUSE_SUPER_MAGIC: i64 = 0x6573_5546;
const V9FS_MAGIC: i64 = 0x0102_1997;
const NETWORK_FS_MAGICS: &[i64] = &[
NFS_SUPER_MAGIC,
CIFS_MAGIC_NUMBER,
SMB_SUPER_MAGIC,
SMB2_MAGIC_NUMBER,
AFS_SUPER_MAGIC,
CODA_SUPER_MAGIC,
NCP_SUPER_MAGIC,
FUSE_SUPER_MAGIC,
V9FS_MAGIC,
];
pub fn is_network_fs(path: &Path) -> bool {
let Ok(c_path) = CString::new(path.as_os_str().as_bytes()) else {
return false;
};
let mut buf: MaybeUninit<libc::statfs> = MaybeUninit::uninit();
let rc = unsafe { libc::statfs(c_path.as_ptr(), buf.as_mut_ptr()) };
if rc != 0 {
return false;
}
let buf = unsafe { buf.assume_init() };
let f_type: i64 = buf.f_type.into();
NETWORK_FS_MAGICS.contains(&f_type)
}
}
#[cfg(not(any(
target_os = "macos",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly",
target_os = "linux",
)))]
mod imp {
use std::path::Path;
pub fn is_network_fs(_path: &Path) -> bool {
false
}
}