Advertisement
Guest User

Untitled

a guest
Jul 20th, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.67 KB | None | 0 0
  1. #![allow(unused)]
  2.  
  3. use std::path::Path;
  4. use std::path::PathBuf;
  5. use std::path::{Ancestors};
  6. use std::fs::{OpenOptions, ReadDir,};
  7. use std::io::{self, Read, Write};
  8. use std::str::FromStr;
  9.  
  10. #[cfg(target_os = "linux")]
  11. const PATH_PREFIX: &'static str = "/proc/sys";
  12. #[cfg(not(target_os = "linux"))]
  13. const PATH_PREFIX: &'static str = concat!(env!("PWD"), "/proc/sys");
  14.  
  15. #[cfg(target_os = "linux")]
  16. const ROOT_PATH: &'static str = "/proc/sys/kernel";
  17. #[cfg(not(target_os = "linux"))]
  18. const ROOT_PATH: &'static str = concat!(env!("PWD"), "/proc/sys/kernel");
  19.  
  20. pub const CTL_MAXNAME: usize = 10;
  21.  
  22.  
  23. #[derive(Debug)]
  24. pub struct Mib {
  25. path: PathBuf,
  26. }
  27.  
  28. impl Mib {
  29. pub fn name(&self) -> Result<String, io::Error> {
  30. let name = self.path.strip_prefix(PATH_PREFIX)
  31. .map_err(|e| io::Error::new(io::ErrorKind::NotFound, format!("{}", e)))?
  32. .to_str()
  33. .ok_or(io::Error::new(io::ErrorKind::Other, "Not a utf-8 seqs"))?;
  34. Ok(name.replace("/", "."))
  35. }
  36.  
  37. // Get Value by Mib
  38. pub fn value(&self) -> Result<Vec<u8>, io::Error> {
  39. if !self.path.is_file() {
  40. return Err(io::Error::new(io::ErrorKind::Other, "Can not get value from a Node."));
  41. }
  42.  
  43. let mut file = OpenOptions::new().read(true).write(false).open(&self.path)?;
  44. let mut val = Vec::new();
  45. file.read_to_end(&mut val)?;
  46. Ok(val)
  47. }
  48.  
  49. // Set Value By Mib
  50. pub fn set_value(&self, val: &[u8]) -> Result<Vec<u8>, io::Error> {
  51. let mut file = OpenOptions::new().read(false).write(true).open(&self.path)?;
  52. file.write_all(val)?;
  53. self.value()
  54. }
  55.  
  56. // Get metadata ( ValueKind )
  57. pub fn metadata(&self) -> Result<(), io::Error> {
  58. unimplemented!()
  59. }
  60.  
  61. #[inline]
  62. pub fn description(&self) -> Result<String, std::io::Error> {
  63. Err(io::Error::new(io::ErrorKind::Other, "Description not available on Linux"))
  64. }
  65.  
  66. pub fn iter(&self) -> Result<MibIter, io::Error> {
  67. MibIter::new(&self.path)
  68. }
  69. }
  70.  
  71.  
  72.  
  73. impl FromStr for Mib {
  74. type Err = io::Error;
  75.  
  76. fn from_str(s: &str) -> Result<Self, Self::Err> {
  77. let path = if s.starts_with(PATH_PREFIX) {
  78. if s.ends_with(PATH_PREFIX) {
  79. return Err(io::Error::from(io::ErrorKind::NotFound));
  80. }
  81. PathBuf::from(s)
  82. } else {
  83. PathBuf::from(PATH_PREFIX).join(s.replace(".", "/"))
  84. };
  85.  
  86. // return absolute path, and ensure the path is exists.
  87. let path = path.canonicalize()?;
  88.  
  89. debug_assert!(path.is_absolute());
  90. debug_assert!(path.exists());
  91. debug_assert!(path.starts_with(PATH_PREFIX));
  92.  
  93. Ok(Self { path, })
  94. }
  95. }
  96.  
  97. impl Default for Mib {
  98. fn default() -> Self {
  99. Self {
  100. path: PathBuf::from(ROOT_PATH)
  101. }
  102. }
  103. }
  104.  
  105. #[derive(Debug)]
  106. pub struct MibIter {
  107. dirs: Vec<ReadDir>,
  108. }
  109.  
  110. impl MibIter {
  111. fn new(path: &Path) -> Result<Self, io::Error> {
  112. let root = Path::new(PATH_PREFIX);
  113. debug_assert!(root.is_dir());
  114.  
  115. let mut dirs = Vec::new();
  116. dirs.push(root.read_dir()?);
  117.  
  118. fn seek(dirs: &mut Vec<ReadDir>, stop_path: &Path) -> Result<(), io::Error> {
  119. if dirs.len() == 0 {
  120. return Ok(());
  121. }
  122.  
  123. let idx = dirs.len() - 1;
  124. let mut dir = match dirs.get_mut(idx) {
  125. Some(dir) => dir,
  126. None => return Ok(()),
  127. };
  128.  
  129. loop {
  130. let entry = dir.next();
  131. if entry.is_none() {
  132. dirs.remove(idx);
  133. return seek(dirs, stop_path);
  134. }
  135.  
  136. let entry = entry.unwrap()?;
  137. let file_type = entry.file_type()?;
  138. let file_path = entry.path();
  139.  
  140. if file_type.is_dir() {
  141. dirs.push(file_path.read_dir()?);
  142. if file_path == stop_path {
  143. break;
  144. }
  145.  
  146. return seek(dirs, stop_path);
  147.  
  148. } else if file_type.is_file() {
  149. // println!("Skip: {:?}", file_path);
  150. if file_path == stop_path {
  151. break;
  152. }
  153. } else {
  154. // TODO: symlink
  155. unimplemented!()
  156. }
  157. }
  158.  
  159. Ok(())
  160. }
  161.  
  162. seek(&mut dirs, &path)?;
  163.  
  164. Ok(MibIter {
  165. dirs: dirs,
  166. })
  167. }
  168. }
  169.  
  170. impl Iterator for MibIter {
  171. type Item = Result<Mib, std::io::Error>;
  172.  
  173. fn next(&mut self) -> Option<Self::Item> {
  174. if self.dirs.len() == 0 {
  175. return None;
  176. }
  177.  
  178. let idx = self.dirs.len() - 1;
  179. let mut dir = self.dirs.get_mut(idx).unwrap();
  180.  
  181. match dir.next() {
  182. Some(Ok(entry)) => {
  183. let file_type = match entry.file_type() {
  184. Ok(file_type) => file_type,
  185. Err(e) => return Some(Err(e)),
  186. };
  187. let file_path = entry.path();
  188.  
  189. if file_type.is_dir() {
  190. match file_path.read_dir() {
  191. Ok(sub_dir) => self.dirs.push(sub_dir),
  192. Err(e) => return Some(Err(e)),
  193. }
  194. self.next()
  195. } else if file_type.is_file() {
  196. let s = file_path.to_string_lossy().to_string();
  197. Some(Mib::from_str(&s))
  198. } else {
  199. // TODO: hanlde symlink
  200. unimplemented!()
  201. }
  202. },
  203. Some(Err(e)) => return Some(Err(e)),
  204. None => {
  205. self.dirs.remove(idx);
  206. self.next()
  207. }
  208. }
  209. }
  210. }
  211.  
  212. /*
  213. macOS:
  214.  
  215. ```python
  216. import os
  217.  
  218. os.makedirs("proc/sys/kernel/keys")
  219. os.makedirs("proc/sys/net/ipv4/")
  220. os.system("touch proc/sys/kernel/a")
  221. os.system("touch proc/sys/kernel/osrelease")
  222. os.system("touch proc/sys/kernel/ostype")
  223. os.system("touch proc/sys/kernel/version")
  224. os.system("touch proc/sys/kernel/keys/root_maxbytes")
  225. os.system("touch proc/sys/kernel/keys/root_maxkeys")
  226. os.system("touch proc/sys/net/ipv4/ip_forward")
  227. os.system("touch proc/sys/net/ipv4/tcp_mem")
  228. os.system("touch proc/sys/net/ipv4/udp_mem")
  229. ```
  230. */
  231. fn main() -> Result<(), io::Error> {
  232. // Get Value
  233. let mib = "kernel.ostype".parse::<Mib>()?;
  234. println!("{:?}", mib.value());
  235.  
  236. // Walk (NextMib)
  237. for x in mib.iter()? {
  238. let next_mib = x?;
  239. println!("{:?}", next_mib);
  240. println!("{:?}", next_mib.value());
  241. }
  242.  
  243. Ok(())
  244. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement