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), Box> { 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> { 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(()) }