Skip to content

Commit 6c959b6

Browse files
authored
Merge pull request #311 from yamaura/proc_devices
Add support for /dev/devices
2 parents f2a51ef + dc70412 commit 6c959b6

File tree

4 files changed

+206
-1
lines changed

4 files changed

+206
-1
lines changed

procfs-core/src/devices.rs

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

procfs-core/src/lib.rs

Lines changed: 3 additions & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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)