1- //! FFI for statvfs functions
1+ //! Get filesystem statistics
22//!
3- //! See the `vfs::Statvfs` struct for some rusty wrappers
3+ //! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
4+ //! for more details.
5+ use std:: mem;
6+ use std:: os:: unix:: io:: AsRawFd ;
7+
8+ use libc:: { self , c_ulong} ;
49
510use { Errno , Result , NixPath } ;
6- use std:: os:: unix:: io:: AsRawFd ;
711
8- pub mod vfs {
9- //! Structs related to the `statvfs` and `fstatvfs` functions
10- //!
11- //! The `Statvfs` struct has some wrappers methods around the `statvfs` and
12- //! `fstatvfs` calls.
13-
14- use libc:: { c_ulong, c_int} ;
15- use std:: os:: unix:: io:: AsRawFd ;
16- use { Result , NixPath } ;
17-
18- use super :: { statvfs, fstatvfs} ;
19-
20- bitflags ! (
21- /// Mount Flags
22- #[ repr( C ) ]
23- #[ derive( Default ) ]
24- pub struct FsFlags : c_ulong {
25- /// Read Only
26- const RDONLY = 1 ;
27- /// Do not allow the set-uid bits to have an effect
28- const NOSUID = 2 ;
29- /// Do not interpret character or block-special devices
30- const NODEV = 4 ;
31- /// Do not allow execution of binaries on the filesystem
32- const NOEXEC = 8 ;
33- /// All IO should be done synchronously
34- const SYNCHRONOUS = 16 ;
35- /// Allow mandatory locks on the filesystem
36- const MANDLOCK = 64 ;
37- const WRITE = 128 ;
38- const APPEND = 256 ;
39- const IMMUTABLE = 512 ;
40- /// Do not update access times on files
41- const NOATIME = 1024 ;
42- /// Do not update access times on files
43- const NODIRATIME = 2048 ;
44- /// Update access time relative to modify/change time
45- const RELATIME = 4096 ;
46- }
47- ) ;
48-
49- /// The posix statvfs struct
50- ///
51- /// http://linux.die.net/man/2/statvfs
12+ bitflags ! (
13+ /// File system mount Flags
5214 #[ repr( C ) ]
53- #[ derive( Debug , Copy , Clone ) ]
54- pub struct Statvfs {
55- /// Filesystem block size. This is the value that will lead to
56- /// most efficient use of the filesystem
57- pub f_bsize : c_ulong ,
58- /// Fragment Size -- actual minimum unit of allocation on this
59- /// filesystem
60- pub f_frsize : c_ulong ,
61- /// Total number of blocks on the filesystem
62- pub f_blocks : u64 ,
63- /// Number of unused blocks on the filesystem, including those
64- /// reserved for root
65- pub f_bfree : u64 ,
66- /// Number of blocks available to non-root users
67- pub f_bavail : u64 ,
68- /// Total number of inodes available on the filesystem
69- pub f_files : u64 ,
70- /// Number of inodes available on the filesystem
71- pub f_ffree : u64 ,
72- /// Number of inodes available to non-root users
73- pub f_favail : u64 ,
74- /// File System ID
75- pub f_fsid : c_ulong ,
76- /// Mount Flags
77- pub f_flag : FsFlags ,
78- /// Maximum filename length
79- pub f_namemax : c_ulong ,
80- /// Reserved extra space, OS-dependent
81- f_spare : [ c_int ; 6 ] ,
82- }
83-
84- impl Statvfs {
85- /// Create a new `Statvfs` object and fill it with information about
86- /// the mount that contains `path`
87- pub fn for_path < P : ?Sized + NixPath > ( path : & P ) -> Result < Statvfs > {
88- let mut stat = Statvfs :: default ( ) ;
89- let res = statvfs ( path, & mut stat) ;
90- res. map ( |_| stat)
91- }
92-
93- /// Replace information in this struct with information about `path`
94- pub fn update_with_path < P : ?Sized + NixPath > ( & mut self , path : & P ) -> Result < ( ) > {
95- statvfs ( path, self )
96- }
97-
98- /// Create a new `Statvfs` object and fill it with information from fd
99- pub fn for_fd < T : AsRawFd > ( fd : & T ) -> Result < Statvfs > {
100- let mut stat = Statvfs :: default ( ) ;
101- let res = fstatvfs ( fd, & mut stat) ;
102- res. map ( |_| stat)
103- }
104-
105- /// Replace information in this struct with information about `fd`
106- pub fn update_with_fd < T : AsRawFd > ( & mut self , fd : & T ) -> Result < ( ) > {
107- fstatvfs ( fd, self )
108- }
109- }
110-
111- impl Default for Statvfs {
112- /// Create a statvfs object initialized to all zeros
113- fn default ( ) -> Self {
114- Statvfs {
115- f_bsize : 0 ,
116- f_frsize : 0 ,
117- f_blocks : 0 ,
118- f_bfree : 0 ,
119- f_bavail : 0 ,
120- f_files : 0 ,
121- f_ffree : 0 ,
122- f_favail : 0 ,
123- f_fsid : 0 ,
124- f_flag : FsFlags :: default ( ) ,
125- f_namemax : 0 ,
126- f_spare : [ 0 , 0 , 0 , 0 , 0 , 0 ] ,
127- }
128- }
15+ #[ derive( Default ) ]
16+ pub struct FsFlags : c_ulong {
17+ /// Read Only
18+ const RDONLY = libc:: ST_RDONLY ;
19+ /// Do not allow the set-uid bits to have an effect
20+ const NOSUID = libc:: ST_NOSUID ;
21+ /// Do not interpret character or block-special devices
22+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
23+ const NODEV = libc:: ST_NODEV ;
24+ /// Do not allow execution of binaries on the filesystem
25+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
26+ const NOEXEC = libc:: ST_NOEXEC ;
27+ /// All IO should be done synchronously
28+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
29+ const SYNCHRONOUS = libc:: ST_SYNCHRONOUS ;
30+ /// Allow mandatory locks on the filesystem
31+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
32+ const MANDLOCK = libc:: ST_MANDLOCK ;
33+ /// Write on file/directory/symlink
34+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
35+ const WRITE = libc:: ST_WRITE ;
36+ /// Append-only file
37+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
38+ const APPEND = libc:: ST_APPEND ;
39+ /// Immutable file
40+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
41+ const IMMUTABLE = libc:: ST_IMMUTABLE ;
42+ /// Do not update access times on files
43+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
44+ const NOATIME = libc:: ST_NOATIME ;
45+ /// Do not update access times on files
46+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
47+ const NODIRATIME = libc:: ST_NODIRATIME ;
48+ /// Update access time relative to modify/change time
49+ #[ cfg( any( target_os = "android" , all( target_os = "linux" , not( target_env = "musl" ) ) ) ) ]
50+ const RELATIME = libc:: ST_RELATIME ;
51+ }
52+ ) ;
53+
54+ /// Wrapper around the POSIX `statvfs` struct
55+ ///
56+ /// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
57+ // FIXME: Replace with repr(transparent)
58+ #[ repr( C ) ]
59+ pub struct Statvfs ( libc:: statvfs ) ;
60+
61+ impl Statvfs {
62+ /// get the file system block size
63+ pub fn block_size ( & self ) -> libc:: c_ulong {
64+ self . 0 . f_bsize
12965 }
130- }
13166
132- mod ffi {
133- use libc:: { c_char, c_int} ;
134- use sys:: statvfs:: vfs;
67+ /// Get the fundamental file system block size
68+ pub fn fragment_size ( & self ) -> libc:: c_ulong {
69+ self . 0 . f_frsize
70+ }
13571
136- extern {
137- pub fn statvfs ( path : * const c_char , buf : * mut vfs:: Statvfs ) -> c_int ;
138- pub fn fstatvfs ( fd : c_int , buf : * mut vfs:: Statvfs ) -> c_int ;
72+ /// Get the number of blocks.
73+ ///
74+ /// Units are in units of `fragment_size()`
75+ pub fn blocks ( & self ) -> libc:: fsblkcnt_t {
76+ self . 0 . f_blocks
77+ }
78+
79+ /// Get the number of free blocks in the file system
80+ pub fn blocks_free ( & self ) -> libc:: fsblkcnt_t {
81+ self . 0 . f_bfree
13982 }
83+
84+ /// Get the number of free blocks for unprivileged users
85+ pub fn blocks_available ( & self ) -> libc:: fsblkcnt_t {
86+ self . 0 . f_bavail
87+ }
88+
89+ /// Get the total number of file inodes
90+ pub fn files ( & self ) -> libc:: fsfilcnt_t {
91+ self . 0 . f_files
92+ }
93+
94+ /// Get the number of free file inodes
95+ pub fn files_free ( & self ) -> libc:: fsfilcnt_t {
96+ self . 0 . f_ffree
97+ }
98+
99+ /// Get the number of free file inodes for unprivileged users
100+ pub fn files_available ( & self ) -> libc:: fsfilcnt_t {
101+ self . 0 . f_favail
102+ }
103+
104+ /// Get the file system id
105+ pub fn filesystem_id ( & self ) -> c_ulong {
106+ self . 0 . f_fsid
107+ }
108+
109+ /// Get the mount flags
110+ pub fn flags ( & self ) -> FsFlags {
111+ FsFlags :: from_bits_truncate ( self . 0 . f_flag )
112+ }
113+
114+ /// Get the maximum filename length
115+ pub fn name_max ( & self ) -> libc:: c_ulong {
116+ self . 0 . f_namemax
117+ }
118+
140119}
141120
142- /// Fill an existing `Statvfs` object with information about the `path`
143- pub fn statvfs < P : ?Sized + NixPath > ( path : & P , stat : & mut vfs :: Statvfs ) -> Result < ( ) > {
121+ /// Return a `Statvfs` object with information about the `path`
122+ pub fn statvfs < P : ?Sized + NixPath > ( path : & P ) -> Result < Statvfs > {
144123 unsafe {
145124 Errno :: clear ( ) ;
125+ let mut stat: Statvfs = mem:: uninitialized ( ) ;
146126 let res = try!(
147- path. with_nix_path ( |path| ffi :: statvfs ( path. as_ptr ( ) , stat) )
127+ path. with_nix_path ( |path| libc :: statvfs ( path. as_ptr ( ) , & mut stat. 0 ) )
148128 ) ;
149129
150- Errno :: result ( res) . map ( drop )
130+ Errno :: result ( res) . map ( |_| stat )
151131 }
152132}
153133
154- /// Fill an existing `Statvfs` object with information about `fd`
155- pub fn fstatvfs < T : AsRawFd > ( fd : & T , stat : & mut vfs :: Statvfs ) -> Result < ( ) > {
134+ /// Return a `Statvfs` object with information about `fd`
135+ pub fn fstatvfs < T : AsRawFd > ( fd : & T ) -> Result < Statvfs > {
156136 unsafe {
157137 Errno :: clear ( ) ;
158- Errno :: result ( ffi:: fstatvfs ( fd. as_raw_fd ( ) , stat) ) . map ( drop)
138+ let mut stat: Statvfs = mem:: uninitialized ( ) ;
139+ Errno :: result ( libc:: fstatvfs ( fd. as_raw_fd ( ) , & mut stat. 0 ) ) . map ( |_| stat)
159140 }
160141}
161142
@@ -166,14 +147,12 @@ mod test {
166147
167148 #[ test]
168149 fn statvfs_call ( ) {
169- let mut stat = vfs:: Statvfs :: default ( ) ;
170- statvfs ( "/" . as_bytes ( ) , & mut stat) . unwrap ( )
150+ statvfs ( "/" . as_bytes ( ) ) . unwrap ( ) ;
171151 }
172152
173153 #[ test]
174154 fn fstatvfs_call ( ) {
175- let mut stat = vfs:: Statvfs :: default ( ) ;
176155 let root = File :: open ( "/" ) . unwrap ( ) ;
177- fstatvfs ( & root, & mut stat ) . unwrap ( )
156+ fstatvfs ( & root) . unwrap ( ) ;
178157 }
179158}
0 commit comments