1 | //! Get system identification |
2 | use crate::{Errno, Result}; |
3 | use libc::c_char; |
4 | use std::ffi::OsStr; |
5 | use std::mem; |
6 | use std::os::unix::ffi::OsStrExt; |
7 | |
8 | /// Describes the running system. Return type of [`uname`]. |
9 | #[derive (Clone, Copy, Debug, Eq, Hash, PartialEq)] |
10 | #[repr (transparent)] |
11 | pub struct UtsName(libc::utsname); |
12 | |
13 | impl UtsName { |
14 | /// Name of the operating system implementation. |
15 | pub fn sysname(&self) -> &OsStr { |
16 | cast_and_trim(&self.0.sysname) |
17 | } |
18 | |
19 | /// Network name of this machine. |
20 | pub fn nodename(&self) -> &OsStr { |
21 | cast_and_trim(&self.0.nodename) |
22 | } |
23 | |
24 | /// Release level of the operating system. |
25 | pub fn release(&self) -> &OsStr { |
26 | cast_and_trim(&self.0.release) |
27 | } |
28 | |
29 | /// Version level of the operating system. |
30 | pub fn version(&self) -> &OsStr { |
31 | cast_and_trim(&self.0.version) |
32 | } |
33 | |
34 | /// Machine hardware platform. |
35 | pub fn machine(&self) -> &OsStr { |
36 | cast_and_trim(&self.0.machine) |
37 | } |
38 | |
39 | /// NIS or YP domain name of this machine. |
40 | #[cfg (any(target_os = "android" , target_os = "linux" ))] |
41 | pub fn domainname(&self) -> &OsStr { |
42 | cast_and_trim(&self.0.domainname) |
43 | } |
44 | } |
45 | |
46 | /// Get system identification |
47 | pub fn uname() -> Result<UtsName> { |
48 | unsafe { |
49 | let mut ret: MaybeUninit = mem::MaybeUninit::zeroed(); |
50 | Errno::result(libc::uname(buf:ret.as_mut_ptr()))?; |
51 | Ok(UtsName(ret.assume_init())) |
52 | } |
53 | } |
54 | |
55 | fn cast_and_trim(slice: &[c_char]) -> &OsStr { |
56 | let length: usize = slice |
57 | .iter() |
58 | .position(|&byte| byte == 0) |
59 | .unwrap_or(default:slice.len()); |
60 | let bytes: &[u8] = |
61 | unsafe { std::slice::from_raw_parts(data:slice.as_ptr().cast(), len:length) }; |
62 | |
63 | OsStr::from_bytes(slice:bytes) |
64 | } |
65 | |
66 | #[cfg (test)] |
67 | mod test { |
68 | #[cfg (target_os = "linux" )] |
69 | #[test ] |
70 | pub fn test_uname_linux() { |
71 | assert_eq!(super::uname().unwrap().sysname(), "Linux" ); |
72 | } |
73 | |
74 | #[cfg (any(target_os = "macos" , target_os = "ios" ))] |
75 | #[test ] |
76 | pub fn test_uname_darwin() { |
77 | assert_eq!(super::uname().unwrap().sysname(), "Darwin" ); |
78 | } |
79 | |
80 | #[cfg (target_os = "freebsd" )] |
81 | #[test ] |
82 | pub fn test_uname_freebsd() { |
83 | assert_eq!(super::uname().unwrap().sysname(), "FreeBSD" ); |
84 | } |
85 | } |
86 | |