summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
authorAlexander Polakov <plhk@sdf.org>2015-09-15 11:56:21 +0300
committerCarl Lerche <me@carllerche.com>2015-09-28 13:04:12 -0700
commit8da9b314e973e756c8384a6110fb85c899d64561 (patch)
tree4fe07285629ffefd108f127c81a8af21622e0666 /src/sys
parent5948204460595c791431d33c52bd9751babd336a (diff)
downloadnix-8da9b314e973e756c8384a6110fb85c899d64561.zip
quotactl() API for linux
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/mod.rs7
-rw-r--r--src/sys/quota.rs126
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: &quota::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))
+ }
+}