1use crate::{convert_res, set_errno, Errno};
2use libc::{c_int, RLIM64_INFINITY, RLIM_INFINITY};
3use rustix::process::{Pid, Resource, Rlimit};
4
5#[cfg(not(target_env = "musl"))]
6use libc::__rlimit_resource_t;
7#[cfg(target_env = "musl")]
8#[allow(non_camel_case_types)]
9type __rlimit_resource_t = c_int;
10
11#[no_mangle]
12unsafe extern "C" fn getrlimit(
13 resource: __rlimit_resource_t,
14 old_limit: *mut libc::rlimit,
15) -> c_int {
16 libc!(libc::getrlimit(resource, old_limit));
17
18 let resource = match resource_to_rustix(resource) {
19 Some(resource) => resource,
20 None => return -1,
21 };
22 let limit = rustix::process::getrlimit(resource);
23 if !old_limit.is_null() {
24 *old_limit = rustix_to_rlimit(limit);
25 }
26 0
27}
28
29#[no_mangle]
30unsafe extern "C" fn getrlimit64(
31 resource: __rlimit_resource_t,
32 old_limit: *mut libc::rlimit64,
33) -> c_int {
34 libc!(libc::getrlimit64(resource, old_limit));
35
36 let resource = match resource_to_rustix(resource) {
37 Some(resource) => resource,
38 None => return -1,
39 };
40 let limit = rustix::process::getrlimit(resource);
41 if !old_limit.is_null() {
42 *old_limit = rustix_to_rlimit64(limit);
43 }
44 0
45}
46
47#[no_mangle]
48unsafe extern "C" fn setrlimit(
49 resource: __rlimit_resource_t,
50 new_limit: *const libc::rlimit,
51) -> c_int {
52 libc!(libc::setrlimit(resource, new_limit));
53
54 let resource = match resource_to_rustix(resource) {
55 Some(resource) => resource,
56 None => return -1,
57 };
58 let new_limit = rlimit_to_rustix(*new_limit);
59 match convert_res(rustix::process::setrlimit(resource, new_limit)) {
60 Some(()) => 0,
61 None => -1,
62 }
63}
64
65#[no_mangle]
66unsafe extern "C" fn setrlimit64(
67 resource: __rlimit_resource_t,
68 new_limit: *const libc::rlimit64,
69) -> c_int {
70 libc!(libc::setrlimit64(resource, new_limit));
71
72 let resource = match resource_to_rustix(resource) {
73 Some(resource) => resource,
74 None => return -1,
75 };
76 let new_limit = rlimit64_to_rustix(*new_limit);
77 match convert_res(rustix::process::setrlimit(resource, new_limit)) {
78 Some(()) => 0,
79 None => -1,
80 }
81}
82
83#[no_mangle]
84unsafe extern "C" fn prlimit(
85 pid: libc::pid_t,
86 resource: __rlimit_resource_t,
87 new_limit: *const libc::rlimit,
88 old_limit: *mut libc::rlimit,
89) -> c_int {
90 libc!(libc::prlimit(pid, resource, new_limit, old_limit));
91
92 let resource = match resource_to_rustix(resource) {
93 Some(resource) => resource,
94 None => return -1,
95 };
96 let new_limit = rlimit_to_rustix(*new_limit);
97 let pid = Pid::from_raw(pid as _);
98 match convert_res(rustix::process::prlimit(pid, resource, new_limit)) {
99 Some(limit) => {
100 if !old_limit.is_null() {
101 *old_limit = rustix_to_rlimit(limit);
102 }
103 0
104 }
105 None => -1,
106 }
107}
108
109#[no_mangle]
110unsafe extern "C" fn prlimit64(
111 pid: libc::pid_t,
112 resource: __rlimit_resource_t,
113 new_limit: *const libc::rlimit64,
114 old_limit: *mut libc::rlimit64,
115) -> c_int {
116 libc!(libc::prlimit64(pid, resource, new_limit, old_limit));
117
118 let resource = match resource_to_rustix(resource) {
119 Some(resource) => resource,
120 None => return -1,
121 };
122 let new_limit = rlimit64_to_rustix(*new_limit);
123 let pid = Pid::from_raw(pid as _);
124 match convert_res(rustix::process::prlimit(pid, resource, new_limit)) {
125 Some(limit) => {
126 if !old_limit.is_null() {
127 *old_limit = rustix_to_rlimit64(limit);
128 }
129 0
130 }
131 None => -1,
132 }
133}
134
135fn resource_to_rustix(resource: __rlimit_resource_t) -> Option<Resource> {
136 Some(match resource {
137 libc::RLIMIT_CPU => Resource::Cpu,
138 libc::RLIMIT_FSIZE => Resource::Fsize,
139 libc::RLIMIT_DATA => Resource::Data,
140 libc::RLIMIT_STACK => Resource::Stack,
141 libc::RLIMIT_CORE => Resource::Core,
142 libc::RLIMIT_RSS => Resource::Rss,
143 libc::RLIMIT_NPROC => Resource::Nproc,
144 libc::RLIMIT_NOFILE => Resource::Nofile,
145 libc::RLIMIT_MEMLOCK => Resource::Memlock,
146 libc::RLIMIT_AS => Resource::As,
147 libc::RLIMIT_LOCKS => Resource::Locks,
148 libc::RLIMIT_SIGPENDING => Resource::Sigpending,
149 libc::RLIMIT_MSGQUEUE => Resource::Msgqueue,
150 libc::RLIMIT_NICE => Resource::Nice,
151 libc::RLIMIT_RTPRIO => Resource::Rtprio,
152 libc::RLIMIT_RTTIME => Resource::Rttime,
153 _ => {
154 set_errno(Errno(libc::EINVAL));
155 return None;
156 }
157 })
158}
159
160fn rlimit_to_rustix(limit: libc::rlimit) -> Rlimit {
161 Rlimit {
162 current: if limit.rlim_cur == RLIM_INFINITY {
163 None
164 } else {
165 Some(limit.rlim_cur.into())
166 },
167 maximum: if limit.rlim_max == RLIM_INFINITY {
168 None
169 } else {
170 Some(limit.rlim_max.into())
171 },
172 }
173}
174
175fn rlimit64_to_rustix(limit: libc::rlimit64) -> Rlimit {
176 Rlimit {
177 current: if limit.rlim_cur == RLIM64_INFINITY {
178 None
179 } else {
180 Some(limit.rlim_cur)
181 },
182 maximum: if limit.rlim_max == RLIM64_INFINITY {
183 None
184 } else {
185 Some(limit.rlim_max)
186 },
187 }
188}
189
190fn rustix_to_rlimit(limit: Rlimit) -> libc::rlimit {
191 libc::rlimit {
192 rlim_cur: match limit.current {
193 Some(lim) => lim.try_into().unwrap(),
194 None => RLIM_INFINITY,
195 },
196 rlim_max: match limit.maximum {
197 Some(lim) => lim.try_into().unwrap(),
198 None => RLIM_INFINITY,
199 },
200 }
201}
202
203fn rustix_to_rlimit64(limit: Rlimit) -> libc::rlimit64 {
204 libc::rlimit64 {
205 rlim_cur: match limit.current {
206 Some(lim) => lim,
207 None => RLIM64_INFINITY,
208 },
209 rlim_max: match limit.maximum {
210 Some(lim) => lim,
211 None => RLIM64_INFINITY,
212 },
213 }
214}