1//! Get filesystem statistics, non-portably 2//! 3//! See [`statvfs`](crate::sys::statvfs) for a portable alternative. 4#[cfg(not(any(target_os = "linux", target_os = "android")))] 5use std::ffi::CStr; 6use std::fmt::{self, Debug}; 7use std::mem; 8use std::os::unix::io::AsRawFd; 9 10use cfg_if::cfg_if; 11 12#[cfg(all( 13 feature = "mount", 14 any( 15 target_os = "dragonfly", 16 target_os = "freebsd", 17 target_os = "macos", 18 target_os = "netbsd", 19 target_os = "openbsd" 20 ) 21))] 22use crate::mount::MntFlags; 23#[cfg(target_os = "linux")] 24use crate::sys::statvfs::FsFlags; 25use crate::{errno::Errno, NixPath, Result}; 26 27/// Identifies a mounted file system 28#[cfg(target_os = "android")] 29#[cfg_attr(docsrs, doc(cfg(all())))] 30pub type fsid_t = libc::__fsid_t; 31/// Identifies a mounted file system 32#[cfg(not(target_os = "android"))] 33#[cfg_attr(docsrs, doc(cfg(all())))] 34pub type fsid_t = libc::fsid_t; 35 36cfg_if! { 37 if #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] { 38 type type_of_statfs = libc::statfs64; 39 const LIBC_FSTATFS: unsafe extern fn 40 (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int 41 = libc::fstatfs64; 42 const LIBC_STATFS: unsafe extern fn 43 (path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int 44 = libc::statfs64; 45 } else { 46 type type_of_statfs = libc::statfs; 47 const LIBC_FSTATFS: unsafe extern fn 48 (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int 49 = libc::fstatfs; 50 const LIBC_STATFS: unsafe extern fn 51 (path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int 52 = libc::statfs; 53 } 54} 55 56/// Describes a mounted file system 57#[derive(Clone, Copy)] 58#[repr(transparent)] 59pub struct Statfs(type_of_statfs); 60 61#[cfg(target_os = "freebsd")] 62type fs_type_t = u32; 63#[cfg(target_os = "android")] 64type fs_type_t = libc::c_ulong; 65#[cfg(all(target_os = "linux", target_arch = "s390x"))] 66type fs_type_t = libc::c_uint; 67#[cfg(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")))] 68type fs_type_t = libc::c_ulong; 69#[cfg(all(target_os = "linux", target_env = "uclibc"))] 70type fs_type_t = libc::c_int; 71#[cfg(all( 72 target_os = "linux", 73 not(any( 74 target_arch = "s390x", 75 target_env = "musl", 76 target_env = "ohos", 77 target_env = "uclibc" 78 )) 79))] 80type fs_type_t = libc::__fsword_t; 81 82/// Describes the file system type as known by the operating system. 83#[cfg(any( 84 target_os = "freebsd", 85 target_os = "android", 86 all(target_os = "linux", target_arch = "s390x"), 87 all(target_os = "linux", any(target_env = "musl", target_env = "ohos")), 88 all( 89 target_os = "linux", 90 not(any(target_arch = "s390x", target_env = "musl", target_env = "ohos")) 91 ), 92))] 93#[derive(Eq, Copy, Clone, PartialEq, Debug)] 94pub struct FsType(pub fs_type_t); 95 96// These constants are defined without documentation in the Linux headers, so we 97// can't very well document them here. 98#[cfg(any(target_os = "linux", target_os = "android"))] 99#[allow(missing_docs)] 100pub const ADFS_SUPER_MAGIC: FsType = 101 FsType(libc::ADFS_SUPER_MAGIC as fs_type_t); 102#[cfg(any(target_os = "linux", target_os = "android"))] 103#[allow(missing_docs)] 104pub const AFFS_SUPER_MAGIC: FsType = 105 FsType(libc::AFFS_SUPER_MAGIC as fs_type_t); 106#[cfg(any(target_os = "linux", target_os = "android"))] 107#[allow(missing_docs)] 108pub const AFS_SUPER_MAGIC: FsType = FsType(libc::AFS_SUPER_MAGIC as fs_type_t); 109#[cfg(any(target_os = "linux", target_os = "android"))] 110#[allow(missing_docs)] 111pub const AUTOFS_SUPER_MAGIC: FsType = 112 FsType(libc::AUTOFS_SUPER_MAGIC as fs_type_t); 113#[cfg(any(target_os = "linux", target_os = "android"))] 114#[allow(missing_docs)] 115pub const BPF_FS_MAGIC: FsType = FsType(libc::BPF_FS_MAGIC as fs_type_t); 116#[cfg(any(target_os = "linux", target_os = "android"))] 117#[allow(missing_docs)] 118pub const BTRFS_SUPER_MAGIC: FsType = 119 FsType(libc::BTRFS_SUPER_MAGIC as fs_type_t); 120#[cfg(any(target_os = "linux", target_os = "android"))] 121#[allow(missing_docs)] 122pub const CGROUP2_SUPER_MAGIC: FsType = 123 FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t); 124#[cfg(any(target_os = "linux", target_os = "android"))] 125#[allow(missing_docs)] 126pub const CGROUP_SUPER_MAGIC: FsType = 127 FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t); 128#[cfg(any(target_os = "linux", target_os = "android"))] 129#[allow(missing_docs)] 130pub const CODA_SUPER_MAGIC: FsType = 131 FsType(libc::CODA_SUPER_MAGIC as fs_type_t); 132#[cfg(any(target_os = "linux", target_os = "android"))] 133#[allow(missing_docs)] 134pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t); 135#[cfg(any(target_os = "linux", target_os = "android"))] 136#[allow(missing_docs)] 137pub const DEBUGFS_MAGIC: FsType = FsType(libc::DEBUGFS_MAGIC as fs_type_t); 138#[cfg(any(target_os = "linux", target_os = "android"))] 139#[allow(missing_docs)] 140pub const DEVPTS_SUPER_MAGIC: FsType = 141 FsType(libc::DEVPTS_SUPER_MAGIC as fs_type_t); 142#[cfg(any(target_os = "linux", target_os = "android"))] 143#[allow(missing_docs)] 144pub const ECRYPTFS_SUPER_MAGIC: FsType = 145 FsType(libc::ECRYPTFS_SUPER_MAGIC as fs_type_t); 146#[cfg(any(target_os = "linux", target_os = "android"))] 147#[allow(missing_docs)] 148pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t); 149#[cfg(any(target_os = "linux", target_os = "android"))] 150#[allow(missing_docs)] 151pub const EXT2_SUPER_MAGIC: FsType = 152 FsType(libc::EXT2_SUPER_MAGIC as fs_type_t); 153#[cfg(any(target_os = "linux", target_os = "android"))] 154#[allow(missing_docs)] 155pub const EXT3_SUPER_MAGIC: FsType = 156 FsType(libc::EXT3_SUPER_MAGIC as fs_type_t); 157#[cfg(any(target_os = "linux", target_os = "android"))] 158#[allow(missing_docs)] 159pub const EXT4_SUPER_MAGIC: FsType = 160 FsType(libc::EXT4_SUPER_MAGIC as fs_type_t); 161#[cfg(any(target_os = "linux", target_os = "android"))] 162#[allow(missing_docs)] 163pub const F2FS_SUPER_MAGIC: FsType = 164 FsType(libc::F2FS_SUPER_MAGIC as fs_type_t); 165#[cfg(any(target_os = "linux", target_os = "android"))] 166#[allow(missing_docs)] 167pub const FUSE_SUPER_MAGIC: FsType = 168 FsType(libc::FUSE_SUPER_MAGIC as fs_type_t); 169#[cfg(any(target_os = "linux", target_os = "android"))] 170#[allow(missing_docs)] 171pub const FUTEXFS_SUPER_MAGIC: FsType = 172 FsType(libc::FUTEXFS_SUPER_MAGIC as fs_type_t); 173#[cfg(any(target_os = "linux", target_os = "android"))] 174#[allow(missing_docs)] 175pub const HOSTFS_SUPER_MAGIC: FsType = 176 FsType(libc::HOSTFS_SUPER_MAGIC as fs_type_t); 177#[cfg(any(target_os = "linux", target_os = "android"))] 178#[allow(missing_docs)] 179pub const HPFS_SUPER_MAGIC: FsType = 180 FsType(libc::HPFS_SUPER_MAGIC as fs_type_t); 181#[cfg(any(target_os = "linux", target_os = "android"))] 182#[allow(missing_docs)] 183pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t); 184#[cfg(any(target_os = "linux", target_os = "android"))] 185#[allow(missing_docs)] 186pub const ISOFS_SUPER_MAGIC: FsType = 187 FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t); 188#[cfg(any(target_os = "linux", target_os = "android"))] 189#[allow(missing_docs)] 190pub const JFFS2_SUPER_MAGIC: FsType = 191 FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t); 192#[cfg(any(target_os = "linux", target_os = "android"))] 193#[allow(missing_docs)] 194pub const MINIX2_SUPER_MAGIC2: FsType = 195 FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t); 196#[cfg(any(target_os = "linux", target_os = "android"))] 197#[allow(missing_docs)] 198pub const MINIX2_SUPER_MAGIC: FsType = 199 FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t); 200#[cfg(any(target_os = "linux", target_os = "android"))] 201#[allow(missing_docs)] 202pub const MINIX3_SUPER_MAGIC: FsType = 203 FsType(libc::MINIX3_SUPER_MAGIC as fs_type_t); 204#[cfg(any(target_os = "linux", target_os = "android"))] 205#[allow(missing_docs)] 206pub const MINIX_SUPER_MAGIC2: FsType = 207 FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t); 208#[cfg(any(target_os = "linux", target_os = "android"))] 209#[allow(missing_docs)] 210pub const MINIX_SUPER_MAGIC: FsType = 211 FsType(libc::MINIX_SUPER_MAGIC as fs_type_t); 212#[cfg(any(target_os = "linux", target_os = "android"))] 213#[allow(missing_docs)] 214pub const MSDOS_SUPER_MAGIC: FsType = 215 FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t); 216#[cfg(any(target_os = "linux", target_os = "android"))] 217#[allow(missing_docs)] 218pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t); 219#[cfg(any(target_os = "linux", target_os = "android"))] 220#[allow(missing_docs)] 221pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t); 222#[cfg(any(target_os = "linux", target_os = "android"))] 223#[allow(missing_docs)] 224pub const NILFS_SUPER_MAGIC: FsType = 225 FsType(libc::NILFS_SUPER_MAGIC as fs_type_t); 226#[cfg(any(target_os = "linux", target_os = "android"))] 227#[allow(missing_docs)] 228pub const OCFS2_SUPER_MAGIC: FsType = 229 FsType(libc::OCFS2_SUPER_MAGIC as fs_type_t); 230#[cfg(any(target_os = "linux", target_os = "android"))] 231#[allow(missing_docs)] 232pub const OPENPROM_SUPER_MAGIC: FsType = 233 FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t); 234#[cfg(any(target_os = "linux", target_os = "android"))] 235#[allow(missing_docs)] 236pub const OVERLAYFS_SUPER_MAGIC: FsType = 237 FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t); 238#[cfg(any(target_os = "linux", target_os = "android"))] 239#[allow(missing_docs)] 240pub const PROC_SUPER_MAGIC: FsType = 241 FsType(libc::PROC_SUPER_MAGIC as fs_type_t); 242#[cfg(any(target_os = "linux", target_os = "android"))] 243#[allow(missing_docs)] 244pub const QNX4_SUPER_MAGIC: FsType = 245 FsType(libc::QNX4_SUPER_MAGIC as fs_type_t); 246#[cfg(any(target_os = "linux", target_os = "android"))] 247#[allow(missing_docs)] 248pub const QNX6_SUPER_MAGIC: FsType = 249 FsType(libc::QNX6_SUPER_MAGIC as fs_type_t); 250#[cfg(any(target_os = "linux", target_os = "android"))] 251#[allow(missing_docs)] 252pub const RDTGROUP_SUPER_MAGIC: FsType = 253 FsType(libc::RDTGROUP_SUPER_MAGIC as fs_type_t); 254#[cfg(any(target_os = "linux", target_os = "android"))] 255#[allow(missing_docs)] 256pub const REISERFS_SUPER_MAGIC: FsType = 257 FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t); 258#[cfg(any(target_os = "linux", target_os = "android"))] 259#[allow(missing_docs)] 260pub const SECURITYFS_MAGIC: FsType = 261 FsType(libc::SECURITYFS_MAGIC as fs_type_t); 262#[cfg(any(target_os = "linux", target_os = "android"))] 263#[allow(missing_docs)] 264pub const SELINUX_MAGIC: FsType = FsType(libc::SELINUX_MAGIC as fs_type_t); 265#[cfg(any(target_os = "linux", target_os = "android"))] 266#[allow(missing_docs)] 267pub const SMACK_MAGIC: FsType = FsType(libc::SMACK_MAGIC as fs_type_t); 268#[cfg(any(target_os = "linux", target_os = "android"))] 269#[allow(missing_docs)] 270pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t); 271#[cfg(any(target_os = "linux", target_os = "android"))] 272#[allow(missing_docs)] 273pub const SYSFS_MAGIC: FsType = FsType(libc::SYSFS_MAGIC as fs_type_t); 274#[cfg(any(target_os = "linux", target_os = "android"))] 275#[allow(missing_docs)] 276pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t); 277#[cfg(any(target_os = "linux", target_os = "android"))] 278#[allow(missing_docs)] 279pub const TRACEFS_MAGIC: FsType = FsType(libc::TRACEFS_MAGIC as fs_type_t); 280#[cfg(any(target_os = "linux", target_os = "android"))] 281#[allow(missing_docs)] 282pub const UDF_SUPER_MAGIC: FsType = FsType(libc::UDF_SUPER_MAGIC as fs_type_t); 283#[cfg(any(target_os = "linux", target_os = "android"))] 284#[allow(missing_docs)] 285pub const USBDEVICE_SUPER_MAGIC: FsType = 286 FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t); 287#[cfg(any(target_os = "linux", target_os = "android"))] 288#[allow(missing_docs)] 289pub const XENFS_SUPER_MAGIC: FsType = 290 FsType(libc::XENFS_SUPER_MAGIC as fs_type_t); 291#[cfg(any(target_os = "linux", target_os = "android"))] 292#[allow(missing_docs)] 293pub const NSFS_MAGIC: FsType = FsType(libc::NSFS_MAGIC as fs_type_t); 294#[cfg(all( 295 any(target_os = "linux", target_os = "android"), 296 not(any(target_env = "musl", target_env = "ohos")) 297))] 298#[allow(missing_docs)] 299pub const XFS_SUPER_MAGIC: FsType = FsType(libc::XFS_SUPER_MAGIC as fs_type_t); 300 301impl Statfs { 302 /// Magic code defining system type 303 #[cfg(not(any( 304 target_os = "openbsd", 305 target_os = "dragonfly", 306 target_os = "ios", 307 target_os = "macos" 308 )))] 309 #[cfg_attr(docsrs, doc(cfg(all())))] 310 pub fn filesystem_type(&self) -> FsType { 311 FsType(self.0.f_type) 312 } 313 314 /// Magic code defining system type 315 #[cfg(not(any(target_os = "linux", target_os = "android")))] 316 #[cfg_attr(docsrs, doc(cfg(all())))] 317 pub fn filesystem_type_name(&self) -> &str { 318 let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) }; 319 c_str.to_str().unwrap() 320 } 321 322 /// Optimal transfer block size 323 #[cfg(any(target_os = "ios", target_os = "macos"))] 324 #[cfg_attr(docsrs, doc(cfg(all())))] 325 pub fn optimal_transfer_size(&self) -> i32 { 326 self.0.f_iosize 327 } 328 329 /// Optimal transfer block size 330 #[cfg(target_os = "openbsd")] 331 #[cfg_attr(docsrs, doc(cfg(all())))] 332 pub fn optimal_transfer_size(&self) -> u32 { 333 self.0.f_iosize 334 } 335 336 /// Optimal transfer block size 337 #[cfg(all(target_os = "linux", target_arch = "s390x"))] 338 #[cfg_attr(docsrs, doc(cfg(all())))] 339 pub fn optimal_transfer_size(&self) -> u32 { 340 self.0.f_bsize 341 } 342 343 /// Optimal transfer block size 344 #[cfg(any( 345 target_os = "android", 346 all(target_os = "linux", any(target_env = "musl", target_env = "ohos")) 347 ))] 348 #[cfg_attr(docsrs, doc(cfg(all())))] 349 pub fn optimal_transfer_size(&self) -> libc::c_ulong { 350 self.0.f_bsize 351 } 352 353 /// Optimal transfer block size 354 #[cfg(all( 355 target_os = "linux", 356 not(any( 357 target_arch = "s390x", 358 target_env = "musl", 359 target_env = "ohos", 360 target_env = "uclibc" 361 )) 362 ))] 363 #[cfg_attr(docsrs, doc(cfg(all())))] 364 pub fn optimal_transfer_size(&self) -> libc::__fsword_t { 365 self.0.f_bsize 366 } 367 368 /// Optimal transfer block size 369 #[cfg(all(target_os = "linux", target_env = "uclibc"))] 370 #[cfg_attr(docsrs, doc(cfg(all())))] 371 pub fn optimal_transfer_size(&self) -> libc::c_int { 372 self.0.f_bsize 373 } 374 375 /// Optimal transfer block size 376 #[cfg(target_os = "dragonfly")] 377 #[cfg_attr(docsrs, doc(cfg(all())))] 378 pub fn optimal_transfer_size(&self) -> libc::c_long { 379 self.0.f_iosize 380 } 381 382 /// Optimal transfer block size 383 #[cfg(target_os = "freebsd")] 384 #[cfg_attr(docsrs, doc(cfg(all())))] 385 pub fn optimal_transfer_size(&self) -> u64 { 386 self.0.f_iosize 387 } 388 389 /// Size of a block 390 #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))] 391 #[cfg_attr(docsrs, doc(cfg(all())))] 392 pub fn block_size(&self) -> u32 { 393 self.0.f_bsize 394 } 395 396 /// Size of a block 397 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 398 #[cfg(all(target_os = "linux", target_arch = "s390x"))] 399 #[cfg_attr(docsrs, doc(cfg(all())))] 400 pub fn block_size(&self) -> u32 { 401 self.0.f_bsize 402 } 403 404 /// Size of a block 405 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 406 #[cfg(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")))] 407 #[cfg_attr(docsrs, doc(cfg(all())))] 408 pub fn block_size(&self) -> libc::c_ulong { 409 self.0.f_bsize 410 } 411 412 /// Size of a block 413 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 414 #[cfg(all(target_os = "linux", target_env = "uclibc"))] 415 #[cfg_attr(docsrs, doc(cfg(all())))] 416 pub fn block_size(&self) -> libc::c_int { 417 self.0.f_bsize 418 } 419 420 /// Size of a block 421 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 422 #[cfg(all( 423 target_os = "linux", 424 not(any( 425 target_arch = "s390x", 426 target_env = "musl", 427 target_env = "ohos", 428 target_env = "uclibc" 429 )) 430 ))] 431 #[cfg_attr(docsrs, doc(cfg(all())))] 432 pub fn block_size(&self) -> libc::__fsword_t { 433 self.0.f_bsize 434 } 435 436 /// Size of a block 437 #[cfg(target_os = "freebsd")] 438 #[cfg_attr(docsrs, doc(cfg(all())))] 439 pub fn block_size(&self) -> u64 { 440 self.0.f_bsize 441 } 442 443 /// Size of a block 444 #[cfg(target_os = "android")] 445 #[cfg_attr(docsrs, doc(cfg(all())))] 446 pub fn block_size(&self) -> libc::c_ulong { 447 self.0.f_bsize 448 } 449 450 /// Size of a block 451 #[cfg(target_os = "dragonfly")] 452 #[cfg_attr(docsrs, doc(cfg(all())))] 453 pub fn block_size(&self) -> libc::c_long { 454 self.0.f_bsize 455 } 456 457 /// Get the mount flags 458 #[cfg(all( 459 feature = "mount", 460 any( 461 target_os = "dragonfly", 462 target_os = "freebsd", 463 target_os = "macos", 464 target_os = "netbsd", 465 target_os = "openbsd" 466 ) 467 ))] 468 #[cfg_attr(docsrs, doc(cfg(all())))] 469 #[allow(clippy::unnecessary_cast)] // Not unnecessary on all arches 470 pub fn flags(&self) -> MntFlags { 471 MntFlags::from_bits_truncate(self.0.f_flags as i32) 472 } 473 474 /// Get the mount flags 475 // The f_flags field exists on Android and Fuchsia too, but without man 476 // pages I can't tell if it can be cast to FsFlags. 477 #[cfg(target_os = "linux")] 478 #[cfg_attr(docsrs, doc(cfg(all())))] 479 pub fn flags(&self) -> FsFlags { 480 FsFlags::from_bits_truncate(self.0.f_flags as libc::c_ulong) 481 } 482 483 /// Maximum length of filenames 484 #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] 485 #[cfg_attr(docsrs, doc(cfg(all())))] 486 pub fn maximum_name_length(&self) -> u32 { 487 self.0.f_namemax 488 } 489 490 /// Maximum length of filenames 491 #[cfg(all(target_os = "linux", target_arch = "s390x"))] 492 #[cfg_attr(docsrs, doc(cfg(all())))] 493 pub fn maximum_name_length(&self) -> u32 { 494 self.0.f_namelen 495 } 496 497 /// Maximum length of filenames 498 #[cfg(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")))] 499 #[cfg_attr(docsrs, doc(cfg(all())))] 500 pub fn maximum_name_length(&self) -> libc::c_ulong { 501 self.0.f_namelen 502 } 503 504 /// Maximum length of filenames 505 #[cfg(all(target_os = "linux", target_env = "uclibc"))] 506 #[cfg_attr(docsrs, doc(cfg(all())))] 507 pub fn maximum_name_length(&self) -> libc::c_int { 508 self.0.f_namelen 509 } 510 511 /// Maximum length of filenames 512 #[cfg(all( 513 target_os = "linux", 514 not(any( 515 target_arch = "s390x", 516 target_env = "musl", 517 target_env = "ohos", 518 target_env = "uclibc" 519 )) 520 ))] 521 #[cfg_attr(docsrs, doc(cfg(all())))] 522 pub fn maximum_name_length(&self) -> libc::__fsword_t { 523 self.0.f_namelen 524 } 525 526 /// Maximum length of filenames 527 #[cfg(target_os = "android")] 528 #[cfg_attr(docsrs, doc(cfg(all())))] 529 pub fn maximum_name_length(&self) -> libc::c_ulong { 530 self.0.f_namelen 531 } 532 533 /// Total data blocks in filesystem 534 #[cfg(any( 535 target_os = "ios", 536 target_os = "macos", 537 target_os = "android", 538 target_os = "freebsd", 539 target_os = "fuchsia", 540 target_os = "openbsd", 541 target_os = "linux", 542 ))] 543 #[cfg_attr(docsrs, doc(cfg(all())))] 544 pub fn blocks(&self) -> u64 { 545 self.0.f_blocks 546 } 547 548 /// Total data blocks in filesystem 549 #[cfg(target_os = "dragonfly")] 550 #[cfg_attr(docsrs, doc(cfg(all())))] 551 pub fn blocks(&self) -> libc::c_long { 552 self.0.f_blocks 553 } 554 555 /// Total data blocks in filesystem 556 #[cfg(target_os = "emscripten")] 557 #[cfg_attr(docsrs, doc(cfg(all())))] 558 pub fn blocks(&self) -> u32 { 559 self.0.f_blocks 560 } 561 562 /// Free blocks in filesystem 563 #[cfg(any( 564 target_os = "ios", 565 target_os = "macos", 566 target_os = "android", 567 target_os = "freebsd", 568 target_os = "fuchsia", 569 target_os = "openbsd", 570 target_os = "linux", 571 ))] 572 #[cfg_attr(docsrs, doc(cfg(all())))] 573 pub fn blocks_free(&self) -> u64 { 574 self.0.f_bfree 575 } 576 577 /// Free blocks in filesystem 578 #[cfg(target_os = "dragonfly")] 579 #[cfg_attr(docsrs, doc(cfg(all())))] 580 pub fn blocks_free(&self) -> libc::c_long { 581 self.0.f_bfree 582 } 583 584 /// Free blocks in filesystem 585 #[cfg(target_os = "emscripten")] 586 #[cfg_attr(docsrs, doc(cfg(all())))] 587 pub fn blocks_free(&self) -> u32 { 588 self.0.f_bfree 589 } 590 591 /// Free blocks available to unprivileged user 592 #[cfg(any( 593 target_os = "ios", 594 target_os = "macos", 595 target_os = "android", 596 target_os = "fuchsia", 597 target_os = "linux", 598 ))] 599 #[cfg_attr(docsrs, doc(cfg(all())))] 600 pub fn blocks_available(&self) -> u64 { 601 self.0.f_bavail 602 } 603 604 /// Free blocks available to unprivileged user 605 #[cfg(target_os = "dragonfly")] 606 #[cfg_attr(docsrs, doc(cfg(all())))] 607 pub fn blocks_available(&self) -> libc::c_long { 608 self.0.f_bavail 609 } 610 611 /// Free blocks available to unprivileged user 612 #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] 613 #[cfg_attr(docsrs, doc(cfg(all())))] 614 pub fn blocks_available(&self) -> i64 { 615 self.0.f_bavail 616 } 617 618 /// Free blocks available to unprivileged user 619 #[cfg(target_os = "emscripten")] 620 #[cfg_attr(docsrs, doc(cfg(all())))] 621 pub fn blocks_available(&self) -> u32 { 622 self.0.f_bavail 623 } 624 625 /// Total file nodes in filesystem 626 #[cfg(any( 627 target_os = "ios", 628 target_os = "macos", 629 target_os = "android", 630 target_os = "freebsd", 631 target_os = "fuchsia", 632 target_os = "openbsd", 633 target_os = "linux", 634 ))] 635 #[cfg_attr(docsrs, doc(cfg(all())))] 636 pub fn files(&self) -> u64 { 637 self.0.f_files 638 } 639 640 /// Total file nodes in filesystem 641 #[cfg(target_os = "dragonfly")] 642 #[cfg_attr(docsrs, doc(cfg(all())))] 643 pub fn files(&self) -> libc::c_long { 644 self.0.f_files 645 } 646 647 /// Total file nodes in filesystem 648 #[cfg(target_os = "emscripten")] 649 #[cfg_attr(docsrs, doc(cfg(all())))] 650 pub fn files(&self) -> u32 { 651 self.0.f_files 652 } 653 654 /// Free file nodes in filesystem 655 #[cfg(any( 656 target_os = "ios", 657 target_os = "macos", 658 target_os = "android", 659 target_os = "fuchsia", 660 target_os = "openbsd", 661 target_os = "linux", 662 ))] 663 #[cfg_attr(docsrs, doc(cfg(all())))] 664 pub fn files_free(&self) -> u64 { 665 self.0.f_ffree 666 } 667 668 /// Free file nodes in filesystem 669 #[cfg(target_os = "dragonfly")] 670 #[cfg_attr(docsrs, doc(cfg(all())))] 671 pub fn files_free(&self) -> libc::c_long { 672 self.0.f_ffree 673 } 674 675 /// Free file nodes in filesystem 676 #[cfg(target_os = "freebsd")] 677 #[cfg_attr(docsrs, doc(cfg(all())))] 678 pub fn files_free(&self) -> i64 { 679 self.0.f_ffree 680 } 681 682 /// Free file nodes in filesystem 683 #[cfg(target_os = "emscripten")] 684 #[cfg_attr(docsrs, doc(cfg(all())))] 685 pub fn files_free(&self) -> u32 { 686 self.0.f_ffree 687 } 688 689 /// Filesystem ID 690 pub fn filesystem_id(&self) -> fsid_t { 691 self.0.f_fsid 692 } 693} 694 695impl Debug for Statfs { 696 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 697 let mut ds = f.debug_struct("Statfs"); 698 ds.field("optimal_transfer_size", &self.optimal_transfer_size()); 699 ds.field("block_size", &self.block_size()); 700 ds.field("blocks", &self.blocks()); 701 ds.field("blocks_free", &self.blocks_free()); 702 ds.field("blocks_available", &self.blocks_available()); 703 ds.field("files", &self.files()); 704 ds.field("files_free", &self.files_free()); 705 ds.field("filesystem_id", &self.filesystem_id()); 706 #[cfg(all( 707 feature = "mount", 708 any( 709 target_os = "dragonfly", 710 target_os = "freebsd", 711 target_os = "macos", 712 target_os = "netbsd", 713 target_os = "openbsd" 714 ) 715 ))] 716 ds.field("flags", &self.flags()); 717 ds.finish() 718 } 719} 720 721/// Describes a mounted file system. 722/// 723/// The result is OS-dependent. For a portable alternative, see 724/// [`statvfs`](crate::sys::statvfs::statvfs). 725/// 726/// # Arguments 727/// 728/// `path` - Path to any file within the file system to describe 729pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> { 730 unsafe { 731 let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit(); 732 let res = path.with_nix_path(|path| { 733 LIBC_STATFS(path.as_ptr(), stat.as_mut_ptr()) 734 })?; 735 Errno::result(res).map(|_| Statfs(stat.assume_init())) 736 } 737} 738 739/// Describes a mounted file system. 740/// 741/// The result is OS-dependent. For a portable alternative, see 742/// [`fstatvfs`](crate::sys::statvfs::fstatvfs). 743/// 744/// # Arguments 745/// 746/// `fd` - File descriptor of any open file within the file system to describe 747pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> { 748 unsafe { 749 let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit(); 750 Errno::result(LIBC_FSTATFS(fd.as_raw_fd(), stat.as_mut_ptr())) 751 .map(|_| Statfs(stat.assume_init())) 752 } 753} 754 755#[cfg(test)] 756mod test { 757 use std::fs::File; 758 759 use crate::sys::statfs::*; 760 use crate::sys::statvfs::*; 761 use std::path::Path; 762 763 #[test] 764 fn statfs_call() { 765 check_statfs("/tmp"); 766 check_statfs("/dev"); 767 check_statfs("/run"); 768 check_statfs("/"); 769 } 770 771 #[test] 772 fn fstatfs_call() { 773 check_fstatfs("/tmp"); 774 check_fstatfs("/dev"); 775 check_fstatfs("/run"); 776 check_fstatfs("/"); 777 } 778 779 fn check_fstatfs(path: &str) { 780 if !Path::new(path).exists() { 781 return; 782 } 783 let vfs = statvfs(path.as_bytes()).unwrap(); 784 let file = File::open(path).unwrap(); 785 let fs = fstatfs(&file).unwrap(); 786 assert_fs_equals(fs, vfs); 787 } 788 789 fn check_statfs(path: &str) { 790 if !Path::new(path).exists() { 791 return; 792 } 793 let vfs = statvfs(path.as_bytes()).unwrap(); 794 let fs = statfs(path.as_bytes()).unwrap(); 795 assert_fs_equals(fs, vfs); 796 } 797 798 // The cast is not unnecessary on all platforms. 799 #[allow(clippy::unnecessary_cast)] 800 fn assert_fs_equals(fs: Statfs, vfs: Statvfs) { 801 assert_eq!(fs.files() as u64, vfs.files() as u64); 802 assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); 803 assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); 804 } 805 806 // This test is ignored because files_free/blocks_free can change after statvfs call and before 807 // statfs call. 808 #[test] 809 #[ignore] 810 fn statfs_call_strict() { 811 check_statfs_strict("/tmp"); 812 check_statfs_strict("/dev"); 813 check_statfs_strict("/run"); 814 check_statfs_strict("/"); 815 } 816 817 // This test is ignored because files_free/blocks_free can change after statvfs call and before 818 // fstatfs call. 819 #[test] 820 #[ignore] 821 fn fstatfs_call_strict() { 822 check_fstatfs_strict("/tmp"); 823 check_fstatfs_strict("/dev"); 824 check_fstatfs_strict("/run"); 825 check_fstatfs_strict("/"); 826 } 827 828 fn check_fstatfs_strict(path: &str) { 829 if !Path::new(path).exists() { 830 return; 831 } 832 let vfs = statvfs(path.as_bytes()); 833 let file = File::open(path).unwrap(); 834 let fs = fstatfs(&file); 835 assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) 836 } 837 838 fn check_statfs_strict(path: &str) { 839 if !Path::new(path).exists() { 840 return; 841 } 842 let vfs = statvfs(path.as_bytes()); 843 let fs = statfs(path.as_bytes()); 844 assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) 845 } 846 847 // The cast is not unnecessary on all platforms. 848 #[allow(clippy::unnecessary_cast)] 849 fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) { 850 assert_eq!(fs.files_free() as u64, vfs.files_free() as u64); 851 assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64); 852 assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64); 853 assert_eq!(fs.files() as u64, vfs.files() as u64); 854 assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); 855 assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); 856 } 857} 858