1use crate::{expect, from_str, ProcResult};
2use std::io::BufRead;
3
4#[cfg(feature = "serde1")]
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
10pub enum LockType {
11 FLock,
13
14 Posix,
16
17 ODF,
19
20 Other(String),
22}
23
24impl LockType {
25 pub fn as_str(&self) -> &str {
26 match self {
27 LockType::FLock => "FLOCK",
28 LockType::Posix => "POSIX",
29 LockType::ODF => "ODF",
30 LockType::Other(s) => s.as_ref(),
31 }
32 }
33}
34
35impl From<&str> for LockType {
36 fn from(s: &str) -> LockType {
37 match s {
38 "FLOCK" => LockType::FLock,
39 "OFDLCK" => LockType::ODF,
40 "POSIX" => LockType::Posix,
41 x => LockType::Other(x.to_string()),
42 }
43 }
44}
45
46#[derive(Debug, Clone)]
48#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
49pub enum LockMode {
50 Advisory,
51 Mandatory,
52
53 Other(String),
55}
56
57impl LockMode {
58 pub fn as_str(&self) -> &str {
59 match self {
60 LockMode::Advisory => "ADVISORY",
61 LockMode::Mandatory => "MANDATORY",
62 LockMode::Other(s) => s.as_ref(),
63 }
64 }
65}
66
67impl From<&str> for LockMode {
68 fn from(s: &str) -> LockMode {
69 match s {
70 "ADVISORY" => LockMode::Advisory,
71 "MANDATORY" => LockMode::Mandatory,
72 x => LockMode::Other(x.to_string()),
73 }
74 }
75}
76
77#[derive(Debug, Clone)]
79#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
80pub enum LockKind {
81 Read,
83
84 Write,
86
87 Other(String),
89}
90
91impl LockKind {
92 pub fn as_str(&self) -> &str {
93 match self {
94 LockKind::Read => "READ",
95 LockKind::Write => "WRITE",
96 LockKind::Other(s) => s.as_ref(),
97 }
98 }
99}
100
101impl From<&str> for LockKind {
102 fn from(s: &str) -> LockKind {
103 match s {
104 "READ" => LockKind::Read,
105 "WRITE" => LockKind::Write,
106 x => LockKind::Other(x.to_string()),
107 }
108 }
109}
110
111#[derive(Debug, Clone)]
112#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
113pub struct Lock {
118 pub lock_type: LockType,
120 pub mode: LockMode,
122 pub kind: LockKind,
124 pub pid: Option<i32>,
132 pub devmaj: u32,
134 pub devmin: u32,
136 pub inode: u64,
138 pub offset_first: u64,
142 pub offset_last: Option<u64>,
147}
148
149impl Lock {
150 fn from_line(line: &str) -> ProcResult<Lock> {
151 let mut s = line.split_whitespace();
152
153 let _ = expect!(s.next());
154 let typ = {
155 let t = expect!(s.next());
156 if t == "->" {
157 From::from(expect!(s.next()))
159 } else {
160 From::from(t)
161 }
162 };
163 let mode = From::from(expect!(s.next()));
164 let kind = From::from(expect!(s.next()));
165 let pid = expect!(s.next());
166 let disk_inode = expect!(s.next());
167 let offset_first = from_str!(u64, expect!(s.next()));
168 let offset_last = expect!(s.next());
169
170 let mut dis = disk_inode.split(':');
171 let devmaj = from_str!(u32, expect!(dis.next()), 16);
172 let devmin = from_str!(u32, expect!(dis.next()), 16);
173 let inode = from_str!(u64, expect!(dis.next()));
174
175 Ok(Lock {
176 lock_type: typ,
177 mode,
178 kind,
179 pid: if pid == "-1" { None } else { Some(from_str!(i32, pid)) },
180 devmaj,
181 devmin,
182 inode,
183 offset_first,
184 offset_last: if offset_last == "EOF" {
185 None
186 } else {
187 Some(from_str!(u64, offset_last))
188 },
189 })
190 }
191}
192
193#[derive(Debug, Clone)]
194#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
195pub struct Locks(pub Vec<Lock>);
197
198impl super::FromBufRead for Locks {
199 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
200 let mut v = Vec::new();
201
202 for line in r.lines() {
203 let line = line?;
204 v.push(Lock::from_line(&line)?);
205 }
206 Ok(Locks(v))
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 #[test]
213 fn test_blocked() {
214 let data = r#"1: POSIX ADVISORY WRITE 723 00:14:16845 0 EOF
215 2: FLOCK ADVISORY WRITE 652 00:14:16763 0 EOF
216 3: FLOCK ADVISORY WRITE 1594 fd:00:396528 0 EOF
217 4: FLOCK ADVISORY WRITE 1594 fd:00:396527 0 EOF
218 5: FLOCK ADVISORY WRITE 2851 fd:00:529372 0 EOF
219 6: POSIX ADVISORY WRITE 1280 00:14:16200 0 0
220 6: -> POSIX ADVISORY WRITE 1281 00:14:16200 0 0
221 6: -> POSIX ADVISORY WRITE 1279 00:14:16200 0 0
222 6: -> POSIX ADVISORY WRITE 1282 00:14:16200 0 0
223 6: -> POSIX ADVISORY WRITE 1283 00:14:16200 0 0
224 7: OFDLCK ADVISORY READ -1 00:06:1028 0 EOF
225 8: FLOCK ADVISORY WRITE 6471 fd:00:529426 0 EOF
226 9: FLOCK ADVISORY WRITE 6471 fd:00:529424 0 EOF
227 10: FLOCK ADVISORY WRITE 6471 fd:00:529420 0 EOF
228 11: FLOCK ADVISORY WRITE 6471 fd:00:529418 0 EOF
229 12: POSIX ADVISORY WRITE 1279 00:14:23553 0 EOF
230 13: FLOCK ADVISORY WRITE 6471 fd:00:393838 0 EOF
231 14: POSIX ADVISORY WRITE 655 00:14:16146 0 EOF"#;
232
233 for line in data.lines() {
234 super::Lock::from_line(line.trim()).unwrap();
235 }
236 }
237}