1b8a62b91Sopenharmony_ci//! Uname support.
2b8a62b91Sopenharmony_ci//!
3b8a62b91Sopenharmony_ci//! # Safety
4b8a62b91Sopenharmony_ci//!
5b8a62b91Sopenharmony_ci//! This function converts from `struct utsname` fields provided from the
6b8a62b91Sopenharmony_ci//! kernel into `&str` references, which assumes that they're NUL-terminated.
7b8a62b91Sopenharmony_ci#![allow(unsafe_code)]
8b8a62b91Sopenharmony_ci
9b8a62b91Sopenharmony_ciuse crate::backend;
10b8a62b91Sopenharmony_ciuse crate::ffi::CStr;
11b8a62b91Sopenharmony_ciuse core::fmt;
12b8a62b91Sopenharmony_ci
13b8a62b91Sopenharmony_ci/// `uname()`—Returns high-level information about the runtime OS and
14b8a62b91Sopenharmony_ci/// hardware.
15b8a62b91Sopenharmony_ci#[inline]
16b8a62b91Sopenharmony_cipub fn uname() -> Uname {
17b8a62b91Sopenharmony_ci    Uname(backend::process::syscalls::uname())
18b8a62b91Sopenharmony_ci}
19b8a62b91Sopenharmony_ci
20b8a62b91Sopenharmony_ci/// `struct utsname`—Return type for [`uname`].
21b8a62b91Sopenharmony_ci#[doc(alias = "utsname")]
22b8a62b91Sopenharmony_cipub struct Uname(backend::process::types::RawUname);
23b8a62b91Sopenharmony_ci
24b8a62b91Sopenharmony_ciimpl Uname {
25b8a62b91Sopenharmony_ci    /// `sysname`—Operating system release name
26b8a62b91Sopenharmony_ci    #[inline]
27b8a62b91Sopenharmony_ci    pub fn sysname(&self) -> &CStr {
28b8a62b91Sopenharmony_ci        Self::to_cstr(self.0.sysname.as_ptr().cast())
29b8a62b91Sopenharmony_ci    }
30b8a62b91Sopenharmony_ci
31b8a62b91Sopenharmony_ci    /// `nodename`—Name with vague meaning
32b8a62b91Sopenharmony_ci    ///
33b8a62b91Sopenharmony_ci    /// This is intended to be a network name, however it's unable to convey
34b8a62b91Sopenharmony_ci    /// information about hosts that have multiple names, or any information
35b8a62b91Sopenharmony_ci    /// about where the names are visible.
36b8a62b91Sopenharmony_ci    #[inline]
37b8a62b91Sopenharmony_ci    pub fn nodename(&self) -> &CStr {
38b8a62b91Sopenharmony_ci        Self::to_cstr(self.0.nodename.as_ptr().cast())
39b8a62b91Sopenharmony_ci    }
40b8a62b91Sopenharmony_ci
41b8a62b91Sopenharmony_ci    /// `release`—Operating system release version string
42b8a62b91Sopenharmony_ci    #[inline]
43b8a62b91Sopenharmony_ci    pub fn release(&self) -> &CStr {
44b8a62b91Sopenharmony_ci        Self::to_cstr(self.0.release.as_ptr().cast())
45b8a62b91Sopenharmony_ci    }
46b8a62b91Sopenharmony_ci
47b8a62b91Sopenharmony_ci    /// `version`—Operating system build identifiers
48b8a62b91Sopenharmony_ci    #[inline]
49b8a62b91Sopenharmony_ci    pub fn version(&self) -> &CStr {
50b8a62b91Sopenharmony_ci        Self::to_cstr(self.0.version.as_ptr().cast())
51b8a62b91Sopenharmony_ci    }
52b8a62b91Sopenharmony_ci
53b8a62b91Sopenharmony_ci    /// `machine`—Hardware architecture identifier
54b8a62b91Sopenharmony_ci    #[inline]
55b8a62b91Sopenharmony_ci    pub fn machine(&self) -> &CStr {
56b8a62b91Sopenharmony_ci        Self::to_cstr(self.0.machine.as_ptr().cast())
57b8a62b91Sopenharmony_ci    }
58b8a62b91Sopenharmony_ci
59b8a62b91Sopenharmony_ci    /// `domainname`—NIS or YP domain identifier
60b8a62b91Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
61b8a62b91Sopenharmony_ci    #[inline]
62b8a62b91Sopenharmony_ci    pub fn domainname(&self) -> &CStr {
63b8a62b91Sopenharmony_ci        Self::to_cstr(self.0.domainname.as_ptr().cast())
64b8a62b91Sopenharmony_ci    }
65b8a62b91Sopenharmony_ci
66b8a62b91Sopenharmony_ci    #[inline]
67b8a62b91Sopenharmony_ci    fn to_cstr<'a>(ptr: *const u8) -> &'a CStr {
68b8a62b91Sopenharmony_ci        // Safety: Strings returned from the kernel are always NUL-terminated.
69b8a62b91Sopenharmony_ci        unsafe { CStr::from_ptr(ptr.cast()) }
70b8a62b91Sopenharmony_ci    }
71b8a62b91Sopenharmony_ci}
72b8a62b91Sopenharmony_ci
73b8a62b91Sopenharmony_ciimpl fmt::Debug for Uname {
74b8a62b91Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
75b8a62b91Sopenharmony_ci        #[cfg(not(any(target_os = "android", target_os = "linux")))]
76b8a62b91Sopenharmony_ci        {
77b8a62b91Sopenharmony_ci            write!(
78b8a62b91Sopenharmony_ci                fmt,
79b8a62b91Sopenharmony_ci                "{} {} {} {} {}",
80b8a62b91Sopenharmony_ci                self.sysname().to_string_lossy(),
81b8a62b91Sopenharmony_ci                self.nodename().to_string_lossy(),
82b8a62b91Sopenharmony_ci                self.release().to_string_lossy(),
83b8a62b91Sopenharmony_ci                self.version().to_string_lossy(),
84b8a62b91Sopenharmony_ci                self.machine().to_string_lossy(),
85b8a62b91Sopenharmony_ci            )
86b8a62b91Sopenharmony_ci        }
87b8a62b91Sopenharmony_ci        #[cfg(any(target_os = "android", target_os = "linux"))]
88b8a62b91Sopenharmony_ci        {
89b8a62b91Sopenharmony_ci            write!(
90b8a62b91Sopenharmony_ci                fmt,
91b8a62b91Sopenharmony_ci                "{} {} {} {} {} {}",
92b8a62b91Sopenharmony_ci                self.sysname().to_string_lossy(),
93b8a62b91Sopenharmony_ci                self.nodename().to_string_lossy(),
94b8a62b91Sopenharmony_ci                self.release().to_string_lossy(),
95b8a62b91Sopenharmony_ci                self.version().to_string_lossy(),
96b8a62b91Sopenharmony_ci                self.machine().to_string_lossy(),
97b8a62b91Sopenharmony_ci                self.domainname().to_string_lossy(),
98b8a62b91Sopenharmony_ci            )
99b8a62b91Sopenharmony_ci        }
100b8a62b91Sopenharmony_ci    }
101b8a62b91Sopenharmony_ci}
102