Skip to main content

nix/sys/
statfs.rs

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