use cfg_if::cfg_if;
use crate::errno::Errno;
use crate::Result;
pub use libc::rlim_t;
use std::mem;
cfg_if! {
if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
use libc::{__rlimit_resource_t, rlimit};
} else if #[cfg(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "dragonfly",
all(target_os = "linux", not(target_env = "gnu"))
))]{
use libc::{c_int, rlimit};
}
}
libc_enum! {
#[cfg_attr(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), repr(u32))]
#[cfg_attr(any(
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "dragonfly",
all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc")))
), repr(i32))]
#[non_exhaustive]
pub enum Resource {
#[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_AS,
RLIMIT_CORE,
RLIMIT_CPU,
RLIMIT_DATA,
RLIMIT_FSIZE,
RLIMIT_NOFILE,
RLIMIT_STACK,
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_KQUEUES,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_LOCKS,
#[cfg(any(
target_os = "android",
target_os = "freebsd",
target_os = "openbsd",
target_os = "linux",
target_os = "netbsd"
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_MEMLOCK,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_MSGQUEUE,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_NICE,
#[cfg(any(
target_os = "android",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "linux",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_NPROC,
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_NPTS,
#[cfg(any(target_os = "android",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "linux",
))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_RSS,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_RTPRIO,
#[cfg(any(target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_RTTIME,
#[cfg(any(target_os = "android", target_os = "linux"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_SIGPENDING,
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_SBSIZE,
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_SWAP,
#[cfg(target_os = "freebsd")]
#[cfg_attr(docsrs, doc(cfg(all())))]
RLIMIT_VMEM,
}
}
pub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> {
let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit();
cfg_if! {
if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) };
} else {
let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) };
}
}
Errno::result(res).map(|_| {
let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() };
(rlim_cur, rlim_max)
})
}
pub fn setrlimit(
resource: Resource,
soft_limit: rlim_t,
hard_limit: rlim_t,
) -> Result<()> {
let new_rlim = rlimit {
rlim_cur: soft_limit,
rlim_max: hard_limit,
};
cfg_if! {
if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{
let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) };
}else{
let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) };
}
}
Errno::result(res).map(drop)
}