1 //! Get filesystem statistics, non-portably
2 //!
3 //! See [`statvfs`](crate::sys::statvfs) for a portable alternative.
4 #[cfg(not(any(target_os = "linux", target_os = "android")))]
5 use std::ffi::CStr;
6 use std::fmt::{self, Debug};
7 use std::mem;
8 use std::os::unix::io::AsRawFd;
9
10 use cfg_if::cfg_if;
11
12 #[cfg(all(
13 feature = "mount",
14 any(
15 target_os = "dragonfly",
16 target_os = "freebsd",
17 target_os = "macos",
18 target_os = "netbsd",
19 target_os = "openbsd"
20 )
21 ))]
22 use crate::mount::MntFlags;
23 #[cfg(target_os = "linux")]
24 use crate::sys::statvfs::FsFlags;
25 use crate::{errno::Errno, NixPath, Result};
26
27 /// Identifies a mounted file system
28 #[cfg(target_os = "android")]
29 #[cfg_attr(docsrs, doc(cfg(all())))]
30 pub type fsid_t = libc::__fsid_t;
31 /// Identifies a mounted file system
32 #[cfg(not(target_os = "android"))]
33 #[cfg_attr(docsrs, doc(cfg(all())))]
34 pub type fsid_t = libc::fsid_t;
35
36 cfg_if! {
37 if #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] {
38 type type_of_statfs = libc::statfs64;
39 const LIBC_FSTATFS: unsafe extern fn
40 (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
41 = libc::fstatfs64;
42 const LIBC_STATFS: unsafe extern fn
43 (path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int
44 = libc::statfs64;
45 } else {
46 type type_of_statfs = libc::statfs;
47 const LIBC_FSTATFS: unsafe extern fn
48 (fd: libc::c_int, buf: *mut type_of_statfs) -> libc::c_int
49 = libc::fstatfs;
50 const LIBC_STATFS: unsafe extern fn
51 (path: *const libc::c_char, buf: *mut type_of_statfs) -> libc::c_int
52 = libc::statfs;
53 }
54 }
55
56 /// Describes a mounted file system
57 #[derive(Clone, Copy)]
58 #[repr(transparent)]
59 pub struct Statfs(type_of_statfs);
60
61 #[cfg(target_os = "freebsd")]
62 type fs_type_t = u32;
63 #[cfg(target_os = "android")]
64 type fs_type_t = libc::c_ulong;
65 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
66 type fs_type_t = libc::c_uint;
67 #[cfg(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")))]
68 type fs_type_t = libc::c_ulong;
69 #[cfg(all(target_os = "linux", target_env = "uclibc"))]
70 type fs_type_t = libc::c_int;
71 #[cfg(all(
72 target_os = "linux",
73 not(any(
74 target_arch = "s390x",
75 target_env = "musl",
76 target_env = "ohos",
77 target_env = "uclibc"
78 ))
79 ))]
80 type fs_type_t = libc::__fsword_t;
81
82 /// Describes the file system type as known by the operating system.
83 #[cfg(any(
84 target_os = "freebsd",
85 target_os = "android",
86 all(target_os = "linux", target_arch = "s390x"),
87 all(target_os = "linux", any(target_env = "musl", target_env = "ohos")),
88 all(
89 target_os = "linux",
90 not(any(target_arch = "s390x", target_env = "musl", target_env = "ohos"))
91 ),
92 ))]
93 #[derive(Eq, Copy, Clone, PartialEq, Debug)]
94 pub struct FsType(pub fs_type_t);
95
96 // These constants are defined without documentation in the Linux headers, so we
97 // can't very well document them here.
98 #[cfg(any(target_os = "linux", target_os = "android"))]
99 #[allow(missing_docs)]
100 pub const ADFS_SUPER_MAGIC: FsType =
101 FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
102 #[cfg(any(target_os = "linux", target_os = "android"))]
103 #[allow(missing_docs)]
104 pub const AFFS_SUPER_MAGIC: FsType =
105 FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
106 #[cfg(any(target_os = "linux", target_os = "android"))]
107 #[allow(missing_docs)]
108 pub const AFS_SUPER_MAGIC: FsType = FsType(libc::AFS_SUPER_MAGIC as fs_type_t);
109 #[cfg(any(target_os = "linux", target_os = "android"))]
110 #[allow(missing_docs)]
111 pub const AUTOFS_SUPER_MAGIC: FsType =
112 FsType(libc::AUTOFS_SUPER_MAGIC as fs_type_t);
113 #[cfg(any(target_os = "linux", target_os = "android"))]
114 #[allow(missing_docs)]
115 pub const BPF_FS_MAGIC: FsType = FsType(libc::BPF_FS_MAGIC as fs_type_t);
116 #[cfg(any(target_os = "linux", target_os = "android"))]
117 #[allow(missing_docs)]
118 pub const BTRFS_SUPER_MAGIC: FsType =
119 FsType(libc::BTRFS_SUPER_MAGIC as fs_type_t);
120 #[cfg(any(target_os = "linux", target_os = "android"))]
121 #[allow(missing_docs)]
122 pub const CGROUP2_SUPER_MAGIC: FsType =
123 FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
124 #[cfg(any(target_os = "linux", target_os = "android"))]
125 #[allow(missing_docs)]
126 pub const CGROUP_SUPER_MAGIC: FsType =
127 FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
128 #[cfg(any(target_os = "linux", target_os = "android"))]
129 #[allow(missing_docs)]
130 pub const CODA_SUPER_MAGIC: FsType =
131 FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
132 #[cfg(any(target_os = "linux", target_os = "android"))]
133 #[allow(missing_docs)]
134 pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
135 #[cfg(any(target_os = "linux", target_os = "android"))]
136 #[allow(missing_docs)]
137 pub const DEBUGFS_MAGIC: FsType = FsType(libc::DEBUGFS_MAGIC as fs_type_t);
138 #[cfg(any(target_os = "linux", target_os = "android"))]
139 #[allow(missing_docs)]
140 pub const DEVPTS_SUPER_MAGIC: FsType =
141 FsType(libc::DEVPTS_SUPER_MAGIC as fs_type_t);
142 #[cfg(any(target_os = "linux", target_os = "android"))]
143 #[allow(missing_docs)]
144 pub const ECRYPTFS_SUPER_MAGIC: FsType =
145 FsType(libc::ECRYPTFS_SUPER_MAGIC as fs_type_t);
146 #[cfg(any(target_os = "linux", target_os = "android"))]
147 #[allow(missing_docs)]
148 pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
149 #[cfg(any(target_os = "linux", target_os = "android"))]
150 #[allow(missing_docs)]
151 pub const EXT2_SUPER_MAGIC: FsType =
152 FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
153 #[cfg(any(target_os = "linux", target_os = "android"))]
154 #[allow(missing_docs)]
155 pub const EXT3_SUPER_MAGIC: FsType =
156 FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
157 #[cfg(any(target_os = "linux", target_os = "android"))]
158 #[allow(missing_docs)]
159 pub const EXT4_SUPER_MAGIC: FsType =
160 FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
161 #[cfg(any(target_os = "linux", target_os = "android"))]
162 #[allow(missing_docs)]
163 pub const F2FS_SUPER_MAGIC: FsType =
164 FsType(libc::F2FS_SUPER_MAGIC as fs_type_t);
165 #[cfg(any(target_os = "linux", target_os = "android"))]
166 #[allow(missing_docs)]
167 pub const FUSE_SUPER_MAGIC: FsType =
168 FsType(libc::FUSE_SUPER_MAGIC as fs_type_t);
169 #[cfg(any(target_os = "linux", target_os = "android"))]
170 #[allow(missing_docs)]
171 pub const FUTEXFS_SUPER_MAGIC: FsType =
172 FsType(libc::FUTEXFS_SUPER_MAGIC as fs_type_t);
173 #[cfg(any(target_os = "linux", target_os = "android"))]
174 #[allow(missing_docs)]
175 pub const HOSTFS_SUPER_MAGIC: FsType =
176 FsType(libc::HOSTFS_SUPER_MAGIC as fs_type_t);
177 #[cfg(any(target_os = "linux", target_os = "android"))]
178 #[allow(missing_docs)]
179 pub const HPFS_SUPER_MAGIC: FsType =
180 FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
181 #[cfg(any(target_os = "linux", target_os = "android"))]
182 #[allow(missing_docs)]
183 pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
184 #[cfg(any(target_os = "linux", target_os = "android"))]
185 #[allow(missing_docs)]
186 pub const ISOFS_SUPER_MAGIC: FsType =
187 FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
188 #[cfg(any(target_os = "linux", target_os = "android"))]
189 #[allow(missing_docs)]
190 pub const JFFS2_SUPER_MAGIC: FsType =
191 FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
192 #[cfg(any(target_os = "linux", target_os = "android"))]
193 #[allow(missing_docs)]
194 pub const MINIX2_SUPER_MAGIC2: FsType =
195 FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
196 #[cfg(any(target_os = "linux", target_os = "android"))]
197 #[allow(missing_docs)]
198 pub const MINIX2_SUPER_MAGIC: FsType =
199 FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
200 #[cfg(any(target_os = "linux", target_os = "android"))]
201 #[allow(missing_docs)]
202 pub const MINIX3_SUPER_MAGIC: FsType =
203 FsType(libc::MINIX3_SUPER_MAGIC as fs_type_t);
204 #[cfg(any(target_os = "linux", target_os = "android"))]
205 #[allow(missing_docs)]
206 pub const MINIX_SUPER_MAGIC2: FsType =
207 FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
208 #[cfg(any(target_os = "linux", target_os = "android"))]
209 #[allow(missing_docs)]
210 pub const MINIX_SUPER_MAGIC: FsType =
211 FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
212 #[cfg(any(target_os = "linux", target_os = "android"))]
213 #[allow(missing_docs)]
214 pub const MSDOS_SUPER_MAGIC: FsType =
215 FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
216 #[cfg(any(target_os = "linux", target_os = "android"))]
217 #[allow(missing_docs)]
218 pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
219 #[cfg(any(target_os = "linux", target_os = "android"))]
220 #[allow(missing_docs)]
221 pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
222 #[cfg(any(target_os = "linux", target_os = "android"))]
223 #[allow(missing_docs)]
224 pub const NILFS_SUPER_MAGIC: FsType =
225 FsType(libc::NILFS_SUPER_MAGIC as fs_type_t);
226 #[cfg(any(target_os = "linux", target_os = "android"))]
227 #[allow(missing_docs)]
228 pub const OCFS2_SUPER_MAGIC: FsType =
229 FsType(libc::OCFS2_SUPER_MAGIC as fs_type_t);
230 #[cfg(any(target_os = "linux", target_os = "android"))]
231 #[allow(missing_docs)]
232 pub const OPENPROM_SUPER_MAGIC: FsType =
233 FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
234 #[cfg(any(target_os = "linux", target_os = "android"))]
235 #[allow(missing_docs)]
236 pub const OVERLAYFS_SUPER_MAGIC: FsType =
237 FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
238 #[cfg(any(target_os = "linux", target_os = "android"))]
239 #[allow(missing_docs)]
240 pub const PROC_SUPER_MAGIC: FsType =
241 FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
242 #[cfg(any(target_os = "linux", target_os = "android"))]
243 #[allow(missing_docs)]
244 pub const QNX4_SUPER_MAGIC: FsType =
245 FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
246 #[cfg(any(target_os = "linux", target_os = "android"))]
247 #[allow(missing_docs)]
248 pub const QNX6_SUPER_MAGIC: FsType =
249 FsType(libc::QNX6_SUPER_MAGIC as fs_type_t);
250 #[cfg(any(target_os = "linux", target_os = "android"))]
251 #[allow(missing_docs)]
252 pub const RDTGROUP_SUPER_MAGIC: FsType =
253 FsType(libc::RDTGROUP_SUPER_MAGIC as fs_type_t);
254 #[cfg(any(target_os = "linux", target_os = "android"))]
255 #[allow(missing_docs)]
256 pub const REISERFS_SUPER_MAGIC: FsType =
257 FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
258 #[cfg(any(target_os = "linux", target_os = "android"))]
259 #[allow(missing_docs)]
260 pub const SECURITYFS_MAGIC: FsType =
261 FsType(libc::SECURITYFS_MAGIC as fs_type_t);
262 #[cfg(any(target_os = "linux", target_os = "android"))]
263 #[allow(missing_docs)]
264 pub const SELINUX_MAGIC: FsType = FsType(libc::SELINUX_MAGIC as fs_type_t);
265 #[cfg(any(target_os = "linux", target_os = "android"))]
266 #[allow(missing_docs)]
267 pub const SMACK_MAGIC: FsType = FsType(libc::SMACK_MAGIC as fs_type_t);
268 #[cfg(any(target_os = "linux", target_os = "android"))]
269 #[allow(missing_docs)]
270 pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
271 #[cfg(any(target_os = "linux", target_os = "android"))]
272 #[allow(missing_docs)]
273 pub const SYSFS_MAGIC: FsType = FsType(libc::SYSFS_MAGIC as fs_type_t);
274 #[cfg(any(target_os = "linux", target_os = "android"))]
275 #[allow(missing_docs)]
276 pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
277 #[cfg(any(target_os = "linux", target_os = "android"))]
278 #[allow(missing_docs)]
279 pub const TRACEFS_MAGIC: FsType = FsType(libc::TRACEFS_MAGIC as fs_type_t);
280 #[cfg(any(target_os = "linux", target_os = "android"))]
281 #[allow(missing_docs)]
282 pub const UDF_SUPER_MAGIC: FsType = FsType(libc::UDF_SUPER_MAGIC as fs_type_t);
283 #[cfg(any(target_os = "linux", target_os = "android"))]
284 #[allow(missing_docs)]
285 pub const USBDEVICE_SUPER_MAGIC: FsType =
286 FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
287 #[cfg(any(target_os = "linux", target_os = "android"))]
288 #[allow(missing_docs)]
289 pub const XENFS_SUPER_MAGIC: FsType =
290 FsType(libc::XENFS_SUPER_MAGIC as fs_type_t);
291 #[cfg(any(target_os = "linux", target_os = "android"))]
292 #[allow(missing_docs)]
293 pub const NSFS_MAGIC: FsType = FsType(libc::NSFS_MAGIC as fs_type_t);
294 #[cfg(all(
295 any(target_os = "linux", target_os = "android"),
296 not(any(target_env = "musl", target_env = "ohos"))
297 ))]
298 #[allow(missing_docs)]
299 pub const XFS_SUPER_MAGIC: FsType = FsType(libc::XFS_SUPER_MAGIC as fs_type_t);
300
301 impl Statfs {
302 /// Magic code defining system type
303 #[cfg(not(any(
304 target_os = "openbsd",
305 target_os = "dragonfly",
306 target_os = "ios",
307 target_os = "macos"
308 )))]
309 #[cfg_attr(docsrs, doc(cfg(all())))]
filesystem_type(&self) -> FsType310 pub fn filesystem_type(&self) -> FsType {
311 FsType(self.0.f_type)
312 }
313
314 /// Magic code defining system type
315 #[cfg(not(any(target_os = "linux", target_os = "android")))]
316 #[cfg_attr(docsrs, doc(cfg(all())))]
filesystem_type_name(&self) -> &str317 pub fn filesystem_type_name(&self) -> &str {
318 let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
319 c_str.to_str().unwrap()
320 }
321
322 /// Optimal transfer block size
323 #[cfg(any(target_os = "ios", target_os = "macos"))]
324 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> i32325 pub fn optimal_transfer_size(&self) -> i32 {
326 self.0.f_iosize
327 }
328
329 /// Optimal transfer block size
330 #[cfg(target_os = "openbsd")]
331 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> u32332 pub fn optimal_transfer_size(&self) -> u32 {
333 self.0.f_iosize
334 }
335
336 /// Optimal transfer block size
337 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
338 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> u32339 pub fn optimal_transfer_size(&self) -> u32 {
340 self.0.f_bsize
341 }
342
343 /// Optimal transfer block size
344 #[cfg(any(
345 target_os = "android",
346 all(target_os = "linux", any(target_env = "musl", target_env = "ohos"))
347 ))]
348 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> libc::c_ulong349 pub fn optimal_transfer_size(&self) -> libc::c_ulong {
350 self.0.f_bsize
351 }
352
353 /// Optimal transfer block size
354 #[cfg(all(
355 target_os = "linux",
356 not(any(
357 target_arch = "s390x",
358 target_env = "musl",
359 target_env = "ohos",
360 target_env = "uclibc"
361 ))
362 ))]
363 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> libc::__fsword_t364 pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
365 self.0.f_bsize
366 }
367
368 /// Optimal transfer block size
369 #[cfg(all(target_os = "linux", target_env = "uclibc"))]
370 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> libc::c_int371 pub fn optimal_transfer_size(&self) -> libc::c_int {
372 self.0.f_bsize
373 }
374
375 /// Optimal transfer block size
376 #[cfg(target_os = "dragonfly")]
377 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> libc::c_long378 pub fn optimal_transfer_size(&self) -> libc::c_long {
379 self.0.f_iosize
380 }
381
382 /// Optimal transfer block size
383 #[cfg(target_os = "freebsd")]
384 #[cfg_attr(docsrs, doc(cfg(all())))]
optimal_transfer_size(&self) -> u64385 pub fn optimal_transfer_size(&self) -> u64 {
386 self.0.f_iosize
387 }
388
389 /// Size of a block
390 #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
391 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> u32392 pub fn block_size(&self) -> u32 {
393 self.0.f_bsize
394 }
395
396 /// Size of a block
397 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
398 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
399 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> u32400 pub fn block_size(&self) -> u32 {
401 self.0.f_bsize
402 }
403
404 /// Size of a block
405 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
406 #[cfg(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")))]
407 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> libc::c_ulong408 pub fn block_size(&self) -> libc::c_ulong {
409 self.0.f_bsize
410 }
411
412 /// Size of a block
413 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
414 #[cfg(all(target_os = "linux", target_env = "uclibc"))]
415 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> libc::c_int416 pub fn block_size(&self) -> libc::c_int {
417 self.0.f_bsize
418 }
419
420 /// Size of a block
421 // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
422 #[cfg(all(
423 target_os = "linux",
424 not(any(
425 target_arch = "s390x",
426 target_env = "musl",
427 target_env = "ohos",
428 target_env = "uclibc"
429 ))
430 ))]
431 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> libc::__fsword_t432 pub fn block_size(&self) -> libc::__fsword_t {
433 self.0.f_bsize
434 }
435
436 /// Size of a block
437 #[cfg(target_os = "freebsd")]
438 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> u64439 pub fn block_size(&self) -> u64 {
440 self.0.f_bsize
441 }
442
443 /// Size of a block
444 #[cfg(target_os = "android")]
445 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> libc::c_ulong446 pub fn block_size(&self) -> libc::c_ulong {
447 self.0.f_bsize
448 }
449
450 /// Size of a block
451 #[cfg(target_os = "dragonfly")]
452 #[cfg_attr(docsrs, doc(cfg(all())))]
block_size(&self) -> libc::c_long453 pub fn block_size(&self) -> libc::c_long {
454 self.0.f_bsize
455 }
456
457 /// Get the mount flags
458 #[cfg(all(
459 feature = "mount",
460 any(
461 target_os = "dragonfly",
462 target_os = "freebsd",
463 target_os = "macos",
464 target_os = "netbsd",
465 target_os = "openbsd"
466 )
467 ))]
468 #[cfg_attr(docsrs, doc(cfg(all())))]
469 #[allow(clippy::unnecessary_cast)] // Not unnecessary on all arches
flags(&self) -> MntFlags470 pub fn flags(&self) -> MntFlags {
471 MntFlags::from_bits_truncate(self.0.f_flags as i32)
472 }
473
474 /// Get the mount flags
475 // The f_flags field exists on Android and Fuchsia too, but without man
476 // pages I can't tell if it can be cast to FsFlags.
477 #[cfg(target_os = "linux")]
478 #[cfg_attr(docsrs, doc(cfg(all())))]
flags(&self) -> FsFlags479 pub fn flags(&self) -> FsFlags {
480 FsFlags::from_bits_truncate(self.0.f_flags as libc::c_ulong)
481 }
482
483 /// Maximum length of filenames
484 #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
485 #[cfg_attr(docsrs, doc(cfg(all())))]
maximum_name_length(&self) -> u32486 pub fn maximum_name_length(&self) -> u32 {
487 self.0.f_namemax
488 }
489
490 /// Maximum length of filenames
491 #[cfg(all(target_os = "linux", target_arch = "s390x"))]
492 #[cfg_attr(docsrs, doc(cfg(all())))]
maximum_name_length(&self) -> u32493 pub fn maximum_name_length(&self) -> u32 {
494 self.0.f_namelen
495 }
496
497 /// Maximum length of filenames
498 #[cfg(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")))]
499 #[cfg_attr(docsrs, doc(cfg(all())))]
maximum_name_length(&self) -> libc::c_ulong500 pub fn maximum_name_length(&self) -> libc::c_ulong {
501 self.0.f_namelen
502 }
503
504 /// Maximum length of filenames
505 #[cfg(all(target_os = "linux", target_env = "uclibc"))]
506 #[cfg_attr(docsrs, doc(cfg(all())))]
maximum_name_length(&self) -> libc::c_int507 pub fn maximum_name_length(&self) -> libc::c_int {
508 self.0.f_namelen
509 }
510
511 /// Maximum length of filenames
512 #[cfg(all(
513 target_os = "linux",
514 not(any(
515 target_arch = "s390x",
516 target_env = "musl",
517 target_env = "ohos",
518 target_env = "uclibc"
519 ))
520 ))]
521 #[cfg_attr(docsrs, doc(cfg(all())))]
maximum_name_length(&self) -> libc::__fsword_t522 pub fn maximum_name_length(&self) -> libc::__fsword_t {
523 self.0.f_namelen
524 }
525
526 /// Maximum length of filenames
527 #[cfg(target_os = "android")]
528 #[cfg_attr(docsrs, doc(cfg(all())))]
maximum_name_length(&self) -> libc::c_ulong529 pub fn maximum_name_length(&self) -> libc::c_ulong {
530 self.0.f_namelen
531 }
532
533 /// Total data blocks in filesystem
534 #[cfg(any(
535 target_os = "ios",
536 target_os = "macos",
537 target_os = "android",
538 target_os = "freebsd",
539 target_os = "fuchsia",
540 target_os = "openbsd",
541 target_os = "linux",
542 ))]
543 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks(&self) -> u64544 pub fn blocks(&self) -> u64 {
545 self.0.f_blocks
546 }
547
548 /// Total data blocks in filesystem
549 #[cfg(target_os = "dragonfly")]
550 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks(&self) -> libc::c_long551 pub fn blocks(&self) -> libc::c_long {
552 self.0.f_blocks
553 }
554
555 /// Total data blocks in filesystem
556 #[cfg(target_os = "emscripten")]
557 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks(&self) -> u32558 pub fn blocks(&self) -> u32 {
559 self.0.f_blocks
560 }
561
562 /// Free blocks in filesystem
563 #[cfg(any(
564 target_os = "ios",
565 target_os = "macos",
566 target_os = "android",
567 target_os = "freebsd",
568 target_os = "fuchsia",
569 target_os = "openbsd",
570 target_os = "linux",
571 ))]
572 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks_free(&self) -> u64573 pub fn blocks_free(&self) -> u64 {
574 self.0.f_bfree
575 }
576
577 /// Free blocks in filesystem
578 #[cfg(target_os = "dragonfly")]
579 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks_free(&self) -> libc::c_long580 pub fn blocks_free(&self) -> libc::c_long {
581 self.0.f_bfree
582 }
583
584 /// Free blocks in filesystem
585 #[cfg(target_os = "emscripten")]
586 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks_free(&self) -> u32587 pub fn blocks_free(&self) -> u32 {
588 self.0.f_bfree
589 }
590
591 /// Free blocks available to unprivileged user
592 #[cfg(any(
593 target_os = "ios",
594 target_os = "macos",
595 target_os = "android",
596 target_os = "fuchsia",
597 target_os = "linux",
598 ))]
599 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks_available(&self) -> u64600 pub fn blocks_available(&self) -> u64 {
601 self.0.f_bavail
602 }
603
604 /// Free blocks available to unprivileged user
605 #[cfg(target_os = "dragonfly")]
606 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks_available(&self) -> libc::c_long607 pub fn blocks_available(&self) -> libc::c_long {
608 self.0.f_bavail
609 }
610
611 /// Free blocks available to unprivileged user
612 #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
613 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks_available(&self) -> i64614 pub fn blocks_available(&self) -> i64 {
615 self.0.f_bavail
616 }
617
618 /// Free blocks available to unprivileged user
619 #[cfg(target_os = "emscripten")]
620 #[cfg_attr(docsrs, doc(cfg(all())))]
blocks_available(&self) -> u32621 pub fn blocks_available(&self) -> u32 {
622 self.0.f_bavail
623 }
624
625 /// Total file nodes in filesystem
626 #[cfg(any(
627 target_os = "ios",
628 target_os = "macos",
629 target_os = "android",
630 target_os = "freebsd",
631 target_os = "fuchsia",
632 target_os = "openbsd",
633 target_os = "linux",
634 ))]
635 #[cfg_attr(docsrs, doc(cfg(all())))]
files(&self) -> u64636 pub fn files(&self) -> u64 {
637 self.0.f_files
638 }
639
640 /// Total file nodes in filesystem
641 #[cfg(target_os = "dragonfly")]
642 #[cfg_attr(docsrs, doc(cfg(all())))]
files(&self) -> libc::c_long643 pub fn files(&self) -> libc::c_long {
644 self.0.f_files
645 }
646
647 /// Total file nodes in filesystem
648 #[cfg(target_os = "emscripten")]
649 #[cfg_attr(docsrs, doc(cfg(all())))]
files(&self) -> u32650 pub fn files(&self) -> u32 {
651 self.0.f_files
652 }
653
654 /// Free file nodes in filesystem
655 #[cfg(any(
656 target_os = "ios",
657 target_os = "macos",
658 target_os = "android",
659 target_os = "fuchsia",
660 target_os = "openbsd",
661 target_os = "linux",
662 ))]
663 #[cfg_attr(docsrs, doc(cfg(all())))]
files_free(&self) -> u64664 pub fn files_free(&self) -> u64 {
665 self.0.f_ffree
666 }
667
668 /// Free file nodes in filesystem
669 #[cfg(target_os = "dragonfly")]
670 #[cfg_attr(docsrs, doc(cfg(all())))]
files_free(&self) -> libc::c_long671 pub fn files_free(&self) -> libc::c_long {
672 self.0.f_ffree
673 }
674
675 /// Free file nodes in filesystem
676 #[cfg(target_os = "freebsd")]
677 #[cfg_attr(docsrs, doc(cfg(all())))]
files_free(&self) -> i64678 pub fn files_free(&self) -> i64 {
679 self.0.f_ffree
680 }
681
682 /// Free file nodes in filesystem
683 #[cfg(target_os = "emscripten")]
684 #[cfg_attr(docsrs, doc(cfg(all())))]
files_free(&self) -> u32685 pub fn files_free(&self) -> u32 {
686 self.0.f_ffree
687 }
688
689 /// Filesystem ID
filesystem_id(&self) -> fsid_t690 pub fn filesystem_id(&self) -> fsid_t {
691 self.0.f_fsid
692 }
693 }
694
695 impl Debug for Statfs {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result696 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
697 let mut ds = f.debug_struct("Statfs");
698 ds.field("optimal_transfer_size", &self.optimal_transfer_size());
699 ds.field("block_size", &self.block_size());
700 ds.field("blocks", &self.blocks());
701 ds.field("blocks_free", &self.blocks_free());
702 ds.field("blocks_available", &self.blocks_available());
703 ds.field("files", &self.files());
704 ds.field("files_free", &self.files_free());
705 ds.field("filesystem_id", &self.filesystem_id());
706 #[cfg(all(
707 feature = "mount",
708 any(
709 target_os = "dragonfly",
710 target_os = "freebsd",
711 target_os = "macos",
712 target_os = "netbsd",
713 target_os = "openbsd"
714 )
715 ))]
716 ds.field("flags", &self.flags());
717 ds.finish()
718 }
719 }
720
721 /// Describes a mounted file system.
722 ///
723 /// The result is OS-dependent. For a portable alternative, see
724 /// [`statvfs`](crate::sys::statvfs::statvfs).
725 ///
726 /// # Arguments
727 ///
728 /// `path` - Path to any file within the file system to describe
statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs>729 pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
730 unsafe {
731 let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
732 let res = path.with_nix_path(|path| {
733 LIBC_STATFS(path.as_ptr(), stat.as_mut_ptr())
734 })?;
735 Errno::result(res).map(|_| Statfs(stat.assume_init()))
736 }
737 }
738
739 /// Describes a mounted file system.
740 ///
741 /// The result is OS-dependent. For a portable alternative, see
742 /// [`fstatvfs`](crate::sys::statvfs::fstatvfs).
743 ///
744 /// # Arguments
745 ///
746 /// `fd` - File descriptor of any open file within the file system to describe
fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs>747 pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
748 unsafe {
749 let mut stat = mem::MaybeUninit::<type_of_statfs>::uninit();
750 Errno::result(LIBC_FSTATFS(fd.as_raw_fd(), stat.as_mut_ptr()))
751 .map(|_| Statfs(stat.assume_init()))
752 }
753 }
754
755 #[cfg(test)]
756 mod test {
757 use std::fs::File;
758
759 use crate::sys::statfs::*;
760 use crate::sys::statvfs::*;
761 use std::path::Path;
762
763 #[test]
statfs_call()764 fn statfs_call() {
765 check_statfs("/tmp");
766 check_statfs("/dev");
767 check_statfs("/run");
768 check_statfs("/");
769 }
770
771 #[test]
fstatfs_call()772 fn fstatfs_call() {
773 check_fstatfs("/tmp");
774 check_fstatfs("/dev");
775 check_fstatfs("/run");
776 check_fstatfs("/");
777 }
778
check_fstatfs(path: &str)779 fn check_fstatfs(path: &str) {
780 if !Path::new(path).exists() {
781 return;
782 }
783 let vfs = statvfs(path.as_bytes()).unwrap();
784 let file = File::open(path).unwrap();
785 let fs = fstatfs(&file).unwrap();
786 assert_fs_equals(fs, vfs);
787 }
788
check_statfs(path: &str)789 fn check_statfs(path: &str) {
790 if !Path::new(path).exists() {
791 return;
792 }
793 let vfs = statvfs(path.as_bytes()).unwrap();
794 let fs = statfs(path.as_bytes()).unwrap();
795 assert_fs_equals(fs, vfs);
796 }
797
798 // The cast is not unnecessary on all platforms.
799 #[allow(clippy::unnecessary_cast)]
assert_fs_equals(fs: Statfs, vfs: Statvfs)800 fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
801 assert_eq!(fs.files() as u64, vfs.files() as u64);
802 assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
803 assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
804 }
805
806 // This test is ignored because files_free/blocks_free can change after statvfs call and before
807 // statfs call.
808 #[test]
809 #[ignore]
statfs_call_strict()810 fn statfs_call_strict() {
811 check_statfs_strict("/tmp");
812 check_statfs_strict("/dev");
813 check_statfs_strict("/run");
814 check_statfs_strict("/");
815 }
816
817 // This test is ignored because files_free/blocks_free can change after statvfs call and before
818 // fstatfs call.
819 #[test]
820 #[ignore]
fstatfs_call_strict()821 fn fstatfs_call_strict() {
822 check_fstatfs_strict("/tmp");
823 check_fstatfs_strict("/dev");
824 check_fstatfs_strict("/run");
825 check_fstatfs_strict("/");
826 }
827
check_fstatfs_strict(path: &str)828 fn check_fstatfs_strict(path: &str) {
829 if !Path::new(path).exists() {
830 return;
831 }
832 let vfs = statvfs(path.as_bytes());
833 let file = File::open(path).unwrap();
834 let fs = fstatfs(&file);
835 assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
836 }
837
check_statfs_strict(path: &str)838 fn check_statfs_strict(path: &str) {
839 if !Path::new(path).exists() {
840 return;
841 }
842 let vfs = statvfs(path.as_bytes());
843 let fs = statfs(path.as_bytes());
844 assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
845 }
846
847 // The cast is not unnecessary on all platforms.
848 #[allow(clippy::unnecessary_cast)]
assert_fs_equals_strict(fs: Statfs, vfs: Statvfs)849 fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
850 assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
851 assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
852 assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
853 assert_eq!(fs.files() as u64, vfs.files() as u64);
854 assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
855 assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
856 }
857 }
858