1
- use { Errno , Result , NixPath } ;
1
+ //! Set and configure disk quotas for users, groups, or projects.
2
+ use std:: default:: Default ;
3
+ use std:: { mem, ptr} ;
2
4
use libc:: { self , c_int, c_char} ;
5
+ use { Errno , Result , NixPath } ;
6
+
7
+ struct QuotaCmd ( QuotaSubCmd , QuotaType ) ;
8
+
9
+ impl QuotaCmd {
10
+ fn as_int ( & self ) -> c_int {
11
+ ( ( ( self . 0 as i32 ) << 8 ) | ( ( self . 1 as i32 ) & 0x00ff ) ) as c_int
12
+ }
13
+ }
14
+
15
+ // linux quota version >= 2
16
+ libc_enum ! {
17
+ #[ repr( i32 ) ]
18
+ enum QuotaSubCmd {
19
+ Q_SYNC ,
20
+ Q_QUOTAON ,
21
+ Q_QUOTAOFF ,
22
+ Q_GETFMT ,
23
+ Q_GETINFO ,
24
+ Q_SETINFO ,
25
+ Q_GETQUOTA ,
26
+ Q_SETQUOTA ,
27
+ }
28
+ }
29
+
30
+ libc_enum ! {
31
+ /// The scope of the quota.
32
+ #[ repr( i32 ) ]
33
+ pub enum QuotaType {
34
+ /// Specify a user quota
35
+ USRQUOTA ,
36
+ /// Specify a group quota
37
+ GRPQUOTA ,
38
+ }
39
+ }
40
+
41
+ libc_enum ! {
42
+ /// The type of quota format to use.
43
+ #[ repr( i32 ) ]
44
+ pub enum QuotaFmt {
45
+ /// Use the original quota format.
46
+ QFMT_VFS_OLD ,
47
+ /// Use the standard VFS v0 quota format.
48
+ ///
49
+ /// Handles 32-bit UIDs/GIDs and quota limits up to 2^42 bytes/2^32 inodes.
50
+ QFMT_VFS_V0 ,
51
+ /// Use the VFS v1 quota format.
52
+ ///
53
+ /// Handles 32-bit UIDs/GIDs and quota limits of 2^64 bytes/2^64 inodes.
54
+ QFMT_VFS_V1 ,
55
+ }
56
+ }
57
+
58
+ libc_bitflags ! (
59
+ /// Indicates the quota fields that are valid to read from.
60
+ #[ derive( Default ) ]
61
+ pub struct QuotaValidFlags : u32 {
62
+ /// The block hard & soft limit fields.
63
+ QIF_BLIMITS ;
64
+ /// The current space field.
65
+ QIF_SPACE ;
66
+ /// The inode hard & soft limit fields.
67
+ QIF_ILIMITS ;
68
+ /// The current inodes field.
69
+ QIF_INODES ;
70
+ /// The disk use time limit field.
71
+ QIF_BTIME ;
72
+ /// The file quote time limit field.
73
+ QIF_ITIME ;
74
+ /// All block & inode limits.
75
+ QIF_LIMITS ;
76
+ /// The space & inodes usage fields.
77
+ QIF_USAGE ;
78
+ /// The time limit fields.
79
+ QIF_TIMES ;
80
+ /// All fields.
81
+ QIF_ALL ;
82
+ }
83
+ ) ;
84
+
85
+ // FIXME: Change to repr(transparent)
86
+ #[ repr( C ) ]
87
+ #[ derive( Clone , Copy ) ]
88
+ pub struct Dqblk ( libc:: dqblk ) ;
89
+
90
+ impl Default for Dqblk {
91
+ fn default ( ) -> Dqblk {
92
+ Dqblk ( libc:: dqblk {
93
+ dqb_bhardlimit : 0 ,
94
+ dqb_bsoftlimit : 0 ,
95
+ dqb_curspace : 0 ,
96
+ dqb_ihardlimit : 0 ,
97
+ dqb_isoftlimit : 0 ,
98
+ dqb_curinodes : 0 ,
99
+ dqb_btime : 0 ,
100
+ dqb_itime : 0 ,
101
+ dqb_valid : 0 ,
102
+ } )
103
+ }
104
+ }
3
105
4
- #[ cfg( all( target_os = "linux" ,
5
- any( target_arch = "x86" ,
6
- target_arch = "x86_64" ,
7
- target_arch = "arm" ) ) ,
8
- ) ]
9
- pub mod quota {
10
- use libc:: { self , c_int} ;
106
+ impl Dqblk {
107
+ /// The absolute limit on disk quota blocks allocated.
108
+ pub fn blocks_hard_limit ( & self ) -> Option < u64 > {
109
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
110
+ if valid_fields. contains ( QIF_BLIMITS ) {
111
+ Some ( self . 0 . dqb_bhardlimit )
112
+ } else {
113
+ None
114
+ }
115
+ } Set quota information for user/group id.
11
116
12
- pub struct QuotaCmd ( pub QuotaSubCmd , pub QuotaType ) ;
13
- pub type QuotaSubCmd = c_int ;
14
117
15
- impl QuotaCmd {
16
- pub fn as_int ( & self ) -> c_int {
17
- ( ( self . 0 << 8 ) | ( self . 1 & 0x00ff ) ) as c_int
118
+ /// Preferred limit on disk quota blocks
119
+ pub fn blocks_soft_limit ( & self ) -> Option < u64 > {
120
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
121
+ if valid_fields. contains ( QIF_BLIMITS ) {
122
+ Some ( self . 0 . dqb_bsoftlimit )
123
+ } else {
124
+ None
18
125
}
19
126
}
20
127
21
- // linux quota version >= 2
22
- pub const Q_SYNC : QuotaSubCmd = 0x800001 ;
23
- pub const Q_QUOTAON : QuotaSubCmd = 0x800002 ;
24
- pub const Q_QUOTAOFF : QuotaSubCmd = 0x800003 ;
25
- pub const Q_GETFMT : QuotaSubCmd = 0x800004 ;
26
- pub const Q_GETINFO : QuotaSubCmd = 0x800005 ;
27
- pub const Q_SETINFO : QuotaSubCmd = 0x800006 ;
28
- pub const Q_GETQUOTA : QuotaSubCmd = 0x800007 ;
29
- pub const Q_SETQUOTA : QuotaSubCmd = 0x800008 ;
30
-
31
- pub type QuotaType = c_int ;
32
-
33
- pub const USRQUOTA : QuotaType = 0 ;
34
- pub const GRPQUOTA : QuotaType = 1 ;
35
-
36
- pub type QuotaFmt = c_int ;
37
-
38
- pub const QFMT_VFS_OLD : QuotaFmt = 1 ;
39
- pub const QFMT_VFS_V0 : QuotaFmt = 2 ;
40
- pub const QFMT_VFS_V1 : QuotaFmt = 4 ;
41
-
42
- libc_bitflags ! (
43
- #[ derive( Default ) ]
44
- pub struct QuotaValidFlags : u32 {
45
- QIF_BLIMITS ;
46
- QIF_SPACE ;
47
- QIF_ILIMITS ;
48
- QIF_INODES ;
49
- QIF_BTIME ;
50
- QIF_ITIME ;
51
- QIF_LIMITS ;
52
- QIF_USAGE ;
53
- QIF_TIMES ;
54
- QIF_ALL ;
128
+ /// Current occupied space (bytes)
129
+ pub fn occupied_space ( & self ) -> Option < u64 > {
130
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
131
+ if valid_fields. contains ( QIF_SPACE ) {
132
+ Some ( self . 0 . dqb_curspace )
133
+ } else {
134
+ None
135
+ }
136
+ }
137
+
138
+ /// Maximum number of allocated inodes
139
+ pub fn inodes_hard_limit ( & self ) -> Option < u64 > {
140
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
141
+ if valid_fields. contains ( QIF_ILIMITS ) {
142
+ Some ( self . 0 . dqb_ihardlimit )
143
+ } else {
144
+ None
145
+ }
146
+ }
147
+
148
+ /// Preferred inode limit
149
+ pub fn inodes_soft_limit ( & self ) -> Option < u64 > {
150
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
151
+ if valid_fields. contains ( QIF_ILIMITS ) {
152
+ Some ( self . 0 . dqb_isoftlimit )
153
+ } else {
154
+ None
55
155
}
56
- ) ;
57
-
58
- #[ repr( C ) ]
59
- #[ derive( Default , Debug , Copy , Clone ) ]
60
- pub struct Dqblk {
61
- pub bhardlimit : u64 ,
62
- pub bsoftlimit : u64 ,
63
- pub curspace : u64 ,
64
- pub ihardlimit : u64 ,
65
- pub isoftlimit : u64 ,
66
- pub curinodes : u64 ,
67
- pub btime : u64 ,
68
- pub itime : u64 ,
69
- pub valid : QuotaValidFlags ,
70
156
}
71
- }
72
157
73
- use std:: ptr;
158
+ /// Current number of allocated inodes.
159
+ pub fn allocated_inodes ( & self ) -> Option < u64 > {
160
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
161
+ if valid_fields. contains ( QIF_INODES ) {
162
+ Some ( self . 0 . dqb_curinodes )
163
+ } else {
164
+ None
165
+ }
166
+ }
167
+
168
+ /// Time limit for excessive disk use.
169
+ pub fn block_time_limit ( & self ) -> Option < u64 > {
170
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
171
+ if valid_fields. contains ( QIF_BTIME ) {
172
+ Some ( self . 0 . dqb_btime )
173
+ } else {
174
+ None
175
+ }
176
+ }
177
+
178
+ /// Time limit for excessive files.
179
+ pub fn inode_time_limit ( & self ) -> Option < u64 > {
180
+ let valid_fields = QuotaValidFlags :: from_bits_truncate ( self . 0 . dqb_valid ) ;
181
+ if valid_fields. contains ( QIF_ITIME ) {
182
+ Some ( self . 0 . dqb_itime )
183
+ } else {
184
+ None
185
+ }
186
+ }
187
+ }
74
188
75
- fn quotactl < P : ?Sized + NixPath > ( cmd : quota :: QuotaCmd , special : Option < & P > , id : c_int , addr : * mut c_char ) -> Result < ( ) > {
189
+ fn quotactl < P : ?Sized + NixPath > ( cmd : QuotaCmd , special : Option < & P > , id : c_int , addr : * mut c_char ) -> Result < ( ) > {
76
190
unsafe {
77
191
Errno :: clear ( ) ;
78
192
let res = try!(
@@ -86,27 +200,35 @@ fn quotactl<P: ?Sized + NixPath>(cmd: quota::QuotaCmd, special: Option<&P>, id:
86
200
}
87
201
}
88
202
89
- pub fn quotactl_on < P : ?Sized + NixPath > ( which : quota:: QuotaType , special : & P , format : quota:: QuotaFmt , quota_file : & P ) -> Result < ( ) > {
203
+ /// Turn on disk quotas for a block device.
204
+ pub fn quotactl_on < P : ?Sized + NixPath > ( which : QuotaType , special : & P , format : QuotaFmt , quota_file : & P ) -> Result < ( ) > {
90
205
try!( quota_file. with_nix_path ( |path| {
91
206
let mut path_copy = path. to_bytes_with_nul ( ) . to_owned ( ) ;
92
207
let p: * mut c_char = path_copy. as_mut_ptr ( ) as * mut c_char ;
93
- quotactl ( quota :: QuotaCmd ( quota :: Q_QUOTAON , which) , Some ( special) , format as c_int , p)
208
+ quotactl ( QuotaCmd ( QuotaSubCmd :: Q_QUOTAON , which) , Some ( special) , format as c_int , p)
94
209
} ) )
95
210
}
96
211
97
- pub fn quotactl_off < P : ?Sized + NixPath > ( which : quota:: QuotaType , special : & P ) -> Result < ( ) > {
98
- quotactl ( quota:: QuotaCmd ( quota:: Q_QUOTAOFF , which) , Some ( special) , 0 , ptr:: null_mut ( ) )
212
+ /// Disable disk quotas for a block device.
213
+ pub fn quotactl_off < P : ?Sized + NixPath > ( which : QuotaType , special : & P ) -> Result < ( ) > {
214
+ quotactl ( QuotaCmd ( QuotaSubCmd :: Q_QUOTAOFF , which) , Some ( special) , 0 , ptr:: null_mut ( ) )
99
215
}
100
216
101
- pub fn quotactl_sync < P : ?Sized + NixPath > ( which : quota:: QuotaType , special : Option < & P > ) -> Result < ( ) > {
102
- quotactl ( quota:: QuotaCmd ( quota:: Q_SYNC , which) , special, 0 , ptr:: null_mut ( ) )
217
+ /// Update the on-disk copy of quota usages for a filesystem.
218
+ pub fn quotactl_sync < P : ?Sized + NixPath > ( which : QuotaType , special : Option < & P > ) -> Result < ( ) > {
219
+ quotactl ( QuotaCmd ( QuotaSubCmd :: Q_SYNC , which) , special, 0 , ptr:: null_mut ( ) )
103
220
}
104
221
105
- pub fn quotactl_get < P : ?Sized + NixPath > ( which : quota:: QuotaType , special : & P , id : c_int , dqblk : & mut quota:: Dqblk ) -> Result < ( ) > {
106
- quotactl ( quota:: QuotaCmd ( quota:: Q_GETQUOTA , which) , Some ( special) , id, dqblk as * mut _ as * mut c_char )
222
+ /// Get disk quota limits and current usage for the given user/group id.
223
+ pub fn quotactl_get < P : ?Sized + NixPath > ( which : QuotaType , special : & P , id : c_int ) -> Result < Dqblk > {
224
+ let mut dqblk = unsafe { mem:: uninitialized ( ) } ;
225
+ quotactl ( QuotaCmd ( QuotaSubCmd :: Q_GETQUOTA , which) , Some ( special) , id, & mut dqblk as * mut _ as * mut c_char ) ?;
226
+ dqblk
107
227
}
108
228
109
- pub fn quotactl_set < P : ?Sized + NixPath > ( which : quota:: QuotaType , special : & P , id : c_int , dqblk : & quota:: Dqblk ) -> Result < ( ) > {
229
+ /// Configure quota values for the specified fields for a given user/group id.
230
+ pub fn quotactl_set < P : ?Sized + NixPath > ( which : QuotaType , special : & P , id : c_int , dqblk : & Dqblk , fields : QuotaValidFlags ) -> Result < ( ) > {
110
231
let mut dqblk_copy = * dqblk;
111
- quotactl ( quota:: QuotaCmd ( quota:: Q_SETQUOTA , which) , Some ( special) , id, & mut dqblk_copy as * mut _ as * mut c_char )
232
+ dqblk_copy. 0 . dqb_valid = fields. bits ( ) ;
233
+ quotactl ( QuotaCmd ( QuotaSubCmd :: Q_SETQUOTA , which) , Some ( special) , id, & mut dqblk_copy as * mut _ as * mut c_char )
112
234
}
0 commit comments