Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![allow(unused)]
- use std::path::Path;
- use std::path::PathBuf;
- use std::path::{Ancestors};
- use std::fs::{OpenOptions, ReadDir,};
- use std::io::{self, Read, Write};
- use std::str::FromStr;
- #[cfg(target_os = "linux")]
- const PATH_PREFIX: &'static str = "/proc/sys";
- #[cfg(not(target_os = "linux"))]
- const PATH_PREFIX: &'static str = concat!(env!("PWD"), "/proc/sys");
- #[cfg(target_os = "linux")]
- const ROOT_PATH: &'static str = "/proc/sys/kernel";
- #[cfg(not(target_os = "linux"))]
- const ROOT_PATH: &'static str = concat!(env!("PWD"), "/proc/sys/kernel");
- pub const CTL_MAXNAME: usize = 10;
- #[derive(Debug)]
- pub struct Mib {
- path: PathBuf,
- }
- impl Mib {
- pub fn name(&self) -> Result<String, io::Error> {
- let name = self.path.strip_prefix(PATH_PREFIX)
- .map_err(|e| io::Error::new(io::ErrorKind::NotFound, format!("{}", e)))?
- .to_str()
- .ok_or(io::Error::new(io::ErrorKind::Other, "Not a utf-8 seqs"))?;
- Ok(name.replace("/", "."))
- }
- // Get Value by Mib
- pub fn value(&self) -> Result<Vec<u8>, io::Error> {
- if !self.path.is_file() {
- return Err(io::Error::new(io::ErrorKind::Other, "Can not get value from a Node."));
- }
- let mut file = OpenOptions::new().read(true).write(false).open(&self.path)?;
- let mut val = Vec::new();
- file.read_to_end(&mut val)?;
- Ok(val)
- }
- // Set Value By Mib
- pub fn set_value(&self, val: &[u8]) -> Result<Vec<u8>, io::Error> {
- let mut file = OpenOptions::new().read(false).write(true).open(&self.path)?;
- file.write_all(val)?;
- self.value()
- }
- // Get metadata ( ValueKind )
- pub fn metadata(&self) -> Result<(), io::Error> {
- unimplemented!()
- }
- #[inline]
- pub fn description(&self) -> Result<String, std::io::Error> {
- Err(io::Error::new(io::ErrorKind::Other, "Description not available on Linux"))
- }
- pub fn iter(&self) -> Result<MibIter, io::Error> {
- MibIter::new(&self.path)
- }
- }
- impl FromStr for Mib {
- type Err = io::Error;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- let path = if s.starts_with(PATH_PREFIX) {
- if s.ends_with(PATH_PREFIX) {
- return Err(io::Error::from(io::ErrorKind::NotFound));
- }
- PathBuf::from(s)
- } else {
- PathBuf::from(PATH_PREFIX).join(s.replace(".", "/"))
- };
- // return absolute path, and ensure the path is exists.
- let path = path.canonicalize()?;
- debug_assert!(path.is_absolute());
- debug_assert!(path.exists());
- debug_assert!(path.starts_with(PATH_PREFIX));
- Ok(Self { path, })
- }
- }
- impl Default for Mib {
- fn default() -> Self {
- Self {
- path: PathBuf::from(ROOT_PATH)
- }
- }
- }
- #[derive(Debug)]
- pub struct MibIter {
- dirs: Vec<ReadDir>,
- }
- impl MibIter {
- fn new(path: &Path) -> Result<Self, io::Error> {
- let root = Path::new(PATH_PREFIX);
- debug_assert!(root.is_dir());
- let mut dirs = Vec::new();
- dirs.push(root.read_dir()?);
- fn seek(dirs: &mut Vec<ReadDir>, stop_path: &Path) -> Result<(), io::Error> {
- if dirs.len() == 0 {
- return Ok(());
- }
- let idx = dirs.len() - 1;
- let mut dir = match dirs.get_mut(idx) {
- Some(dir) => dir,
- None => return Ok(()),
- };
- loop {
- let entry = dir.next();
- if entry.is_none() {
- dirs.remove(idx);
- return seek(dirs, stop_path);
- }
- let entry = entry.unwrap()?;
- let file_type = entry.file_type()?;
- let file_path = entry.path();
- if file_type.is_dir() {
- dirs.push(file_path.read_dir()?);
- if file_path == stop_path {
- break;
- }
- return seek(dirs, stop_path);
- } else if file_type.is_file() {
- // println!("Skip: {:?}", file_path);
- if file_path == stop_path {
- break;
- }
- } else {
- // TODO: symlink
- unimplemented!()
- }
- }
- Ok(())
- }
- seek(&mut dirs, &path)?;
- Ok(MibIter {
- dirs: dirs,
- })
- }
- }
- impl Iterator for MibIter {
- type Item = Result<Mib, std::io::Error>;
- fn next(&mut self) -> Option<Self::Item> {
- if self.dirs.len() == 0 {
- return None;
- }
- let idx = self.dirs.len() - 1;
- let mut dir = self.dirs.get_mut(idx).unwrap();
- match dir.next() {
- Some(Ok(entry)) => {
- let file_type = match entry.file_type() {
- Ok(file_type) => file_type,
- Err(e) => return Some(Err(e)),
- };
- let file_path = entry.path();
- if file_type.is_dir() {
- match file_path.read_dir() {
- Ok(sub_dir) => self.dirs.push(sub_dir),
- Err(e) => return Some(Err(e)),
- }
- self.next()
- } else if file_type.is_file() {
- let s = file_path.to_string_lossy().to_string();
- Some(Mib::from_str(&s))
- } else {
- // TODO: hanlde symlink
- unimplemented!()
- }
- },
- Some(Err(e)) => return Some(Err(e)),
- None => {
- self.dirs.remove(idx);
- self.next()
- }
- }
- }
- }
- /*
- macOS:
- ```python
- import os
- os.makedirs("proc/sys/kernel/keys")
- os.makedirs("proc/sys/net/ipv4/")
- os.system("touch proc/sys/kernel/a")
- os.system("touch proc/sys/kernel/osrelease")
- os.system("touch proc/sys/kernel/ostype")
- os.system("touch proc/sys/kernel/version")
- os.system("touch proc/sys/kernel/keys/root_maxbytes")
- os.system("touch proc/sys/kernel/keys/root_maxkeys")
- os.system("touch proc/sys/net/ipv4/ip_forward")
- os.system("touch proc/sys/net/ipv4/tcp_mem")
- os.system("touch proc/sys/net/ipv4/udp_mem")
- ```
- */
- fn main() -> Result<(), io::Error> {
- // Get Value
- let mib = "kernel.ostype".parse::<Mib>()?;
- println!("{:?}", mib.value());
- // Walk (NextMib)
- for x in mib.iter()? {
- let next_mib = x?;
- println!("{:?}", next_mib);
- println!("{:?}", next_mib.value());
- }
- Ok(())
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement