#![forbid(unsafe_code)]
#![deny(missing_debug_implementations)]
pub mod bootloader;
pub mod cmdline;
pub mod os_release;
pub mod selabel;
pub mod uki;
pub mod write_boot;
use std::ffi::OsStr;
use anyhow::Result;
use rustix::fd::AsFd;
use composefs::{fsverity::FsVerityHashValue, repository::Repository, tree::FileSystem};
use crate::bootloader::{BootEntry, get_boot_resources};
const REQUIRED_TOPLEVEL_TO_EMPTY_DIRS: &[&str] = &["boot", "sysroot"];
fn empty_toplevel_dirs<ObjectID: FsVerityHashValue>(fs: &mut FileSystem<ObjectID>) -> Result<()> {
let usr_mtime = fs.root.get_directory(OsStr::new("usr"))?.stat.st_mtim_sec;
for d in REQUIRED_TOPLEVEL_TO_EMPTY_DIRS {
let d = fs.root.get_directory_mut(d.as_ref())?;
d.stat.st_mtim_sec = usr_mtime;
d.clear();
}
Ok(())
}
pub trait BootOps<ObjectID: FsVerityHashValue> {
fn transform_for_boot(
&mut self,
repo: &Repository<ObjectID>,
) -> Result<Vec<BootEntry<ObjectID>>>;
fn transform_for_boot_from_dir(&mut self, rootfs: impl AsFd) -> Result<()>;
}
impl<ObjectID: FsVerityHashValue> BootOps<ObjectID> for FileSystem<ObjectID> {
fn transform_for_boot(
&mut self,
repo: &Repository<ObjectID>,
) -> Result<Vec<BootEntry<ObjectID>>> {
let boot_entries = get_boot_resources(self, repo)?;
empty_toplevel_dirs(self)?;
self.compact();
selabel::selabel(self, repo)?;
Ok(boot_entries)
}
fn transform_for_boot_from_dir(&mut self, rootfs: impl AsFd) -> Result<()> {
empty_toplevel_dirs(self)?;
self.compact();
selabel::selabel_from_dir(self, rootfs)?;
Ok(())
}
}