use {
std::{
env,
path::{Path, PathBuf},
},
crate::Sealed,
};
#[cfg(unix)]
#[cfg(feature="libc")]
use {
core::{
ffi::CStr,
mem,
},
alloc::ffi::CString,
std::{
io::Error,
os::unix::prelude::OsStrExt,
},
crate::{FileSystem, Result},
};
pub trait PathExt: Sealed {
fn shorten<P>(&self, base: P) -> &Path where P: AsRef<Path>;
fn shorten_here(&self) -> &Path;
#[cfg(all(feature="libc", unix))]
#[doc(cfg(all(feature="libc", unix)))]
fn file_system(&self) -> Result<FileSystem>;
}
macro_rules! impl_path_ext { ($($ty: ty),+$(,)?) => {
$(
impl Sealed for $ty {}
impl PathExt for $ty {
fn shorten<P>(&self, base: P) -> &Path where P: AsRef<Path> {
self.strip_prefix(base).unwrap_or(self)
}
fn shorten_here(&self) -> &Path {
env::current_dir().map(|d| self.shorten(d)).unwrap_or(self)
}
#[cfg(all(feature="libc", unix))]
#[doc(cfg(all(feature="libc", unix)))]
fn file_system(&self) -> Result<FileSystem> {
file_system(self)
}
}
)+
}}
impl_path_ext!(&Path, PathBuf);
#[cfg(all(feature="libc", unix))]
#[doc(cfg(all(feature="libc", unix)))]
fn file_system(path: &Path) -> Result<FileSystem> {
match unsafe {
let mut statfs = mem::zeroed::<libc::statfs>();
match libc::statfs(CString::new(path.as_os_str().as_bytes())?.as_ptr(), &mut statfs) {
0 => statfs.f_type,
_ => return Err(fmt_err_code("statfs")),
}
} {
libc::ADFS_SUPER_MAGIC => Ok(FileSystem::ADFSSuper),
libc::AFFS_SUPER_MAGIC => Ok(FileSystem::AFFSSuper),
libc::AFS_SUPER_MAGIC => Ok(FileSystem::AFSSuper),
libc::AUTOFS_SUPER_MAGIC => Ok(FileSystem::AutoFSSuper),
libc::BPF_FS_MAGIC => Ok(FileSystem::BpfFS),
libc::BTRFS_SUPER_MAGIC => Ok(FileSystem::BtrFSSuper),
libc::CGROUP_SUPER_MAGIC => Ok(FileSystem::CgroupSuper),
libc::CGROUP2_SUPER_MAGIC => Ok(FileSystem::Cgroup2Super),
libc::CODA_SUPER_MAGIC => Ok(FileSystem::CodaSuper),
libc::CRAMFS_MAGIC => Ok(FileSystem::CramFS),
libc::DEBUGFS_MAGIC => Ok(FileSystem::DebugFS),
libc::DEVPTS_SUPER_MAGIC => Ok(FileSystem::DevPtsSuper),
libc::ECRYPTFS_SUPER_MAGIC => Ok(FileSystem::EcryptFSSuper),
libc::EFS_SUPER_MAGIC => Ok(FileSystem::EFSSuper),
libc::EXT4_SUPER_MAGIC => Ok(FileSystem::Ext234Super),
libc::F2FS_SUPER_MAGIC => Ok(FileSystem::F2FSSuper),
libc::FUSE_SUPER_MAGIC => Ok(FileSystem::FuseSuper),
libc::FUTEXFS_SUPER_MAGIC => Ok(FileSystem::FutexFSSuper),
libc::HOSTFS_SUPER_MAGIC => Ok(FileSystem::HostFSSuper),
libc::HPFS_SUPER_MAGIC => Ok(FileSystem::HPFSSuper),
libc::HUGETLBFS_MAGIC => Ok(FileSystem::HugeTLBFS),
libc::ISOFS_SUPER_MAGIC => Ok(FileSystem::IsoFSSuper),
libc::JFFS2_SUPER_MAGIC => Ok(FileSystem::JFFS2Super),
libc::MINIX_SUPER_MAGIC => Ok(FileSystem::MINIXSuper),
libc::MINIX_SUPER_MAGIC2 => Ok(FileSystem::MINIXSuper2),
libc::MINIX2_SUPER_MAGIC => Ok(FileSystem::MINIX2Super),
libc::MINIX2_SUPER_MAGIC2 => Ok(FileSystem::MINIX2Super2),
libc::MINIX3_SUPER_MAGIC => Ok(FileSystem::MINIX3Super),
libc::MSDOS_SUPER_MAGIC => Ok(FileSystem::MSDOSSuper),
libc::NCP_SUPER_MAGIC => Ok(FileSystem::NCPSuper),
libc::NFS_SUPER_MAGIC => Ok(FileSystem::NFSSuper),
libc::NILFS_SUPER_MAGIC => Ok(FileSystem::NILFSSuper),
libc::NSFS_MAGIC => Ok(FileSystem::NSFS),
libc::OCFS2_SUPER_MAGIC => Ok(FileSystem::OCFS2Super),
libc::OPENPROM_SUPER_MAGIC => Ok(FileSystem::OpenPROMSuper),
libc::OVERLAYFS_SUPER_MAGIC => Ok(FileSystem::OverlayFSSuper),
libc::PROC_SUPER_MAGIC => Ok(FileSystem::ProcSuper),
libc::QNX4_SUPER_MAGIC => Ok(FileSystem::QNX4Super),
libc::QNX6_SUPER_MAGIC => Ok(FileSystem::QNX6Super),
libc::REISERFS_SUPER_MAGIC => Ok(FileSystem::ReiserFSSuper),
libc::SECURITYFS_MAGIC => Ok(FileSystem::SecurityFS),
libc::SELINUX_MAGIC => Ok(FileSystem::SELinux),
libc::SMACK_MAGIC => Ok(FileSystem::Smack),
libc::SMB_SUPER_MAGIC => Ok(FileSystem::SMBSuper),
libc::SYSFS_MAGIC => Ok(FileSystem::SysFS),
libc::TMPFS_MAGIC => Ok(FileSystem::TmpFS),
libc::TRACEFS_MAGIC => Ok(FileSystem::TraceFS),
libc::UDF_SUPER_MAGIC => Ok(FileSystem::UDFSuper),
libc::USBDEVICE_SUPER_MAGIC => Ok(FileSystem::USBDeviceSuper),
libc::XENFS_SUPER_MAGIC => Ok(FileSystem::XENFSSuper),
libc::XFS_SUPER_MAGIC => Ok(FileSystem::XFSSuper),
_ => Ok(FileSystem::Unknown),
}
}
#[cfg(feature="libc")]
#[doc(cfg(feature="libc"))]
fn fmt_err_code<S>(fn_name: S) -> Error where S: AsRef<str> {
let err_code = unsafe {
*libc::__errno_location()
};
err!(
"libc::{fn_name}() failed: {err_code}: {err:?}",
fn_name=fn_name.as_ref(),
err=unsafe { CStr::from_ptr(libc::strerror(err_code)) },
)
}