diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 82934164b9..be51b4579c 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -15,6 +15,8 @@ pub mod memfd; #[cfg(not(any(target_os = "ios", target_os = "freebsd", target_os = "dragonfly")))] pub mod ioctl; +pub mod resource; + #[cfg(any(target_os = "linux", target_os = "android"))] pub mod sendfile; diff --git a/src/sys/resource.rs b/src/sys/resource.rs new file mode 100644 index 0000000000..dd9d7b3dd5 --- /dev/null +++ b/src/sys/resource.rs @@ -0,0 +1,54 @@ +use std::mem; + +use libc::{self, c_int}; +pub use libc::{rlimit, RLIM_INFINITY}; +#[cfg(any(target_os = "linux", + target_os = "openbsd", + target_os = "netbsd", + target_os = "bitrig"))] +pub use libc::{RLIM_SAVED_CUR, RLIM_SAVED_MAX}; + +use {Errno, Result}; + +#[repr(i32)] +pub enum Resource { + // POSIX + RLIMIT_CORE = libc::RLIMIT_CORE, + RLIMIT_CPU = libc::RLIMIT_CPU, + RLIMIT_DATA = libc::RLIMIT_DATA, + RLIMIT_FSIZE = libc::RLIMIT_FSIZE, + RLIMIT_NOFILE = libc::RLIMIT_NOFILE, + RLIMIT_STACK = libc::RLIMIT_STACK, + RLIMIT_AS = libc::RLIMIT_AS, + // BSDs and Linux + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_MEMLOCK = libc::RLIMIT_MEMLOCK, + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_NPROC = libc::RLIMIT_NPROC, + #[cfg(all(unix, not(target_os = "solaris")))] + RLIMIT_RSS = libc::RLIMIT_RSS, + // Linux-only + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_LOCKS = libc::RLIMIT_LOCKS, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_MSGQUEUE = libc::RLIMIT_MSGQUEUE, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_NICE = libc::RLIMIT_NICE, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_RTPRIO = libc::RLIMIT_RTPRIO, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_RTTIME = libc::RLIMIT_RTTIME, + #[cfg(any(target_os = "linux", target_os = "android"))] + RLIMIT_SIGPENDING = libc::RLIMIT_SIGPENDING, +} + +pub fn getrlimit(resource: Resource) -> Result { + let mut rlim = unsafe { mem::uninitialized() }; + let res = unsafe { libc::getrlimit(resource as c_int, &mut rlim as *mut _) }; + Errno::result(res).map(|_| rlim) +} + +pub fn setrlimit(resource: Resource, rlim: rlimit) -> Result<()> { + let res = unsafe { libc::setrlimit(resource as c_int, &rlim as *const _) }; + Errno::result(res).map(drop) +} diff --git a/test/test.rs b/test/test.rs index 045f8f1837..961ab0b1d5 100644 --- a/test/test.rs +++ b/test/test.rs @@ -11,6 +11,7 @@ mod sys; mod test_fcntl; mod test_net; mod test_nix_path; +mod test_resource; #[cfg(any(target_os = "linux", target_os = "android"))] mod test_sendfile; mod test_stat; diff --git a/test/test_resource.rs b/test/test_resource.rs new file mode 100644 index 0000000000..acdb079699 --- /dev/null +++ b/test/test_resource.rs @@ -0,0 +1,22 @@ +use nix::sys::resource::{Resource, getrlimit, setrlimit}; + +#[test] +pub fn test_resource_limits() { + let mut limit = getrlimit(Resource::RLIMIT_STACK).unwrap(); + assert!(limit.rlim_cur != limit.rlim_max); + + let orig_limit = limit; + + limit.rlim_cur = limit.rlim_max; + setrlimit(Resource::RLIMIT_STACK, limit).unwrap(); + + let limit2 = getrlimit(Resource::RLIMIT_STACK).unwrap(); + assert_eq!(limit.rlim_cur, limit2.rlim_cur); + assert_eq!(limit.rlim_max, limit2.rlim_max); + + setrlimit(Resource::RLIMIT_STACK, orig_limit).unwrap(); + + let final_limit = getrlimit(Resource::RLIMIT_STACK).unwrap(); + assert_eq!(orig_limit.rlim_cur, final_limit.rlim_cur); + assert_eq!(orig_limit.rlim_max, final_limit.rlim_max); +}