1use crate::errors::{Errno, error};
6use crate::{
7 RLIM_INFINITY, RLIMIT_AS, RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA, RLIMIT_FSIZE, RLIMIT_LOCKS,
8 RLIMIT_MEMLOCK, RLIMIT_MSGQUEUE, RLIMIT_NICE, RLIMIT_NOFILE, RLIMIT_NPROC, RLIMIT_RSS,
9 RLIMIT_RTPRIO, RLIMIT_RTTIME, RLIMIT_SIGPENDING, RLIMIT_STACK, rlimit, uapi,
10};
11use std::collections::HashMap;
12
13pub struct ResourceDesc {
15 pub name: &'static str,
17
18 pub unit: &'static str,
20}
21
22impl ResourceDesc {
23 fn new(name: &'static str, unit: &'static str) -> ResourceDesc {
24 ResourceDesc { name, unit }
25 }
26}
27
28#[allow(clippy::upper_case_acronyms)]
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30pub enum Resource {
31 CPU,
32 FSIZE,
33 DATA,
34 STACK,
35 CORE,
36 RSS,
37 NPROC,
38 NOFILE,
39 MEMLOCK,
40 AS,
41 LOCKS,
42 SIGPENDING,
43 MSGQUEUE,
44 NICE,
45 RTPRIO,
46 RTTIME,
47}
48
49impl Resource {
50 pub const ALL: [Resource; 16] = [
51 Resource::CPU,
52 Resource::FSIZE,
53 Resource::DATA,
54 Resource::STACK,
55 Resource::CORE,
56 Resource::RSS,
57 Resource::NPROC,
58 Resource::NOFILE,
59 Resource::MEMLOCK,
60 Resource::AS,
61 Resource::LOCKS,
62 Resource::SIGPENDING,
63 Resource::MSGQUEUE,
64 Resource::NICE,
65 Resource::RTPRIO,
66 Resource::RTTIME,
67 ];
68
69 pub fn from_raw(raw: u32) -> Result<Resource, Errno> {
70 Ok(match raw {
71 RLIMIT_CPU => Resource::CPU,
72 RLIMIT_FSIZE => Resource::FSIZE,
73 RLIMIT_DATA => Resource::DATA,
74 RLIMIT_STACK => Resource::STACK,
75 RLIMIT_CORE => Resource::CORE,
76 RLIMIT_RSS => Resource::RSS,
77 RLIMIT_NPROC => Resource::NPROC,
78 RLIMIT_NOFILE => Resource::NOFILE,
79 RLIMIT_MEMLOCK => Resource::MEMLOCK,
80 RLIMIT_AS => Resource::AS,
81 RLIMIT_LOCKS => Resource::LOCKS,
82 RLIMIT_SIGPENDING => Resource::SIGPENDING,
83 RLIMIT_MSGQUEUE => Resource::MSGQUEUE,
84 RLIMIT_NICE => Resource::NICE,
85 RLIMIT_RTPRIO => Resource::RTPRIO,
86 RLIMIT_RTTIME => Resource::RTTIME,
87 _ => return error!(EINVAL),
88 })
89 }
90
91 pub fn desc(&self) -> ResourceDesc {
92 match self {
93 Resource::CPU => ResourceDesc::new("Max cpu time", "seconds"),
94 Resource::FSIZE => ResourceDesc::new("Max file size", "bytes"),
95 Resource::DATA => ResourceDesc::new("Max data size", "bytes"),
96 Resource::STACK => ResourceDesc::new("Max stack size", "bytes"),
97 Resource::CORE => ResourceDesc::new("Max core file size", "bytes"),
98 Resource::RSS => ResourceDesc::new("Max resident set", "bytes"),
99 Resource::NPROC => ResourceDesc::new("Max processes", "processes"),
100 Resource::NOFILE => ResourceDesc::new("Max open files", "files"),
101 Resource::MEMLOCK => ResourceDesc::new("Max locked memory", "bytes"),
102 Resource::AS => ResourceDesc::new("Max address space", "bytes"),
103 Resource::LOCKS => ResourceDesc::new("Max file locks", "bytes"),
104 Resource::SIGPENDING => ResourceDesc::new("Max pending signals", "signals"),
105 Resource::MSGQUEUE => ResourceDesc::new("Max msgqueue size", "bytes"),
106 Resource::NICE => ResourceDesc::new("Max nice priority", ""),
107 Resource::RTPRIO => ResourceDesc::new("Max realtime priority", ""),
108 Resource::RTTIME => ResourceDesc::new("Max realtime timeout", "us"),
109 }
110 }
111}
112
113#[derive(Debug, Clone)]
114pub struct ResourceLimits {
115 values: HashMap<Resource, rlimit>,
116}
117
118const INFINITE_LIMIT: rlimit =
119 rlimit { rlim_cur: RLIM_INFINITY as u64, rlim_max: RLIM_INFINITY as u64 };
120
121const NPROC_LIMIT: u64 = 0x1FFFFFFF;
125
126const SIGPENDING_LIMIT: u64 = 0x1FFFFFFF;
129
130const DEFAULT_LIMITS: [(Resource, rlimit); 9] = [
131 (Resource::STACK, rlimit { rlim_cur: uapi::_STK_LIM as u64, rlim_max: RLIM_INFINITY as u64 }),
132 (Resource::CORE, rlimit { rlim_cur: 0, rlim_max: uapi::RLIM_INFINITY as u64 }),
133 (Resource::NPROC, rlimit { rlim_cur: NPROC_LIMIT, rlim_max: NPROC_LIMIT }),
134 (
135 Resource::NOFILE,
136 rlimit { rlim_cur: uapi::INR_OPEN_CUR as u64, rlim_max: uapi::INR_OPEN_MAX as u64 },
137 ),
138 (
139 Resource::MEMLOCK,
140 rlimit { rlim_cur: uapi::MLOCK_LIMIT as u64, rlim_max: uapi::MLOCK_LIMIT as u64 },
141 ),
142 (Resource::SIGPENDING, rlimit { rlim_cur: SIGPENDING_LIMIT, rlim_max: SIGPENDING_LIMIT }),
143 (
144 Resource::MSGQUEUE,
145 rlimit { rlim_cur: uapi::MQ_BYTES_MAX as u64, rlim_max: uapi::MQ_BYTES_MAX as u64 },
146 ),
147 (Resource::NICE, rlimit { rlim_cur: 0, rlim_max: 0 }),
148 (Resource::RTPRIO, rlimit { rlim_cur: 0, rlim_max: 0 }),
149];
150
151impl Default for ResourceLimits {
152 fn default() -> Self {
153 let mut limits = Self { values: Default::default() };
154 for (resource, value) in DEFAULT_LIMITS.iter() {
155 limits.set(*resource, *value);
156 }
157 limits
158 }
159}
160
161impl ResourceLimits {
164 pub fn get(&self, resource: Resource) -> rlimit {
165 *self.values.get(&resource).unwrap_or(&INFINITE_LIMIT)
166 }
167
168 pub fn set(&mut self, resource: Resource, value: rlimit) {
169 self.values.insert(resource, value);
170 }
171}