Coverage Report

Created: 2024-05-20 06:38

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