1 //! Set and configure disk quotas for users, groups, or projects.
5 //! Enabling and setting a quota:
8 //! # use nix::sys::quota::{Dqblk, quotactl_on, quotactl_set, QuotaFmt, QuotaType, QuotaValidFlags};
9 //! quotactl_on(QuotaType::USRQUOTA, "/dev/sda1", QuotaFmt::QFMT_VFS_V1, "aquota.user").unwrap();
10 //! let mut dqblk: Dqblk = Default::default();
11 //! dqblk.set_blocks_hard_limit(10000);
12 //! dqblk.set_blocks_soft_limit(8000);
13 //! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QuotaValidFlags::QIF_BLIMITS).unwrap();
15 use crate::errno
::Errno
;
16 use crate::{NixPath, Result}
;
17 use libc
::{self, c_char, c_int}
;
18 use std
::default::Default
;
21 struct QuotaCmd(QuotaSubCmd
, QuotaType
);
24 #[allow(unused_unsafe)]
25 fn as_int(&self) -> c_int
{
26 unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
30 // linux quota version >= 2
43 /// The scope of the quota.
47 /// Specify a user quota
49 /// Specify a group quota
55 /// The type of quota format to use.
59 /// Use the original quota format.
61 /// Use the standard VFS v0 quota format.
63 /// Handles 32-bit UIDs/GIDs and quota limits up to 2<sup>32</sup> bytes/2<sup>32</sup> inodes.
65 /// Use the VFS v1 quota format.
67 /// Handles 32-bit UIDs/GIDs and quota limits of 2<sup>64</sup> bytes/2<sup>64</sup> inodes.
73 /// Indicates the quota fields that are valid to read from.
75 pub struct QuotaValidFlags
: u32 {
76 /// The block hard & soft limit fields.
78 /// The current space field.
80 /// The inode hard & soft limit fields.
82 /// The current inodes field.
84 /// The disk use time limit field.
86 /// The file quote time limit field.
88 /// All block & inode limits.
90 /// The space & inodes usage fields.
92 /// The time limit fields.
99 /// Wrapper type for `if_dqblk`
101 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
102 pub struct Dqblk(libc
::dqblk
);
104 impl Default
for Dqblk
{
105 fn default() -> Dqblk
{
121 /// The absolute limit on disk quota blocks allocated.
122 pub fn blocks_hard_limit(&self) -> Option
<u64> {
124 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
125 if valid_fields
.contains(QuotaValidFlags
::QIF_BLIMITS
) {
126 Some(self.0.dqb_bhardlimit
)
132 /// Set the absolute limit on disk quota blocks allocated.
133 pub fn set_blocks_hard_limit(&mut self, limit
: u64) {
134 self.0.dqb_bhardlimit
= limit
;
137 /// Preferred limit on disk quota blocks
138 pub fn blocks_soft_limit(&self) -> Option
<u64> {
140 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
141 if valid_fields
.contains(QuotaValidFlags
::QIF_BLIMITS
) {
142 Some(self.0.dqb_bsoftlimit
)
148 /// Set the preferred limit on disk quota blocks allocated.
149 pub fn set_blocks_soft_limit(&mut self, limit
: u64) {
150 self.0.dqb_bsoftlimit
= limit
;
153 /// Current occupied space (bytes).
154 pub fn occupied_space(&self) -> Option
<u64> {
156 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
157 if valid_fields
.contains(QuotaValidFlags
::QIF_SPACE
) {
158 Some(self.0.dqb_curspace
)
164 /// Maximum number of allocated inodes.
165 pub fn inodes_hard_limit(&self) -> Option
<u64> {
167 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
168 if valid_fields
.contains(QuotaValidFlags
::QIF_ILIMITS
) {
169 Some(self.0.dqb_ihardlimit
)
175 /// Set the maximum number of allocated inodes.
176 pub fn set_inodes_hard_limit(&mut self, limit
: u64) {
177 self.0.dqb_ihardlimit
= limit
;
180 /// Preferred inode limit
181 pub fn inodes_soft_limit(&self) -> Option
<u64> {
183 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
184 if valid_fields
.contains(QuotaValidFlags
::QIF_ILIMITS
) {
185 Some(self.0.dqb_isoftlimit
)
191 /// Set the preferred limit of allocated inodes.
192 pub fn set_inodes_soft_limit(&mut self, limit
: u64) {
193 self.0.dqb_isoftlimit
= limit
;
196 /// Current number of allocated inodes.
197 pub fn allocated_inodes(&self) -> Option
<u64> {
199 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
200 if valid_fields
.contains(QuotaValidFlags
::QIF_INODES
) {
201 Some(self.0.dqb_curinodes
)
207 /// Time limit for excessive disk use.
208 pub fn block_time_limit(&self) -> Option
<u64> {
210 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
211 if valid_fields
.contains(QuotaValidFlags
::QIF_BTIME
) {
212 Some(self.0.dqb_btime
)
218 /// Set the time limit for excessive disk use.
219 pub fn set_block_time_limit(&mut self, limit
: u64) {
220 self.0.dqb_btime
= limit
;
223 /// Time limit for excessive files.
224 pub fn inode_time_limit(&self) -> Option
<u64> {
226 QuotaValidFlags
::from_bits_truncate(self.0.dqb_valid
);
227 if valid_fields
.contains(QuotaValidFlags
::QIF_ITIME
) {
228 Some(self.0.dqb_itime
)
234 /// Set the time limit for excessive files.
235 pub fn set_inode_time_limit(&mut self, limit
: u64) {
236 self.0.dqb_itime
= limit
;
240 fn quotactl
<P
: ?Sized
+ NixPath
>(
248 let res
= match special
{
249 Some(dev
) => dev
.with_nix_path(|path
| {
250 libc
::quotactl(cmd
.as_int(), path
.as_ptr(), id
, addr
)
252 None
=> Ok(libc
::quotactl(cmd
.as_int(), ptr
::null(), id
, addr
)),
255 Errno
::result(res
).map(drop
)
259 /// Turn on disk quotas for a block device.
260 pub fn quotactl_on
<P
: ?Sized
+ NixPath
>(
266 quota_file
.with_nix_path(|path
| {
267 let mut path_copy
= path
.to_bytes_with_nul().to_owned();
268 let p
: *mut c_char
= path_copy
.as_mut_ptr() as *mut c_char
;
270 QuotaCmd(QuotaSubCmd
::Q_QUOTAON
, which
),
278 /// Disable disk quotas for a block device.
279 pub fn quotactl_off
<P
: ?Sized
+ NixPath
>(
284 QuotaCmd(QuotaSubCmd
::Q_QUOTAOFF
, which
),
291 /// Update the on-disk copy of quota usages for a filesystem.
293 /// If `special` is `None`, then all file systems with active quotas are sync'd.
294 pub fn quotactl_sync
<P
: ?Sized
+ NixPath
>(
299 QuotaCmd(QuotaSubCmd
::Q_SYNC
, which
),
306 /// Get disk quota limits and current usage for the given user/group id.
307 pub fn quotactl_get
<P
: ?Sized
+ NixPath
>(
312 let mut dqblk
= mem
::MaybeUninit
::uninit();
314 QuotaCmd(QuotaSubCmd
::Q_GETQUOTA
, which
),
317 dqblk
.as_mut_ptr() as *mut c_char
,
319 Ok(unsafe { Dqblk(dqblk.assume_init()) }
)
322 /// Configure quota values for the specified fields for a given user/group id.
323 pub fn quotactl_set
<P
: ?Sized
+ NixPath
>(
328 fields
: QuotaValidFlags
,
330 let mut dqblk_copy
= *dqblk
;
331 dqblk_copy
.0.dqb_valid
= fields
.bits();
333 QuotaCmd(QuotaSubCmd
::Q_SETQUOTA
, which
),
336 &mut dqblk_copy
as *mut _
as *mut c_char
,