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