1use crate::bindings as C;
2use crate::resource::Resource;
3
4use std::{io, mem};
5
6#[allow(clippy::unnecessary_cast)]
8pub const INFINITY: u64 = C::RLIM_INFINITY as u64;
9
10fn check_supported(resource: Resource) -> io::Result<()> {
11 let raw_resource = resource.as_raw();
12 if raw_resource == u8::MAX {
13 return Err(io::Error::new(io::ErrorKind::Other, "unsupported resource"));
14 }
15 Ok(())
16}
17
18#[allow(clippy::unnecessary_min_or_max)]
22#[inline]
23pub fn setrlimit(resource: Resource, soft: u64, hard: u64) -> io::Result<()> {
24 check_supported(resource)?;
25 let rlim = C::rlimit {
26 rlim_cur: soft.min(INFINITY) as _,
27 rlim_max: hard.min(INFINITY) as _,
28 };
29 #[allow(clippy::cast_lossless)]
30 let ret = unsafe { C::setrlimit(resource.as_raw() as _, &rlim) };
31 if ret == 0 {
32 Ok(())
33 } else {
34 Err(io::Error::last_os_error())
35 }
36}
37
38#[allow(clippy::unnecessary_min_or_max)]
42#[inline]
43pub fn getrlimit(resource: Resource) -> io::Result<(u64, u64)> {
44 check_supported(resource)?;
45 let mut rlim = unsafe { mem::zeroed() };
46 #[allow(clippy::cast_lossless)]
47 let ret = unsafe { C::getrlimit(resource.as_raw() as _, &mut rlim) };
48
49 #[allow(clippy::unnecessary_cast)]
50 if ret == 0 {
51 let soft = (rlim.rlim_cur as u64).min(INFINITY);
52 let hard = (rlim.rlim_max as u64).min(INFINITY);
53 Ok((soft, hard))
54 } else {
55 Err(io::Error::last_os_error())
56 }
57}
58
59#[allow(non_camel_case_types)]
61#[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "android"))))]
62#[cfg(any(doc, target_os = "linux", target_os = "android"))]
63pub type pid_t = i32;
64
65#[allow(clippy::unnecessary_min_or_max)]
69#[inline]
70#[cfg_attr(docsrs, doc(cfg(any(target_os = "linux", target_os = "android"))))]
71#[cfg(any(doc, rlimit__has_prlimit64))]
72pub fn prlimit(
73 pid: pid_t,
74 resource: Resource,
75 new_limit: Option<(u64, u64)>,
76 old_limit: Option<(&mut u64, &mut u64)>,
77) -> io::Result<()> {
78 check_supported(resource)?;
79
80 let new_rlim: Option<C::rlimit> = new_limit.map(|(soft, hard)| C::rlimit {
81 rlim_cur: soft.min(INFINITY) as _,
82 rlim_max: hard.min(INFINITY) as _,
83 });
84
85 let new_rlimit_ptr: *const C::rlimit = match new_rlim {
86 Some(ref rlim) => rlim,
87 None => std::ptr::null(),
88 };
89
90 let mut old_rlim: C::rlimit = unsafe { mem::zeroed() };
91
92 let old_rlimit_ptr: *mut C::rlimit = if old_limit.is_some() {
93 &mut old_rlim
94 } else {
95 std::ptr::null_mut()
96 };
97
98 #[allow(clippy::cast_lossless)]
99 let ret = unsafe { C::prlimit(pid, resource.as_raw() as _, new_rlimit_ptr, old_rlimit_ptr) };
100
101 if ret == 0 {
102 #[allow(clippy::unnecessary_cast)]
103 if let Some((soft, hard)) = old_limit {
104 *soft = (old_rlim.rlim_cur as u64).min(INFINITY);
105 *hard = (old_rlim.rlim_max as u64).min(INFINITY);
106 }
107
108 Ok(())
109 } else {
110 Err(io::Error::last_os_error())
111 }
112}