summaryrefslogtreecommitdiff
path: root/init/src
diff options
context:
space:
mode:
Diffstat (limited to 'init/src')
-rw-r--r--init/src/main.rs26
-rw-r--r--init/src/mounts/fstab.rs164
-rw-r--r--init/src/rescue/initrd.rs0
3 files changed, 145 insertions, 45 deletions
diff --git a/init/src/main.rs b/init/src/main.rs
index 1138ccf..e944424 100644
--- a/init/src/main.rs
+++ b/init/src/main.rs
@@ -1,10 +1,36 @@
mod mounts;
mod pid_one;
+use crate::mounts::fstab::FstabEntry;
+use crate::mounts::rescue;
use crate::pid_one::check_pid;
+// RULE: I will not use .expect() and .unwrap() in this project. This causes panic,
+// which will affect stability.
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Initializing your system.");
check_pid().expect("\x1b[31m * \x1b[0m Runned not as first process. init/src/pid_one.rs:8:8");
+
+ match FstabEntry::parse_fstab("/etc/fstab") {
+ Ok(entries) => {
+ println!("\x1b[32m * \x1b[0m Sucessfully parsed /etc/fstab.");
+ for entry in &entries {
+ let _ = entry.mount();
+ }
+ },
+ Err(error) => {
+ println!("\x1b[33m * \x1b[0m Looks like fstab broken. Mounting all without reading /etc/fstab.");
+ println!("\x1b[33m * \x1b[0m Error:\n {}", error);
+ let _ = rescue::mount_system();
+
+ // Minimal mounts without fstab, because /etc/fstab needs fixes :)
+ // Btw it should be used if fstab broken or has syntax-errors
+ // TODO: If fstab contains syntax errors, mount everything else that does not contain them through it anyway.
+ }
+ }
+
+
+
Ok(())
}
diff --git a/init/src/mounts/fstab.rs b/init/src/mounts/fstab.rs
index 0765cfd..919607c 100644
--- a/init/src/mounts/fstab.rs
+++ b/init/src/mounts/fstab.rs
@@ -1,5 +1,6 @@
use libc::{self};
use std::ffi::CString;
+use std::{fs, fmt};
#[derive(Debug)]
pub struct FstabEntry {
@@ -11,62 +12,128 @@ pub struct FstabEntry {
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);
+impl fmt::Display for FstabEntry {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{} {} {} {} {} {}",
+ self.source, self.mountpoint, self.fstype, self.options, self.dump, self.pass
+ )
+ }
+}
+
+impl FstabEntry {
+ fn parse_line(line: &str) -> Result<Self, Box<dyn std::error::Error>> {
+ let line = line.trim();
+
+ if line.is_empty() || line.starts_with('#') {
+ return Err("Empty line or comment".into());
+ }
+
+ let parts: Vec<&str> = line.split_whitespace().collect();
+
+ if parts.len() != 6 {
+ return Err(format!("Invalid number of fields in fstab entry: {}", line).into());
+ }
+
+ let source = parts[0].to_string();
+ let mountpoint = parts[1].to_string();
+ let fstype = parts[2].to_string();
+ let options = parts[3].to_string();
+
+ let dump = parts[4].parse::<u32>().map_err(|e| {
+ format!("Failed to parse dump field '{}': {}", parts[4], e)
+ })?;
+
+ let pass = parts[5].parse::<u32>().map_err(|e| {
+ format!("Failed to parse pass field '{}': {}", parts[5], e)
+ })?;
+
+ Ok(FstabEntry {
+ source,
+ mountpoint,
+ fstype,
+ options,
+ dump,
+ pass,
+ })
+ }
+
+ pub fn parse_fstab(path: &str) -> Result<Vec<FstabEntry>, Box<dyn std::error::Error>> {
+ let content = fs::read_to_string(path)?;
+
+ let mut entries = Vec::new();
+ for line in content.lines() {
+ match Self::parse_line(line) {
+ Ok(entry) => entries.push(entry),
+ Err(_) => {
+ println!("\x1b[32m * \x1b[0m Warning: Skipping invalid fstab line: {}", line);
+ continue;
}
}
}
+
+ Ok(entries)
}
- let data = if data_parts.is_empty() {
- None
- } else {
- Some(data_parts.join(","))
- };
+ pub fn parse_mount_options(
+ &self,
+ ) -> Result<(libc::c_ulong, Option<String>), Box<dyn std::error::Error>> {
+ let mut flags = 0;
+ let mut data_parts = Vec::new();
+ let options = &self.options;
- Ok((flags, data))
-}
+ 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;
+ pub fn mount(&self) -> Result<(), Box<dyn std::error::Error>> {
+ println!("\x1b[32m * \x1b[0m Started mounting {} from {}", self.mountpoint, self.source);
+
+ if self.fstype == "swap" {
+ println!("\x1b[30m * \x1b[0m Skipping swap: {}", self.source);
+ return Ok(());
}
- if entry.mountpoint == "none" {
- continue;
+ if self.mountpoint == "none" {
+ return Ok(());
}
- if entry.options.contains("noauto") {
- continue;
+ if self.options.contains("noauto") {
+ return Ok(());
}
- let (flags, data) = parse_mount_options(&entry.options)?;
+ let (flags, data) = self.parse_mount_options()?;
- let source_c = CString::new(&*entry.source)?;
- let target_c = CString::new(&*entry.mountpoint)?;
- let fstype_c = CString::new(&*entry.fstype)?;
+ let source_c = CString::new(&*self.source)?;
+ let target_c = CString::new(&*self.mountpoint)?;
+ let fstype_c = CString::new(&*self.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
@@ -87,12 +154,19 @@ pub fn mount_from_fstab(entries: &[FstabEntry]) -> Result<(), Box<dyn std::error
if ret != 0 {
eprintln!(
"\x1b[31m * \x1b[0m Failed to mount {}: {}",
- entry.mountpoint,
+ self.mountpoint,
std::io::Error::last_os_error()
);
} else {
- println!("\x1b[32m * \x1b[0m Mounted {}", entry.mountpoint);
+ println!("\x1b[32m * \x1b[0m Mounted {}", self.mountpoint);
+ }
+ Ok(())
+ }
+
+ pub fn mount_from_fstab(entries: &[FstabEntry]) -> Result<(), Box<dyn std::error::Error>> {
+ for entry in entries {
+ entry.mount()?;
}
+ Ok(())
}
- Ok(())
} \ No newline at end of file
diff --git a/init/src/rescue/initrd.rs b/init/src/rescue/initrd.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/init/src/rescue/initrd.rs