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