      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161

    //! Get filesystem statistics
    //!
    //! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
    //! for more details.
    use std::mem;
    use std::os::unix::io::AsRawFd;

    use libc::{self, c_ulong};

    use {Result, NixPath};
    use errno::Errno;

    libc_bitflags!(
        /// File system mount Flags
        #[repr(C)]
        #[derive(Default)]
        pub struct FsFlags: c_ulong {
            /// Read Only
            ST_RDONLY;
            /// Do not allow the set-uid bits to have an effect
            ST_NOSUID;
            /// Do not interpret character or block-special devices
            #[cfg(any(target_os = "android", target_os = "linux"))]
            ST_NODEV;
            /// Do not allow execution of binaries on the filesystem
            #[cfg(any(target_os = "android", target_os = "linux"))]
            ST_NOEXEC;
            /// All IO should be done synchronously
            #[cfg(any(target_os = "android", target_os = "linux"))]
            ST_SYNCHRONOUS;
            /// Allow mandatory locks on the filesystem
            #[cfg(any(target_os = "android", target_os = "linux"))]
            ST_MANDLOCK;
            /// Write on file/directory/symlink
            #[cfg(target_os = "linux")]
            ST_WRITE;
            /// Append-only file
            #[cfg(target_os = "linux")]
            ST_APPEND;
            /// Immutable file
            #[cfg(target_os = "linux")]
            ST_IMMUTABLE;
            /// Do not update access times on files
            #[cfg(any(target_os = "android", target_os = "linux"))]
            ST_NOATIME;
            /// Do not update access times on files
            #[cfg(any(target_os = "android", target_os = "linux"))]
            ST_NODIRATIME;
            /// Update access time relative to modify/change time
            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))]
            ST_RELATIME;
        }
    );

    /// Wrapper around the POSIX `statvfs` struct
    ///
    /// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
    // FIXME: Replace with repr(transparent)
    #[repr(C)]
    #[derive(Clone, Copy)]
    #[allow(missing_debug_implementations)]
    pub struct Statvfs(libc::statvfs);

    impl Statvfs {
        /// get the file system block size
        pub fn block_size(&self) -> c_ulong {
            self.0.f_bsize
        }

        /// Get the fundamental file system block size
        pub fn fragment_size(&self) -> c_ulong {
            self.0.f_frsize
        }

        /// Get the number of blocks.
        ///
        /// Units are in units of `fragment_size()`
        pub fn blocks(&self) -> libc::fsblkcnt_t {
            self.0.f_blocks
        }

        /// Get the number of free blocks in the file system
        pub fn blocks_free(&self) -> libc::fsblkcnt_t {
            self.0.f_bfree
        }

        /// Get the number of free blocks for unprivileged users
        pub fn blocks_available(&self) -> libc::fsblkcnt_t {
            self.0.f_bavail
        }

        /// Get the total number of file inodes
        pub fn files(&self) -> libc::fsfilcnt_t {
            self.0.f_files
        }

        /// Get the number of free file inodes
        pub fn files_free(&self) -> libc::fsfilcnt_t {
            self.0.f_ffree
        }

        /// Get the number of free file inodes for unprivileged users
        pub fn files_available(&self) -> libc::fsfilcnt_t {
            self.0.f_favail
        }

        /// Get the file system id
        pub fn filesystem_id(&self) -> c_ulong {
            self.0.f_fsid
        }

        /// Get the mount flags
        pub fn flags(&self) -> FsFlags {
            FsFlags::from_bits_truncate(self.0.f_flag)
        }

        /// Get the maximum filename length
        pub fn name_max(&self) -> c_ulong {
            self.0.f_namemax
        }

    }

    /// Return a `Statvfs` object with information about the `path`
    pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
        unsafe {
            Errno::clear();
            let mut stat: Statvfs = mem::uninitialized();
            let res = path.with_nix_path(|path|
                libc::statvfs(path.as_ptr(), &mut stat.0)
            )?;

            Errno::result(res).map(|_| stat)
        }
    }

    /// Return a `Statvfs` object with information about `fd`
    pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
        unsafe {
            Errno::clear();
            let mut stat: Statvfs = mem::uninitialized();
            Errno::result(libc::fstatvfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
        }
    }

    #[cfg(test)]
    mod test {
        use std::fs::File;
        use sys::statvfs::*;

        #[test]
        fn statvfs_call() {
            statvfs("/".as_bytes()).unwrap();
        }

        #[test]
        fn fstatvfs_call() {
            let root = File::open("/").unwrap();
            fstatvfs(&root).unwrap();
        }
    }

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g., `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g., `str,u8` or `String,struct:Vec,test`)