| //! Get system identification |
| use crate::{Errno, Result}; |
| use libc::c_char; |
| use std::ffi::OsStr; |
| use std::mem; |
| use std::os::unix::ffi::OsStrExt; |
| |
| /// Describes the running system. Return type of [`uname`]. |
| #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] |
| #[repr(transparent)] |
| pub struct UtsName(libc::utsname); |
| |
| impl UtsName { |
| /// Name of the operating system implementation. |
| pub fn sysname(&self) -> &OsStr { |
| cast_and_trim(&self.0.sysname) |
| } |
| |
| /// Network name of this machine. |
| pub fn nodename(&self) -> &OsStr { |
| cast_and_trim(&self.0.nodename) |
| } |
| |
| /// Release level of the operating system. |
| pub fn release(&self) -> &OsStr { |
| cast_and_trim(&self.0.release) |
| } |
| |
| /// Version level of the operating system. |
| pub fn version(&self) -> &OsStr { |
| cast_and_trim(&self.0.version) |
| } |
| |
| /// Machine hardware platform. |
| pub fn machine(&self) -> &OsStr { |
| cast_and_trim(&self.0.machine) |
| } |
| |
| /// NIS or YP domain name of this machine. |
| #[cfg(any(target_os = "android", target_os = "linux"))] |
| pub fn domainname(&self) -> &OsStr { |
| cast_and_trim(&self.0.domainname) |
| } |
| } |
| |
| /// Get system identification |
| pub fn uname() -> Result<UtsName> { |
| unsafe { |
| let mut ret = mem::MaybeUninit::zeroed(); |
| Errno::result(libc::uname(ret.as_mut_ptr()))?; |
| Ok(UtsName(ret.assume_init())) |
| } |
| } |
| |
| fn cast_and_trim(slice: &[c_char]) -> &OsStr { |
| let length = slice |
| .iter() |
| .position(|&byte| byte == 0) |
| .unwrap_or(slice.len()); |
| let bytes = |
| unsafe { std::slice::from_raw_parts(slice.as_ptr().cast(), length) }; |
| |
| OsStr::from_bytes(bytes) |
| } |
| |
| #[cfg(test)] |
| mod test { |
| #[cfg(target_os = "linux")] |
| #[test] |
| pub fn test_uname_linux() { |
| assert_eq!(super::uname().unwrap().sysname(), "Linux"); |
| } |
| |
| #[cfg(any(target_os = "macos", target_os = "ios"))] |
| #[test] |
| pub fn test_uname_darwin() { |
| assert_eq!(super::uname().unwrap().sysname(), "Darwin"); |
| } |
| |
| #[cfg(target_os = "freebsd")] |
| #[test] |
| pub fn test_uname_freebsd() { |
| assert_eq!(super::uname().unwrap().sysname(), "FreeBSD"); |
| } |
| } |