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 libc;
8 
9 use {NixPath, Result};
10 use errno::Errno;
11 
12 #[cfg(target_os = "android")]
13 pub type fsid_t = libc::__fsid_t;
14 #[cfg(not(target_os = "android"))]
15 pub type fsid_t = libc::fsid_t;
16 
17 #[derive(Clone, Copy)]
18 #[repr(transparent)]
19 pub struct Statfs(libc::statfs);
20 
21 #[cfg(target_os = "freebsd")]
22 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
23 pub struct FsType(u32);
24 #[cfg(target_os = "dragonfly")]
25 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
26 pub struct FsType(i32);
27 #[cfg(target_os = "android")]
28 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
29 pub struct FsType(libc::c_ulong);
30 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
31 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
32 pub struct FsType(u32);
33 #[cfg(all(target_os = "linux", target_env = "musl"))]
34 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
35 pub struct FsType(libc::c_ulong);
36 #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
37 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
38 pub struct FsType(libc::c_long);
39 
40 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
41 pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC);
42 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
43 pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC);
44 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
45 pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC);
46 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
47 pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC);
48 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
49 pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC);
50 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
51 pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC);
52 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
53 pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC);
54 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
55 pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC);
56 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
57 pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC);
58 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
59 pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC);
60 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
61 pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC);
62 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
63 pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC);
64 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
65 pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC);
66 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
67 pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2);
68 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
69 pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC);
70 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
71 pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2);
72 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
73 pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC);
74 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
75 pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC);
76 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
77 pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC);
78 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
79 pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC);
80 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
81 pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC);
82 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
83 pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC);
84 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
85 pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC);
86 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
87 pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC);
88 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
89 pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC);
90 #[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
91 pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC);
92 
93 impl Statfs {
94     /// Magic code defining system type
95     #[cfg(not(any(
96         target_os = "openbsd",
97         target_os = "ios",
98         target_os = "macos"
99     )))]
filesystem_type(&self) -> FsType100     pub fn filesystem_type(&self) -> FsType {
101         FsType(self.0.f_type)
102     }
103 
104     /// Magic code defining system type
105     #[cfg(not(any(target_os = "linux", target_os = "android")))]
filesystem_type_name(&self) -> &str106     pub fn filesystem_type_name(&self) -> &str {
107         let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
108         c_str.to_str().unwrap()
109     }
110 
111     /// Optimal transfer block size
112     #[cfg(any(target_os = "ios", target_os = "macos"))]
optimal_transfer_size(&self) -> i32113     pub fn optimal_transfer_size(&self) -> i32 {
114         self.0.f_iosize
115     }
116 
117     /// Optimal transfer block size
118     #[cfg(target_os = "openbsd")]
optimal_transfer_size(&self) -> u32119     pub fn optimal_transfer_size(&self) -> u32 {
120         self.0.f_iosize
121     }
122 
123     /// Optimal transfer block size
124     #[cfg(all(target_os = "linux", target_arch = "s390x"))]
optimal_transfer_size(&self) -> u32125     pub fn optimal_transfer_size(&self) -> u32 {
126         self.0.f_bsize
127     }
128 
129     /// Optimal transfer block size
130     #[cfg(any(
131         target_os = "android",
132         all(target_os = "linux", target_env = "musl")
133     ))]
optimal_transfer_size(&self) -> libc::c_ulong134     pub fn optimal_transfer_size(&self) -> libc::c_ulong {
135         self.0.f_bsize
136     }
137 
138     /// Optimal transfer block size
139     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
optimal_transfer_size(&self) -> libc::c_long140     pub fn optimal_transfer_size(&self) -> libc::c_long {
141         self.0.f_bsize
142     }
143 
144     /// Optimal transfer block size
145     #[cfg(target_os = "dragonfly")]
optimal_transfer_size(&self) -> libc::c_long146     pub fn optimal_transfer_size(&self) -> libc::c_long {
147         self.0.f_iosize
148     }
149 
150     /// Optimal transfer block size
151     #[cfg(target_os = "freebsd")]
optimal_transfer_size(&self) -> u64152     pub fn optimal_transfer_size(&self) -> u64 {
153         self.0.f_iosize
154     }
155 
156     /// Size of a block
157     #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
block_size(&self) -> u32158     pub fn block_size(&self) -> u32 {
159         self.0.f_bsize
160     }
161 
162     /// Size of a block
163     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
164     #[cfg(all(target_os = "linux", target_arch = "s390x"))]
block_size(&self) -> u32165     pub fn block_size(&self) -> u32 {
166         self.0.f_bsize
167     }
168 
169     /// Size of a block
170     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
171     #[cfg(all(target_os = "linux", target_env = "musl"))]
block_size(&self) -> libc::c_ulong172     pub fn block_size(&self) -> libc::c_ulong {
173         self.0.f_bsize
174     }
175 
176     /// Size of a block
177     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
178     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
block_size(&self) -> libc::c_long179     pub fn block_size(&self) -> libc::c_long {
180         self.0.f_bsize
181     }
182 
183     /// Size of a block
184     #[cfg(target_os = "freebsd")]
block_size(&self) -> u64185     pub fn block_size(&self) -> u64 {
186         self.0.f_bsize
187     }
188 
189     /// Size of a block
190     #[cfg(target_os = "android")]
block_size(&self) -> libc::c_ulong191     pub fn block_size(&self) -> libc::c_ulong {
192         self.0.f_bsize
193     }
194 
195     /// Size of a block
196     #[cfg(target_os = "dragonfly")]
block_size(&self) -> libc::c_long197     pub fn block_size(&self) -> libc::c_long {
198         self.0.f_bsize
199     }
200 
201     /// Maximum length of filenames
202     #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
maximum_name_length(&self) -> u32203     pub fn maximum_name_length(&self) -> u32 {
204         self.0.f_namemax
205     }
206 
207     /// Maximum length of filenames
208     #[cfg(all(target_os = "linux", target_arch = "s390x"))]
maximum_name_length(&self) -> u32209     pub fn maximum_name_length(&self) -> u32 {
210         self.0.f_namelen
211     }
212 
213     /// Maximum length of filenames
214     #[cfg(all(target_os = "linux", target_env = "musl"))]
maximum_name_length(&self) -> libc::c_ulong215     pub fn maximum_name_length(&self) -> libc::c_ulong {
216         self.0.f_namelen
217     }
218 
219     /// Maximum length of filenames
220     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
maximum_name_length(&self) -> libc::c_long221     pub fn maximum_name_length(&self) -> libc::c_long {
222         self.0.f_namelen
223     }
224 
225     /// Maximum length of filenames
226     #[cfg(target_os = "android")]
maximum_name_length(&self) -> libc::c_ulong227     pub fn maximum_name_length(&self) -> libc::c_ulong {
228         self.0.f_namelen
229     }
230 
231     /// Total data blocks in filesystem
232     #[cfg(any(
233         target_os = "ios",
234         target_os = "macos",
235         target_os = "android",
236         target_os = "freebsd",
237         target_os = "openbsd",
238     ))]
blocks(&self) -> u64239     pub fn blocks(&self) -> u64 {
240         self.0.f_blocks
241     }
242 
243     /// Total data blocks in filesystem
244     #[cfg(target_os = "dragonfly")]
blocks(&self) -> libc::c_long245     pub fn blocks(&self) -> libc::c_long {
246         self.0.f_blocks
247     }
248 
249     /// Total data blocks in filesystem
250     #[cfg(all(target_os = "linux", target_env = "musl"))]
blocks(&self) -> u64251     pub fn blocks(&self) -> u64 {
252         self.0.f_blocks
253     }
254 
255     /// Total data blocks in filesystem
256     #[cfg(not(any(
257         target_os = "ios",
258         target_os = "macos",
259         target_os = "android",
260         target_os = "freebsd",
261         target_os = "openbsd",
262         target_os = "dragonfly",
263         all(target_os = "linux", target_env = "musl")
264     )))]
blocks(&self) -> libc::c_ulong265     pub fn blocks(&self) -> libc::c_ulong {
266         self.0.f_blocks
267     }
268 
269     /// Free blocks in filesystem
270     #[cfg(any(
271         target_os = "ios",
272         target_os = "macos",
273         target_os = "android",
274         target_os = "freebsd",
275         target_os = "openbsd",
276     ))]
blocks_free(&self) -> u64277     pub fn blocks_free(&self) -> u64 {
278         self.0.f_bfree
279     }
280 
281     /// Free blocks in filesystem
282     #[cfg(target_os = "dragonfly")]
blocks_free(&self) -> libc::c_long283     pub fn blocks_free(&self) -> libc::c_long {
284         self.0.f_bfree
285     }
286 
287     /// Free blocks in filesystem
288     #[cfg(all(target_os = "linux", target_env = "musl"))]
blocks_free(&self) -> u64289     pub fn blocks_free(&self) -> u64 {
290         self.0.f_bfree
291     }
292 
293     /// Free blocks in filesystem
294     #[cfg(not(any(
295         target_os = "ios",
296         target_os = "macos",
297         target_os = "android",
298         target_os = "freebsd",
299         target_os = "openbsd",
300         target_os = "dragonfly",
301         all(target_os = "linux", target_env = "musl")
302     )))]
blocks_free(&self) -> libc::c_ulong303     pub fn blocks_free(&self) -> libc::c_ulong {
304         self.0.f_bfree
305     }
306 
307     /// Free blocks available to unprivileged user
308     #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
blocks_available(&self) -> u64309     pub fn blocks_available(&self) -> u64 {
310         self.0.f_bavail
311     }
312 
313     /// Free blocks available to unprivileged user
314     #[cfg(target_os = "dragonfly")]
blocks_available(&self) -> libc::c_long315     pub fn blocks_available(&self) -> libc::c_long {
316         self.0.f_bavail
317     }
318 
319     /// Free blocks available to unprivileged user
320     #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
blocks_available(&self) -> i64321     pub fn blocks_available(&self) -> i64 {
322         self.0.f_bavail
323     }
324 
325     /// Free blocks available to unprivileged user
326     #[cfg(all(target_os = "linux", target_env = "musl"))]
blocks_available(&self) -> u64327     pub fn blocks_available(&self) -> u64 {
328         self.0.f_bavail
329     }
330 
331     /// Free blocks available to unprivileged user
332     #[cfg(not(any(
333         target_os = "ios",
334         target_os = "macos",
335         target_os = "android",
336         target_os = "freebsd",
337         target_os = "openbsd",
338         target_os = "dragonfly",
339         all(target_os = "linux", target_env = "musl")
340     )))]
blocks_available(&self) -> libc::c_ulong341     pub fn blocks_available(&self) -> libc::c_ulong {
342         self.0.f_bavail
343     }
344 
345     /// Total file nodes in filesystem
346     #[cfg(any(
347         target_os = "ios",
348         target_os = "macos",
349         target_os = "android",
350         target_os = "freebsd",
351         target_os = "openbsd",
352     ))]
files(&self) -> u64353     pub fn files(&self) -> u64 {
354         self.0.f_files
355     }
356 
357     /// Total file nodes in filesystem
358     #[cfg(target_os = "dragonfly")]
files(&self) -> libc::c_long359     pub fn files(&self) -> libc::c_long {
360         self.0.f_files
361     }
362 
363     /// Total file nodes in filesystem
364     #[cfg(all(target_os = "linux", target_env = "musl"))]
files(&self) -> u64365     pub fn files(&self) -> u64 {
366         self.0.f_files
367     }
368 
369     /// Total file nodes in filesystem
370     #[cfg(not(any(
371         target_os = "ios",
372         target_os = "macos",
373         target_os = "android",
374         target_os = "freebsd",
375         target_os = "openbsd",
376         target_os = "dragonfly",
377         all(target_os = "linux", target_env = "musl")
378     )))]
files(&self) -> libc::c_ulong379     pub fn files(&self) -> libc::c_ulong {
380         self.0.f_files
381     }
382 
383     /// Free file nodes in filesystem
384     #[cfg(any(
385             target_os = "android",
386             target_os = "ios",
387             all(target_os = "linux", target_env = "musl"),
388             target_os = "macos",
389             target_os = "openbsd"
390     ))]
files_free(&self) -> u64391     pub fn files_free(&self) -> u64 {
392         self.0.f_ffree
393     }
394 
395     /// Free file nodes in filesystem
396     #[cfg(target_os = "dragonfly")]
files_free(&self) -> libc::c_long397     pub fn files_free(&self) -> libc::c_long {
398         self.0.f_ffree
399     }
400 
401     /// Free file nodes in filesystem
402     #[cfg(target_os = "freebsd")]
files_free(&self) -> i64403     pub fn files_free(&self) -> i64 {
404         self.0.f_ffree
405     }
406 
407     /// Free file nodes in filesystem
408     #[cfg(not(any(
409         target_os = "ios",
410         target_os = "macos",
411         target_os = "android",
412         target_os = "freebsd",
413         target_os = "openbsd",
414         target_os = "dragonfly",
415         all(target_os = "linux", target_env = "musl")
416     )))]
files_free(&self) -> libc::c_ulong417     pub fn files_free(&self) -> libc::c_ulong {
418         self.0.f_ffree
419     }
420 
421     /// Filesystem ID
filesystem_id(&self) -> fsid_t422     pub fn filesystem_id(&self) -> fsid_t {
423         self.0.f_fsid
424     }
425 }
426 
427 impl Debug for Statfs {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result428     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
429         f.debug_struct("Statfs")
430             .field("optimal_transfer_size", &self.optimal_transfer_size())
431             .field("block_size", &self.block_size())
432             .field("blocks", &self.blocks())
433             .field("blocks_free", &self.blocks_free())
434             .field("blocks_available", &self.blocks_available())
435             .field("files", &self.files())
436             .field("files_free", &self.files_free())
437             .field("filesystem_id", &self.filesystem_id())
438             .finish()
439     }
440 }
441 
statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs>442 pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
443     unsafe {
444         let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
445         let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?;
446         Errno::result(res).map(|_| Statfs(stat.assume_init()))
447     }
448 }
449 
fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs>450 pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
451     unsafe {
452         let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
453         Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr()))
454             .map(|_| Statfs(stat.assume_init()))
455     }
456 }
457 
458 #[cfg(test)]
459 mod test {
460     use std::fs::File;
461 
462     use sys::statfs::*;
463     use sys::statvfs::*;
464     use std::path::Path;
465 
466     #[test]
statfs_call()467     fn statfs_call() {
468         check_statfs("/tmp");
469         check_statfs("/dev");
470         check_statfs("/run");
471         check_statfs("/");
472     }
473 
474     #[test]
fstatfs_call()475     fn fstatfs_call() {
476         check_fstatfs("/tmp");
477         check_fstatfs("/dev");
478         check_fstatfs("/run");
479         check_fstatfs("/");
480     }
481 
check_fstatfs(path: &str)482     fn check_fstatfs(path: &str) {
483         if !Path::new(path).exists() {
484             return;
485         }
486         let vfs = statvfs(path.as_bytes()).unwrap();
487         let file = File::open(path).unwrap();
488         let fs = fstatfs(&file).unwrap();
489         assert_fs_equals(fs, vfs);
490     }
491 
check_statfs(path: &str)492     fn check_statfs(path: &str) {
493         if !Path::new(path).exists() {
494             return;
495         }
496         let vfs = statvfs(path.as_bytes()).unwrap();
497         let fs = statfs(path.as_bytes()).unwrap();
498         assert_fs_equals(fs, vfs);
499     }
500 
assert_fs_equals(fs: Statfs, vfs: Statvfs)501     fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
502         assert_eq!(fs.files() as u64, vfs.files() as u64);
503         assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
504         assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
505     }
506 
507     // This test is ignored because files_free/blocks_free can change after statvfs call and before
508     // statfs call.
509     #[test]
510     #[ignore]
statfs_call_strict()511     fn statfs_call_strict() {
512         check_statfs_strict("/tmp");
513         check_statfs_strict("/dev");
514         check_statfs_strict("/run");
515         check_statfs_strict("/");
516     }
517 
518     // This test is ignored because files_free/blocks_free can change after statvfs call and before
519     // fstatfs call.
520     #[test]
521     #[ignore]
fstatfs_call_strict()522     fn fstatfs_call_strict() {
523         check_fstatfs_strict("/tmp");
524         check_fstatfs_strict("/dev");
525         check_fstatfs_strict("/run");
526         check_fstatfs_strict("/");
527     }
528 
check_fstatfs_strict(path: &str)529     fn check_fstatfs_strict(path: &str) {
530         if !Path::new(path).exists() {
531             return;
532         }
533         let vfs = statvfs(path.as_bytes());
534         let file = File::open(path).unwrap();
535         let fs = fstatfs(&file);
536         assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
537     }
538 
check_statfs_strict(path: &str)539     fn check_statfs_strict(path: &str) {
540         if !Path::new(path).exists() {
541             return;
542         }
543         let vfs = statvfs(path.as_bytes());
544         let fs = statfs(path.as_bytes());
545         assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
546     }
547 
assert_fs_equals_strict(fs: Statfs, vfs: Statvfs)548     fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
549         assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
550         assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
551         assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
552         assert_eq!(fs.files() as u64, vfs.files() as u64);
553         assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
554         assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
555     }
556 }
557