diff options
author | Alexander Polakov <plhk@sdf.org> | 2015-09-15 11:56:21 +0300 |
---|---|---|
committer | Carl Lerche <me@carllerche.com> | 2015-09-28 13:04:12 -0700 |
commit | 8da9b314e973e756c8384a6110fb85c899d64561 (patch) | |
tree | 4fe07285629ffefd108f127c81a8af21622e0666 | |
parent | 5948204460595c791431d33c52bd9751babd336a (diff) | |
download | nix-8da9b314e973e756c8384a6110fb85c899d64561.zip |
quotactl() API for linux
-rw-r--r-- | src/sys/mod.rs | 7 | ||||
-rw-r--r-- | src/sys/quota.rs | 126 |
2 files changed, 133 insertions, 0 deletions
diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 3e4a0836..acf48107 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -49,3 +49,10 @@ pub mod time; pub mod ptrace; pub mod select; + +#[cfg(all(target_os = "linux", + any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm")), + )] +pub mod quota; diff --git a/src/sys/quota.rs b/src/sys/quota.rs new file mode 100644 index 00000000..9b39c98e --- /dev/null +++ b/src/sys/quota.rs @@ -0,0 +1,126 @@ +use {Result, NixPath, from_ffi}; +use errno::Errno; +use libc::{c_int, c_char}; + +#[cfg(all(target_os = "linux", + any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm")), + )] +pub mod quota { + use libc::c_int; + + pub struct QuotaCmd(pub QuotaSubCmd, pub QuotaType); + pub type QuotaSubCmd = c_int; + + impl QuotaCmd { + pub fn as_int(&self) -> c_int { + ((self.0 << 8) | (self.1 & 0x00ff)) as c_int + } + } + + // linux quota version >= 2 + pub const Q_SYNC: QuotaSubCmd = 0x800001; + pub const Q_QUOTAON: QuotaSubCmd = 0x800002; + pub const Q_QUOTAOFF: QuotaSubCmd = 0x800003; + pub const Q_GETFMT: QuotaSubCmd = 0x800004; + pub const Q_GETINFO: QuotaSubCmd = 0x800005; + pub const Q_SETINFO: QuotaSubCmd = 0x800006; + pub const Q_GETQUOTA: QuotaSubCmd = 0x800007; + pub const Q_SETQUOTA: QuotaSubCmd = 0x800008; + + pub type QuotaType = c_int; + + pub const USRQUOTA: QuotaType = 0; + pub const GRPQUOTA: QuotaType = 1; + + pub type QuotaFmt = c_int; + + pub const QFMT_VFS_OLD: QuotaFmt = 1; + pub const QFMT_VFS_V0: QuotaFmt = 2; + pub const QFMT_VFS_V1: QuotaFmt = 4; + + bitflags!( + #[derive(Default)] + flags QuotaValidFlags: u32 { + const QIF_BLIMITS = 1, + const QIF_SPACE = 2, + const QIF_ILIMITS = 4, + const QIF_INODES = 8, + const QIF_BTIME = 16, + const QIF_ITIME = 32, + const QIF_LIMITS = QIF_BLIMITS.bits | QIF_ILIMITS.bits, + const QIF_USAGE = QIF_SPACE.bits | QIF_INODES.bits, + const QIF_TIMES = QIF_BTIME.bits | QIF_ITIME.bits, + const QIF_ALL = QIF_LIMITS.bits | QIF_USAGE.bits | QIF_TIMES.bits + } + ); + + #[repr(C)] + #[derive(Default,Debug,Copy,Clone)] + pub struct Dqblk { + pub bhardlimit: u64, + pub bsoftlimit: u64, + pub curspace: u64, + pub ihardlimit: u64, + pub isoftlimit: u64, + pub curinodes: u64, + pub btime: u64, + pub itime: u64, + pub valid: QuotaValidFlags, + } +} + +mod ffi { + use libc::{c_int, c_char}; + + extern { + pub fn quotactl(cmd: c_int, special: * const c_char, id: c_int, data: *mut c_char) -> c_int; + } +} + +use std::ptr; + +fn quotactl<P: ?Sized + NixPath>(cmd: quota::QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> { + unsafe { + Errno::clear(); + let res = try!( + match special { + Some(dev) => dev.with_nix_path(|path| ffi::quotactl(cmd.as_int(), path.as_ptr(), id, addr)), + None => Ok(ffi::quotactl(cmd.as_int(), ptr::null(), id, addr)), + } + ); + from_ffi(res) + } +} + +pub fn quotactl_on<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P, format: quota::QuotaFmt, quota_file: &P) -> Result<()> { + try!(quota_file.with_nix_path(|path| { + let mut path_copy = path.to_bytes_with_nul().to_owned(); + let p: *mut i8 = path_copy.as_mut_ptr() as *mut i8; + quotactl(quota::QuotaCmd(quota::Q_QUOTAON, which), Some(special), format as c_int, p) + })) +} + +pub fn quotactl_off<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P) -> Result<()> { + quotactl(quota::QuotaCmd(quota::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut()) +} + +pub fn quotactl_sync<P: ?Sized + NixPath>(which: quota::QuotaType, special: Option<&P>) -> Result<()> { + quotactl(quota::QuotaCmd(quota::Q_SYNC, which), special, 0, ptr::null_mut()) +} + +pub fn quotactl_get<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P, id: c_int, dqblk: &mut quota::Dqblk) -> Result<()> { + use std::mem; + unsafe { + quotactl(quota::QuotaCmd(quota::Q_GETQUOTA, which), Some(special), id, mem::transmute(dqblk)) + } +} + +pub fn quotactl_set<P: ?Sized + NixPath>(which: quota::QuotaType, special: &P, id: c_int, dqblk: "a::Dqblk) -> Result<()> { + use std::mem; + let mut dqblk_copy = *dqblk; + unsafe { + quotactl(quota::QuotaCmd(quota::Q_SETQUOTA, which), Some(special), id, mem::transmute(&mut dqblk_copy)) + } +} |