diff options
| -rw-r--r-- | Cargo.lock | 110 | ||||
| -rw-r--r-- | init/src/main.rs | 26 | ||||
| -rw-r--r-- | init/src/mounts/fstab.rs | 164 | ||||
| -rw-r--r-- | init/src/rescue/initrd.rs | 0 | ||||
| -rw-r--r-- | vegilctl/Cargo.toml | 1 |
5 files changed, 256 insertions, 45 deletions
@@ -3,6 +3,89 @@ version = 4 [[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] name = "errno" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -21,14 +104,41 @@ dependencies = [ ] [[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] name = "libc" version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] name = "vegilctl" version = "0.1.0" +dependencies = [ + "clap", +] [[package]] name = "windows-link" 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 diff --git a/vegilctl/Cargo.toml b/vegilctl/Cargo.toml index 035764a..73077a8 100644 --- a/vegilctl/Cargo.toml +++ b/vegilctl/Cargo.toml @@ -5,3 +5,4 @@ edition = "2024" description = "Vegil init user control." [dependencies] +clap = "4.5.53" |
