use std::path::Path;
pub fn is_network_filesystem(path: &Path) -> bool {
#[cfg(target_os = "macos")]
{
use std::ffi::CStr;
use std::os::unix::ffi::OsStrExt;
let probe = nearest_existing(path);
let Ok(c) = std::ffi::CString::new(probe.as_os_str().as_bytes()) else {
return false;
};
let mut st: libc::statfs = unsafe { std::mem::zeroed() };
if unsafe { libc::statfs(c.as_ptr(), &mut st) } != 0 {
return false;
}
let name = unsafe { CStr::from_ptr(st.f_fstypename.as_ptr()) }
.to_string_lossy()
.to_ascii_lowercase();
matches!(
name.as_str(),
"nfs" | "smbfs" | "afpfs" | "webdav" | "cifs" | "ftp" | "osxfusefs" | "macfuse"
)
}
#[cfg(all(unix, not(target_os = "macos")))]
{
use std::os::unix::ffi::OsStrExt;
let probe = nearest_existing(path);
let Ok(c) = std::ffi::CString::new(probe.as_os_str().as_bytes()) else {
return false;
};
let mut st: libc::statfs = unsafe { std::mem::zeroed() };
if unsafe { libc::statfs(c.as_ptr(), &mut st) } != 0 {
return false;
}
const NFS: i64 = 0x6969;
const SMB: i64 = 0x517B;
const CIFS: i64 = 0xFF53_4D42;
const SMB2: i64 = 0xFE53_4D42;
const AFS: i64 = 0x5346_414F;
const CEPH: i64 = 0x00C3_6400;
matches!(st.f_type as i64, NFS | SMB | CIFS | SMB2 | AFS | CEPH)
}
#[cfg(windows)]
{
let text = path.to_string_lossy();
text.starts_with(r"\\") && !text.starts_with(r"\\?\") && !text.starts_with(r"\\.\")
|| text.to_ascii_lowercase().contains("\\onedrive")
}
#[cfg(not(any(unix, windows)))]
{
let _ = path;
false
}
}
#[cfg(unix)]
fn nearest_existing(path: &Path) -> std::path::PathBuf {
path.ancestors()
.find(|p| !p.as_os_str().is_empty() && p.exists())
.map(Path::to_path_buf)
.unwrap_or_else(|| std::path::PathBuf::from("."))
}