linux_syscalls/env/kernel/
common.rs1use core::{cell::UnsafeCell, fmt};
2
3#[allow(non_camel_case_types)]
4#[repr(C)]
6#[derive(Copy, Clone)]
7pub struct utsname {
8 pub sysname: [u8; 65],
10 pub nodename: [u8; 65],
12 pub release: [u8; 65],
14 pub version: [u8; 65],
16 pub machine: [u8; 65],
18 pub domainname: [u8; 65],
20}
21
22#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
23pub struct Version {
25 pub major: u32,
26 pub minor: u32,
27 pub revision: u32,
28}
29
30impl fmt::Display for Version {
31 #[inline]
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "{}.{}.{}", self.major, self.minor, self.revision)
34 }
35}
36
37#[cfg(feature = "bare")]
38#[macro_export]
59macro_rules! kversion {
60 (> $($rest:tt)+) => {
61 *$crate::env::kernel_version() > $crate::kversion!($($rest)+)
62 };
63 (< $($rest:tt)+) => {
64 *$crate::env::kernel_version() < $crate::kversion!($($rest)+)
65 };
66 (== $($rest:tt)+) => {
67 *$crate::env::kernel_version() == $crate::kversion!($($rest)+)
68 };
69 (>= $($rest:tt)+) => {
70 *$crate::env::kernel_version() >= $crate::kversion!($($rest)+)
71 };
72 (<= $($rest:tt)+) => {
73 *$crate::env::kernel_version() <= $crate::kversion!($($rest)+)
74 };
75 ($major:expr) => {
76 $crate::kversion!($major, 0)
77 };
78 ($major:expr, $minor:expr) => {
79 $crate::kversion!($major, $minor, 0)
80 };
81 ($major:expr, $minor:expr, $revision:expr) => {
82 $crate::env::kernel::Version {
83 major: $major,
84 minor: $minor,
85 revision: $revision,
86 }
87 };
88}
89
90#[cfg(not(feature = "bare"))]
91#[macro_export]
112macro_rules! kversion {
113 (> $($rest:tt)+) => {
114 *$crate::env::unchecked_kernel_version() > $crate::kversion!($($rest)+)
115 };
116 (< $($rest:tt)+) => {
117 *$crate::env::unchecked_kernel_version() < $crate::kversion!($($rest)+)
118 };
119 (== $($rest:tt)+) => {
120 *$crate::env::unchecked_kernel_version() == $crate::kversion!($($rest)+)
121 };
122 (>= $($rest:tt)+) => {
123 *$crate::env::unchecked_kernel_version() >= $crate::kversion!($($rest)+)
124 };
125 (<= $($rest:tt)+) => {
126 *$crate::env::unchecked_kernel_version() <= $crate::kversion!($($rest)+)
127 };
128 ($major:expr) => {
129 $crate::kversion!($major, 0)
130 };
131 ($major:expr, $minor:expr) => {
132 $crate::kversion!($major, $minor, 0)
133 };
134 ($major:expr, $minor:expr, $revision:expr) => {
135 $crate::env::kernel::Version {
136 major: $major,
137 minor: $minor,
138 revision: $revision,
139 }
140 };
141}
142
143pub(crate) static mut UNAME: UnsafeCell<utsname> = UnsafeCell::new(utsname {
144 sysname: [0; 65],
145 nodename: [0; 65],
146 release: [0; 65],
147 version: [0; 65],
148 machine: [0; 65],
149 domainname: [0; 65],
150});
151pub(crate) static mut KERNEL_VERSION: UnsafeCell<Version> = UnsafeCell::new(kversion!(0));
152
153pub(super) unsafe fn init_version() {
154 let release = cstr(&(*UNAME.get()).release);
155
156 let (major, release) = if let Some(res) = version_rest(release) {
157 res
158 } else {
159 panic!("Invalid kernel version")
160 };
161
162 let (minor, release) = if let Some(res) = version_rest(release) {
163 res
164 } else {
165 panic!("Invalid kernel version")
166 };
167
168 let revision = if let Some(res) = version_last(release) {
169 res
170 } else {
171 panic!("Invalid kernel version")
172 };
173
174 let k = &mut *KERNEL_VERSION.get();
175 k.major = major;
176 k.minor = minor;
177 k.revision = revision;
178}
179
180fn atoi_raw(b: &[u8]) -> Option<(u32, usize)> {
181 let mut acc = 0u32;
182 let mut i = 0;
183
184 for c in b.iter().copied() {
185 if c.is_ascii_digit() {
186 acc = acc.checked_mul(10)?.checked_add((c - b'0') as u32)?;
187 } else {
188 return if i == 0 { None } else { Some((acc, i)) };
189 }
190 i += 1;
191 }
192
193 Some((acc, i))
194}
195
196fn version_rest(b: &[u8]) -> Option<(u32, &[u8])> {
197 let (n, size) = atoi_raw(b)?;
198 if Some(b'.') == b.get(size).copied() {
199 Some((n, unsafe { b.get_unchecked((size + 1)..) }))
200 } else {
201 None
202 }
203}
204
205#[inline]
206fn version_last(b: &[u8]) -> Option<u32> {
207 Some(atoi_raw(b)?.0)
208}
209
210unsafe fn cstr(s: &[u8]) -> &[u8] {
211 if let Some(i) = s.iter().copied().position(|c| c == 0) {
212 s.get_unchecked(..i)
213 } else {
214 s
215 }
216}
217
218#[inline]
219pub(crate) unsafe fn version() -> &'static Version {
220 &*KERNEL_VERSION.get()
221}
222
223#[inline]
224pub(crate) unsafe fn uname() -> &'static utsname {
225 &*UNAME.get()
226}