1#[cfg(target_os = "freebsd")]
4use temperature::Temperature;
5use enum_as_inner::EnumAsInner;
6
7#[derive(Debug, EnumAsInner, PartialEq, PartialOrd)]
23pub enum CtlValue {
24 None,
25 Node(Vec<u8>),
26 Int(i32),
27 String(String),
28 S64(i64),
29 Struct(Vec<u8>),
30 Uint(u32),
31 Long(i64),
32 Ulong(u64),
33 U64(u64),
34 U8(u8),
35 U16(u16),
36 S8(i8),
37 S16(i16),
38 S32(i32),
39 U32(u32),
40 #[cfg(target_os = "freebsd")]
41 Temperature(Temperature),
42}
43
44impl std::fmt::Display for CtlValue {
45 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46 let s = match self {
47 CtlValue::None => "[None]".to_owned(),
48 CtlValue::Int(i) => format!("{}", i),
49 CtlValue::Uint(i) => format!("{}", i),
50 CtlValue::Long(i) => format!("{}", i),
51 CtlValue::Ulong(i) => format!("{}", i),
52 CtlValue::U8(i) => format!("{}", i),
53 CtlValue::U16(i) => format!("{}", i),
54 CtlValue::U32(i) => format!("{}", i),
55 CtlValue::U64(i) => format!("{}", i),
56 CtlValue::S8(i) => format!("{}", i),
57 CtlValue::S16(i) => format!("{}", i),
58 CtlValue::S32(i) => format!("{}", i),
59 CtlValue::S64(i) => format!("{}", i),
60 CtlValue::Struct(_) => "[Opaque Struct]".to_owned(),
61 CtlValue::Node(_) => "[Node]".to_owned(),
62 CtlValue::String(s) => s.to_owned(),
63 #[cfg(target_os = "freebsd")]
64 CtlValue::Temperature(t) => format!("{}", t.kelvin()),
65 };
66 write!(f, "{}", s)
67 }
68}
69
70#[cfg(all(test, any(target_os = "linux", target_os = "android")))]
71mod tests_linux {
72 use crate::sys;
73 use crate::Sysctl;
74
75 #[test]
76 fn ctl_value_string() {
77 let output = std::process::Command::new("sysctl")
80 .arg("-n")
81 .arg("kernel.version")
82 .output()
83 .expect("failed to execute process");
84 let ver = String::from_utf8_lossy(&output.stdout);
85 let s = match sys::funcs::value("/proc/sys/kernel/version") {
86 Ok(crate::CtlValue::String(s)) => s,
87 _ => panic!("crate::value() returned Error"),
88 };
89 assert_eq!(s.trim(), ver.trim());
90
91 let kernversion = crate::Ctl::new("kernel.version").unwrap();
92 let s = match kernversion.value() {
93 Ok(crate::CtlValue::String(s)) => s,
94 _ => "...".into(),
95 };
96 assert_eq!(s.trim(), ver.trim());
97 }
98}
99
100#[cfg(all(test, any(target_os = "freebsd", target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "visionos")))]
101mod tests_unix {
102 use crate::sys;
103 use crate::Sysctl;
104
105 #[test]
106 fn ctl_value_string() {
107 let output = std::process::Command::new("sysctl")
108 .arg("-n")
109 .arg("kern.version")
110 .output()
111 .expect("failed to execute process");
112 let ver = String::from_utf8_lossy(&output.stdout);
113 let ctl = crate::Ctl::new("kern.version").expect("Ctl::new");
114 let s = match ctl.value() {
115 Ok(crate::CtlValue::String(s)) => s,
116 _ => "...".into(),
117 };
118 assert_eq!(s.trim(), ver.trim());
119
120 let kernversion = crate::Ctl::new("kern.version").unwrap();
121 let s = match kernversion.value() {
122 Ok(crate::CtlValue::String(s)) => s,
123 _ => "...".into(),
124 };
125 assert_eq!(s.trim(), ver.trim());
126 }
127
128 #[test]
129 fn ctl_value_int() {
130 let output = std::process::Command::new("sysctl")
131 .arg("-n")
132 .arg("kern.osrevision")
133 .output()
134 .expect("failed to execute process");
135 let rev_str = String::from_utf8_lossy(&output.stdout);
136 let rev = rev_str.trim().parse::<i32>().unwrap();
137
138 let ctl =
139 crate::Ctl::new("kern.osrevision").expect("Could not get kern.osrevision sysctl.");
140 let n = match ctl.value() {
141 Ok(crate::CtlValue::Int(n)) => n,
142 Ok(_) => 0,
143 Err(_) => 0,
144 };
145 assert_eq!(n, rev);
146 }
147
148 #[test]
149 fn ctl_value_oid_int() {
150 let output = std::process::Command::new("sysctl")
151 .arg("-n")
152 .arg("kern.osrevision")
153 .output()
154 .expect("failed to execute process");
155 let rev_str = String::from_utf8_lossy(&output.stdout);
156 let rev = rev_str.trim().parse::<i32>().unwrap();
157 let n = match sys::funcs::value_oid(&mut vec![libc::CTL_KERN, libc::KERN_OSREV]) {
158 Ok(crate::CtlValue::Int(n)) => n,
159 Ok(_) => 0,
160 Err(_) => 0,
161 };
162 assert_eq!(n, rev);
163 }
164
165 #[test]
166 fn ctl_struct_type() {
167 let info = crate::CtlInfo {
168 ctl_type: crate::CtlType::Int,
169 fmt: "S,TYPE".into(),
170 flags: 0,
171 };
172
173 assert_eq!(info.struct_type(), Some("TYPE".into()));
174
175 let info = crate::CtlInfo {
176 ctl_type: crate::CtlType::Int,
177 fmt: "I".into(),
178 flags: 0,
179 };
180 assert_eq!(info.struct_type(), None);
181 }
182}