use super::{run, run_output, Image, LoopDevice, Mount}; use crate::IMAGE_SIZE_GB; use anyhow::{anyhow, Context as _}; use std::{ fs::{self, File}, path::PathBuf }; pub fn prepare_img() -> anyhow::Result { eprintln!("Preparing empty image ..."); // let's create a file with the correct size let path = PathBuf::from("alpi.img"); let file = File::create(&path).context("Failed to create alpi.img")?; file.set_len(IMAGE_SIZE_GB * 1024 * 1024 * 1024)?; drop(file); // lets get the thing partitioned let size = format!("{IMAGE_SIZE_GB}G"); run_parted!(path, "mktable", "msdos")?; run_parted!(path, "mkpart", "primary", "fat32", "0G", "128M")?; run_parted!(path, "mkpart", "primary", "ext4", "128M", &size)?; // create a loopback device let output = run_output(&["losetup", "-f", "--show", path.to_str().unwrap()])?; print!("{output}"); let idx = output.find("/dev/loop").ok_or_else(|| anyhow!("Unable to identify loop device"))?; let mut end = idx + "/dev/loop".len(); while (output.as_bytes()[end] as char).is_ascii_digit() { end += 1; } let device = LoopDevice(output[idx .. end].to_owned()); // TODO: Somehow create the file systems without root run(&["mkfs.fat", "-n", "ALPI-BOOT", "-F", "32", &device.part(1)])?; run(&["mkfs.ext4", "-q", "-F", "-L", "ALPI", "-O", "^has_journal", &device.part(2)])?; run_parted!(path, "p")?; // mount everything let root = Mount::create(&device.part(2))?; let boot = root.0.join("boot"); fs::create_dir_all(&boot)?; run(&["mount", &device.part(1), boot.to_str().unwrap()])?; let boot = Mount(boot); let dev = root.0.join("dev"); fs::create_dir_all(&dev)?; run(&["mount", "udev", dev.to_str().unwrap(), "-t", "devtmpfs", "-o", "mode=0755,nosuid"])?; let dev = Mount(dev); Ok(Image { path, device, boot, dev, root }) }