1 #![allow(non_camel_case_types)]
2 
3 mod resource;
4 
5 pub use self::resource::{RawResource, Resource};
6 
7 #[cfg(target_os = "linux")]
8 group! {
9     mod proc_limits;
10     pub use self::proc_limits::{ProcLimit, ProcLimits};
11 }
12 
13 // #begin-codegen
14 // generated from rust-lang/libc 6568dacc81b2dd2edae571ab97bbca94bc662595
15 #[cfg(any(target_os = "emscripten", target_os = "fuchsia", target_os = "linux",))]
16 group! {
17     type c_rlimit = libc::rlimit64;
18     use libc::setrlimit64 as c_setrlimit;
19     use libc::getrlimit64 as c_getrlimit;
20     const RLIM_INFINITY: u64 = u64::MAX;
21     const RLIM_SAVED_CUR: u64 = u64::MAX;
22     const RLIM_SAVED_MAX: u64 = u64::MAX;
23 }
24 
25 #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "linux",)))]
26 group! {
27     type c_rlimit = libc::rlimit;
28     use libc::setrlimit as c_setrlimit;
29     use libc::getrlimit as c_getrlimit;
30     #[cfg(any(
31         all(target_os = "linux", target_env = "gnu"),
32         all(target_os = "linux", target_env = "musl"),
33         all(target_os = "linux", target_env = "uclibc", target_arch = "arm"),
34         all(target_os = "linux", target_env = "uclibc", target_arch = "mips"),
35         all(target_os = "linux", target_env = "uclibc", target_arch = "mips64"),
36         all(target_os = "linux", target_env = "uclibc", target_arch = "x86_64"),
37         any(target_os = "freebsd", target_os = "dragonfly"),
38         any(target_os = "macos", target_os = "ios"),
39         any(target_os = "openbsd", target_os = "netbsd"),
40         target_os = "android",
41         target_os = "emscripten",
42         target_os = "fuchsia",
43         target_os = "solarish",
44     ))]
45     const RLIM_INFINITY: u64 = libc::RLIM_INFINITY as u64;
46     #[cfg(any(
47         any(target_os = "openbsd", target_os = "netbsd"),
48         target_os = "emscripten",
49         target_os = "fuchsia",
50         target_os = "linux",
51     ))]
52     const RLIM_SAVED_CUR: u64 = libc::RLIM_SAVED_CUR as u64;
53     #[cfg(any(
54         any(target_os = "openbsd", target_os = "netbsd"),
55         target_os = "emscripten",
56         target_os = "fuchsia",
57         target_os = "linux",
58     ))]
59     const RLIM_SAVED_MAX: u64 = libc::RLIM_SAVED_MAX as u64;
60 }
61 
62 /// A value indicating no limit.
63 #[cfg(any(
64     all(target_os = "linux", target_env = "gnu"),
65     all(target_os = "linux", target_env = "musl"),
66     all(target_os = "linux", target_env = "uclibc", target_arch = "arm"),
67     all(target_os = "linux", target_env = "uclibc", target_arch = "mips"),
68     all(target_os = "linux", target_env = "uclibc", target_arch = "mips64"),
69     all(target_os = "linux", target_env = "uclibc", target_arch = "x86_64"),
70     any(target_os = "freebsd", target_os = "dragonfly"),
71     any(target_os = "macos", target_os = "ios"),
72     any(target_os = "openbsd", target_os = "netbsd"),
73     target_os = "android",
74     target_os = "emscripten",
75     target_os = "fuchsia",
76     target_os = "solarish",
77 ))]
78 pub const INFINITY: u64 = RLIM_INFINITY;
79 
80 /// A value indicating an unrepresentable saved soft limit.
81 #[cfg(any(
82     any(target_os = "openbsd", target_os = "netbsd"),
83     target_os = "emscripten",
84     target_os = "fuchsia",
85     target_os = "linux",
86 ))]
87 pub const SAVED_CUR: u64 = RLIM_SAVED_CUR;
88 
89 /// A value indicating an unrepresentable saved hard limit.
90 #[cfg(any(
91     any(target_os = "openbsd", target_os = "netbsd"),
92     target_os = "emscripten",
93     target_os = "fuchsia",
94     target_os = "linux",
95 ))]
96 pub const SAVED_MAX: u64 = RLIM_SAVED_MAX;
97 
98 // #end-codegen
99 
100 use std::io;
101 use std::mem;
102 
103 use libc::c_int;
104 
105 #[cfg(target_os = "linux")]
106 group! {
107     use std::ptr;
108     use libc::pid_t;
109 }
110 
111 /// Set resource limits.
112 /// # Errors
113 /// \[Linux\] See <https://man7.org/linux/man-pages/man2/setrlimit.2.html>
114 #[inline]
setrlimit(resource: Resource, soft: u64, hard: u64) -> io::Result<()>115 pub fn setrlimit(resource: Resource, soft: u64, hard: u64) -> io::Result<()> {
116     let raw_resource = resource.as_raw();
117 
118     let rlim = c_rlimit {
119         rlim_cur: soft.min(INFINITY) as _,
120         rlim_max: hard.min(INFINITY) as _,
121     };
122 
123     let ret: c_int = unsafe { c_setrlimit(raw_resource, &rlim) };
124 
125     if ret == 0 {
126         Ok(())
127     } else {
128         Err(io::Error::last_os_error())
129     }
130 }
131 
132 /// Get resource limits.
133 /// # Errors
134 /// \[Linux\] See <https://man7.org/linux/man-pages/man2/getrlimit.2.html>
135 #[inline]
getrlimit(resource: Resource) -> io::Result<(u64, u64)>136 pub fn getrlimit(resource: Resource) -> io::Result<(u64, u64)> {
137     let raw_resource = resource.as_raw();
138 
139     let mut rlim: c_rlimit = unsafe { mem::zeroed() };
140 
141     let ret: c_int = unsafe { c_getrlimit(raw_resource, &mut rlim) };
142 
143     if ret == 0 {
144         let soft = rlim.rlim_cur as u64;
145         let hard = rlim.rlim_max as u64;
146         Ok((soft, hard))
147     } else {
148         Err(io::Error::last_os_error())
149     }
150 }
151 
152 /// \[Linux\] Set and get the resource limits of an arbitrary process.
153 /// # Errors
154 /// See <https://man7.org/linux/man-pages/man2/prlimit.2.html>
155 #[inline]
156 #[cfg(target_os = "linux")]
prlimit( pid: pid_t, resource: Resource, new_limit: Option<(u64, u64)>, old_limit: Option<(&mut u64, &mut u64)>, ) -> io::Result<()>157 pub fn prlimit(
158     pid: pid_t,
159     resource: Resource,
160     new_limit: Option<(u64, u64)>,
161     old_limit: Option<(&mut u64, &mut u64)>,
162 ) -> io::Result<()> {
163     let raw_resource = resource.as_raw();
164 
165     let new_rlim: Option<libc::rlimit> = new_limit.map(|(soft, hard)| libc::rlimit {
166         rlim_cur: soft.min(INFINITY) as _,
167         rlim_max: hard.min(INFINITY) as _,
168     });
169 
170     let new_rlimit_ptr: *const libc::rlimit = match new_rlim {
171         Some(ref rlim) => rlim,
172         None => ptr::null(),
173     };
174 
175     let mut old_rlim: libc::rlimit = unsafe { mem::zeroed() };
176 
177     let old_rlimit_ptr: *mut libc::rlimit = if old_limit.is_some() {
178         &mut old_rlim
179     } else {
180         ptr::null_mut()
181     };
182 
183     let ret: c_int = unsafe { libc::prlimit(pid, raw_resource, new_rlimit_ptr, old_rlimit_ptr) };
184 
185     if ret == 0 {
186         if let Some((soft, hard)) = old_limit {
187             *soft = old_rlim.rlim_cur as u64;
188             *hard = old_rlim.rlim_max as u64;
189         }
190 
191         Ok(())
192     } else {
193         Err(io::Error::last_os_error())
194     }
195 }
196