sysctl/
traits.rs

1// traits.rs
2
3use ctl_error::SysctlError;
4use ctl_flags::CtlFlags;
5use ctl_info::CtlInfo;
6use ctl_type::CtlType;
7use ctl_value::CtlValue;
8
9pub trait Sysctl {
10    /// Construct a Ctl from the name.
11    ///
12    /// Returns a result containing the struct Ctl on success or a SysctlError
13    /// on failure.
14    ///
15    /// # Example
16    /// ```
17    /// # use sysctl::Sysctl;
18    /// #
19    /// let ctl = sysctl::Ctl::new("kern.ostype");
20    /// ```
21    ///
22    /// If the sysctl does not exist, `Err(SysctlError::NotFound)` is returned.
23    /// ```
24    /// # use sysctl::Sysctl;
25    /// #
26    /// let ctl = sysctl::Ctl::new("this.sysctl.does.not.exist");
27    /// match ctl {
28    ///     Err(sysctl::SysctlError::NotFound(_)) => (),
29    ///     Err(e) => panic!(format!("Wrong error type returned: {:?}", e)),
30    ///     Ok(_) => panic!("Nonexistent sysctl seems to exist"),
31    /// }
32    /// ```
33    fn new(name: &str) -> Result<Self, SysctlError>
34    where
35        Self: std::marker::Sized;
36
37    /// Construct a Ctl from the name, type and format.
38    ///
39    /// Returns a result containing the struct Ctl on success or a SysctlError
40    /// on failure.
41    ///
42    /// # Example
43    /// ```
44    /// # use sysctl::{CtlType, Sysctl};
45    /// #
46    /// let ctl = sysctl::Ctl::new_with_type("kern.ostype", CtlType::String, "");
47    /// ```
48    ///
49    /// If the sysctl does not exist, `Err(SysctlError::NotFound)` is returned.
50    /// ```
51    /// # use sysctl::{CtlType, Sysctl};
52    /// #
53    /// let ctl = sysctl::Ctl::new_with_type("this.sysctl.does.not.exist", CtlType::String, "");
54    /// match ctl {
55    ///     Err(sysctl::SysctlError::NotFound(_)) => (),
56    ///     Err(e) => panic!("Wrong error type returned: {:?}", e),
57    ///     Ok(_) => panic!("Nonexistent sysctl seems to exist"),
58    /// }
59    /// ```
60    fn new_with_type(name: &str, ctl_type: CtlType, fmt: &str) -> Result<Self, SysctlError>
61    where
62        Self: std::marker::Sized;
63
64    /// Returns a result containing the sysctl name on success, or a
65    /// SysctlError on failure.
66    ///
67    /// # Example
68    /// ```
69    /// # use sysctl::Sysctl;
70    /// if let Ok(ctl) = sysctl::Ctl::new("kern.ostype") {
71    ///     assert_eq!(ctl.name().unwrap(), "kern.ostype");
72    /// }
73    /// ```
74    fn name(&self) -> Result<String, SysctlError>;
75
76    /// Returns a result containing the sysctl value type on success,
77    /// or a Sysctl Error on failure.
78    ///
79    /// # Example
80    ///
81    /// ```
82    /// # use sysctl::Sysctl;
83    /// if let Ok(ctl) = sysctl::Ctl::new("kern.ostype") {
84    ///     let value_type = ctl.value_type().unwrap();
85    ///     assert_eq!(value_type, sysctl::CtlType::String);
86    /// }
87    /// ```
88    fn value_type(&self) -> Result<CtlType, SysctlError>;
89
90    /// Returns a result containing the sysctl description if success, or an
91    /// Error on failure.
92    ///
93    /// # Example
94    /// ```
95    /// # use sysctl::Sysctl;
96    /// if let Ok(ctl) = sysctl::Ctl::new("kern.ostype") {
97    ///     println!("Description: {:?}", ctl.description())
98    /// }
99    /// ```
100    fn description(&self) -> Result<String, SysctlError>;
101
102    /// Returns a result containing the sysctl value on success, or a
103    /// SysctlError on failure.
104    ///
105    /// # Example
106    /// ```
107    /// # use sysctl::Sysctl;
108    /// if let Ok(ctl) = sysctl::Ctl::new("kern.ostype") {
109    ///     println!("Value: {:?}", ctl.value());
110    /// }
111    /// ```
112    fn value(&self) -> Result<CtlValue, SysctlError>;
113
114    /// A generic method that takes returns a result containing the sysctl
115    /// value if success, or a SysctlError on failure.
116    ///
117    /// May only be called for sysctls of type Opaque or Struct.
118    /// # Example
119    /// ```
120    /// # use sysctl::Sysctl;
121    /// #[derive(Debug)]
122    /// #[repr(C)]
123    /// struct ClockInfo {
124    ///     hz: libc::c_int, /* clock frequency */
125    ///     tick: libc::c_int, /* micro-seconds per hz tick */
126    ///     spare: libc::c_int,
127    ///     stathz: libc::c_int, /* statistics clock frequency */
128    ///     profhz: libc::c_int, /* profiling clock frequency */
129    /// }
130    ///
131    /// if let Ok(ctl) = sysctl::Ctl::new("kern.clockrate") {
132    ///     println!("{:?}", ctl.value_as::<ClockInfo>());
133    /// }
134    /// ```
135    fn value_as<T>(&self) -> Result<Box<T>, SysctlError>;
136
137    /// Returns a result containing the sysctl value as String on
138    /// success, or a SysctlError on failure.
139    ///
140    /// # Example
141    /// ```
142    /// # use sysctl::Sysctl;
143    /// if let Ok(ctl) = sysctl::Ctl::new("kern.osrevision") {
144    ///     println!("Value: {:?}", ctl.value_string());
145    /// }
146    /// ```
147    fn value_string(&self) -> Result<String, SysctlError>;
148
149    #[cfg_attr(feature = "cargo-clippy", allow(clippy::needless_doctest_main))]
150    /// Sets the value of a sysctl.
151    /// Fetches and returns the new value if successful, or returns a
152    /// SysctlError on failure.
153    /// # Example
154    /// ```
155    /// use sysctl::Sysctl;
156    ///
157    /// fn main() {
158    ///     if unsafe { libc::getuid() } == 0 {
159    ///         if let Ok(ctl) = sysctl::Ctl::new("hw.usb.debug") {
160    ///             let org = ctl.value().unwrap();
161    ///             let set = ctl.set_value(sysctl::CtlValue::Int(1)).unwrap();
162    ///             assert_eq!(set, sysctl::CtlValue::Int(1));
163    ///             ctl.set_value(org).unwrap();
164    ///         }
165    ///     }
166    /// }
167    fn set_value(&self, value: CtlValue) -> Result<CtlValue, SysctlError>;
168
169    #[cfg_attr(feature = "cargo-clippy", allow(clippy::needless_doctest_main))]
170    /// Sets the value of a sysctl with input as string.
171    /// Fetches and returns the new value if successful, or returns a
172    /// SysctlError on failure.
173    /// # Example
174    /// ```
175    /// use sysctl::Sysctl;
176    ///
177    /// fn main() {
178    ///     if unsafe { libc::getuid() } == 0 {
179    ///         if let Ok(ctl) = sysctl::Ctl::new("hw.usb.debug") {
180    ///             let org = ctl.value_string().unwrap();
181    ///             let set = ctl.set_value_string("1");
182    ///             println!("hw.usb.debug: -> {:?}", set);
183    ///             ctl.set_value_string(&org).unwrap();
184    ///         }
185    ///     }
186    /// }
187    fn set_value_string(&self, value: &str) -> Result<String, SysctlError>;
188
189    /// Get the flags for a sysctl.
190    ///
191    /// Returns a Result containing the flags on success,
192    /// or a SysctlError on failure.
193    ///
194    /// # Example
195    /// ```
196    /// # use sysctl::Sysctl;
197    /// if let Ok(ctl) = sysctl::Ctl::new("kern.ostype") {
198    ///     let readable = ctl.flags().unwrap().contains(sysctl::CtlFlags::RD);
199    ///     assert!(readable);
200    /// }
201    /// ```
202    fn flags(&self) -> Result<CtlFlags, SysctlError>;
203
204    #[cfg_attr(feature = "cargo-clippy", allow(clippy::needless_doctest_main))]
205    /// Returns a Result containing the control metadata for a sysctl.
206    ///
207    /// Returns a Result containing the CtlInfo struct on success,
208    /// or a SysctlError on failure.
209    ///
210    /// # Example
211    /// ```
212    /// use sysctl::Sysctl;
213    ///
214    /// fn main() {
215    ///     if let Ok(ctl) = sysctl::Ctl::new("kern.osrevision") {
216    ///         let info = ctl.info().unwrap();
217    ///
218    ///         // kern.osrevision is not a structure.
219    ///         assert_eq!(info.struct_type(), None);
220    ///     }
221    /// }
222    /// ```
223    fn info(&self) -> Result<CtlInfo, SysctlError>;
224}