sysctl/linux/
ctl.rs

1// linux/ctl.rs
2
3use super::funcs::{path_to_name, set_value, value};
4use crate::consts::*;
5use crate::ctl_error::SysctlError;
6use crate::ctl_flags::CtlFlags;
7use crate::ctl_info::CtlInfo;
8use crate::ctl_type::CtlType;
9use crate::ctl_value::CtlValue;
10use crate::traits::Sysctl;
11
12use std::str::FromStr;
13
14/// This struct represents a system control.
15#[derive(Debug, Clone, PartialEq)]
16pub struct Ctl {
17    name: String,
18}
19
20impl FromStr for Ctl {
21    type Err = SysctlError;
22
23    fn from_str(name: &str) -> Result<Self, Self::Err> {
24        let ctl = Ctl {
25            name: path_to_name(name),
26        };
27        let _ =
28            std::fs::File::open(ctl.path()).map_err(|_| SysctlError::NotFound(name.to_owned()))?;
29        Ok(ctl)
30    }
31}
32
33impl Ctl {
34    pub fn path(&self) -> String {
35        format!("/proc/sys/{}", self.name.replace(".", "/"))
36    }
37}
38
39impl Sysctl for Ctl {
40    fn new(name: &str) -> Result<Self, SysctlError> {
41        Ctl::from_str(name)
42    }
43
44    fn new_with_type(name: &str, _ctl_type: CtlType, _fmt: &str) -> Result<Self, SysctlError> {
45        Ctl::from_str(name)
46    }
47
48    fn name(&self) -> Result<String, SysctlError> {
49        Ok(self.name.clone())
50    }
51
52    fn value_type(&self) -> Result<CtlType, SysctlError> {
53        let md = std::fs::metadata(&self.path()).map_err(SysctlError::IoError)?;
54        if md.is_dir() {
55            Ok(CtlType::Node)
56        } else {
57            Ok(CtlType::String)
58        }
59    }
60
61    fn description(&self) -> Result<String, SysctlError> {
62        Ok("[N/A]".to_owned())
63    }
64
65    fn value(&self) -> Result<CtlValue, SysctlError> {
66        value(&self.path())
67    }
68
69    fn value_string(&self) -> Result<String, SysctlError> {
70        self.value().map(|v| format!("{}", v))
71    }
72
73    fn value_as<T>(&self) -> Result<Box<T>, SysctlError> {
74        Err(SysctlError::NotSupported)
75    }
76
77    fn set_value(&self, value: CtlValue) -> Result<CtlValue, SysctlError> {
78        set_value(&self.path(), value)
79    }
80
81    fn set_value_string(&self, value: &str) -> Result<String, SysctlError> {
82        self.set_value(CtlValue::String(value.to_owned()))?;
83        self.value_string()
84    }
85
86    fn flags(&self) -> Result<CtlFlags, SysctlError> {
87        Ok(self.info()?.flags())
88    }
89
90    fn info(&self) -> Result<CtlInfo, SysctlError> {
91        let md = std::fs::metadata(&self.path()).map_err(SysctlError::IoError)?;
92        let mut flags = 0;
93        if md.permissions().readonly() {
94            flags |= CTLFLAG_RD;
95        } else {
96            flags |= CTLFLAG_RW;
97        }
98        let s = CtlInfo {
99            ctl_type: CtlType::String,
100            fmt: "".to_owned(),
101            flags: flags,
102        };
103        Ok(s)
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use crate::Sysctl;
110
111    #[test]
112    fn ctl_new() {
113        let _ = super::Ctl::new("kernel.ostype").expect("Ctl::new");
114    }
115}