1
- //! FFI for statvfs functions
1
+ //! Get filesystem statistics
2
2
//!
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} ;
4
9
5
10
use { Errno , Result , NixPath } ;
6
- use std:: os:: unix:: io:: AsRawFd ;
7
11
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
52
14
#[ 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
129
65
}
130
- }
131
66
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
+ }
135
71
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
139
82
}
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
+
140
119
}
141
120
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 > {
144
123
unsafe {
145
124
Errno :: clear ( ) ;
125
+ let mut stat: Statvfs = mem:: uninitialized ( ) ;
146
126
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 ) )
148
128
) ;
149
129
150
- Errno :: result ( res) . map ( drop )
130
+ Errno :: result ( res) . map ( |_| stat )
151
131
}
152
132
}
153
133
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 > {
156
136
unsafe {
157
137
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)
159
140
}
160
141
}
161
142
@@ -166,14 +147,12 @@ mod test {
166
147
167
148
#[ test]
168
149
fn statvfs_call ( ) {
169
- let mut stat = vfs:: Statvfs :: default ( ) ;
170
- statvfs ( "/" . as_bytes ( ) , & mut stat) . unwrap ( )
150
+ statvfs ( "/" . as_bytes ( ) ) . unwrap ( ) ;
171
151
}
172
152
173
153
#[ test]
174
154
fn fstatvfs_call ( ) {
175
- let mut stat = vfs:: Statvfs :: default ( ) ;
176
155
let root = File :: open ( "/" ) . unwrap ( ) ;
177
- fstatvfs ( & root, & mut stat ) . unwrap ( )
156
+ fstatvfs ( & root) . unwrap ( ) ;
178
157
}
179
158
}
0 commit comments