1 use std::fmt::{self, Debug};
2 use std::mem;
3 use std::os::unix::io::AsRawFd;
4 #[cfg(not(any(target_os = "linux", target_os = "android")))]
5 use std::ffi::CStr;
6 
7 use crate::{NixPath, Result, errno::Errno};
8 
9 #[cfg(target_os = "android")]
10 pub type fsid_t = libc::__fsid_t;
11 #[cfg(not(target_os = "android"))]
12 pub type fsid_t = libc::fsid_t;
13 
14 #[derive(Clone, Copy)]
15 #[repr(transparent)]
16 pub struct Statfs(libc::statfs);
17 
18 #[cfg(target_os = "freebsd")]
19 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
20 pub struct FsType(pub u32);
21 #[cfg(target_os = "android")]
22 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
23 pub struct FsType(pub libc::c_ulong);
24 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
25 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
26 pub struct FsType(pub u32);
27 #[cfg(all(target_os = "linux", target_env = "musl"))]
28 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
29 pub struct FsType(pub libc::c_ulong);
30 #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
31 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
32 pub struct FsType(pub libc::c_long);
33 
34 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
35 pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC);
36 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
37 pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC);
38 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
39 pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC);
40 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
41 pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC);
42 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
43 pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC);
44 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
45 pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC);
46 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
47 pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC);
48 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
49 pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC);
50 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
51 pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC);
52 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
53 pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC);
54 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
55 pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC);
56 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
57 pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC);
58 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
59 pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC);
60 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
61 pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2);
62 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
63 pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC);
64 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
65 pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2);
66 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
67 pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC);
68 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
69 pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC);
70 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
71 pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC);
72 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
73 pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC);
74 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
75 pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC);
76 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
77 pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC);
78 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
79 pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC);
80 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
81 pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC);
82 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
83 pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC);
84 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
85 pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC);
86 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
87 pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC);
88 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
89 pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC);
90 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
91 pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC);
92 
93 impl Statfs {
94     /// Magic code defining system type
95     #[cfg(not(any(
96         target_os = "openbsd",
97         target_os = "dragonfly",
98         target_os = "ios",
99         target_os = "macos"
100     )))]
filesystem_type(&self) -> FsType101     pub fn filesystem_type(&self) -> FsType {
102         FsType(self.0.f_type)
103     }
104 
105     /// Magic code defining system type
106     #[cfg(not(any(target_os = "linux", target_os = "android")))]
filesystem_type_name(&self) -> &str107     pub fn filesystem_type_name(&self) -> &str {
108         let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
109         c_str.to_str().unwrap()
110     }
111 
112     /// Optimal transfer block size
113     #[cfg(any(target_os = "ios", target_os = "macos"))]
optimal_transfer_size(&self) -> i32114     pub fn optimal_transfer_size(&self) -> i32 {
115         self.0.f_iosize
116     }
117 
118     /// Optimal transfer block size
119     #[cfg(target_os = "openbsd")]
optimal_transfer_size(&self) -> u32120     pub fn optimal_transfer_size(&self) -> u32 {
121         self.0.f_iosize
122     }
123 
124     /// Optimal transfer block size
125     #[cfg(all(target_os = "linux", target_arch = "s390x"))]
optimal_transfer_size(&self) -> u32126     pub fn optimal_transfer_size(&self) -> u32 {
127         self.0.f_bsize
128     }
129 
130     /// Optimal transfer block size
131     #[cfg(any(
132         target_os = "android",
133         all(target_os = "linux", target_env = "musl")
134     ))]
optimal_transfer_size(&self) -> libc::c_ulong135     pub fn optimal_transfer_size(&self) -> libc::c_ulong {
136         self.0.f_bsize
137     }
138 
139     /// Optimal transfer block size
140     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
optimal_transfer_size(&self) -> libc::c_long141     pub fn optimal_transfer_size(&self) -> libc::c_long {
142         self.0.f_bsize
143     }
144 
145     /// Optimal transfer block size
146     #[cfg(target_os = "dragonfly")]
optimal_transfer_size(&self) -> libc::c_long147     pub fn optimal_transfer_size(&self) -> libc::c_long {
148         self.0.f_iosize
149     }
150 
151     /// Optimal transfer block size
152     #[cfg(target_os = "freebsd")]
optimal_transfer_size(&self) -> u64153     pub fn optimal_transfer_size(&self) -> u64 {
154         self.0.f_iosize
155     }
156 
157     /// Size of a block
158     #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
block_size(&self) -> u32159     pub fn block_size(&self) -> u32 {
160         self.0.f_bsize
161     }
162 
163     /// Size of a block
164     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
165     #[cfg(all(target_os = "linux", target_arch = "s390x"))]
block_size(&self) -> u32166     pub fn block_size(&self) -> u32 {
167         self.0.f_bsize
168     }
169 
170     /// Size of a block
171     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
172     #[cfg(all(target_os = "linux", target_env = "musl"))]
block_size(&self) -> libc::c_ulong173     pub fn block_size(&self) -> libc::c_ulong {
174         self.0.f_bsize
175     }
176 
177     /// Size of a block
178     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
179     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
block_size(&self) -> libc::c_long180     pub fn block_size(&self) -> libc::c_long {
181         self.0.f_bsize
182     }
183 
184     /// Size of a block
185     #[cfg(target_os = "freebsd")]
block_size(&self) -> u64186     pub fn block_size(&self) -> u64 {
187         self.0.f_bsize
188     }
189 
190     /// Size of a block
191     #[cfg(target_os = "android")]
block_size(&self) -> libc::c_ulong192     pub fn block_size(&self) -> libc::c_ulong {
193         self.0.f_bsize
194     }
195 
196     /// Size of a block
197     #[cfg(target_os = "dragonfly")]
block_size(&self) -> libc::c_long198     pub fn block_size(&self) -> libc::c_long {
199         self.0.f_bsize
200     }
201 
202     /// Maximum length of filenames
203     #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
maximum_name_length(&self) -> u32204     pub fn maximum_name_length(&self) -> u32 {
205         self.0.f_namemax
206     }
207 
208     /// Maximum length of filenames
209     #[cfg(all(target_os = "linux", target_arch = "s390x"))]
maximum_name_length(&self) -> u32210     pub fn maximum_name_length(&self) -> u32 {
211         self.0.f_namelen
212     }
213 
214     /// Maximum length of filenames
215     #[cfg(all(target_os = "linux", target_env = "musl"))]
maximum_name_length(&self) -> libc::c_ulong216     pub fn maximum_name_length(&self) -> libc::c_ulong {
217         self.0.f_namelen
218     }
219 
220     /// Maximum length of filenames
221     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
maximum_name_length(&self) -> libc::c_long222     pub fn maximum_name_length(&self) -> libc::c_long {
223         self.0.f_namelen
224     }
225 
226     /// Maximum length of filenames
227     #[cfg(target_os = "android")]
maximum_name_length(&self) -> libc::c_ulong228     pub fn maximum_name_length(&self) -> libc::c_ulong {
229         self.0.f_namelen
230     }
231 
232     /// Total data blocks in filesystem
233     #[cfg(any(
234         target_os = "ios",
235         target_os = "macos",
236         target_os = "android",
237         target_os = "freebsd",
238         target_os = "openbsd",
239     ))]
blocks(&self) -> u64240     pub fn blocks(&self) -> u64 {
241         self.0.f_blocks
242     }
243 
244     /// Total data blocks in filesystem
245     #[cfg(target_os = "dragonfly")]
blocks(&self) -> libc::c_long246     pub fn blocks(&self) -> libc::c_long {
247         self.0.f_blocks
248     }
249 
250     /// Total data blocks in filesystem
251     #[cfg(all(target_os = "linux", target_env = "musl"))]
blocks(&self) -> u64252     pub fn blocks(&self) -> u64 {
253         self.0.f_blocks
254     }
255 
256     /// Total data blocks in filesystem
257     #[cfg(not(any(
258         target_os = "ios",
259         target_os = "macos",
260         target_os = "android",
261         target_os = "freebsd",
262         target_os = "openbsd",
263         target_os = "dragonfly",
264         all(target_os = "linux", target_env = "musl")
265     )))]
blocks(&self) -> libc::c_ulong266     pub fn blocks(&self) -> libc::c_ulong {
267         self.0.f_blocks
268     }
269 
270     /// Free blocks in filesystem
271     #[cfg(any(
272         target_os = "ios",
273         target_os = "macos",
274         target_os = "android",
275         target_os = "freebsd",
276         target_os = "openbsd",
277     ))]
blocks_free(&self) -> u64278     pub fn blocks_free(&self) -> u64 {
279         self.0.f_bfree
280     }
281 
282     /// Free blocks in filesystem
283     #[cfg(target_os = "dragonfly")]
blocks_free(&self) -> libc::c_long284     pub fn blocks_free(&self) -> libc::c_long {
285         self.0.f_bfree
286     }
287 
288     /// Free blocks in filesystem
289     #[cfg(all(target_os = "linux", target_env = "musl"))]
blocks_free(&self) -> u64290     pub fn blocks_free(&self) -> u64 {
291         self.0.f_bfree
292     }
293 
294     /// Free blocks in filesystem
295     #[cfg(not(any(
296         target_os = "ios",
297         target_os = "macos",
298         target_os = "android",
299         target_os = "freebsd",
300         target_os = "openbsd",
301         target_os = "dragonfly",
302         all(target_os = "linux", target_env = "musl")
303     )))]
blocks_free(&self) -> libc::c_ulong304     pub fn blocks_free(&self) -> libc::c_ulong {
305         self.0.f_bfree
306     }
307 
308     /// Free blocks available to unprivileged user
309     #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
blocks_available(&self) -> u64310     pub fn blocks_available(&self) -> u64 {
311         self.0.f_bavail
312     }
313 
314     /// Free blocks available to unprivileged user
315     #[cfg(target_os = "dragonfly")]
blocks_available(&self) -> libc::c_long316     pub fn blocks_available(&self) -> libc::c_long {
317         self.0.f_bavail
318     }
319 
320     /// Free blocks available to unprivileged user
321     #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
blocks_available(&self) -> i64322     pub fn blocks_available(&self) -> i64 {
323         self.0.f_bavail
324     }
325 
326     /// Free blocks available to unprivileged user
327     #[cfg(all(target_os = "linux", target_env = "musl"))]
blocks_available(&self) -> u64328     pub fn blocks_available(&self) -> u64 {
329         self.0.f_bavail
330     }
331 
332     /// Free blocks available to unprivileged user
333     #[cfg(not(any(
334         target_os = "ios",
335         target_os = "macos",
336         target_os = "android",
337         target_os = "freebsd",
338         target_os = "openbsd",
339         target_os = "dragonfly",
340         all(target_os = "linux", target_env = "musl")
341     )))]
blocks_available(&self) -> libc::c_ulong342     pub fn blocks_available(&self) -> libc::c_ulong {
343         self.0.f_bavail
344     }
345 
346     /// Total file nodes in filesystem
347     #[cfg(any(
348         target_os = "ios",
349         target_os = "macos",
350         target_os = "android",
351         target_os = "freebsd",
352         target_os = "openbsd",
353     ))]
files(&self) -> u64354     pub fn files(&self) -> u64 {
355         self.0.f_files
356     }
357 
358     /// Total file nodes in filesystem
359     #[cfg(target_os = "dragonfly")]
files(&self) -> libc::c_long360     pub fn files(&self) -> libc::c_long {
361         self.0.f_files
362     }
363 
364     /// Total file nodes in filesystem
365     #[cfg(all(target_os = "linux", target_env = "musl"))]
files(&self) -> u64366     pub fn files(&self) -> u64 {
367         self.0.f_files
368     }
369 
370     /// Total file nodes in filesystem
371     #[cfg(not(any(
372         target_os = "ios",
373         target_os = "macos",
374         target_os = "android",
375         target_os = "freebsd",
376         target_os = "openbsd",
377         target_os = "dragonfly",
378         all(target_os = "linux", target_env = "musl")
379     )))]
files(&self) -> libc::c_ulong380     pub fn files(&self) -> libc::c_ulong {
381         self.0.f_files
382     }
383 
384     /// Free file nodes in filesystem
385     #[cfg(any(
386             target_os = "android",
387             target_os = "ios",
388             all(target_os = "linux", target_env = "musl"),
389             target_os = "macos",
390             target_os = "openbsd"
391     ))]
files_free(&self) -> u64392     pub fn files_free(&self) -> u64 {
393         self.0.f_ffree
394     }
395 
396     /// Free file nodes in filesystem
397     #[cfg(target_os = "dragonfly")]
files_free(&self) -> libc::c_long398     pub fn files_free(&self) -> libc::c_long {
399         self.0.f_ffree
400     }
401 
402     /// Free file nodes in filesystem
403     #[cfg(target_os = "freebsd")]
files_free(&self) -> i64404     pub fn files_free(&self) -> i64 {
405         self.0.f_ffree
406     }
407 
408     /// Free file nodes in filesystem
409     #[cfg(not(any(
410         target_os = "ios",
411         target_os = "macos",
412         target_os = "android",
413         target_os = "freebsd",
414         target_os = "openbsd",
415         target_os = "dragonfly",
416         all(target_os = "linux", target_env = "musl")
417     )))]
files_free(&self) -> libc::c_ulong418     pub fn files_free(&self) -> libc::c_ulong {
419         self.0.f_ffree
420     }
421 
422     /// Filesystem ID
filesystem_id(&self) -> fsid_t423     pub fn filesystem_id(&self) -> fsid_t {
424         self.0.f_fsid
425     }
426 }
427 
428 impl Debug for Statfs {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result429     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
430         f.debug_struct("Statfs")
431             .field("optimal_transfer_size", &self.optimal_transfer_size())
432             .field("block_size", &self.block_size())
433             .field("blocks", &self.blocks())
434             .field("blocks_free", &self.blocks_free())
435             .field("blocks_available", &self.blocks_available())
436             .field("files", &self.files())
437             .field("files_free", &self.files_free())
438             .field("filesystem_id", &self.filesystem_id())
439             .finish()
440     }
441 }
442 
statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs>443 pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
444     unsafe {
445         let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
446         let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?;
447         Errno::result(res).map(|_| Statfs(stat.assume_init()))
448     }
449 }
450 
fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs>451 pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
452     unsafe {
453         let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
454         Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr()))
455             .map(|_| Statfs(stat.assume_init()))
456     }
457 }
458 
459 #[cfg(test)]
460 mod test {
461     use std::fs::File;
462 
463     use crate::sys::statfs::*;
464     use crate::sys::statvfs::*;
465     use std::path::Path;
466 
467     #[test]
statfs_call()468     fn statfs_call() {
469         check_statfs("/tmp");
470         check_statfs("/dev");
471         check_statfs("/run");
472         check_statfs("/");
473     }
474 
475     #[test]
fstatfs_call()476     fn fstatfs_call() {
477         check_fstatfs("/tmp");
478         check_fstatfs("/dev");
479         check_fstatfs("/run");
480         check_fstatfs("/");
481     }
482 
check_fstatfs(path: &str)483     fn check_fstatfs(path: &str) {
484         if !Path::new(path).exists() {
485             return;
486         }
487         let vfs = statvfs(path.as_bytes()).unwrap();
488         let file = File::open(path).unwrap();
489         let fs = fstatfs(&file).unwrap();
490         assert_fs_equals(fs, vfs);
491     }
492 
check_statfs(path: &str)493     fn check_statfs(path: &str) {
494         if !Path::new(path).exists() {
495             return;
496         }
497         let vfs = statvfs(path.as_bytes()).unwrap();
498         let fs = statfs(path.as_bytes()).unwrap();
499         assert_fs_equals(fs, vfs);
500     }
501 
assert_fs_equals(fs: Statfs, vfs: Statvfs)502     fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
503         assert_eq!(fs.files() as u64, vfs.files() as u64);
504         assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
505         assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
506     }
507 
508     // This test is ignored because files_free/blocks_free can change after statvfs call and before
509     // statfs call.
510     #[test]
511     #[ignore]
statfs_call_strict()512     fn statfs_call_strict() {
513         check_statfs_strict("/tmp");
514         check_statfs_strict("/dev");
515         check_statfs_strict("/run");
516         check_statfs_strict("/");
517     }
518 
519     // This test is ignored because files_free/blocks_free can change after statvfs call and before
520     // fstatfs call.
521     #[test]
522     #[ignore]
fstatfs_call_strict()523     fn fstatfs_call_strict() {
524         check_fstatfs_strict("/tmp");
525         check_fstatfs_strict("/dev");
526         check_fstatfs_strict("/run");
527         check_fstatfs_strict("/");
528     }
529 
check_fstatfs_strict(path: &str)530     fn check_fstatfs_strict(path: &str) {
531         if !Path::new(path).exists() {
532             return;
533         }
534         let vfs = statvfs(path.as_bytes());
535         let file = File::open(path).unwrap();
536         let fs = fstatfs(&file);
537         assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
538     }
539 
check_statfs_strict(path: &str)540     fn check_statfs_strict(path: &str) {
541         if !Path::new(path).exists() {
542             return;
543         }
544         let vfs = statvfs(path.as_bytes());
545         let fs = statfs(path.as_bytes());
546         assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
547     }
548 
assert_fs_equals_strict(fs: Statfs, vfs: Statvfs)549     fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
550         assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
551         assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
552         assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
553         assert_eq!(fs.files() as u64, vfs.files() as u64);
554         assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
555         assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
556     }
557 }
558