summaryrefslogtreecommitdiff
path: root/src/sys/quota.rs
blob: 199d08e284b7617ec7118cb5f656db93199e43b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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 c_char = path_copy.as_mut_ptr() as *mut c_char;
		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))
	}
}