1 //! Uname and other system-level functions.
2 //!
3 //! # Safety
4 //!
5 //! This function converts from `struct utsname` fields provided from the
6 //! kernel into `&str` references, which assumes that they're NUL-terminated.
7 #![allow(unsafe_code)]
8
9 use crate::backend;
10 #[cfg(target_os = "linux")]
11 use crate::backend::c;
12 use crate::ffi::CStr;
13 #[cfg(not(any(target_os = "espidf", target_os = "emscripten", target_os = "vita")))]
14 use crate::io;
15 use core::fmt;
16
17 #[cfg(linux_kernel)]
18 pub use backend::system::types::Sysinfo;
19
20 /// `uname()`—Returns high-level information about the runtime OS and
21 /// hardware.
22 ///
23 /// For `gethostname()`, use [`Uname::nodename`] on the result.
24 ///
25 /// # References
26 /// - [POSIX]
27 /// - [Linux]
28 /// - [Apple]
29 /// - [NetBSD]
30 /// - [FreeBSD]
31 /// - [OpenBSD]
32 /// - [DragonFly BSD]
33 /// - [illumos]
34 /// - [glibc]
35 ///
36 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/uname.html
37 /// [Linux]: https://man7.org/linux/man-pages/man2/uname.2.html
38 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/uname.3.html
39 /// [NetBSD]: https://man.netbsd.org/uname.3
40 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=uname&sektion=3
41 /// [OpenBSD]: https://man.openbsd.org/uname.3
42 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=uname§ion=3
43 /// [illumos]: https://illumos.org/man/2/uname
44 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Platform-Type.html
45 #[doc(alias = "gethostname")]
46 #[inline]
uname() -> Uname47 pub fn uname() -> Uname {
48 Uname(backend::system::syscalls::uname())
49 }
50
51 /// `struct utsname`—Return type for [`uname`].
52 #[doc(alias = "utsname")]
53 pub struct Uname(backend::system::types::RawUname);
54
55 impl Uname {
56 /// `sysname`—Operating system release name
57 #[inline]
sysname(&self) -> &CStr58 pub fn sysname(&self) -> &CStr {
59 Self::to_cstr(self.0.sysname.as_ptr().cast())
60 }
61
62 /// `nodename`—Name with vague meaning
63 ///
64 /// This is intended to be a network name, however it's unable to convey
65 /// information about hosts that have multiple names, or any information
66 /// about where the names are visible.
67 ///
68 /// This corresponds to the `gethostname` value.
69 #[inline]
nodename(&self) -> &CStr70 pub fn nodename(&self) -> &CStr {
71 Self::to_cstr(self.0.nodename.as_ptr().cast())
72 }
73
74 /// `release`—Operating system release version string
75 #[inline]
release(&self) -> &CStr76 pub fn release(&self) -> &CStr {
77 Self::to_cstr(self.0.release.as_ptr().cast())
78 }
79
80 /// `version`—Operating system build identifiers
81 #[inline]
version(&self) -> &CStr82 pub fn version(&self) -> &CStr {
83 Self::to_cstr(self.0.version.as_ptr().cast())
84 }
85
86 /// `machine`—Hardware architecture identifier
87 #[inline]
machine(&self) -> &CStr88 pub fn machine(&self) -> &CStr {
89 Self::to_cstr(self.0.machine.as_ptr().cast())
90 }
91
92 /// `domainname`—NIS or YP domain identifier
93 #[cfg(linux_kernel)]
94 #[inline]
domainname(&self) -> &CStr95 pub fn domainname(&self) -> &CStr {
96 Self::to_cstr(self.0.domainname.as_ptr().cast())
97 }
98
99 #[inline]
to_cstr<'a>(ptr: *const u8) -> &'a CStr100 fn to_cstr<'a>(ptr: *const u8) -> &'a CStr {
101 // SAFETY: Strings returned from the kernel are always NUL-terminated.
102 unsafe { CStr::from_ptr(ptr.cast()) }
103 }
104 }
105
106 impl fmt::Debug for Uname {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result107 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
108 #[cfg(not(linux_kernel))]
109 {
110 write!(
111 fmt,
112 "{:?} {:?} {:?} {:?} {:?}",
113 self.sysname(),
114 self.nodename(),
115 self.release(),
116 self.version(),
117 self.machine(),
118 )
119 }
120 #[cfg(linux_kernel)]
121 {
122 write!(
123 fmt,
124 "{:?} {:?} {:?} {:?} {:?} {:?}",
125 self.sysname(),
126 self.nodename(),
127 self.release(),
128 self.version(),
129 self.machine(),
130 self.domainname(),
131 )
132 }
133 }
134 }
135
136 /// `sysinfo()`—Returns status information about the runtime OS.
137 ///
138 /// # References
139 /// - [Linux]
140 ///
141 /// [Linux]: https://man7.org/linux/man-pages/man2/uname.2.html
142 #[cfg(linux_kernel)]
143 #[inline]
sysinfo() -> Sysinfo144 pub fn sysinfo() -> Sysinfo {
145 backend::system::syscalls::sysinfo()
146 }
147
148 /// `sethostname(name)`—Sets the system host name.
149 ///
150 /// # References
151 /// - [Linux]
152 ///
153 /// [Linux]: https://man7.org/linux/man-pages/man2/sethostname.2.html
154 #[cfg(not(any(
155 target_os = "emscripten",
156 target_os = "espidf",
157 target_os = "redox",
158 target_os = "vita",
159 target_os = "wasi"
160 )))]
161 #[inline]
sethostname(name: &[u8]) -> io::Result<()>162 pub fn sethostname(name: &[u8]) -> io::Result<()> {
163 backend::system::syscalls::sethostname(name)
164 }
165
166 /// Reboot command for use with [`reboot`].
167 #[cfg(target_os = "linux")]
168 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
169 #[repr(i32)]
170 #[non_exhaustive]
171 pub enum RebootCommand {
172 /// Disables the Ctrl-Alt-Del keystroke.
173 ///
174 /// When disabled, the keystroke will send a [`Signal::Int`] to pid 1.
175 ///
176 /// [`Signal::Int`]: crate::process::Signal::Int
177 CadOff = c::LINUX_REBOOT_CMD_CAD_OFF,
178 /// Enables the Ctrl-Alt-Del keystroke.
179 ///
180 /// When enabled, the keystroke will trigger a [`Restart`].
181 ///
182 /// [`Restart`]: Self::Restart
183 CadOn = c::LINUX_REBOOT_CMD_CAD_ON,
184 /// Prints the message "System halted" and halts the system
185 Halt = c::LINUX_REBOOT_CMD_HALT,
186 /// Execute a kernel that has been loaded earlier with [`kexec_load`].
187 ///
188 /// [`kexec_load`]: https://man7.org/linux/man-pages/man2/kexec_load.2.html
189 Kexec = c::LINUX_REBOOT_CMD_KEXEC,
190 /// Prints the message "Power down.", stops the system, and tries to remove
191 /// all power
192 PowerOff = c::LINUX_REBOOT_CMD_POWER_OFF,
193 /// Prints the message "Restarting system." and triggers a restart
194 Restart = c::LINUX_REBOOT_CMD_RESTART,
195 /// Hibernate the system by suspending to disk
196 SwSuspend = c::LINUX_REBOOT_CMD_SW_SUSPEND,
197 }
198
199 /// `reboot`—Reboot the system or enable/disable Ctrl-Alt-Del
200 ///
201 /// The reboot syscall, despite the name, can actually do much more than
202 /// reboot.
203 ///
204 /// Among other things, it can:
205 /// - Restart, Halt, Power Off, and Suspend the system
206 /// - Enable and disable the Ctrl-Alt-Del keystroke
207 /// - Execute other kernels
208 /// - Terminate init inside PID namespaces
209 ///
210 /// It is highly recommended to carefully read the kernel documentation before
211 /// calling this function.
212 ///
213 /// # References
214 /// - [Linux]
215 ///
216 /// [Linux]: https://man7.org/linux/man-pages/man2/reboot.2.html
217 #[cfg(target_os = "linux")]
reboot(cmd: RebootCommand) -> io::Result<()>218 pub fn reboot(cmd: RebootCommand) -> io::Result<()> {
219 backend::system::syscalls::reboot(cmd)
220 }
221