diff --git a/Cargo.lock b/Cargo.lock index 83d30fa..761279b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,37 +95,6 @@ dependencies = [ "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "citadel-image" -version = "0.1.0" -dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libcitadel 0.1.0", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "citadel-install" -version = "0.1.0" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "libcitadel 0.1.0", - "rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "citadel-mount" -version = "0.1.0" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)", - "libcitadel 0.1.0", -] - [[package]] name = "citadel-realms" version = "0.1.0" @@ -142,6 +111,19 @@ dependencies = [ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "citadel-tool" +version = "0.1.0" +dependencies = [ + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libcitadel 0.1.0", + "rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "clap" version = "2.32.0" diff --git a/Cargo.toml b/Cargo.toml index 94f00e2..1857050 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,6 @@ [workspace] -members = ["citadel-desktopd", "citadel-image", "citadel-install", "citadel-mount", "citadel-realms"] +members = ["citadel-desktopd", "citadel-realms", "citadel-tool" ] +[profile.release] +lto = true +codegen-units = 1 +incremental = false diff --git a/citadel-install/Cargo.toml b/citadel-install/Cargo.toml deleted file mode 100644 index 48fb04f..0000000 --- a/citadel-install/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "citadel-install" -version = "0.1.0" -authors = ["Bruce Leidl "] -homepage = "http://github.com/subgraph/citadel" -edition = "2018" - -[dependencies] -libcitadel = { path = "../libcitadel" } -failure = "0.1.3" -libc = "0.2" -rpassword = "2.1.0" diff --git a/citadel-mount/Cargo.toml b/citadel-mount/Cargo.toml deleted file mode 100644 index d4eb9ed..0000000 --- a/citadel-mount/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "citadel-mount" -version = "0.1.0" -authors = ["Bruce Leidl "] -homepage = "http://github.com/subgraph/citadel" - -[dependencies] -libcitadel = { path = "../libcitadel" } -failure = "0.1.3" -libc = "0.2" diff --git a/citadel-mount/src/main.rs b/citadel-mount/src/main.rs deleted file mode 100644 index 1822d29..0000000 --- a/citadel-mount/src/main.rs +++ /dev/null @@ -1,94 +0,0 @@ -#[macro_use] extern crate failure; -#[macro_use] extern crate libcitadel; - -use std::process::exit; -use std::env; -use std::fs; - -use libcitadel::{Result,CommandLine,set_verbose,format_error,ResourceImage,util}; - - -mod rootfs; - -/// mount command supports 4 subcommands -/// -/// citadel-mount rootfs -/// citadel-mount kernel -/// citadel-mount extra -/// citadel-mount overlay -/// -/// 'rootfs' creates the /dev/mapper/rootfs device which will be mounted as root filesystem -/// -/// 'kernel' mounts a resource bundle containing kernel modules -/// 'extra' mounts a resource bundle containing extra files -/// 'overlay' mounts a tmpfs overlay over rootfs filesystem only if citadel.overlay is set -/// - -fn main() { - - if CommandLine::verbose() { - set_verbose(true); - } - - let mut args = env::args(); - args.next(); - let result = match args.next() { - Some(ref s) if s == "rootfs" => mount_rootfs(), - Some(ref s) if s == "kernel" => mount_kernel(), - Some(ref s) if s == "extra" => mount_extra(), - Some(ref s) if s == "overlay" => mount_overlay(), - _ => Err(format_err!("Bad or missing argument")), - }; - - if let Err(ref e) = result { - warn!("Failed: {}", format_error(e)); - exit(1); - } -} - -fn mount_rootfs() -> Result<()> { - info!("citadel-mount rootfs"); - rootfs::setup_rootfs() -} - -fn mount_kernel() -> Result<()> { - info!("citadel-mount kernel"); - let mut image = ResourceImage::find("kernel")?; - image.mount()?; - Ok(()) -} - -fn mount_extra() -> Result<()> { - info!("citadel-mount extra"); - let mut image = ResourceImage::find("extra")?; - image.mount()?; - Ok(()) -} - -fn mount_overlay() -> Result<()> { - if !CommandLine::overlay() { - info!("Not mounting rootfs overlay because citadel.overlay is not enabled"); - return Ok(()) - } - info!("Creating rootfs overlay"); - - info!("Moving /sysroot mount to /rootfs.ro"); - fs::create_dir_all("/rootfs.ro")?; - util::exec_cmdline("/usr/bin/mount", "--make-private /")?; - util::exec_cmdline("/usr/bin/mount", "--move /sysroot /rootfs.ro")?; - info!("Mounting tmpfs on /rootfs.rw"); - fs::create_dir_all("/rootfs.rw")?; - util::exec_cmdline("/usr/bin/mount", "-t tmpfs -orw,noatime,mode=755 rootfs.rw /rootfs.rw")?; - info!("Creating /rootfs.rw/work /rootfs.rw/upperdir"); - fs::create_dir_all("/rootfs.rw/upperdir")?; - fs::create_dir_all("/rootfs.rw/work")?; - info!("Mounting overlay on /sysroot"); - util::exec_cmdline("/usr/bin/mount", "-t overlay overlay -olowerdir=/rootfs.ro,upperdir=/rootfs.rw/upperdir,workdir=/rootfs.rw/work /sysroot")?; - - info!("Moving /rootfs.ro and /rootfs.rw to new root"); - fs::create_dir_all("/sysroot/rootfs.ro")?; - fs::create_dir_all("/sysroot/rootfs.rw")?; - util::exec_cmdline("/usr/bin/mount", "--move /rootfs.ro /sysroot/rootfs.ro")?; - util::exec_cmdline("/usr/bin/mount", "--move /rootfs.rw /sysroot/rootfs.rw")?; - Ok(()) -} diff --git a/citadel-image/Cargo.toml b/citadel-tool/Cargo.toml similarity index 71% rename from citadel-image/Cargo.toml rename to citadel-tool/Cargo.toml index 8f0391b..06b4262 100644 --- a/citadel-image/Cargo.toml +++ b/citadel-tool/Cargo.toml @@ -1,14 +1,14 @@ [package] -name = "citadel-image" +name = "citadel-tool" version = "0.1.0" authors = ["Bruce Leidl "] -homepage = "https://github.com/subgraph/citadel" edition = "2018" [dependencies] libcitadel = { path = "../libcitadel" } +failure = "0.1" +rpassword = "2.1.0" clap = "2.32.0" -failure = "0.1.3" serde_derive = "1.0.82" serde = "1.0.82" toml = "0.4.10" diff --git a/citadel-install/src/disks.rs b/citadel-tool/src/boot/disks.rs similarity index 98% rename from citadel-install/src/disks.rs rename to citadel-tool/src/boot/disks.rs index 8fe1008..7e2f86d 100644 --- a/citadel-install/src/disks.rs +++ b/citadel-tool/src/boot/disks.rs @@ -1,8 +1,8 @@ use std::path::{Path, PathBuf}; use std::fs; -use crate::Result; -use crate::util; +use libcitadel::Result; +use libcitadel::util; /// /// Represents a disk partition device on the system diff --git a/citadel-install/src/main.rs b/citadel-tool/src/boot/live.rs similarity index 53% rename from citadel-install/src/main.rs rename to citadel-tool/src/boot/live.rs index a1fa3a6..4372bc8 100644 --- a/citadel-install/src/main.rs +++ b/citadel-tool/src/boot/live.rs @@ -1,71 +1,43 @@ -#[macro_use] extern crate failure; -mod installer; -mod cli; -mod util; -mod disks; - -use std::result; -use std::path::Path; -use std::env; -use std::time; -use std::fs; -use std::ffi::OsStr; use std::thread::{self,JoinHandle}; -use std::process::exit; -use failure::Error; +use std::time; +use std::path::Path; +use std::ffi::OsStr; +use std::fs; + +use libcitadel::Result; +use libcitadel::util; use libcitadel::ResourceImage; +use crate::boot::disks; +use crate::boot::rootfs::setup_rootfs_resource; +use crate::install::installer::Installer; -pub type Result = result::Result; +const IMAGE_DIRECTORY: &str = "/run/citadel/images"; -fn main() { - - let mut args = env::args(); - args.next(); - let result = match args.next() { - Some(ref s) if s == "live-setup" => live_setup(), - Some(ref s) if s == "copy-artifacts" => copy_artifacts(), - Some(ref s) => cli_install_to(s), - None => cli_install(), - }; - - if let Err(ref e) = result { - println!("Failed: {}", format_error(e)); - exit(1); - } +pub fn live_rootfs() -> Result<()> { + copy_artifacts()?; + let rootfs = find_rootfs_image()?; + setup_rootfs_resource(&rootfs) } -pub fn format_error(err: &Error) -> String { - let mut output = err.to_string(); - let mut prev = err.as_fail(); - while let Some(next) = prev.cause() { - output.push_str(": "); - output.push_str(&next.to_string()); - prev = next; - } - output -} - -fn live_setup() -> Result<()> { - if !Path::new("/etc/initrd-release").exists() { - bail!("Not running in initramfs, cannot do live-setup"); - } - let installer = installer::Installer::new_livesetup(); - installer.run() +pub fn live_setup() -> Result<()> { + decompress_images()?; + let live = Installer::new_livesetup(); + live.run() } fn copy_artifacts() -> Result<()> { - for _ in 0..3 { if try_copy_artifacts()? { - decompress_images()?; + //decompress_images()?; return Ok(()) } // Try again after waiting for more devices to be discovered - println!("Failed to find partition with images, trying again in 2 seconds"); + info!("Failed to find partition with images, trying again in 2 seconds"); thread::sleep(time::Duration::from_secs(2)); } Err(format_err!("Could not find partition containing resource images")) + } fn try_copy_artifacts() -> Result { @@ -89,22 +61,22 @@ fn try_copy_artifacts() -> Result { } fn deploy_artifacts() -> Result<()> { - let run_images = Path::new("/run/images"); + let run_images = Path::new(IMAGE_DIRECTORY); if !run_images.exists() { fs::create_dir_all(run_images)?; - util::exec_cmdline("/bin/mount", "-t tmpfs -o size=4g images /run/images")?; + util::exec_cmdline("/bin/mount", "-t tmpfs -o size=4g images /run/citadel/images")?; } for entry in fs::read_dir("/boot/images")? { let entry = entry?; - println!("Copying {:?} from /boot/images to /run/images", entry.file_name()); + println!("Copying {:?} from /boot/images to /run/citadel/images", entry.file_name()); fs::copy(entry.path(), run_images.join(entry.file_name()))?; } - println!("Copying bzImage to /run/images"); - fs::copy("/boot/bzImage", "/run/images/bzImage")?; + println!("Copying bzImage to /run/citadel/images"); + fs::copy("/boot/bzImage", "/run/citadel/images/bzImage")?; - println!("Copying bootx64.efi to /run/images"); - fs::copy("/boot/EFI/BOOT/bootx64.efi", "/run/images/bootx64.efi")?; + println!("Copying bootx64.efi to /run/citadel/images"); + fs::copy("/boot/EFI/BOOT/bootx64.efi", "/run/citadel/images/bootx64.efi")?; deploy_syslinux_artifacts()?; @@ -119,9 +91,9 @@ fn deploy_syslinux_artifacts() -> Result<()> { return Ok(()); } - println!("Copying contents of /boot/syslinux to /run/images/syslinux"); + println!("Copying contents of /boot/syslinux to /run/citadel/images/syslinux"); - let run_images_syslinux = Path::new("/run/images/syslinux"); + let run_images_syslinux = Path::new("/run/citadel/images/syslinux"); fs::create_dir_all(run_images_syslinux)?; for entry in fs::read_dir(boot_syslinux)? { let entry = entry?; @@ -134,14 +106,31 @@ fn deploy_syslinux_artifacts() -> Result<()> { Ok(()) } -fn decompress_images() -> Result<()> { - println!("decompressing images"); - let mut threads = Vec::new(); - for entry in fs::read_dir("/run/images")? { +fn find_rootfs_image() -> Result { + for entry in fs::read_dir(IMAGE_DIRECTORY)? { let entry = entry?; if entry.path().extension() == Some(OsStr::new("img")) { if let Ok(image) = ResourceImage::from_path(&entry.path()) { - threads.push(decompress_one_image(image)); + if image.metainfo().image_type() == "rootfs" { + return Ok(image) + } + } + } + } + Err(format_err!("Unable to find rootfs resource image in {}", IMAGE_DIRECTORY)) + +} + +fn decompress_images() -> Result<()> { + println!("decompressing images"); + let mut threads = Vec::new(); + for entry in fs::read_dir("/run/citadel/images")? { + let entry = entry?; + if entry.path().extension() == Some(OsStr::new("img")) { + if let Ok(image) = ResourceImage::from_path(&entry.path()) { + if image.is_compressed() { + threads.push(decompress_one_image(image)); + } } } } @@ -157,19 +146,3 @@ fn decompress_one_image(image: ResourceImage) -> JoinHandle> { image.decompress() }) } - -fn cli_install() -> Result<()> { - let ok = cli::run_cli_install()?; - if !ok { - println!("Install cancelled..."); - } - Ok(()) -} - -fn cli_install_to(target: &str) -> Result<()> { - let ok = cli::run_cli_install_with(target)?; - if !ok { - println!("Install cancelled..."); - } - Ok(()) -} diff --git a/citadel-tool/src/boot/mod.rs b/citadel-tool/src/boot/mod.rs new file mode 100644 index 0000000..046816e --- /dev/null +++ b/citadel-tool/src/boot/mod.rs @@ -0,0 +1,74 @@ +use std::fs; +use std::process::exit; + +use libcitadel::{util,Result,ResourceImage,CommandLine,set_verbose,format_error}; + +mod live; +mod disks; +mod rootfs; + +pub fn main(args: Vec) { + if CommandLine::verbose() { + set_verbose(true); + } + + let command = args.iter().skip(1).next(); + + let result = match command { + Some(s) if s == "rootfs" => do_rootfs(), + Some(s) if s == "setup" => do_setup(), + _ => Err(format_err!("Bad or missing argument")), + }; + + if let Err(ref e) = result { + warn!("Failed: {}", format_error(e)); + exit(1); + } +} + +fn do_rootfs() -> Result<()> { + if CommandLine::live_mode() || CommandLine::install_mode() { + live::live_rootfs() + } else { + rootfs::setup_rootfs() + } +} + + +fn do_setup() -> Result<()> { + if CommandLine::live_mode() || CommandLine::install_mode() { + live::live_setup()?; + } + + ResourceImage::mount_image_type("kernel")?; + ResourceImage::mount_image_type("extra")?; + + if CommandLine::overlay() { + mount_overlay()?; + } + Ok(()) +} + +fn mount_overlay() -> Result<()> { + info!("Creating rootfs overlay"); + + info!("Moving /sysroot mount to /rootfs.ro"); + fs::create_dir_all("/rootfs.ro")?; + util::exec_cmdline("/usr/bin/mount", "--make-private /")?; + util::exec_cmdline("/usr/bin/mount", "--move /sysroot /rootfs.ro")?; + info!("Mounting tmpfs on /rootfs.rw"); + fs::create_dir_all("/rootfs.rw")?; + util::exec_cmdline("/usr/bin/mount", "-t tmpfs -orw,noatime,mode=755 rootfs.rw /rootfs.rw")?; + info!("Creating /rootfs.rw/work /rootfs.rw/upperdir"); + fs::create_dir_all("/rootfs.rw/upperdir")?; + fs::create_dir_all("/rootfs.rw/work")?; + info!("Mounting overlay on /sysroot"); + util::exec_cmdline("/usr/bin/mount", "-t overlay overlay -olowerdir=/rootfs.ro,upperdir=/rootfs.rw/upperdir,workdir=/rootfs.rw/work /sysroot")?; + + info!("Moving /rootfs.ro and /rootfs.rw to new root"); + fs::create_dir_all("/sysroot/rootfs.ro")?; + fs::create_dir_all("/sysroot/rootfs.rw")?; + util::exec_cmdline("/usr/bin/mount", "--move /rootfs.ro /sysroot/rootfs.ro")?; + util::exec_cmdline("/usr/bin/mount", "--move /rootfs.rw /sysroot/rootfs.rw")?; + Ok(()) +} diff --git a/citadel-mount/src/rootfs.rs b/citadel-tool/src/boot/rootfs.rs similarity index 88% rename from citadel-mount/src/rootfs.rs rename to citadel-tool/src/boot/rootfs.rs index 3d53318..95c8135 100644 --- a/citadel-mount/src/rootfs.rs +++ b/citadel-tool/src/boot/rootfs.rs @@ -1,20 +1,11 @@ use std::process::Command; -use libcitadel::{BlockDev,CommandLine,ImageHeader,Partition,Result,verity}; +use libcitadel::{BlockDev,ResourceImage,CommandLine,ImageHeader,Partition,Result,verity}; use std::path::Path; use std::process::Stdio; -use ResourceImage; pub fn setup_rootfs() -> Result<()> { - if CommandLine::install_mode() || CommandLine::live_mode() { - setup_rootfs_resource() - } else { - let p = choose_boot_partiton(true)?; - setup_partition(p) - } -} - -fn setup_partition(mut p: Partition) -> Result<()> { + let mut p = choose_boot_partiton(true)?; if CommandLine::noverity() { setup_partition_unverified(&p) } else { @@ -22,15 +13,11 @@ fn setup_partition(mut p: Partition) -> Result<()> { } } -fn setup_rootfs_resource() -> Result<()> { - info!("Searching for rootfs resource image"); - - let img = ResourceImage::find_rootfs()?; - +pub fn setup_rootfs_resource(rootfs: &ResourceImage) -> Result<()> { if CommandLine::noverity() { - setup_resource_unverified(&img) + setup_resource_unverified(&rootfs) } else { - setup_resource_verified(&img) + setup_resource_verified(&rootfs) } } diff --git a/citadel-image/src/main.rs b/citadel-tool/src/image/mod.rs similarity index 90% rename from citadel-image/src/main.rs rename to citadel-tool/src/image/mod.rs index a873c0d..ce2eef8 100644 --- a/citadel-image/src/main.rs +++ b/citadel-tool/src/image/mod.rs @@ -1,41 +1,29 @@ -#[macro_use] extern crate libcitadel; -#[macro_use] extern crate failure; -#[macro_use] extern crate serde_derive; - -use std::process::exit; use std::path::Path; -use std::fs; +use std::process::exit; use clap::{App,Arg,SubCommand,ArgMatches}; use clap::AppSettings::*; - -use crate::build::UpdateBuilder; -use crate::config::BuildConfig; use libcitadel::{Result,ResourceImage,set_verbose,format_error,Partition,KeyPair,ImageHeader}; +use std::fs; -mod build; -mod config; +pub fn main(args: Vec) { -fn main() { let app = App::new("citadel-image") .about("Citadel update image builder") .settings(&[ArgRequiredElseHelp,ColoredHelp, DisableHelpSubcommand, DisableVersion, DeriveDisplayOrder]) - .subcommand(SubCommand::with_name("build") - .about("Build an update image specified by a configuration file") - .arg(Arg::with_name("build-file") - .required(true) - .help("Path to image build config file"))) .subcommand(SubCommand::with_name("metainfo") .about("Display metainfo variables for an image file") .arg(Arg::with_name("path") .required(true) .help("Path to image file"))) + .subcommand(SubCommand::with_name("generate-verity") .about("Generate dm-verity hash tree for an image file") .arg(Arg::with_name("path") .required(true) .help("Path to image file"))) + .subcommand(SubCommand::with_name("verify") .about("Verify dm-verity hash tree for an image file") .arg(Arg::with_name("path") @@ -72,14 +60,13 @@ fn main() { .subcommand(SubCommand::with_name("verify-shasum") .about("Verify the sha256 sum of the image") .arg(Arg::with_name("path") - .required(true) - .help("Path to image file"))); + .required(true) + .help("Path to image file"))); set_verbose(true); - let matches = app.get_matches(); + let matches = app.get_matches_from(args); let result = match matches.subcommand() { - ("build", Some(m)) => build_image(m), ("metainfo", Some(m)) => metainfo(m), ("generate-verity", Some(m)) => generate_verity(m), ("verify", Some(m)) => verify(m), @@ -99,14 +86,6 @@ fn main() { } } -fn build_image(arg_matches: &ArgMatches) -> Result<()> { - let build_file = arg_matches.value_of("build-file").unwrap(); - let config = BuildConfig::load(build_file)?; - let mut builder = UpdateBuilder::new(config); - builder.build()?; - Ok(()) -} - fn metainfo(arg_matches: &ArgMatches) -> Result<()> { let img = load_image(arg_matches)?; print!("{}",String::from_utf8(img.header().metainfo_bytes())?); @@ -238,7 +217,7 @@ fn install_image(arg_matches: &ArgMatches) -> Result<()> { let image_dir = Path::new("/storage/resources").join(metainfo.channel()); let image_dest = image_dir.join(filename); if image_dest.exists() { - rotate(&image_dest)?; + rotate(&image_dest)?; } fs::rename(source,image_dest)?; Ok(()) @@ -299,9 +278,9 @@ fn choose_install_partition(verbose: bool) -> Result { if verbose { for p in &partitions { info!("Partition: {} (Mounted: {}) (Empty: {})", - p.path().display(), - bool_to_yesno(p.is_mounted()), - bool_to_yesno(!p.is_initialized())); + p.path().display(), + bool_to_yesno(p.is_mounted()), + bool_to_yesno(!p.is_initialized())); } } diff --git a/citadel-install/src/cli.rs b/citadel-tool/src/install/cli.rs similarity index 97% rename from citadel-install/src/cli.rs rename to citadel-tool/src/install/cli.rs index 1191e3c..5ceb2f3 100644 --- a/citadel-install/src/cli.rs +++ b/citadel-tool/src/install/cli.rs @@ -1,9 +1,9 @@ use std::io::{self,Write}; use std::path::Path; -use crate::Result; -use crate::util::Disk; +use libcitadel::Result; +use super::disk::Disk; use rpassword; -use crate::installer::Installer; +use crate::install::installer::Installer; pub fn run_cli_install() -> Result { let disk = match choose_disk()? { diff --git a/citadel-install/src/util.rs b/citadel-tool/src/install/disk.rs similarity index 68% rename from citadel-install/src/util.rs rename to citadel-tool/src/install/disk.rs index a50f07a..c87174a 100644 --- a/citadel-install/src/util.rs +++ b/citadel-tool/src/install/disk.rs @@ -1,58 +1,8 @@ -use std::mem; -use std::ffi::CStr; -use std::str::from_utf8_unchecked; use std::path::{Path,PathBuf}; -use std::process::{Command,ExitStatus,Stdio}; use std::fs; -use libc::{self, c_char}; -use failure::ResultExt; -use libcitadel::OsRelease; +use libcitadel::Result; -use super::Result; - -#[repr(C)] -#[derive(Clone, Copy)] -pub struct UtsName(libc::utsname); - -#[allow(dead_code)] -impl UtsName { - pub fn sysname(&self) -> &str { - to_str(&(&self.0.sysname as *const c_char ) as *const *const c_char) - } - - pub fn nodename(&self) -> &str { - to_str(&(&self.0.nodename as *const c_char ) as *const *const c_char) - } - - pub fn release(&self) -> &str { - to_str(&(&self.0.release as *const c_char ) as *const *const c_char) - } - - pub fn version(&self) -> &str { - to_str(&(&self.0.version as *const c_char ) as *const *const c_char) - } - - pub fn machine(&self) -> &str { - to_str(&(&self.0.machine as *const c_char ) as *const *const c_char) - } -} - -pub fn uname() -> UtsName { - unsafe { - let mut ret: UtsName = mem::uninitialized(); - libc::uname(&mut ret.0); - ret - } -} - -#[inline] -fn to_str<'a>(s: *const *const c_char) -> &'a str { - unsafe { - let res = CStr::from_ptr(*s).to_bytes(); - from_utf8_unchecked(res) - } -} #[derive(Debug, Clone)] pub struct Disk { @@ -110,6 +60,7 @@ impl Disk { } +/* pub fn rootfs_channel() -> &'static str { match OsRelease::citadel_channel() { Some(channel) => channel, @@ -154,3 +105,4 @@ fn check_cmd_status(cmd_path: &str, status: &ExitStatus) -> Result<()> { } Ok(()) } +*/ diff --git a/citadel-install/src/installer.rs b/citadel-tool/src/install/installer.rs similarity index 94% rename from citadel-install/src/installer.rs rename to citadel-tool/src/install/installer.rs index 7d771b5..33ba089 100644 --- a/citadel-install/src/installer.rs +++ b/citadel-tool/src/install/installer.rs @@ -6,11 +6,10 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::time::Instant; -use libcitadel::util::{mount,exec_cmdline_with_output}; +use libcitadel::util::{self,mount,exec_cmdline_with_output}; use libcitadel::RealmFS; - -use super::util; -use super::Result; +use libcitadel::Result; +use libcitadel::OsRelease; const BLKDEACTIVATE: &str = "/sbin/blkdeactivate"; const CRYPTSETUP: &str = "/sbin/cryptsetup"; @@ -40,7 +39,7 @@ const EXTRA_IMAGE_NAME: &str = "citadel-extra.img"; const INSTALL_MOUNT: &str = "/run/installer/mnt"; const LUKS_PASSPHRASE_FILE: &str = "/run/installer/luks-passphrase"; -const DEFAULT_ARTIFACT_DIRECTORY: &str = "/run/images"; +const DEFAULT_ARTIFACT_DIRECTORY: &str = "/run/citadel/images"; const KERNEL_CMDLINE: &str = "add_efi_memmap intel_iommu=off cryptomgr.notests rcupdate.rcu_expedited=1 rcu_nocbs=0-64 tsc=reliable no_timer_check noreplace-smp i915.fastboot=1 quiet splash"; @@ -183,15 +182,15 @@ impl Installer { } fn setup_live_realm(&self) -> Result<()> { - self.cmd(CITADEL_IMAGE, format!("decompress /run/images/base-realmfs.img"))?; + self.cmd(CITADEL_IMAGE, format!("decompress /run/citadel/images/base-realmfs.img"))?; let realmfs_dir = self.storage().join("realms/realmfs-images"); let base_realmfs = realmfs_dir.join("base-realmfs.img"); self.info(format!("creating directory {}", realmfs_dir.display()))?; fs::create_dir_all(&realmfs_dir)?; - self.info(format!("creating symlink {} -> {}", base_realmfs.display(), "/run/images/base-realmfs.img"))?; - unixfs::symlink("/run/images/base-realmfs.img", &base_realmfs)?; + self.info(format!("creating symlink {} -> {}", base_realmfs.display(), "/run/citadel/images/base-realmfs.img"))?; + unixfs::symlink("/run/citadel/images/base-realmfs.img", &base_realmfs)?; self.mount_realmfs()?; self.setup_storage()?; @@ -201,7 +200,7 @@ impl Installer { fs::write(self.storage().join("realms/realm-main/config"), "realmfs = \"base\"")?; let rootfs = self.storage().join("realms/realm-main/rootfs"); fs::remove_file(&rootfs)?; - unixfs::symlink("/run/images/base-realmfs.mountpoint", &rootfs)?; + unixfs::symlink("/run/citadel/images/base-realmfs.mountpoint", &rootfs)?; self.info("Creating /Shared realms directory")?; fs::create_dir_all(self.storage().join("realms/Shared"))?; @@ -211,12 +210,12 @@ impl Installer { } pub fn mount_realmfs(&self) -> Result<()> { - self.info("Creating loop device for /run/images/base-realmfs.img")?; - let args = format!("--offset 4096 -f --show /run/images/base-realmfs.img"); + self.info("Creating loop device for /run/citadel/images/base-realmfs.img")?; + let args = format!("--offset 4096 -f --show /run/citadel/images/base-realmfs.img"); let loopdev = exec_cmdline_with_output("/sbin/losetup", args)?; - self.info("Mounting image at /run/images/base-realmfs.mountpoint")?; - fs::create_dir_all("/run/images/base-realmfs.mountpoint")?; - mount(&loopdev, "/run/images/base-realmfs.mountpoint", Some("-oro"))?; + self.info("Mounting image at /run/citadel/images/base-realmfs.mountpoint")?; + fs::create_dir_all("/run/citadel/images/base-realmfs.mountpoint")?; + mount(&loopdev, "/run/citadel/images/base-realmfs.mountpoint", Some("-oro"))?; Ok(()) } @@ -419,7 +418,7 @@ impl Installer { /* self.info("Creating rootfs symlink")?; unixfs::symlink( - format!("/run/images/{}-realmfs.mountpoint", self.main_realmfs()), + format!("/run/citadel/images/{}-realmfs.mountpoint", self.main_realmfs()), format!("{}/rootfs", realm.display()))?; */ @@ -430,7 +429,10 @@ impl Installer { } fn setup_storage_resources(&self) -> Result<()> { - let channel = util::rootfs_channel(); + let channel = match OsRelease::citadel_channel() { + Some(channel) => channel, + None => "dev", + }; let resources = self.storage().join("resources").join(channel); fs::create_dir_all(&resources)?; diff --git a/citadel-tool/src/install/mod.rs b/citadel-tool/src/install/mod.rs new file mode 100644 index 0000000..8b64f39 --- /dev/null +++ b/citadel-tool/src/install/mod.rs @@ -0,0 +1,28 @@ +use std::process::exit; + +pub(crate) mod installer; +mod cli; +mod disk; + +use libcitadel::format_error; + +pub fn main(args: Vec) { + let mut args = args.iter().skip(1); + let result = if let Some(dev) = args.next() { + cli::run_cli_install_with(dev) + } else { + cli::run_cli_install() + }; + + let ok = match result { + Ok(ok) => ok, + Err(ref err) => { + println!("Install failed: {}", format_error(err)); + exit(1); + }, + }; + if !ok { + println!("Install cancelled..."); + } +} + diff --git a/citadel-tool/src/main.rs b/citadel-tool/src/main.rs new file mode 100644 index 0000000..79675eb --- /dev/null +++ b/citadel-tool/src/main.rs @@ -0,0 +1,58 @@ +#[macro_use] extern crate libcitadel; +#[macro_use] extern crate failure; +#[macro_use] extern crate serde_derive; + +use std::env; +use std::path::Path; +use std::ffi::OsStr; +use std::iter; + +mod boot; +mod image; +mod install; +mod mkimage; + +fn main() { + let exe = match env::current_exe() { + Ok(path) => path, + Err(_e) => { + return; + }, + }; + + let args = env::args().collect::>(); + + if exe == Path::new("/usr/libexec/citadel-boot") { + boot::main(args); + } else if exe == Path::new("/usr/libexec/citadel-install") { + install::main(args); + } else if exe == Path::new("/usr/bin/citadel-image") { + image::main(args); + } else if exe.file_name() == Some(OsStr::new("citadel-mkimage")) { + mkimage::main(args); + } else if exe.file_name() == Some(OsStr::new("citadel-tool")) { + dispatch_command(args); + } else { + println!("Error: unknown executable {}", exe.display()); + } +} + +fn dispatch_command(args: Vec) { + if let Some(command) = args.iter().skip(1).next() { + match command.as_str() { + "boot" => boot::main(rebuild_args("citadel-boot", args)), + "install" => install::main(rebuild_args("citadel-install", args)), + "image" => image::main(rebuild_args("citadel-image", args)), + "mkimage" => mkimage::main(rebuild_args("citadel-mkimage", args)), + _ => println!("Error: unknown command {}", command), + } + } else { + println!("Must provide an argument"); + } +} + +fn rebuild_args(command: &str, args: Vec) -> Vec { + iter::once(command.to_string()) + .chain(args.into_iter().skip(2)) + .collect() +} diff --git a/citadel-image/src/build.rs b/citadel-tool/src/mkimage/build.rs similarity index 99% rename from citadel-image/src/build.rs rename to citadel-tool/src/mkimage/build.rs index b7a8272..908b923 100644 --- a/citadel-image/src/build.rs +++ b/citadel-tool/src/mkimage/build.rs @@ -6,7 +6,7 @@ use std::io::{self,Write}; use failure::ResultExt; use libcitadel::{Result,ImageHeader,verity,util,devkeys}; -use crate::BuildConfig; +use super::config::BuildConfig; use std::path::Path; pub struct UpdateBuilder { diff --git a/citadel-image/src/config.rs b/citadel-tool/src/mkimage/config.rs similarity index 100% rename from citadel-image/src/config.rs rename to citadel-tool/src/mkimage/config.rs diff --git a/citadel-tool/src/mkimage/mod.rs b/citadel-tool/src/mkimage/mod.rs new file mode 100644 index 0000000..5c31d0c --- /dev/null +++ b/citadel-tool/src/mkimage/mod.rs @@ -0,0 +1,31 @@ + +use std::process::exit; + +use libcitadel::Result; + +mod config; +mod build; + +pub fn main(args: Vec) { + + let config_path = match args.iter().skip(1).next() { + Some(arg) => arg, + None => { + println!("Expected config file argument"); + exit(1); + }, + }; + + if let Err(err) = build_image(config_path) { + println!("Error: {}", err); + exit(1); + } + + +} + +fn build_image(config_path: &str) -> Result<()> { + let conf = config::BuildConfig::load(config_path)?; + let mut builder = build::UpdateBuilder::new(conf); + builder.build() +} \ No newline at end of file diff --git a/libcitadel/src/realmfs.rs b/libcitadel/src/realmfs.rs index aad6f79..b45d52d 100644 --- a/libcitadel/src/realmfs.rs +++ b/libcitadel/src/realmfs.rs @@ -6,7 +6,7 @@ use std::io::Write; use crate::{ImageHeader,MetaInfo,Mount,Result,util,verity}; const BASE_PATH: &'static str = "/storage/realms/realmfs-images"; -const RUN_DIRECTORY: &str = "/run/images"; +const RUN_DIRECTORY: &str = "/run/citadel/images"; const MAX_REALMFS_NAME_LEN: usize = 40; diff --git a/libcitadel/src/resource.rs b/libcitadel/src/resource.rs index b44a32e..ca6961c 100644 --- a/libcitadel/src/resource.rs +++ b/libcitadel/src/resource.rs @@ -8,7 +8,7 @@ use crate::{CommandLine,OsRelease,ImageHeader,MetaInfo,Result,Partition,Mount,ve use failure::ResultExt; const STORAGE_BASEDIR: &str = "/sysroot/storage/resources"; -const RUN_DIRECTORY: &str = "/run/images"; +const RUN_DIRECTORY: &str = "/run/citadel/images"; /// Locates and mounts a resource image file. /// @@ -24,7 +24,7 @@ const RUN_DIRECTORY: &str = "/run/images"; /// citadel.noverity: Mount image without dm-verity. Also do not verify header signature. /// citadel.nosignatures: Do not verify header signature. /// -/// A requested image file will be searched for first in /run/images and if not found there the +/// A requested image file will be searched for first in /run/citadel/images and if not found there the /// usual location of /storage/resources is searched. /// pub struct ResourceImage { @@ -35,7 +35,7 @@ pub struct ResourceImage { impl ResourceImage { /// Locate and return a resource image of type `image_type`. - /// First the /run/images directory is searched, and if not found there, + /// First the /run/citadel/images directory is searched, and if not found there, /// the image will be searched for in /storage/resources/$channel pub fn find(image_type: &str) -> Result { let channel = ResourceImage::rootfs_channel(); @@ -59,7 +59,12 @@ impl ResourceImage { Err(format_err!("Failed to find resource image of type: {}", image_type)) } - /// Locate a rootfs image in /run/images and return it + pub fn mount_image_type(image_type: &str) -> Result<()> { + let mut image = ResourceImage::find(image_type)?; + image.mount() + } + + /// Locate a rootfs image in /run/citadel/images and return it pub fn find_rootfs() -> Result { match search_directory(RUN_DIRECTORY, "rootfs", None)? { Some(image) => Ok(image), diff --git a/libcitadel/src/verity.rs b/libcitadel/src/verity.rs index b789601..4300b9a 100644 --- a/libcitadel/src/verity.rs +++ b/libcitadel/src/verity.rs @@ -109,7 +109,7 @@ fn setup_device(srcdev: &str, devname: &str, nblocks: usize, roothash: &str) -> } fn create_image_loop_device(file: &Path) -> Result { - let args = format!("--offset 4096 -f --show {}", file.display()); + let args = format!("--offset 4096 --read-only -f --show {}", file.display()); let output = util::exec_cmdline_with_output(LOSETUP, args)?; Ok(output) }