1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
use libc::{self};
use std::ffi::CString;
#[derive(Debug)]
pub struct FstabEntry {
pub source: String,
pub mountpoint: String,
pub fstype: String,
pub options: String,
pub dump: u32,
pub pass: u32,
}
fn parse_mount_options(
options: &str,
) -> Result<(libc::c_ulong, Option<String>), Box<dyn std::error::Error>> {
let mut flags = 0;
let mut data_parts = Vec::new();
for opt in options.split(',') {
match opt {
"defaults" => { /* handled by not setting any restrictive flags */ }
"ro" => flags |= libc::MS_RDONLY,
"rw" => flags &= !libc::MS_RDONLY,
"noexec" => flags |= libc::MS_NOEXEC,
"nosuid" => flags |= libc::MS_NOSUID,
"nodev" => flags |= libc::MS_NODEV,
"sync" => flags |= libc::MS_SYNCHRONOUS,
"dirsync" => flags |= libc::MS_DIRSYNC,
"bind" => flags |= libc::MS_BIND,
"rbind" => flags |= libc::MS_BIND | libc::MS_REC,
"remount" => flags |= libc::MS_REMOUNT,
_ => {
if !opt.is_empty() {
data_parts.push(opt);
}
}
}
}
let data = if data_parts.is_empty() {
None
} else {
Some(data_parts.join(","))
};
Ok((flags, data))
}
pub fn mount_from_fstab(entries: &[FstabEntry]) -> Result<(), Box<dyn std::error::Error>> {
for entry in entries {
if entry.fstype == "swap" {
println!("Skipping swap: {}", entry.source);
continue;
}
if entry.mountpoint == "none" {
continue;
}
if entry.options.contains("noauto") {
continue;
}
let (flags, data) = parse_mount_options(&entry.options)?;
let source_c = CString::new(&*entry.source)?;
let target_c = CString::new(&*entry.mountpoint)?;
let fstype_c = CString::new(&*entry.fstype)?;
let data_c = data.map(|s| CString::new(s).expect("\x1b[31m * \x1b[0m Something went wrong while mounting partitions. You are going to rescue mode..."));
let data_ptr = data_c
.as_ref()
.map_or(std::ptr::null(), |s| s.as_ptr() as *const libc::c_void);
let ret = unsafe {
libc::syscall(
libc::SYS_mount,
source_c.as_ptr(),
target_c.as_ptr(),
fstype_c.as_ptr(),
flags,
data_ptr,
)
};
if ret != 0 {
eprintln!("Failed to mount {}: {}", entry.mountpoint, std::io::Error::last_os_error());
} else {
println!("Mounted {}", entry.mountpoint);
}
}
Ok(())
}
|