1use 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#[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}