]>
git.proxmox.com Git - proxmox-backup-restore-image.git/blob - src/init-shim-rs/src/main.rs
5 const URANDOM_MAJ
: u64 = 1;
6 const URANDOM_MIN
: u64 = 9;
8 /// Set up a somewhat normal linux userspace environment before starting the restore daemon, and
9 /// provide error messages to the user if doing so fails.
11 /// This is supposed to run as /init in an initramfs image.
13 println
!("[init-shim] beginning user space setup");
15 // /dev is mounted automatically
16 wrap_err("mount /sys", || do_mount("/sys", "sysfs"));
17 wrap_err("mount /proc", || do_mount("/proc", "proc"));
19 // make device nodes required by daemon
20 wrap_err("mknod /dev/urandom", || {
21 do_mknod("/dev/urandom", URANDOM_MAJ
, URANDOM_MIN
)
24 let uptime
= read_uptime();
25 println
!("[init-shim] reached daemon start after {:.2}s", uptime
);
27 do_run("/proxmox-restore-daemon");
30 fn do_mount(target
: &str, fstype
: &str) -> Result
<(), Error
> {
31 use nix
::mount
::{mount, MsFlags}
;
32 fs
::create_dir(target
)?
;
33 let none_type
: Option
<&CStr
> = None
;
38 MsFlags
::MS_NOSUID
| MsFlags
::MS_NOEXEC
,
44 fn do_mknod(path
: &str, maj
: u64, min
: u64) -> Result
<(), Error
> {
46 let dev
= stat
::makedev(maj
, min
);
47 stat
::mknod(path
, stat
::SFlag
::S_IFCHR
, stat
::Mode
::S_IRWXU
, dev
)?
;
51 fn read_uptime() -> f32 {
52 let uptime
= wrap_err("read /proc/uptime", || {
53 fs
::read_to_string("/proc/uptime").map_err(|e
| e
.into())
55 // this can never fail on a sane kernel, so just unwrap
57 .split_ascii_whitespace()
64 fn do_run(cmd
: &str) -> ! {
65 use std
::io
::ErrorKind
;
66 use std
::process
::Command
;
68 let spawn_res
= Command
::new(cmd
).env("RUST_BACKTRACE", "1").spawn();
72 let res
= wrap_err("wait failed", || child
.wait().map_err(|e
| e
.into()));
74 "child process {} (pid={} exitcode={}) exited unexpectedly, check log for more info",
77 res
.code().unwrap_or(-1),
80 Err(err
) if err
.kind() == ErrorKind
::NotFound
=> {
83 "{} missing from image.\n",
84 "This initramfs should only be run with proxmox-file-restore!"
91 "unexpected error during start of {}: {}",
98 fn wrap_err
<R
, F
: FnOnce() -> Result
<R
, Error
>>(op
: &str, f
: F
) -> R
{
101 Err(e
) => error(&format
!("operation '{}' failed: {}", op
, e
)),
105 fn error(msg
: &str) -> ! {
106 use nix
::sys
::reboot
;
108 println
!("\n--------");
109 println
!("ERROR: Init shim failed\n");
111 println
!("--------\n");
113 // in case a fatal error occurs we shut down the VM, there's no sense in continuing and this
114 // will certainly alert whoever started us up in the first place
115 let err
= reboot
::reboot(reboot
::RebootMode
::RB_POWER_OFF
).unwrap_err();
116 println
!("'reboot' syscall failed: {} - cannot continue", err
);
118 // in case 'reboot' fails just loop forever
120 std
::thread
::sleep(std
::time
::Duration
::from_secs(600));