Skip to content

Commit eb26215

Browse files
committed
Add support for /dev/devices
1 parent 784dd2c commit eb26215

File tree

4 files changed

+209
-1
lines changed

4 files changed

+209
-1
lines changed

procfs-core/src/devices.rs

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
use std::io::BufRead;
2+
3+
use super::ProcResult;
4+
use std::str::FromStr;
5+
6+
#[cfg(feature = "serde1")]
7+
use serde::{Deserialize, Serialize};
8+
9+
/// Device entries under `/proc/devices`
10+
#[derive(Debug, Clone)]
11+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
12+
#[allow(non_snake_case)]
13+
pub struct Devices {
14+
/// Character devices
15+
pub char_devices: Vec<CharDeviceEntry>,
16+
/// Block devices
17+
pub block_devices: Vec<BlockDeviceEntry>,
18+
}
19+
20+
/// A charcter device entry under `/proc/devices`
21+
#[derive(Debug, Clone)]
22+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
23+
#[allow(non_snake_case)]
24+
pub struct CharDeviceEntry {
25+
/// Device major number
26+
pub major: u32,
27+
/// Device name
28+
pub name: String,
29+
}
30+
31+
/// A block device entry under `/proc/devices`
32+
#[derive(Debug, Clone)]
33+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
34+
#[allow(non_snake_case)]
35+
pub struct BlockDeviceEntry {
36+
/// Device major number
37+
pub major: i32,
38+
/// Device name
39+
pub name: String,
40+
}
41+
42+
impl super::FromBufRead for Devices {
43+
fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
44+
enum State {
45+
Char,
46+
Block,
47+
}
48+
let mut state = State::Char; // Always start with char devices
49+
let mut devices = Devices {
50+
char_devices: vec![],
51+
block_devices: vec![],
52+
};
53+
54+
for line in r.lines() {
55+
let line = expect!(line);
56+
57+
if line.is_empty() {
58+
continue;
59+
} else if line.starts_with("Character devices:") {
60+
state = State::Char;
61+
continue;
62+
} else if line.starts_with("Block devices:") {
63+
state = State::Block;
64+
continue;
65+
}
66+
67+
let mut s = line.split_whitespace();
68+
69+
match state {
70+
State::Char => {
71+
let major = expect!(u32::from_str(expect!(s.next())));
72+
let name = expect!(s.next()).to_string();
73+
74+
let char_device_entry = CharDeviceEntry { major, name };
75+
76+
devices.char_devices.push(char_device_entry);
77+
}
78+
State::Block => {
79+
let major = expect!(i32::from_str(expect!(s.next())));
80+
let name = expect!(s.next()).to_string();
81+
82+
let block_device_entry = BlockDeviceEntry { major, name };
83+
84+
devices.block_devices.push(block_device_entry);
85+
}
86+
}
87+
}
88+
89+
Ok(devices)
90+
}
91+
}
92+
93+
#[cfg(test)]
94+
mod tests {
95+
use super::*;
96+
#[test]
97+
fn test_devices() {
98+
use crate::FromBufRead;
99+
use std::io::Cursor;
100+
101+
let s = "Character devices:
102+
1 mem
103+
4 /dev/vc/0
104+
4 tty
105+
4 ttyS
106+
5 /dev/tty
107+
5 /dev/console
108+
5 /dev/ptmx
109+
7 vcs
110+
10 misc
111+
13 input
112+
29 fb
113+
90 mtd
114+
136 pts
115+
180 usb
116+
188 ttyUSB
117+
189 usb_device
118+
119+
Block devices:
120+
7 loop
121+
8 sd
122+
65 sd
123+
71 sd
124+
128 sd
125+
135 sd
126+
254 device-mapper
127+
259 blkext
128+
";
129+
130+
let cursor = Cursor::new(s);
131+
let devices = Devices::from_buf_read(cursor).unwrap();
132+
let (chrs, blks) = (devices.char_devices, devices.block_devices);
133+
134+
assert_eq!(chrs.len(), 16);
135+
136+
assert_eq!(chrs[1].major, 4);
137+
assert_eq!(chrs[1].name, "/dev/vc/0");
138+
139+
assert_eq!(chrs[8].major, 10);
140+
assert_eq!(chrs[8].name, "misc");
141+
142+
assert_eq!(chrs[15].major, 189);
143+
assert_eq!(chrs[15].name, "usb_device");
144+
145+
assert_eq!(blks.len(), 8);
146+
147+
assert_eq!(blks[0].major, 7);
148+
assert_eq!(blks[0].name, "loop");
149+
150+
assert_eq!(blks[7].major, 259);
151+
assert_eq!(blks[7].name, "blkext");
152+
}
153+
154+
#[test]
155+
fn test_devices_without_block() {
156+
use crate::FromBufRead;
157+
use std::io::Cursor;
158+
159+
let s = "Character devices:
160+
1 mem
161+
4 /dev/vc/0
162+
4 tty
163+
4 ttyS
164+
5 /dev/tty
165+
5 /dev/console
166+
5 /dev/ptmx
167+
7 vcs
168+
10 misc
169+
13 input
170+
29 fb
171+
90 mtd
172+
136 pts
173+
180 usb
174+
188 ttyUSB
175+
189 usb_device
176+
";
177+
178+
let cursor = Cursor::new(s);
179+
let devices = Devices::from_buf_read(cursor).unwrap();
180+
let (chrs, blks) = (devices.char_devices, devices.block_devices);
181+
182+
assert_eq!(chrs.len(), 16);
183+
184+
assert_eq!(chrs[1].major, 4);
185+
assert_eq!(chrs[1].name, "/dev/vc/0");
186+
187+
assert_eq!(chrs[8].major, 10);
188+
assert_eq!(chrs[8].name, "misc");
189+
190+
assert_eq!(chrs[15].major, 189);
191+
assert_eq!(chrs[15].name, "usb_device");
192+
193+
assert_eq!(blks.len(), 0);
194+
}
195+
}

procfs-core/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ pub use cpuinfo::*;
354354
mod crypto;
355355
pub use crypto::*;
356356

357+
mod devices;
358+
pub use devices::*;
359+
357360
mod diskstats;
358361
pub use diskstats::*;
359362

procfs/src/lib.rs

+10
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,10 @@ impl Current for CpuInfo {
434434
const PATH: &'static str = "/proc/cpuinfo";
435435
}
436436

437+
impl Current for Devices {
438+
const PATH: &'static str = "/proc/devices";
439+
}
440+
437441
impl Current for DiskStats {
438442
const PATH: &'static str = "/proc/diskstats";
439443
}
@@ -685,6 +689,12 @@ mod tests {
685689
//assert_eq!(info.num_cores(), 8);
686690
}
687691

692+
#[test]
693+
fn test_devices() {
694+
let devices = Devices::current().unwrap();
695+
println!("{:#?}", devices);
696+
}
697+
688698
#[test]
689699
fn test_diskstats() {
690700
for disk in super::diskstats().unwrap() {

support.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ This is an approximate list of all the files under the `/proc` mount, and an ind
7171
* [ ] `/proc/config.gz`
7272
* [ ] `/proc/crypto`
7373
* [ ] `/proc/cpuinfo`
74-
* [ ] `/proc/devices`
74+
* [x] `/proc/devices`
7575
* [x] `/proc/diskstats`
7676
* [ ] `/proc/dma`
7777
* [ ] `/proc/driver`

0 commit comments

Comments
 (0)