Skip to content

Commit 8358ecb

Browse files
committed
pmap: use Perms struct instead of String for perms
1 parent 5cb72d5 commit 8358ecb

File tree

1 file changed

+57
-27
lines changed

1 file changed

+57
-27
lines changed

src/uu/pmap/src/maps_format_parser.rs

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
use std::fmt;
67
use std::io::{Error, ErrorKind};
78

89
// Represents a parsed single line from /proc/<PID>/maps for the default and device formats. It
@@ -11,12 +12,50 @@ use std::io::{Error, ErrorKind};
1112
pub struct MapLine {
1213
pub address: String,
1314
pub size_in_kb: u64,
14-
pub perms: String,
15+
pub perms: Perms,
1516
pub offset: String,
1617
pub device: String,
1718
pub mapping: String,
1819
}
1920

21+
// Represents a set of permissions from the "perms" column of /proc/<PID>/maps.
22+
#[derive(Clone, Copy, Debug, PartialEq)]
23+
pub struct Perms {
24+
pub readable: bool,
25+
pub writable: bool,
26+
pub executable: bool,
27+
pub shared: bool,
28+
}
29+
30+
impl From<&str> for Perms {
31+
fn from(s: &str) -> Self {
32+
let mut chars = s.chars();
33+
34+
Self {
35+
readable: chars.next() == Some('r'),
36+
writable: chars.next() == Some('w'),
37+
executable: chars.next() == Some('x'),
38+
shared: chars.next() == Some('s'),
39+
}
40+
}
41+
}
42+
43+
// Please note: While `Perms` has four boolean fields, it's string representation has five
44+
// characters because pmap's default and device formats use five characters for the perms,
45+
// with the last character always being '-'.
46+
impl fmt::Display for Perms {
47+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48+
write!(
49+
f,
50+
"{}{}{}{}-",
51+
if self.readable { 'r' } else { '-' },
52+
if self.writable { 'w' } else { '-' },
53+
if self.executable { 'x' } else { '-' },
54+
if self.shared { 's' } else { '-' },
55+
)
56+
}
57+
}
58+
2059
// Parses a single line from /proc/<PID>/maps. See
2160
// https://www.kernel.org/doc/html/latest/filesystems/proc.html for details about the expected
2261
// format.
@@ -33,7 +72,7 @@ pub fn parse_map_line(line: &str) -> Result<MapLine, Error> {
3372
let (perms, rest) = rest
3473
.split_once(' ')
3574
.ok_or_else(|| Error::from(ErrorKind::InvalidData))?;
36-
let perms = parse_perms(perms);
75+
let perms = Perms::from(perms);
3776

3877
let (offset, rest) = rest
3978
.split_once(' ')
@@ -74,15 +113,6 @@ fn parse_address(memory_range: &str) -> Result<(String, u64), Error> {
74113
Ok((format!("{start:0>16}"), size_in_kb))
75114
}
76115

77-
// Turns a 4-char perms string from /proc/<PID>/maps into a 5-char perms string. The first three
78-
// chars are left untouched.
79-
fn parse_perms(perms: &str) -> String {
80-
let perms = perms.replace("p", "-");
81-
82-
// the fifth char seems to be always '-' in the original pmap
83-
format!("{perms}-")
84-
}
85-
86116
// Pads the device info from /proc/<PID>/maps with zeros and turns AB:CD into 0AB:000CD.
87117
fn parse_device(device: &str) -> Result<String, Error> {
88118
let (major, minor) = device
@@ -113,50 +143,57 @@ mod test {
113143
fn create_map_line(
114144
address: &str,
115145
size_in_kb: u64,
116-
perms: &str,
146+
perms: Perms,
117147
offset: &str,
118148
device: &str,
119149
mapping: &str,
120150
) -> MapLine {
121151
MapLine {
122152
address: address.to_string(),
123153
size_in_kb,
124-
perms: perms.to_string(),
154+
perms,
125155
offset: offset.to_string(),
126156
device: device.to_string(),
127157
mapping: mapping.to_string(),
128158
}
129159
}
130160

161+
#[test]
162+
fn test_perms_to_string() {
163+
assert_eq!("-----", Perms::from("---p").to_string());
164+
assert_eq!("---s-", Perms::from("---s").to_string());
165+
assert_eq!("rwx--", Perms::from("rwxp").to_string());
166+
}
167+
131168
#[test]
132169
fn test_parse_map_line() {
133170
let data = [
134171
(
135-
create_map_line("000062442eb9e000", 16, "r----", "0000000000000000", "008:00008", "konsole"),
172+
create_map_line("000062442eb9e000", 16, Perms::from("r--p"), "0000000000000000", "008:00008", "konsole"),
136173
"62442eb9e000-62442eba2000 r--p 00000000 08:08 10813151 /usr/bin/konsole"
137174
),
138175
(
139-
create_map_line("000071af50000000", 132, "rw---", "0000000000000000", "000:00000", " [ anon ]"),
176+
create_map_line("000071af50000000", 132, Perms::from("rw-p"), "0000000000000000", "000:00000", " [ anon ]"),
140177
"71af50000000-71af50021000 rw-p 00000000 00:00 0 "
141178
),
142179
(
143-
create_map_line("00007ffc3f8df000", 132, "rw---", "0000000000000000", "000:00000", " [ stack ]"),
180+
create_map_line("00007ffc3f8df000", 132, Perms::from("rw-p"), "0000000000000000", "000:00000", " [ stack ]"),
144181
"7ffc3f8df000-7ffc3f900000 rw-p 00000000 00:00 0 [stack]"
145182
),
146183
(
147-
create_map_line("000071af8c9e6000", 16, "rw-s-", "0000000105830000", "000:00010", " [ anon ]"),
184+
create_map_line("000071af8c9e6000", 16, Perms::from("rw-s"), "0000000105830000", "000:00010", " [ anon ]"),
148185
"71af8c9e6000-71af8c9ea000 rw-s 105830000 00:10 1075 anon_inode:i915.gem"
149186
),
150187
(
151-
create_map_line("000071af6cf0c000", 3560, "rw-s-", "0000000000000000", "000:00001", "memfd:wayland-shm (deleted)"),
188+
create_map_line("000071af6cf0c000", 3560, Perms::from("rw-s"), "0000000000000000", "000:00001", "memfd:wayland-shm (deleted)"),
152189
"71af6cf0c000-71af6d286000 rw-s 00000000 00:01 256481 /memfd:wayland-shm (deleted)"
153190
),
154191
(
155-
create_map_line("ffffffffff600000", 4, "--x--", "0000000000000000", "000:00000", " [ anon ]"),
192+
create_map_line("ffffffffff600000", 4, Perms::from("--xp"), "0000000000000000", "000:00000", " [ anon ]"),
156193
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
157194
),
158195
(
159-
create_map_line("00005e8187da8000", 24, "r----", "0000000000000000", "008:00008", "hello world"),
196+
create_map_line("00005e8187da8000", 24, Perms::from("r--p"), "0000000000000000", "008:00008", "hello world"),
160197
"5e8187da8000-5e8187dae000 r--p 00000000 08:08 9524160 /usr/bin/hello world"
161198
),
162199
];
@@ -193,13 +230,6 @@ mod test {
193230
assert!(parse_address("ffffffffff600000-zfffffffff601000").is_err());
194231
}
195232

196-
#[test]
197-
fn test_parse_perms() {
198-
assert_eq!("-----", parse_perms("---p"));
199-
assert_eq!("---s-", parse_perms("---s"));
200-
assert_eq!("rwx--", parse_perms("rwxp"));
201-
}
202-
203233
#[test]
204234
fn test_parse_device() {
205235
assert_eq!("012:00034", parse_device("12:34").unwrap());

0 commit comments

Comments
 (0)