c_scape/process/
rlimit.rs

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}