Skip to content

Commit d518abd

Browse files
authored
feat: reboot(2) for OpenBSD/NetBSD (#2251)
1 parent a09971f commit d518abd

File tree

3 files changed

+136
-42
lines changed

3 files changed

+136
-42
lines changed

changelog/2251.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `reboot(2)` for OpenBSD/NetBSD

src/sys/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ feature! {
7979
pub mod quota;
8080
}
8181

82-
#[cfg(target_os = "linux")]
82+
#[cfg(any(target_os = "linux", netbsdlike))]
8383
feature! {
8484
#![feature = "reboot"]
8585
pub mod reboot;

src/sys/reboot.rs

Lines changed: 134 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,141 @@
1-
//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
1+
//! Reboot/shutdown
2+
//!
3+
//! On Linux, This can also be used to enable/disable Ctrl-Alt-Delete.
24
35
use crate::errno::Errno;
46
use crate::Result;
7+
use cfg_if::cfg_if;
58
use std::convert::Infallible;
6-
use std::mem::drop;
7-
8-
libc_enum! {
9-
/// How exactly should the system be rebooted.
10-
///
11-
/// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
12-
/// enabling/disabling Ctrl-Alt-Delete.
13-
#[repr(i32)]
14-
#[non_exhaustive]
15-
pub enum RebootMode {
16-
/// Halt the system.
17-
RB_HALT_SYSTEM,
18-
/// Execute a kernel that has been loaded earlier with
19-
/// [`kexec_load(2)`](https://man7.org/linux/man-pages/man2/kexec_load.2.html).
20-
RB_KEXEC,
21-
/// Stop the system and switch off power, if possible.
22-
RB_POWER_OFF,
23-
/// Restart the system.
24-
RB_AUTOBOOT,
25-
// we do not support Restart2.
26-
/// Suspend the system using software suspend.
27-
RB_SW_SUSPEND,
28-
}
29-
}
309

31-
/// Reboots or shuts down the system.
32-
pub fn reboot(how: RebootMode) -> Result<Infallible> {
33-
unsafe { libc::reboot(how as libc::c_int) };
34-
Err(Errno::last())
35-
}
10+
cfg_if! {
11+
if #[cfg(target_os = "linux")] {
12+
use std::mem::drop;
13+
14+
libc_enum! {
15+
/// How exactly should the system be rebooted.
16+
///
17+
/// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
18+
/// enabling/disabling Ctrl-Alt-Delete.
19+
#[repr(i32)]
20+
#[non_exhaustive]
21+
pub enum RebootMode {
22+
/// Halt the system.
23+
RB_HALT_SYSTEM,
24+
/// Execute a kernel that has been loaded earlier with
25+
/// [`kexec_load(2)`](https://man7.org/linux/man-pages/man2/kexec_load.2.html).
26+
RB_KEXEC,
27+
/// Stop the system and switch off power, if possible.
28+
RB_POWER_OFF,
29+
/// Restart the system.
30+
RB_AUTOBOOT,
31+
// we do not support Restart2.
32+
/// Suspend the system using software suspend.
33+
RB_SW_SUSPEND,
34+
}
35+
}
36+
37+
/// Reboots or shuts down the system.
38+
pub fn reboot(how: RebootMode) -> Result<Infallible> {
39+
unsafe { libc::reboot(how as libc::c_int) };
40+
Err(Errno::last())
41+
}
3642

37-
/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
38-
///
39-
/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
40-
pub fn set_cad_enabled(enable: bool) -> Result<()> {
41-
let cmd = if enable {
42-
libc::RB_ENABLE_CAD
43-
} else {
44-
libc::RB_DISABLE_CAD
45-
};
46-
let res = unsafe { libc::reboot(cmd) };
47-
Errno::result(res).map(drop)
43+
/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
44+
///
45+
/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
46+
pub fn set_cad_enabled(enable: bool) -> Result<()> {
47+
let cmd = if enable {
48+
libc::RB_ENABLE_CAD
49+
} else {
50+
libc::RB_DISABLE_CAD
51+
};
52+
let res = unsafe { libc::reboot(cmd) };
53+
Errno::result(res).map(drop)
54+
}
55+
} else if #[cfg(netbsdlike)] {
56+
use libc::c_int;
57+
58+
libc_bitflags! {
59+
/// How exactly should the system be rebooted.
60+
pub struct RebootMode: c_int {
61+
/// The default, causing the system to reboot in its usual fashion.
62+
RB_AUTOBOOT;
63+
/// Interpreted by the bootstrap program itself, causing it to
64+
/// prompt on the console as to what file should be booted.
65+
/// Normally, the system is booted from the file “xx(0,0)bsd”,
66+
/// where xx is the default disk name, without prompting for
67+
/// the file name.
68+
RB_ASKNAME;
69+
/// Dump kernel memory before rebooting; see `savecore(8)` for
70+
/// more information.
71+
RB_DUMP;
72+
/// The processor is simply halted; no reboot takes place.
73+
RB_HALT;
74+
/// Power off the system if the system hardware supports the
75+
/// function, otherwise it has no effect.
76+
///
77+
/// Should be used in conjunction with `RB_HALT`.
78+
RB_POWERDOWN;
79+
/// By default, the system will halt if `reboot()` is called during
80+
/// startup (before the system has finished autoconfiguration), even
81+
/// if `RB_HALT` is not specified. This is because `panic(9)`s
82+
/// during startup will probably just repeat on the next boot.
83+
/// Use of this option implies that the user has requested the
84+
/// action specified (for example, using the `ddb(4)` boot reboot
85+
/// command), so the system will reboot if a halt is not explicitly
86+
/// requested.
87+
#[cfg(target_os = "openbsd")]
88+
RB_USERREQ;
89+
/// Load the symbol table and enable a built-in debugger in the
90+
/// system. This option will have no useful function if the kernel
91+
/// is not configured for debugging. Several other options have
92+
/// different meaning if combined with this option, although their
93+
/// use may not be possible via the `reboot()` call. See `ddb(4)` for
94+
/// more information.
95+
RB_KDB;
96+
/// Normally, the disks are sync'd (see `sync(8)`) before the
97+
/// processor is halted or rebooted. This option may be useful
98+
/// if file system changes have been made manually or if the
99+
/// processor is on fire.
100+
RB_NOSYNC;
101+
/// Normally, the reboot procedure involves an automatic disk
102+
/// consistency check and then multi-user operations. `RB_SINGLE`
103+
/// prevents this, booting the system with a single-user shell on
104+
/// the console. `RB_SINGLE` is actually interpreted by the `init(8)`
105+
/// program in the newly booted system.
106+
///
107+
/// When no options are given (i.e., `RB_AUTOBOOT` is used), the
108+
/// system is rebooted from file /bsd in the root file system of
109+
/// unit 0 of a disk chosen in a processor specific way. An automatic
110+
/// consistency check of the disks is normally performed (see `fsck(8)`).
111+
RB_SINGLE;
112+
/// Initially invoke the `userconf(4)` facility when the system
113+
/// starts up again, if it has been compiled into the kernel
114+
/// that is loaded.
115+
#[cfg(target_os = "netbsd")]
116+
RB_USERCONF;
117+
/// Don't update the hardware clock from the system clock, presumably
118+
/// because the system clock is suspect.
119+
#[cfg(target_os = "openbsd")]
120+
RB_TIMEBAD;
121+
}
122+
}
123+
124+
/// Reboot system or halt processor
125+
///
126+
/// For more information, see the man pages:
127+
///
128+
/// * [NetBSD](https://man.netbsd.org/reboot.2)
129+
/// * [OpenBSD](https://man.openbsd.org/reboot.2)
130+
#[cfg(netbsdlike)]
131+
pub fn reboot(how: RebootMode) -> Result<Infallible> {
132+
#[cfg(target_os = "openbsd")]
133+
unsafe { libc::reboot(how.bits()) };
134+
#[cfg(target_os = "netbsd")]
135+
unsafe { libc::reboot(how.bits(), std::ptr::null_mut()) };
136+
137+
Err(Errno::last())
138+
}
139+
}
48140
}
141+

0 commit comments

Comments
 (0)