1use std::fmt::{self, Debug};
5use std::mem;
6use std::os::unix::io::AsRawFd;
7#[cfg(not(any(target_os = "linux", target_os = "android")))]
8use std::ffi::CStr;
9
10use crate::{NixPath, Result, errno::Errno};
11
12#[cfg(target_os = "android")]
14#[cfg_attr(docsrs, doc(cfg(all())))]
15pub type fsid_t = libc::__fsid_t;
16#[cfg(not(target_os = "android"))]
18#[cfg_attr(docsrs, doc(cfg(all())))]
19pub type fsid_t = libc::fsid_t;
20
21#[derive(Clone, Copy)]
23#[repr(transparent)]
24pub struct Statfs(libc::statfs);
25
26#[cfg(target_os = "freebsd")]
27type fs_type_t = u32;
28#[cfg(target_os = "android")]
29type fs_type_t = libc::c_ulong;
30#[cfg(all(target_os = "linux", target_arch = "s390x"))]
31type fs_type_t = libc::c_uint;
32#[cfg(all(target_os = "linux", target_env = "musl"))]
33type fs_type_t = libc::c_ulong;
34#[cfg(all(target_os = "linux", target_env = "uclibc"))]
35type fs_type_t = libc::c_int;
36#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
37type fs_type_t = libc::__fsword_t;
38
39#[cfg(any(
41 target_os = "freebsd",
42 target_os = "android",
43 all(target_os = "linux", target_arch = "s390x"),
44 all(target_os = "linux", target_env = "musl"),
45 all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))),
46))]
47#[derive(Eq, Copy, Clone, PartialEq, Debug)]
48pub struct FsType(pub fs_type_t);
49
50#[cfg(any(target_os = "linux", target_os = "android"))]
53#[allow(missing_docs)]
54pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
55#[cfg(any(target_os = "linux", target_os = "android"))]
56#[allow(missing_docs)]
57pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
58#[cfg(any(target_os = "linux", target_os = "android"))]
59#[allow(missing_docs)]
60pub const AFS_SUPER_MAGIC: FsType = FsType(libc::AFS_SUPER_MAGIC as fs_type_t);
61#[cfg(any(target_os = "linux", target_os = "android"))]
62#[allow(missing_docs)]
63pub const AUTOFS_SUPER_MAGIC: FsType = FsType(libc::AUTOFS_SUPER_MAGIC as fs_type_t);
64#[cfg(any(target_os = "linux", target_os = "android"))]
65#[allow(missing_docs)]
66pub const BPF_FS_MAGIC: FsType = FsType(libc::BPF_FS_MAGIC as fs_type_t);
67#[cfg(any(target_os = "linux", target_os = "android"))]
68#[allow(missing_docs)]
69pub const BTRFS_SUPER_MAGIC: FsType = FsType(libc::BTRFS_SUPER_MAGIC as fs_type_t);
70#[cfg(any(target_os = "linux", target_os = "android"))]
71#[allow(missing_docs)]
72pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
73#[cfg(any(target_os = "linux", target_os = "android"))]
74#[allow(missing_docs)]
75pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
76#[cfg(any(target_os = "linux", target_os = "android"))]
77#[allow(missing_docs)]
78pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
79#[cfg(any(target_os = "linux", target_os = "android"))]
80#[allow(missing_docs)]
81pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
82#[cfg(any(target_os = "linux", target_os = "android"))]
83#[allow(missing_docs)]
84pub const DEBUGFS_MAGIC: FsType = FsType(libc::DEBUGFS_MAGIC as fs_type_t);
85#[cfg(any(target_os = "linux", target_os = "android"))]
86#[allow(missing_docs)]
87pub const DEVPTS_SUPER_MAGIC: FsType = FsType(libc::DEVPTS_SUPER_MAGIC as fs_type_t);
88#[cfg(any(target_os = "linux", target_os = "android"))]
89#[allow(missing_docs)]
90pub const ECRYPTFS_SUPER_MAGIC: FsType = FsType(libc::ECRYPTFS_SUPER_MAGIC as fs_type_t);
91#[cfg(any(target_os = "linux", target_os = "android"))]
92#[allow(missing_docs)]
93pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
94#[cfg(any(target_os = "linux", target_os = "android"))]
95#[allow(missing_docs)]
96pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
97#[cfg(any(target_os = "linux", target_os = "android"))]
98#[allow(missing_docs)]
99pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
100#[cfg(any(target_os = "linux", target_os = "android"))]
101#[allow(missing_docs)]
102pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
103#[cfg(any(target_os = "linux", target_os = "android"))]
104#[allow(missing_docs)]
105pub const F2FS_SUPER_MAGIC: FsType = FsType(libc::F2FS_SUPER_MAGIC as fs_type_t);
106#[cfg(any(target_os = "linux", target_os = "android"))]
107#[allow(missing_docs)]
108pub const FUSE_SUPER_MAGIC: FsType = FsType(libc::FUSE_SUPER_MAGIC as fs_type_t);
109#[cfg(any(target_os = "linux", target_os = "android"))]
110#[allow(missing_docs)]
111pub const FUTEXFS_SUPER_MAGIC: FsType = FsType(libc::FUTEXFS_SUPER_MAGIC as fs_type_t);
112#[cfg(any(target_os = "linux", target_os = "android"))]
113#[allow(missing_docs)]
114pub const HOSTFS_SUPER_MAGIC: FsType = FsType(libc::HOSTFS_SUPER_MAGIC as fs_type_t);
115#[cfg(any(target_os = "linux", target_os = "android"))]
116#[allow(missing_docs)]
117pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
118#[cfg(any(target_os = "linux", target_os = "android"))]
119#[allow(missing_docs)]
120pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
121#[cfg(any(target_os = "linux", target_os = "android"))]
122#[allow(missing_docs)]
123pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
124#[cfg(any(target_os = "linux", target_os = "android"))]
125#[allow(missing_docs)]
126pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
127#[cfg(any(target_os = "linux", target_os = "android"))]
128#[allow(missing_docs)]
129pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
130#[cfg(any(target_os = "linux", target_os = "android"))]
131#[allow(missing_docs)]
132pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
133#[cfg(any(target_os = "linux", target_os = "android"))]
134#[allow(missing_docs)]
135pub const MINIX3_SUPER_MAGIC: FsType = FsType(libc::MINIX3_SUPER_MAGIC as fs_type_t);
136#[cfg(any(target_os = "linux", target_os = "android"))]
137#[allow(missing_docs)]
138pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
139#[cfg(any(target_os = "linux", target_os = "android"))]
140#[allow(missing_docs)]
141pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
142#[cfg(any(target_os = "linux", target_os = "android"))]
143#[allow(missing_docs)]
144pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
145#[cfg(any(target_os = "linux", target_os = "android"))]
146#[allow(missing_docs)]
147pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
148#[cfg(any(target_os = "linux", target_os = "android"))]
149#[allow(missing_docs)]
150pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
151#[cfg(any(target_os = "linux", target_os = "android"))]
152#[allow(missing_docs)]
153pub const NILFS_SUPER_MAGIC: FsType = FsType(libc::NILFS_SUPER_MAGIC as fs_type_t);
154#[cfg(any(target_os = "linux", target_os = "android"))]
155#[allow(missing_docs)]
156pub const OCFS2_SUPER_MAGIC: FsType = FsType(libc::OCFS2_SUPER_MAGIC as fs_type_t);
157#[cfg(any(target_os = "linux", target_os = "android"))]
158#[allow(missing_docs)]
159pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
160#[cfg(any(target_os = "linux", target_os = "android"))]
161#[allow(missing_docs)]
162pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
163#[cfg(any(target_os = "linux", target_os = "android"))]
164#[allow(missing_docs)]
165pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
166#[cfg(any(target_os = "linux", target_os = "android"))]
167#[allow(missing_docs)]
168pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
169#[cfg(any(target_os = "linux", target_os = "android"))]
170#[allow(missing_docs)]
171pub const QNX6_SUPER_MAGIC: FsType = FsType(libc::QNX6_SUPER_MAGIC as fs_type_t);
172#[cfg(any(target_os = "linux", target_os = "android"))]
173#[allow(missing_docs)]
174pub const RDTGROUP_SUPER_MAGIC: FsType = FsType(libc::RDTGROUP_SUPER_MAGIC as fs_type_t);
175#[cfg(any(target_os = "linux", target_os = "android"))]
176#[allow(missing_docs)]
177pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
178#[cfg(any(target_os = "linux", target_os = "android"))]
179#[allow(missing_docs)]
180pub const SECURITYFS_MAGIC: FsType = FsType(libc::SECURITYFS_MAGIC as fs_type_t);
181#[cfg(any(target_os = "linux", target_os = "android"))]
182#[allow(missing_docs)]
183pub const SELINUX_MAGIC: FsType = FsType(libc::SELINUX_MAGIC as fs_type_t);
184#[cfg(any(target_os = "linux", target_os = "android"))]
185#[allow(missing_docs)]
186pub const SMACK_MAGIC: FsType = FsType(libc::SMACK_MAGIC as fs_type_t);
187#[cfg(any(target_os = "linux", target_os = "android"))]
188#[allow(missing_docs)]
189pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
190#[cfg(any(target_os = "linux", target_os = "android"))]
191#[allow(missing_docs)]
192pub const SYSFS_MAGIC: FsType = FsType(libc::SYSFS_MAGIC as fs_type_t);
193#[cfg(any(target_os = "linux", target_os = "android"))]
194#[allow(missing_docs)]
195pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
196#[cfg(any(target_os = "linux", target_os = "android"))]
197#[allow(missing_docs)]
198pub const TRACEFS_MAGIC: FsType = FsType(libc::TRACEFS_MAGIC as fs_type_t);
199#[cfg(any(target_os = "linux", target_os = "android"))]
200#[allow(missing_docs)]
201pub const UDF_SUPER_MAGIC: FsType = FsType(libc::UDF_SUPER_MAGIC as fs_type_t);
202#[cfg(any(target_os = "linux", target_os = "android"))]
203#[allow(missing_docs)]
204pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
205#[cfg(any(target_os = "linux", target_os = "android"))]
206#[allow(missing_docs)]
207pub const XENFS_SUPER_MAGIC: FsType = FsType(libc::XENFS_SUPER_MAGIC as fs_type_t);
208
209
210impl Statfs {
211 #[cfg(not(any(
213 target_os = "openbsd",
214 target_os = "dragonfly",
215 target_os = "ios",
216 target_os = "macos"
217 )))]
218 #[cfg_attr(docsrs, doc(cfg(all())))]
219 pub fn filesystem_type(&self) -> FsType {
220 FsType(self.0.f_type)
221 }
222
223 #[cfg(not(any(target_os = "linux", target_os = "android")))]
225 #[cfg_attr(docsrs, doc(cfg(all())))]
226 pub fn filesystem_type_name(&self) -> &str {
227 let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
228 c_str.to_str().unwrap()
229 }
230
231 #[cfg(any(target_os = "ios", target_os = "macos"))]
233 #[cfg_attr(docsrs, doc(cfg(all())))]
234 pub fn optimal_transfer_size(&self) -> i32 {
235 self.0.f_iosize
236 }
237
238 #[cfg(target_os = "openbsd")]
240 #[cfg_attr(docsrs, doc(cfg(all())))]
241 pub fn optimal_transfer_size(&self) -> u32 {
242 self.0.f_iosize
243 }
244
245 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
247 #[cfg_attr(docsrs, doc(cfg(all())))]
248 pub fn optimal_transfer_size(&self) -> u32 {
249 self.0.f_bsize
250 }
251
252 #[cfg(any(
254 target_os = "android",
255 all(target_os = "linux", target_env = "musl")
256 ))]
257 #[cfg_attr(docsrs, doc(cfg(all())))]
258 pub fn optimal_transfer_size(&self) -> libc::c_ulong {
259 self.0.f_bsize
260 }
261
262 #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
264 #[cfg_attr(docsrs, doc(cfg(all())))]
265 pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
266 self.0.f_bsize
267 }
268
269 #[cfg(all(target_os = "linux", target_env = "uclibc"))]
271 #[cfg_attr(docsrs, doc(cfg(all())))]
272 pub fn optimal_transfer_size(&self) -> libc::c_int {
273 self.0.f_bsize
274 }
275
276 #[cfg(target_os = "dragonfly")]
278 #[cfg_attr(docsrs, doc(cfg(all())))]
279 pub fn optimal_transfer_size(&self) -> libc::c_long {
280 self.0.f_iosize
281 }
282
283 #[cfg(target_os = "freebsd")]
285 #[cfg_attr(docsrs, doc(cfg(all())))]
286 pub fn optimal_transfer_size(&self) -> u64 {
287 self.0.f_iosize
288 }
289
290 #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
292 #[cfg_attr(docsrs, doc(cfg(all())))]
293 pub fn block_size(&self) -> u32 {
294 self.0.f_bsize
295 }
296
297 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
300 #[cfg_attr(docsrs, doc(cfg(all())))]
301 pub fn block_size(&self) -> u32 {
302 self.0.f_bsize
303 }
304
305 #[cfg(all(target_os = "linux", target_env = "musl"))]
308 #[cfg_attr(docsrs, doc(cfg(all())))]
309 pub fn block_size(&self) -> libc::c_ulong {
310 self.0.f_bsize
311 }
312
313 #[cfg(all(target_os = "linux", target_env = "uclibc"))]
316 #[cfg_attr(docsrs, doc(cfg(all())))]
317 pub fn block_size(&self) -> libc::c_int {
318 self.0.f_bsize
319 }
320
321 #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
324 #[cfg_attr(docsrs, doc(cfg(all())))]
325 pub fn block_size(&self) -> libc::__fsword_t {
326 self.0.f_bsize
327 }
328
329 #[cfg(target_os = "freebsd")]
331 #[cfg_attr(docsrs, doc(cfg(all())))]
332 pub fn block_size(&self) -> u64 {
333 self.0.f_bsize
334 }
335
336 #[cfg(target_os = "android")]
338 #[cfg_attr(docsrs, doc(cfg(all())))]
339 pub fn block_size(&self) -> libc::c_ulong {
340 self.0.f_bsize
341 }
342
343 #[cfg(target_os = "dragonfly")]
345 #[cfg_attr(docsrs, doc(cfg(all())))]
346 pub fn block_size(&self) -> libc::c_long {
347 self.0.f_bsize
348 }
349
350 #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
352 #[cfg_attr(docsrs, doc(cfg(all())))]
353 pub fn maximum_name_length(&self) -> u32 {
354 self.0.f_namemax
355 }
356
357 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
359 #[cfg_attr(docsrs, doc(cfg(all())))]
360 pub fn maximum_name_length(&self) -> u32 {
361 self.0.f_namelen
362 }
363
364 #[cfg(all(target_os = "linux", target_env = "musl"))]
366 #[cfg_attr(docsrs, doc(cfg(all())))]
367 pub fn maximum_name_length(&self) -> libc::c_ulong {
368 self.0.f_namelen
369 }
370
371 #[cfg(all(target_os = "linux", target_env = "uclibc"))]
373 #[cfg_attr(docsrs, doc(cfg(all())))]
374 pub fn maximum_name_length(&self) -> libc::c_int {
375 self.0.f_namelen
376 }
377
378 #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl", target_env = "uclibc"))))]
380 #[cfg_attr(docsrs, doc(cfg(all())))]
381 pub fn maximum_name_length(&self) -> libc::__fsword_t {
382 self.0.f_namelen
383 }
384
385 #[cfg(target_os = "android")]
387 #[cfg_attr(docsrs, doc(cfg(all())))]
388 pub fn maximum_name_length(&self) -> libc::c_ulong {
389 self.0.f_namelen
390 }
391
392 #[cfg(any(
394 target_os = "ios",
395 target_os = "macos",
396 target_os = "android",
397 target_os = "freebsd",
398 target_os = "openbsd",
399 ))]
400 #[cfg_attr(docsrs, doc(cfg(all())))]
401 pub fn blocks(&self) -> u64 {
402 self.0.f_blocks
403 }
404
405 #[cfg(target_os = "dragonfly")]
407 #[cfg_attr(docsrs, doc(cfg(all())))]
408 pub fn blocks(&self) -> libc::c_long {
409 self.0.f_blocks
410 }
411
412 #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
414 #[cfg_attr(docsrs, doc(cfg(all())))]
415 pub fn blocks(&self) -> u64 {
416 self.0.f_blocks
417 }
418
419 #[cfg(not(any(
421 target_os = "ios",
422 target_os = "macos",
423 target_os = "android",
424 target_os = "freebsd",
425 target_os = "openbsd",
426 target_os = "dragonfly",
427 all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
428 )))]
429 #[cfg_attr(docsrs, doc(cfg(all())))]
430 pub fn blocks(&self) -> libc::c_ulong {
431 self.0.f_blocks
432 }
433
434 #[cfg(any(
436 target_os = "ios",
437 target_os = "macos",
438 target_os = "android",
439 target_os = "freebsd",
440 target_os = "openbsd",
441 ))]
442 #[cfg_attr(docsrs, doc(cfg(all())))]
443 pub fn blocks_free(&self) -> u64 {
444 self.0.f_bfree
445 }
446
447 #[cfg(target_os = "dragonfly")]
449 #[cfg_attr(docsrs, doc(cfg(all())))]
450 pub fn blocks_free(&self) -> libc::c_long {
451 self.0.f_bfree
452 }
453
454 #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
456 #[cfg_attr(docsrs, doc(cfg(all())))]
457 pub fn blocks_free(&self) -> u64 {
458 self.0.f_bfree
459 }
460
461 #[cfg(not(any(
463 target_os = "ios",
464 target_os = "macos",
465 target_os = "android",
466 target_os = "freebsd",
467 target_os = "openbsd",
468 target_os = "dragonfly",
469 all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
470 )))]
471 #[cfg_attr(docsrs, doc(cfg(all())))]
472 pub fn blocks_free(&self) -> libc::c_ulong {
473 self.0.f_bfree
474 }
475
476 #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
478 #[cfg_attr(docsrs, doc(cfg(all())))]
479 pub fn blocks_available(&self) -> u64 {
480 self.0.f_bavail
481 }
482
483 #[cfg(target_os = "dragonfly")]
485 #[cfg_attr(docsrs, doc(cfg(all())))]
486 pub fn blocks_available(&self) -> libc::c_long {
487 self.0.f_bavail
488 }
489
490 #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
492 #[cfg_attr(docsrs, doc(cfg(all())))]
493 pub fn blocks_available(&self) -> i64 {
494 self.0.f_bavail
495 }
496
497 #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
499 #[cfg_attr(docsrs, doc(cfg(all())))]
500 pub fn blocks_available(&self) -> u64 {
501 self.0.f_bavail
502 }
503
504 #[cfg(not(any(
506 target_os = "ios",
507 target_os = "macos",
508 target_os = "android",
509 target_os = "freebsd",
510 target_os = "openbsd",
511 target_os = "dragonfly",
512 all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
513 )))]
514 #[cfg_attr(docsrs, doc(cfg(all())))]
515 pub fn blocks_available(&self) -> libc::c_ulong {
516 self.0.f_bavail
517 }
518
519 #[cfg(any(
521 target_os = "ios",
522 target_os = "macos",
523 target_os = "android",
524 target_os = "freebsd",
525 target_os = "openbsd",
526 ))]
527 #[cfg_attr(docsrs, doc(cfg(all())))]
528 pub fn files(&self) -> u64 {
529 self.0.f_files
530 }
531
532 #[cfg(target_os = "dragonfly")]
534 #[cfg_attr(docsrs, doc(cfg(all())))]
535 pub fn files(&self) -> libc::c_long {
536 self.0.f_files
537 }
538
539 #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
541 #[cfg_attr(docsrs, doc(cfg(all())))]
542 pub fn files(&self) -> libc::fsfilcnt_t {
543 self.0.f_files
544 }
545
546 #[cfg(not(any(
548 target_os = "ios",
549 target_os = "macos",
550 target_os = "android",
551 target_os = "freebsd",
552 target_os = "openbsd",
553 target_os = "dragonfly",
554 all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
555 )))]
556 #[cfg_attr(docsrs, doc(cfg(all())))]
557 pub fn files(&self) -> libc::c_ulong {
558 self.0.f_files
559 }
560
561 #[cfg(any(
563 target_os = "android",
564 target_os = "ios",
565 target_os = "macos",
566 target_os = "openbsd"
567 ))]
568 #[cfg_attr(docsrs, doc(cfg(all())))]
569 pub fn files_free(&self) -> u64 {
570 self.0.f_ffree
571 }
572
573 #[cfg(target_os = "dragonfly")]
575 #[cfg_attr(docsrs, doc(cfg(all())))]
576 pub fn files_free(&self) -> libc::c_long {
577 self.0.f_ffree
578 }
579
580 #[cfg(target_os = "freebsd")]
582 #[cfg_attr(docsrs, doc(cfg(all())))]
583 pub fn files_free(&self) -> i64 {
584 self.0.f_ffree
585 }
586
587 #[cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32"))))]
589 #[cfg_attr(docsrs, doc(cfg(all())))]
590 pub fn files_free(&self) -> libc::fsfilcnt_t {
591 self.0.f_ffree
592 }
593
594 #[cfg(not(any(
596 target_os = "ios",
597 target_os = "macos",
598 target_os = "android",
599 target_os = "freebsd",
600 target_os = "openbsd",
601 target_os = "dragonfly",
602 all(target_os = "linux", any(target_env = "musl", target_arch = "riscv32", all(target_arch = "x86_64", target_pointer_width = "32")))
603 )))]
604 #[cfg_attr(docsrs, doc(cfg(all())))]
605 pub fn files_free(&self) -> libc::c_ulong {
606 self.0.f_ffree
607 }
608
609 pub fn filesystem_id(&self) -> fsid_t {
611 self.0.f_fsid
612 }
613}
614
615impl Debug for Statfs {
616 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
617 f.debug_struct("Statfs")
618 .field("optimal_transfer_size", &self.optimal_transfer_size())
619 .field("block_size", &self.block_size())
620 .field("blocks", &self.blocks())
621 .field("blocks_free", &self.blocks_free())
622 .field("blocks_available", &self.blocks_available())
623 .field("files", &self.files())
624 .field("files_free", &self.files_free())
625 .field("filesystem_id", &self.filesystem_id())
626 .finish()
627 }
628}
629
630pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
639 unsafe {
640 let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
641 let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?;
642 Errno::result(res).map(|_| Statfs(stat.assume_init()))
643 }
644}
645
646pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
655 unsafe {
656 let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
657 Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr()))
658 .map(|_| Statfs(stat.assume_init()))
659 }
660}
661
662#[cfg(test)]
663mod test {
664 use std::fs::File;
665
666 use crate::sys::statfs::*;
667 use crate::sys::statvfs::*;
668 use std::path::Path;
669
670 #[test]
671 fn statfs_call() {
672 check_statfs("/tmp");
673 check_statfs("/dev");
674 check_statfs("/run");
675 check_statfs("/");
676 }
677
678 #[test]
679 fn fstatfs_call() {
680 check_fstatfs("/tmp");
681 check_fstatfs("/dev");
682 check_fstatfs("/run");
683 check_fstatfs("/");
684 }
685
686 fn check_fstatfs(path: &str) {
687 if !Path::new(path).exists() {
688 return;
689 }
690 let vfs = statvfs(path.as_bytes()).unwrap();
691 let file = File::open(path).unwrap();
692 let fs = fstatfs(&file).unwrap();
693 assert_fs_equals(fs, vfs);
694 }
695
696 fn check_statfs(path: &str) {
697 if !Path::new(path).exists() {
698 return;
699 }
700 let vfs = statvfs(path.as_bytes()).unwrap();
701 let fs = statfs(path.as_bytes()).unwrap();
702 assert_fs_equals(fs, vfs);
703 }
704
705 #[allow(clippy::unnecessary_cast)]
707 fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
708 assert_eq!(fs.files() as u64, vfs.files() as u64);
709 assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
710 assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
711 }
712
713 #[test]
716 #[ignore]
717 fn statfs_call_strict() {
718 check_statfs_strict("/tmp");
719 check_statfs_strict("/dev");
720 check_statfs_strict("/run");
721 check_statfs_strict("/");
722 }
723
724 #[test]
727 #[ignore]
728 fn fstatfs_call_strict() {
729 check_fstatfs_strict("/tmp");
730 check_fstatfs_strict("/dev");
731 check_fstatfs_strict("/run");
732 check_fstatfs_strict("/");
733 }
734
735 fn check_fstatfs_strict(path: &str) {
736 if !Path::new(path).exists() {
737 return;
738 }
739 let vfs = statvfs(path.as_bytes());
740 let file = File::open(path).unwrap();
741 let fs = fstatfs(&file);
742 assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
743 }
744
745 fn check_statfs_strict(path: &str) {
746 if !Path::new(path).exists() {
747 return;
748 }
749 let vfs = statvfs(path.as_bytes());
750 let fs = statfs(path.as_bytes());
751 assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
752 }
753
754 #[allow(clippy::unnecessary_cast)]
756 fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
757 assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
758 assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
759 assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
760 assert_eq!(fs.files() as u64, vfs.files() as u64);
761 assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
762 assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
763 }
764}