proc_getter/lib.rs
1#![cfg(target_os = "linux")]
2#![doc(html_playground_url = "https://play.rust-lang.org/")]
3
4//! ## how to use
5//!
6//! The layout of this crate is very like the /proc/ directory layout.
7//!
8//! Each file correspond to a module which contains everything to interoperate with the file.
9//! Majority modules has a function which has the same name as the file.
10//!
11//! However, function reside in process directories is a little different.
12//! They receive an u32 argument to specify the target process, and the function name has a "_of" suffix.
13//!
14//! ```
15//! use proc_getter::cmdline::*;
16//! use proc_getter::pid::cmdline::*;
17//!
18//! fn main() {
19//! // /proc/cmdline
20//! println!("{:?}", cmdline());
21//!
22//! // /proc/1/cmdline
23//! println!("{:?}", cmdline_of(1));
24//! }
25//! ```
26//!
27//! Everything under proc mod is re-export, so `crate::proc::cmdline` equals to `crate::cmdline`.
28//!
29//! ## Returning value
30//!
31//! The returning value has different type depends on the files.
32//! Some function simply return the content of the file, including ending `\n`.
33//! Some function parse the content and return the wrapping type.
34//!
35//! There are tow possbile cases where return an Err:
36//!
37//! 1. there is a bug because we parse the file content incorrectlly.
38//! 2. the file corresponding to the function is not exist in your computer.
39//!
40//! Otherwise all the function should success in theory,
41//! since files under proc file system are not real file.
42//!
43//! ## which files is supported
44//!
45//! It's very depends on th system.
46//! Here is a list from [red hat], every file in this list should be supported.
47//!
48//![red hat]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/ch-proc
49
50/// all kind of error may occurs in the crate.
51///
52/// IO often occurs when the file is not exists in your system, it wrap an std::io::Error::NotFound.
53/// others should be consider as an error and should be fix.
54#[derive(Debug)]
55pub enum Error {
56 /// contains a std::io::Error, which should be `NotFound`.
57 IO(std::io::Error),
58 /// this error should appear.
59 /// Otherwise it's a situation where unexpected input appears.
60 /// That is a bug.default_read!
61 BadFormat,
62 ParseInt(std::num::ParseIntError),
63 ParseFloat(std::num::ParseFloatError),
64 ParseAddr(std::net::AddrParseError),
65}
66
67impl From<std::net::AddrParseError> for Error {
68 fn from(err: std::net::AddrParseError) -> Self {
69 Error::ParseAddr(err)
70 }
71}
72
73impl From<std::io::Error> for Error {
74 fn from(err: std::io::Error) -> Self {
75 Error::IO(err)
76 }
77}
78
79impl From<std::num::ParseIntError> for Error {
80 fn from(err: std::num::ParseIntError) -> Self {
81 Error::ParseInt(err)
82 }
83}
84
85impl From<std::num::ParseFloatError> for Error {
86 fn from(err: std::num::ParseFloatError) -> Self {
87 Error::ParseFloat(err)
88 }
89}
90
91type Result<T> = std::result::Result<T, Error>;
92
93macro_rules! default_read {
94 ($fn_name: ident, $path: expr) => {
95 /// Read the whole file content and return it.
96 /// Ending line break is included.
97 pub fn $fn_name() -> $crate::Result<String> {
98 Ok(std::fs::read_to_string($path)?)
99 }
100 };
101}
102
103macro_rules! default_list {
104 ($fn_name: ident, $path: expr, $return_type: ty, $parse_code: ident, $sep: expr, $skip: expr) => {
105 pub fn $fn_name() -> $crate::Result<Vec<$return_type>> {
106 let content = std::fs::read_to_string($path)?;
107 let mut ret = vec![];
108 let mut block_iter = content.trim().split($sep);
109 for _ in 0..$skip {
110 let _ = block_iter.next();
111 }
112 for block in block_iter {
113 ret.push($parse_code(block)?);
114 }
115 Ok(ret)
116 }
117 };
118 ($fn_name: ident, $path: expr, $return_type: ty, $parse_code: ident, $sep: expr) => {
119 default_list! {$fn_name, $path, $return_type, $parse_code, $sep, 0}
120 };
121 ($fn_name: ident, $path: expr, $return_type: ty, $parse_code: ident) => {
122 default_list! {$fn_name, $path, $return_type, $parse_code, '\n', 0}
123 };
124}
125
126macro_rules! getter_gen {
127 (
128 $(
129 $filed: ident : $type: ty
130 ), *
131 ) => {
132 $(
133 #[inline(always)]
134 pub fn $filed(&self) -> &$type {
135 &self.$filed
136 }
137 ) *
138 };
139}
140
141pub mod proc;
142#[doc(inline)]
143pub use proc::*;