diff options
| author | namilsk <namilsk@namilsk.tech> | 2026-01-08 18:41:34 +0300 |
|---|---|---|
| committer | namilsk <namilsk@namilsk.tech> | 2026-01-08 18:41:34 +0300 |
| commit | 3a5c327a546ff1838e4dc32b8b67a056c1b95f3d (patch) | |
| tree | 2aac7d8b53dda2104a926b1fa53129db78dd410d | |
| parent | 2cad2077b647770aac103360cbd28b29c513db6c (diff) | |
Implementing main functions of init, check TODO.md
| -rw-r--r-- | init/src/host/mod.rs | 1 | ||||
| -rw-r--r-- | init/src/host/sethn.rs | 37 | ||||
| -rw-r--r-- | init/src/log.rs | 12 | ||||
| -rw-r--r-- | init/src/main.rs | 56 | ||||
| -rw-r--r-- | init/src/mounts/fstab.rs | 48 | ||||
| -rw-r--r-- | init/src/mounts/rescue.rs | 3 |
6 files changed, 128 insertions, 29 deletions
diff --git a/init/src/host/mod.rs b/init/src/host/mod.rs new file mode 100644 index 0000000..4a3de53 --- /dev/null +++ b/init/src/host/mod.rs @@ -0,0 +1 @@ +pub mod sethn;
\ No newline at end of file diff --git a/init/src/host/sethn.rs b/init/src/host/sethn.rs new file mode 100644 index 0000000..1857297 --- /dev/null +++ b/init/src/host/sethn.rs @@ -0,0 +1,37 @@ +use std::{ffi::CString, fs, io}; +use libc::{sethostname, c_char, size_t}; +use crate::log::{log_warning}; + +pub fn try_set_hostname() { + let content = fs::read_to_string("/etc/hostname") + .map(|s| s.trim().to_string()) + .unwrap_or_else(|_| "localhost".to_string()); + + if let Err(e) = perform_set_hostname(&content) { + log_warning(&format!("Failed to set hostname to '{}': {}. Falling back to localhost.", content, e)); + let _ = perform_set_hostname("localhost"); + } +} + +fn perform_set_hostname(name: &str) -> io::Result<()> { + if name.len() > 64 { + return Err(io::Error::new(io::ErrorKind::InvalidInput, "Hostname too long")); + } + + let c_str = CString::new(name).map_err(|_| { + io::Error::new(io::ErrorKind::InvalidInput, "Hostname contains null byte") + })?; + + let res = unsafe { + sethostname( + c_str.as_ptr() as *const c_char, + name.len() as size_t, + ) + }; + + if res != 0 { + return Err(io::Error::last_os_error()); + } + + Ok(()) +}
\ No newline at end of file diff --git a/init/src/log.rs b/init/src/log.rs new file mode 100644 index 0000000..23f644f --- /dev/null +++ b/init/src/log.rs @@ -0,0 +1,12 @@ +pub fn log_critical_error(message: &str) { + println!("\x1b[31m * \x1b[0m {}", message); +} + +pub fn log_warning(message: &str) { + println!("\x1b[33m * \x1b[0m {}", message); +} + +pub fn log_success(message: &str) { + println!("\x1b[32m * \x1b[0m {}", message); +} + diff --git a/init/src/main.rs b/init/src/main.rs index e944424..feea052 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -1,36 +1,78 @@ +mod log; mod mounts; mod pid_one; +mod host; +use crate::log::{log_critical_error, log_warning, log_success}; use crate::mounts::fstab::FstabEntry; use crate::mounts::rescue; use crate::pid_one::check_pid; +use crate::host::sethn::try_set_hostname; + +use std::process::Command; // RULE: I will not use .expect() and .unwrap() in this project. This causes panic, // which will affect stability. +fn spawn_udev() -> Result<(), Box<dyn std::error::Error>> { + log_success("Spawning udev daemon."); + + let udevd_paths = [ + "/sbin/udevd", + "/usr/sbin/udevd", + "/bin/udevd", + "/usr/bin/udevd", + ]; + let udevd_path = udevd_paths + .iter() + .find(|path| std::path::Path::new(path).exists()) + .ok_or("udevd not found in standard locations")?; + + let child = Command::new(udevd_path) + .arg("--daemon") + .spawn() + .map_err(|e| format!("Failed to spawn udevd: {}", e))?; + + log_success(&format!("udevd started with PID: {}", child.id())); + Command::new(udevd_path) + .arg("--trigger") + .output() + .map_err(|e| format!("Failed to trigger udev: {}", e))?; + + Ok(()) +} + 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"); - + if let Err(e) = check_pid() { + log_critical_error(&format!("Runned not as first process. init/src/pid_one.rs:8:8 - {}", e)); + return Err(e); + } + match FstabEntry::parse_fstab("/etc/fstab") { Ok(entries) => { - println!("\x1b[32m * \x1b[0m Sucessfully parsed /etc/fstab."); + log_success("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); + log_warning("Looks like fstab broken. Mounting all without reading /etc/fstab."); + log_warning(&format!("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. } } + let _ = try_set_hostname(); + match spawn_udev() { + Ok(_) => log_success("Successfully started udev daemon."), + Err(e) => log_critical_error(&format!("Failed to start udev daemon: {}", e)), + } Ok(()) } diff --git a/init/src/mounts/fstab.rs b/init/src/mounts/fstab.rs index 3ea62e5..c0cfd58 100644 --- a/init/src/mounts/fstab.rs +++ b/init/src/mounts/fstab.rs @@ -1,6 +1,7 @@ -use libc::{self}; +use crate::log::{log_critical_error, log_warning, log_success}; use std::ffi::CString; -use std::{fs, fmt}; +use std::{fmt, fs}; +use libc::syscall; #[derive(Debug)] pub struct FstabEntry { @@ -16,7 +17,7 @@ impl fmt::Display for FstabEntry { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "{} {} {} {} {} {}", + "Source: {}\n Mountpoint: {}\n FSType: {}\n Options: {}\n Dump: {}\n Pass: {}\n", self.source, self.mountpoint, self.fstype, self.options, self.dump, self.pass ) } @@ -41,13 +42,13 @@ impl FstabEntry { 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 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) - })?; + let pass = parts[5] + .parse::<u32>() + .map_err(|e| format!("Failed to parse pass field '{}': {}", parts[5], e))?; Ok(FstabEntry { source, @@ -67,7 +68,7 @@ impl FstabEntry { match Self::parse_line(line) { Ok(entry) => entries.push(entry), Err(_) => { - println!("\x1b[32m * \x1b[0m Warning: Skipping invalid fstab line: {}", line); + log_warning(&format!("Skipping invalid fstab line: {}", line)); continue; } } @@ -113,11 +114,17 @@ impl FstabEntry { Ok((flags, data)) } + pub fn mount(&self) -> Result<(), Box<dyn std::error::Error>> { - println!("\x1b[32m * \x1b[0m Started mounting {} from {}", self.mountpoint, self.source); - + log_success(&format!("Started mounting {} from {}", self.mountpoint, self.source)); + if self.fstype == "swap" { - println!("\x1b[30m * \x1b[0m Skipping swap: {}", self.source); + log_success(&format!("Filesystem type contains swap, upping it: {}", self.source)); + + unsafe { + syscall(libc::SYS_swapon, &self.source, 0); + } + return Ok(()); } @@ -134,14 +141,14 @@ impl FstabEntry { 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_c = data.map(|s| CString::new(s)).transpose()?; 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( + syscall( libc::SYS_mount, source_c.as_ptr(), target_c.as_ptr(), @@ -152,15 +159,14 @@ impl FstabEntry { }; if ret != 0 { - eprintln!( - "\x1b[31m * \x1b[0m Failed to mount {}: {}", + log_critical_error(&format!( + "Failed to mount {}: {}", self.mountpoint, std::io::Error::last_os_error() - ); + )); } else { - println!("\x1b[32m * \x1b[0m Mounted {}", self.mountpoint); + log_success(&format!("Mounted {}", self.mountpoint)); } Ok(()) } - -}
\ No newline at end of file +} diff --git a/init/src/mounts/rescue.rs b/init/src/mounts/rescue.rs index 84517ed..ad80a84 100644 --- a/init/src/mounts/rescue.rs +++ b/init/src/mounts/rescue.rs @@ -1,3 +1,4 @@ +use crate::log::log_success; use std::ffi::CString; use std::fs::create_dir; @@ -38,7 +39,7 @@ pub fn mount_system() -> Result<(), Box<dyn std::error::Error>> { ) .into()); } - println!("\x1b[32m * \x1b[0m Mounting {}...", target); + log_success(&format!("Mounting {}...", target)); } } |
