procfs_core/process/
limit.rs1use crate::{ProcError, ProcResult};
2
3use std::collections::HashMap;
4use std::io::BufRead;
5use std::str::FromStr;
6
7#[cfg(feature = "serde1")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone)]
14#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
15pub struct Limits {
16 pub max_cpu_time: Limit,
20
21 pub max_file_size: Limit,
25
26 pub max_data_size: Limit,
31
32 pub max_stack_size: Limit,
36
37 pub max_core_file_size: Limit,
41
42 pub max_resident_set: Limit,
47
48 pub max_processes: Limit,
53
54 pub max_open_files: Limit,
59
60 pub max_locked_memory: Limit,
64
65 pub max_address_space: Limit,
69
70 pub max_file_locks: Limit,
75
76 pub max_pending_signals: Limit,
81
82 pub max_msgqueue_size: Limit,
87
88 pub max_nice_priority: Limit,
93
94 pub max_realtime_priority: Limit,
99
100 pub max_realtime_timeout: Limit,
105}
106
107impl crate::FromBufRead for Limits {
108 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
109 let mut lines = r.lines();
110
111 let mut map = HashMap::new();
112
113 while let Some(Ok(line)) = lines.next() {
114 let line = line.trim();
115 if line.starts_with("Limit") {
116 continue;
117 }
118 let s: Vec<_> = line.split_whitespace().collect();
119 let l = s.len();
120
121 let (hard_limit, soft_limit, name) =
122 if line.starts_with("Max nice priority") || line.starts_with("Max realtime priority") {
123 let hard_limit = expect!(s.get(l - 1)).to_owned();
125 let soft_limit = expect!(s.get(l - 2)).to_owned();
126 let name = s[0..l - 2].join(" ");
127 (hard_limit, soft_limit, name)
128 } else {
129 let hard_limit = expect!(s.get(l - 2)).to_owned();
130 let soft_limit = expect!(s.get(l - 3)).to_owned();
131 let name = s[0..l - 3].join(" ");
132 (hard_limit, soft_limit, name)
133 };
134 let _units = expect!(s.get(l - 1));
135
136 map.insert(name.to_owned(), (soft_limit.to_owned(), hard_limit.to_owned()));
137 }
138
139 let limits = Limits {
140 max_cpu_time: Limit::from_pair(expect!(map.remove("Max cpu time")))?,
141 max_file_size: Limit::from_pair(expect!(map.remove("Max file size")))?,
142 max_data_size: Limit::from_pair(expect!(map.remove("Max data size")))?,
143 max_stack_size: Limit::from_pair(expect!(map.remove("Max stack size")))?,
144 max_core_file_size: Limit::from_pair(expect!(map.remove("Max core file size")))?,
145 max_resident_set: Limit::from_pair(expect!(map.remove("Max resident set")))?,
146 max_processes: Limit::from_pair(expect!(map.remove("Max processes")))?,
147 max_open_files: Limit::from_pair(expect!(map.remove("Max open files")))?,
148 max_locked_memory: Limit::from_pair(expect!(map.remove("Max locked memory")))?,
149 max_address_space: Limit::from_pair(expect!(map.remove("Max address space")))?,
150 max_file_locks: Limit::from_pair(expect!(map.remove("Max file locks")))?,
151 max_pending_signals: Limit::from_pair(expect!(map.remove("Max pending signals")))?,
152 max_msgqueue_size: Limit::from_pair(expect!(map.remove("Max msgqueue size")))?,
153 max_nice_priority: Limit::from_pair(expect!(map.remove("Max nice priority")))?,
154 max_realtime_priority: Limit::from_pair(expect!(map.remove("Max realtime priority")))?,
155 max_realtime_timeout: Limit::from_pair(expect!(map.remove("Max realtime timeout")))?,
156 };
157 if cfg!(test) {
158 assert!(map.is_empty(), "Map isn't empty: {:?}", map);
159 }
160 Ok(limits)
161 }
162}
163
164#[derive(Debug, Copy, Clone)]
165#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
166pub struct Limit {
167 pub soft_limit: LimitValue,
168 pub hard_limit: LimitValue,
169}
170
171impl Limit {
172 fn from_pair(l: (String, String)) -> ProcResult<Limit> {
173 let (soft, hard) = l;
174 Ok(Limit {
175 soft_limit: LimitValue::from_str(&soft)?,
176 hard_limit: LimitValue::from_str(&hard)?,
177 })
178 }
179}
180
181#[derive(Debug, Copy, Clone)]
182#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
183pub enum LimitValue {
184 Unlimited,
185 Value(u64),
186}
187
188impl FromStr for LimitValue {
189 type Err = ProcError;
190 fn from_str(s: &str) -> Result<Self, Self::Err> {
191 if s == "unlimited" {
192 Ok(LimitValue::Unlimited)
193 } else {
194 Ok(LimitValue::Value(from_str!(u64, s)))
195 }
196 }
197}