From 04457a47eff5d3a82fee152b4dd4eb81ca2a75a7 Mon Sep 17 00:00:00 2001 From: isa Date: Thu, 29 Aug 2024 14:54:31 -0400 Subject: [PATCH] Improve error handling by using std lib rust code --- citadel-tool/src/boot/live.rs | 60 ++++++----- citadel-tool/src/boot/mod.rs | 40 ++++---- citadel-tool/src/boot/rootfs.rs | 44 +++++--- citadel-tool/src/image/mod.rs | 85 +++++++++------- citadel-tool/src/install/cli.rs | 30 +++--- citadel-tool/src/install/installer.rs | 122 +++++++++++++---------- citadel-tool/src/install/mod.rs | 7 +- citadel-tool/src/install_backend/dbus.rs | 16 +-- citadel-tool/src/install_backend/mod.rs | 10 +- citadel-tool/src/main.rs | 54 +++++----- citadel-tool/src/mkimage/mod.rs | 13 +-- citadel-tool/src/realmfs/mod.rs | 68 +++++++------ citadel-tool/src/sync/desktop_sync.rs | 29 +++--- citadel-tool/src/sync/mod.rs | 13 +-- citadel-tool/src/update/mod.rs | 98 ++++++++++-------- 15 files changed, 372 insertions(+), 317 deletions(-) diff --git a/citadel-tool/src/boot/live.rs b/citadel-tool/src/boot/live.rs index 495d0ce..53490ed 100644 --- a/citadel-tool/src/boot/live.rs +++ b/citadel-tool/src/boot/live.rs @@ -4,7 +4,7 @@ use std::fs; use std::thread::{self,JoinHandle}; use std::time::{self,Instant}; -use libcitadel::{Result, UtsName, util}; +use libcitadel::{UtsName, util}; use libcitadel::ResourceImage; use crate::boot::disks; @@ -13,34 +13,33 @@ use crate::install::installer::Installer; const IMAGE_DIRECTORY: &str = "/run/citadel/images"; -pub fn live_rootfs() -> Result<()> { +pub fn live_rootfs() -> Result<(), Box> { copy_artifacts()?; let rootfs = find_rootfs_image()?; setup_rootfs_resource(&rootfs) } -pub fn live_setup() -> Result<()> { +pub fn live_setup() -> Result<(), Box> { decompress_images(true)?; info!("Starting live setup"); let live = Installer::new_livesetup(); live.run() } -fn copy_artifacts() -> Result<()> { +fn copy_artifacts() -> Result<(), Box> { for _ in 0..3 { if try_copy_artifacts()? { //decompress_images()?; - return Ok(()) + return Ok(()); } // Try again after waiting for more devices to be discovered info!("Failed to find partition with images, trying again in 2 seconds"); thread::sleep(time::Duration::from_secs(2)); } - bail!("could not find partition containing resource images") - + Result::Err("could not find partition containing resource images".into()) } -fn try_copy_artifacts() -> Result { +fn try_copy_artifacts() -> Result> { let rootfs_image = Path::new("/boot/images/citadel-rootfs.img"); // Already mounted? if rootfs_image.exists() { @@ -60,13 +59,13 @@ fn try_copy_artifacts() -> Result { Ok(false) } -fn kernel_version() -> String { +fn kernel_version() -> Result> { let utsname = UtsName::uname(); let v = utsname.release().split('-').collect::>(); - v[0].to_string() + Ok(v[0].to_string()) } -fn deploy_artifacts() -> Result<()> { +fn deploy_artifacts() -> Result<(), Box> { let run_images = Path::new(IMAGE_DIRECTORY); if !run_images.exists() { util::create_dir(run_images)?; @@ -78,7 +77,7 @@ fn deploy_artifacts() -> Result<()> { util::copy_file(dent.path(), run_images.join(dent.file_name())) })?; - let kv = kernel_version(); + let kv = kernel_version()?; println!("Copying bzImage-{} to /run/citadel/images", kv); let from = format!("/boot/bzImage-{}", kv); let to = format!("/run/citadel/images/bzImage-{}", kv); @@ -92,7 +91,7 @@ fn deploy_artifacts() -> Result<()> { Ok(()) } -fn deploy_syslinux_artifacts() -> Result<()> { +fn deploy_syslinux_artifacts() -> Result<(), Box> { let boot_syslinux = Path::new("/boot/syslinux"); if !boot_syslinux.exists() { @@ -112,10 +111,11 @@ fn deploy_syslinux_artifacts() -> Result<()> { } } Ok(()) - }) + })?; + Ok(()) } -fn find_rootfs_image() -> Result { +fn find_rootfs_image() -> Result> { let entries = fs::read_dir(IMAGE_DIRECTORY) .map_err(context!("error reading directory {}", IMAGE_DIRECTORY))?; for entry in entries { @@ -123,15 +123,21 @@ fn find_rootfs_image() -> Result { if entry.path().extension() == Some(OsStr::new("img")) { if let Ok(image) = ResourceImage::from_path(&entry.path()) { if image.metainfo().image_type() == "rootfs" { - return Ok(image) + return Ok(image); } } } } - bail!("unable to find rootfs resource image in {}", IMAGE_DIRECTORY) + Result::Err( + format!( + "unable to find rootfs resource image in {}", + IMAGE_DIRECTORY + ) + .into(), + ) } -fn decompress_images(sync: bool) -> Result<()> { +fn decompress_images(sync: bool) -> Result<(), Box> { info!("Decompressing images"); let mut threads = Vec::new(); util::read_directory("/run/citadel/images", |dent| { @@ -140,9 +146,8 @@ fn decompress_images(sync: bool) -> Result<()> { if image.is_compressed() { if sync { if let Err(err) = decompress_one_image_sync(image) { - warn!("Error: {}", err); + warn!("Error decompressing image: {}", err); } - } else { threads.push(decompress_one_image(image)); } @@ -161,9 +166,11 @@ fn decompress_images(sync: bool) -> Result<()> { Ok(()) } -fn decompress_one_image_sync(image: ResourceImage) -> Result<()> { - let start = Instant::now(); - info!("Decompressing {}", image.path().display()); +fn decompress_one_image_sync( + image: ResourceImage, +) -> Result<(), Box> { + let start = Instant::now(); + info!("Decompressing {}", image.path().display()); image.decompress(true) .map_err(|e| format_err!("Failed to decompress image file {}: {}", image.path().display(), e))?; cmd!("/usr/bin/du", "-h {}", image.path().display())?; @@ -173,8 +180,7 @@ fn decompress_one_image_sync(image: ResourceImage) -> Result<()> { Ok(()) } -fn decompress_one_image(image: ResourceImage) -> JoinHandle> { - thread::spawn(move || { - decompress_one_image_sync(image) - }) +fn decompress_one_image(image: ResourceImage,) -> + JoinHandle>> { + thread::spawn(move || decompress_one_image_sync(image)) } diff --git a/citadel-tool/src/boot/mod.rs b/citadel-tool/src/boot/mod.rs index a049f72..c537394 100644 --- a/citadel-tool/src/boot/mod.rs +++ b/citadel-tool/src/boot/mod.rs @@ -1,7 +1,6 @@ use std::fs; -use std::process::exit; -use libcitadel::{Result, ResourceImage, CommandLine, KeyRing, LogLevel, Logger, util}; +use libcitadel::{ResourceImage, CommandLine, KeyRing, LogLevel, Logger, util}; use libcitadel::RealmManager; use crate::boot::disks::DiskPartition; use std::path::Path; @@ -10,44 +9,40 @@ mod live; mod disks; mod rootfs; -pub fn main(args: Vec) { +pub fn main(args: Vec) -> Result<(), Box> { if CommandLine::debug() { Logger::set_log_level(LogLevel::Debug); } else if CommandLine::verbose() { Logger::set_log_level(LogLevel::Info); } - let result = match args.get(1) { + match args.get(1) { Some(s) if s == "rootfs" => do_rootfs(), Some(s) if s == "setup" => do_setup(), Some(s) if s == "boot-automount" => do_boot_automount(), Some(s) if s == "start-realms" => do_start_realms(), _ => Err(format_err!("Bad or missing argument").into()), - }; + }?; - if let Err(ref e) = result { - warn!("Failed: {}", e); - exit(1); - } + Ok(()) } - -fn do_rootfs() -> Result<()> { +fn do_rootfs() -> Result<(), Box> { if CommandLine::live_mode() || CommandLine::install_mode() { live::live_rootfs() } else { - rootfs::setup_rootfs() + Ok(rootfs::setup_rootfs()?) } } -fn setup_keyring() -> Result<()> { +fn setup_keyring() -> Result<(), Box> { ResourceImage::ensure_storage_mounted()?; let keyring = KeyRing::load_with_cryptsetup_passphrase("/sysroot/storage/keyring")?; keyring.add_keys_to_kernel()?; Ok(()) } -fn do_setup() -> Result<()> { +fn do_setup() -> Result<(), Box> { if CommandLine::live_mode() || CommandLine::install_mode() { live::live_setup()?; } else if let Err(err) = setup_keyring() { @@ -64,8 +59,7 @@ fn do_setup() -> Result<()> { Ok(()) } - -fn mount_overlay() -> Result<()> { +fn mount_overlay() -> Result<(), Box> { info!("Creating rootfs overlay"); info!("Moving /sysroot mount to /rootfs.ro"); @@ -89,13 +83,13 @@ fn mount_overlay() -> Result<()> { Ok(()) } -fn do_start_realms() -> Result<()> { +fn do_start_realms() -> Result<(), Box> { let manager = RealmManager::load()?; - manager.start_boot_realms() + Ok(manager.start_boot_realms()?) } // Write automount unit for /boot partition -fn do_boot_automount() -> Result<()> { +fn do_boot_automount() -> Result<(), Box> { Logger::set_log_level(LogLevel::Info); if CommandLine::live_mode() || CommandLine::install_mode() { @@ -105,10 +99,10 @@ fn do_boot_automount() -> Result<()> { let boot_partition = find_boot_partition()?; info!("Creating /boot automount units for boot partition {}", boot_partition); - cmd!("/usr/bin/systemd-mount", "-A --timeout-idle-sec=300 {} /boot", boot_partition) + Ok(cmd!("/usr/bin/systemd-mount", "-A --timeout-idle-sec=300 {} /boot", boot_partition)?) } -fn find_boot_partition() -> Result { +fn find_boot_partition() -> Result> { let loader_dev = read_loader_dev_efi_var()?; let boot_partitions = DiskPartition::boot_partitions(true)? .into_iter() @@ -116,7 +110,7 @@ fn find_boot_partition() -> Result { .collect::>(); if boot_partitions.len() != 1 { - return Err(format_err!("Cannot uniquely determine boot partition")); + return Result::Err("Cannot uniquely determine boot partition".into()); } Ok(boot_partitions[0].path().display().to_string()) @@ -141,7 +135,7 @@ fn matches_loader_dev(partition: &DiskPartition, dev: &Option) -> bool { const LOADER_EFI_VAR_PATH: &str = "/sys/firmware/efi/efivars/LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f"; -fn read_loader_dev_efi_var() -> Result> { +fn read_loader_dev_efi_var() -> Result, Box> { let efi_var = Path::new(LOADER_EFI_VAR_PATH); if efi_var.exists() { let s = fs::read(efi_var) diff --git a/citadel-tool/src/boot/rootfs.rs b/citadel-tool/src/boot/rootfs.rs index 3a74cb7..29e392b 100644 --- a/citadel-tool/src/boot/rootfs.rs +++ b/citadel-tool/src/boot/rootfs.rs @@ -1,10 +1,10 @@ use std::path::Path; use std::process::{Command,Stdio}; -use libcitadel::{BlockDev, ResourceImage, CommandLine, ImageHeader, Partition, Result, LoopDevice}; +use libcitadel::{BlockDev, ResourceImage, CommandLine, ImageHeader, Partition, LoopDevice}; use libcitadel::verity::Verity; -pub fn setup_rootfs() -> Result<()> { +pub fn setup_rootfs() -> Result<(), Box> { let mut p = choose_boot_partiton(true, CommandLine::revert_rootfs())?; if CommandLine::noverity() { setup_partition_unverified(&p) @@ -13,7 +13,7 @@ pub fn setup_rootfs() -> Result<()> { } } -pub fn setup_rootfs_resource(rootfs: &ResourceImage) -> Result<()> { +pub fn setup_rootfs_resource(rootfs: &ResourceImage) -> Result<(), Box> { if CommandLine::noverity() { setup_resource_unverified(&rootfs) } else { @@ -21,7 +21,7 @@ pub fn setup_rootfs_resource(rootfs: &ResourceImage) -> Result<()> { } } -fn setup_resource_unverified(img: &ResourceImage) -> Result<()> { +fn setup_resource_unverified(img: &ResourceImage) -> Result<(), Box> { if img.is_compressed() { img.decompress(false)?; } @@ -30,25 +30,31 @@ fn setup_resource_unverified(img: &ResourceImage) -> Result<()> { setup_linear_mapping(loopdev.device()) } -fn setup_resource_verified(img: &ResourceImage) -> Result<()> { +fn setup_resource_verified(img: &ResourceImage) -> Result<(), Box> { let _ = img.setup_verity_device()?; Ok(()) } -fn setup_partition_unverified(p: &Partition) -> Result<()> { +fn setup_partition_unverified(p: &Partition) -> Result<(), Box> { info!("Creating /dev/mapper/rootfs device with linear device mapping of partition (no verity)"); setup_linear_mapping(p.path()) } -fn setup_partition_verified(p: &mut Partition) -> Result<()> { +fn setup_partition_verified(p: &mut Partition) -> Result<(), Box> { info!("Creating /dev/mapper/rootfs dm-verity device"); if !CommandLine::nosignatures() { if !p.has_public_key() { - bail!("no public key available for channel {}", p.metainfo().channel()) + return Result::Err( + format!( + "no public key available for channel {}", + p.metainfo().channel() + ) + .into(), + ); } if !p.is_signature_valid() { p.write_status(ImageHeader::STATUS_BAD_SIG)?; - bail!("signature verification failed on partition"); + return Result::Err("signature verification failed on partition".into()); } info!("Image signature is valid for channel {}", p.metainfo().channel()); } @@ -56,7 +62,7 @@ fn setup_partition_verified(p: &mut Partition) -> Result<()> { Ok(()) } -fn setup_linear_mapping(blockdev: &Path) -> Result<()> { +fn setup_linear_mapping(blockdev: &Path) -> Result<(), Box> { let dev = BlockDev::open_ro(blockdev)?; let table = format!("0 {} linear {} 0", dev.nsectors()?, blockdev.display()); @@ -70,7 +76,9 @@ fn setup_linear_mapping(blockdev: &Path) -> Result<()> { .success(); if !ok { - bail!("failed to set up linear identity mapping with /usr/sbin/dmsetup"); + return Result::Err( + "failed to set up linear identity mapping with /usr/sbin/dmsetup".into(), + ); } Ok(()) } @@ -94,7 +102,8 @@ fn choose_revert_partition(best: Option) -> Option { best } -fn choose_boot_partiton(scan: bool, revert_rootfs: bool) -> Result { +fn choose_boot_partiton(scan: bool, revert_rootfs: bool, +) -> Result> { let mut partitions = Partition::rootfs_partitions()?; if scan { @@ -136,14 +145,17 @@ fn compare_boot_partitions(a: Option, b: Partition) -> Option b_v { + if ver_a > ver_b { return Some(a); - } else if b_v > a_v { + } else if ver_b > ver_a { return Some(b); } } diff --git a/citadel-tool/src/image/mod.rs b/citadel-tool/src/image/mod.rs index 884ed12..1bafc02 100644 --- a/citadel-tool/src/image/mod.rs +++ b/citadel-tool/src/image/mod.rs @@ -3,11 +3,10 @@ use std::process::exit; use clap::{App,Arg,SubCommand,ArgMatches}; use clap::AppSettings::*; -use libcitadel::{Result, ResourceImage, Logger, LogLevel, Partition, KeyPair, ImageHeader, util}; +use libcitadel::{ResourceImage, Logger, LogLevel, Partition, KeyPair, ImageHeader, util}; use hex; -pub fn main(args: Vec) { - +pub fn main(args: Vec) -> Result<(), Box> { let app = App::new("citadel-image") .about("Citadel update image builder") .settings(&[ArgRequiredElseHelp,ColoredHelp, DisableHelpSubcommand, DisableVersion, DeriveDisplayOrder]) @@ -91,16 +90,18 @@ pub fn main(args: Vec) { println!("Error: {}", e); exit(1); } + + Ok(()) } -fn info(arg_matches: &ArgMatches) -> Result<()> { +fn info(arg_matches: &ArgMatches) -> Result<(), Box> { let img = load_image(arg_matches)?; - print!("{}",String::from_utf8(img.header().metainfo_bytes())?); + print!("{}", String::from_utf8(img.header().metainfo_bytes())?); info_signature(&img)?; Ok(()) } -fn info_signature(img: &ResourceImage) -> Result<()> { +fn info_signature(img: &ResourceImage) -> Result<(), Box> { if img.header().has_signature() { println!("Signature: {}", hex::encode(&img.header().signature())); } else { @@ -116,15 +117,15 @@ fn info_signature(img: &ResourceImage) -> Result<()> { }, None => { println!("No public key found for channel '{}'", img.metainfo().channel()) }, } - Ok(()) + Ok(()) } -fn metainfo(arg_matches: &ArgMatches) -> Result<()> { +fn metainfo(arg_matches: &ArgMatches) -> Result<(), Box> { let img = load_image(arg_matches)?; - print!("{}",String::from_utf8(img.header().metainfo_bytes())?); + print!("{}", String::from_utf8(img.header().metainfo_bytes())?); Ok(()) } -fn generate_verity(arg_matches: &ArgMatches) -> Result<()> { +fn generate_verity(arg_matches: &ArgMatches) -> Result<(), Box> { let img = load_image(arg_matches)?; if img.has_verity_hashtree() { info!("Image already has dm-verity hashtree appended, doing nothing."); @@ -134,7 +135,7 @@ fn generate_verity(arg_matches: &ArgMatches) -> Result<()> { Ok(()) } -fn verify(arg_matches: &ArgMatches) -> Result<()> { +fn verify(arg_matches: &ArgMatches) -> Result<(), Box> { let img = load_image(arg_matches)?; let ok = img.verify_verity()?; if ok { @@ -145,7 +146,7 @@ fn verify(arg_matches: &ArgMatches) -> Result<()> { Ok(()) } -fn verify_shasum(arg_matches: &ArgMatches) -> Result<()> { +fn verify_shasum(arg_matches: &ArgMatches) -> Result<(), Box> { let img = load_image(arg_matches)?; let shasum = img.generate_shasum()?; if shasum == img.metainfo().shasum() { @@ -158,22 +159,22 @@ fn verify_shasum(arg_matches: &ArgMatches) -> Result<()> { Ok(()) } -fn load_image(arg_matches: &ArgMatches) -> Result { +fn load_image(arg_matches: &ArgMatches) -> Result> { let path = arg_matches.value_of("path").expect("path argument missing"); if !Path::new(path).exists() { - bail!("Cannot load image {}: File does not exist", path); + panic!("Cannot load image {}: File does not exist", path); } let img = ResourceImage::from_path(path)?; if !img.is_valid_image() { - bail!("File {} is not a valid image file", path); + panic!("File {} is not a valid image file", path); } Ok(img) } -fn install_rootfs(arg_matches: &ArgMatches) -> Result<()> { +fn install_rootfs(arg_matches: &ArgMatches) -> Result<(), Box> { if arg_matches.is_present("choose") { let _ = choose_install_partition(true)?; - return Ok(()) + return Ok(()); } let img = load_image(arg_matches)?; @@ -182,7 +183,7 @@ fn install_rootfs(arg_matches: &ArgMatches) -> Result<()> { info!("Verifying sha256 hash of image"); let shasum = img.generate_shasum()?; if shasum != img.metainfo().shasum() { - bail!("image file does not have expected sha256 value"); + panic!("image file does not have expected sha256 value"); } } @@ -196,7 +197,7 @@ fn install_rootfs(arg_matches: &ArgMatches) -> Result<()> { Ok(()) } -fn clear_prefer_boot() -> Result<()> { +fn clear_prefer_boot() -> Result<(), Box> { for mut p in Partition::rootfs_partitions()? { if p.is_initialized() && p.header().has_flag(ImageHeader::FLAG_PREFER_BOOT) { p.clear_flag_and_write(ImageHeader::FLAG_PREFER_BOOT)?; @@ -205,13 +206,13 @@ fn clear_prefer_boot() -> Result<()> { Ok(()) } -fn sign_image(arg_matches: &ArgMatches) -> Result<()> { +fn sign_image(arg_matches: &ArgMatches) -> Result<(), Box> { let _img = load_image(arg_matches)?; info!("Not implemented yet"); Ok(()) } -fn install_image(arg_matches: &ArgMatches) -> Result<()> { +fn install_image(arg_matches: &ArgMatches) -> Result<(), Box> { let source = arg_matches.value_of("path").expect("path argument missing"); let img = load_image(arg_matches)?; let _hdr = img.header(); @@ -220,12 +221,12 @@ fn install_image(arg_matches: &ArgMatches) -> Result<()> { // XXX verify signature? if !(metainfo.image_type() == "kernel" || metainfo.image_type() == "extra") { - bail!("Cannot install image type {}", metainfo.image_type()); + panic!("Cannot install image type {}", metainfo.image_type()); } let shasum = img.generate_shasum()?; if shasum != img.metainfo().shasum() { - bail!("Image shasum does not match metainfo"); + panic!("Image shasum does not match metainfo"); } img.generate_verity_hashtree()?; @@ -233,10 +234,10 @@ fn install_image(arg_matches: &ArgMatches) -> Result<()> { let filename = if metainfo.image_type() == "kernel" { let kernel_version = match metainfo.kernel_version() { Some(version) => version, - None => bail!("Kernel image does not have a kernel version field in metainfo"), + None => panic!("Kernel image does not have a kernel version field in metainfo"), }; if kernel_version.chars().any(|c| c == '/') { - bail!("Kernel version field has / char"); + panic!("Kernel version field has / char"); } format!("citadel-kernel-{}-{:03}.img", kernel_version, metainfo.version()) } else { @@ -244,33 +245,38 @@ fn install_image(arg_matches: &ArgMatches) -> Result<()> { }; if !metainfo.channel().chars().all(|c| c.is_ascii_lowercase()) { - bail!("Refusing to build path from strange channel name {}", metainfo.channel()); + panic!( + "Refusing to build path from strange channel name {}", + metainfo.channel() + ); } let image_dir = Path::new("/storage/resources").join(metainfo.channel()); let image_dest = image_dir.join(filename); if image_dest.exists() { rotate(&image_dest)?; } - util::rename(source, &image_dest) + util::rename(source, &image_dest); + Ok(()) } -fn rotate(path: &Path) -> Result<()> { +fn rotate(path: &Path) -> Result<(), Box> { if !path.exists() || path.file_name().is_none() { return Ok(()); } let filename = path.file_name().unwrap(); let dot_zero = path.with_file_name(format!("{}.0", filename.to_string_lossy())); util::remove_file(&dot_zero)?; - util::rename(path, &dot_zero) + util::rename(path, &dot_zero).unwrap(); + Ok(()) } -fn genkeys() -> Result<()> { +fn genkeys() -> Result<(), Box> { let keypair = KeyPair::generate(); println!("keypair = \"{}\"", keypair.to_hex()); Ok(()) } -fn decompress(arg_matches: &ArgMatches) -> Result<()> { +fn decompress(arg_matches: &ArgMatches) -> Result<(), Box> { let img = load_image(arg_matches)?; if !img.is_compressed() { info!("Image is not compressed, not decompressing."); @@ -280,7 +286,7 @@ fn decompress(arg_matches: &ArgMatches) -> Result<()> { Ok(()) } -fn bless() -> Result<()> { +fn bless() -> Result<(), Box> { for mut p in Partition::rootfs_partitions()? { if p.is_initialized() && p.is_mounted() { p.bless()?; @@ -299,7 +305,7 @@ fn bool_to_yesno(val: bool) -> &'static str { } } -fn choose_install_partition(verbose: bool) -> Result { +fn choose_install_partition(verbose: bool) -> Result> { let partitions = Partition::rootfs_partitions()?; if verbose { @@ -314,9 +320,12 @@ fn choose_install_partition(verbose: bool) -> Result { for p in &partitions { if !p.is_mounted() && !p.is_initialized() { if verbose { - info!("Choosing {} because it is empty and not mounted", p.path().display()); + info!( + "Choosing {} because it is empty and not mounted", + p.path().display() + ); } - return Ok(p.clone()) + return Ok(p.clone()); } } for p in &partitions { @@ -324,10 +333,10 @@ fn choose_install_partition(verbose: bool) -> Result { if verbose { info!("Choosing {} because it is not mounted", p.path().display()); info!("Header metainfo:"); - print!("{}",String::from_utf8(p.header().metainfo_bytes())?); + print!("{}", String::from_utf8(p.header().metainfo_bytes())?); } - return Ok(p.clone()) + return Ok(p.clone()); } } - bail!("No suitable install partition found") + panic!("No suitable install partition found") } diff --git a/citadel-tool/src/install/cli.rs b/citadel-tool/src/install/cli.rs index 27704dc..1a6a226 100644 --- a/citadel-tool/src/install/cli.rs +++ b/citadel-tool/src/install/cli.rs @@ -1,6 +1,5 @@ use std::io::{self,Write}; use std::path::Path; -use libcitadel::Result; use super::disk::Disk; use rpassword; use crate::install::installer::Installer; @@ -8,7 +7,7 @@ use crate::install::installer::Installer; const CITADEL_PASSPHRASE_PROMPT: &str = "Enter a password for the Citadel user (or 'q' to quit)"; const LUKS_PASSPHRASE_PROMPT: &str = "Enter a disk encryption passphrase (or 'q' to quit"; -pub fn run_cli_install() -> Result { +pub fn run_cli_install() -> Result> { let disk = match choose_disk()? { Some(disk) => disk, None => return Ok(false), @@ -33,7 +32,7 @@ pub fn run_cli_install() -> Result { Ok(true) } -pub fn run_cli_install_with>(target: P) -> Result { +pub fn run_cli_install_with>(target: P) -> Result> { let disk = find_disk_by_path(target.as_ref())?; display_disk(&disk); @@ -55,11 +54,15 @@ pub fn run_cli_install_with>(target: P) -> Result { Ok(true) } -fn run_install(disk: Disk, citadel_passphrase: String, passphrase: String) -> Result<()> { +fn run_install( + disk: Disk, + citadel_passphrase: String, + passphrase: String, +) -> Result<(), Box> { let mut install = Installer::new(disk.path(), &citadel_passphrase, &passphrase); install.set_install_syslinux(true); install.verify()?; - install.run() + Ok(install.run()?) } fn display_disk(disk: &Disk) { @@ -70,22 +73,22 @@ fn display_disk(disk: &Disk) { println!(); } -fn find_disk_by_path(path: &Path) -> Result { +fn find_disk_by_path(path: &Path) -> Result> { if !path.exists() { - bail!("Target disk path {} does not exist", path.display()); + panic!("Target disk path {} does not exist", path.display()); } for disk in Disk::probe_all()? { if disk.path() == path { return Ok(disk.clone()); } } - bail!("installation target {} is not a valid disk", path.display()) + panic!("installation target {} is not a valid disk", path.display()) } -fn choose_disk() -> Result> { +fn choose_disk() -> Result, Box> { let disks = Disk::probe_all()?; if disks.is_empty() { - bail!("no disks found."); + panic!("no disks found."); } loop { @@ -96,7 +99,7 @@ fn choose_disk() -> Result> { } if let Ok(n) = line.parse::() { if n > 0 && n <= disks.len() { - return Ok(Some(disks[n-1].clone())); + return Ok(Some(disks[n - 1].clone())); } } } @@ -111,7 +114,7 @@ fn prompt_choose_disk(disks: &[Disk]) { let _ = io::stdout().flush(); } -fn read_line() -> Result { +fn read_line() -> Result> { let mut input = String::new(); io::stdin().read_line(&mut input) .map_err(context!("error reading line from stdin"))?; @@ -146,7 +149,7 @@ fn read_passphrase(prompt: &str) -> io::Result> { } } -fn confirm_install(disk: &Disk) -> Result { +fn confirm_install(disk: &Disk) -> Result> { println!("Are you sure you want to completely erase this this device?"); println!(); println!(" Device: {}", disk.path().display()); @@ -158,4 +161,3 @@ fn confirm_install(disk: &Disk) -> Result { let answer = read_line()?; Ok(answer == "YES") } - diff --git a/citadel-tool/src/install/installer.rs b/citadel-tool/src/install/installer.rs index 5f1133e..1433b50 100644 --- a/citadel-tool/src/install/installer.rs +++ b/citadel-tool/src/install/installer.rs @@ -9,7 +9,6 @@ use pwhash::sha512_crypt; use libcitadel::util; use libcitadel::RealmFS; -use libcitadel::Result; use libcitadel::OsRelease; use libcitadel::KeyRing; use libcitadel::terminal::Base16Scheme; @@ -183,7 +182,7 @@ impl Installer { self.install_syslinux = val; } - pub fn verify(&self) -> Result<()> { + pub fn verify(&self) -> Result<(), Box> { let kernel_img = self.kernel_imagename(); let bzimage = format!("bzImage-{}", self.kernel_version()); let artifacts = vec![ @@ -192,26 +191,29 @@ impl Installer { ]; if !self.target().exists() { - bail!("target device {:?} does not exist", self.target()); + panic!("target device {:?} does not exist", self.target()); } for a in artifacts { if !self.artifact_path(a).exists() { - bail!("required install artifact {} does not exist in {}", a, self.artifact_directory); + panic!( + "required install artifact {} does not exist in {}", + a, self.artifact_directory + ); } } Ok(()) } - pub fn run(&self) -> Result<()> { + pub fn run(&self) -> Result<(), Box> { match self._type { InstallType::Install => self.run_install(), InstallType::LiveSetup => self.run_live_setup(), } } - pub fn run_install(&self) -> Result<()> { + pub fn run_install(&self) -> Result<(), Box> { let start = Instant::now(); self.partition_disk()?; self.setup_luks()?; @@ -224,7 +226,7 @@ impl Installer { Ok(()) } - pub fn run_live_setup(&self) -> Result<()> { + pub fn run_live_setup(&self) -> Result<(), Box> { self.cmd_list(&[ "/bin/mount -t tmpfs var-tmpfs /sysroot/var", "/bin/mount -t tmpfs home-tmpfs /sysroot/home", @@ -242,8 +244,7 @@ impl Installer { Ok(()) } - fn setup_live_realm(&self) -> Result<()> { - + fn setup_live_realm(&self) -> Result<(), Box> { let realmfs_dir = self.storage().join("realms/realmfs-images"); let base_realmfs = realmfs_dir.join("base-realmfs.img"); @@ -261,14 +262,14 @@ impl Installer { Ok(()) } - pub fn partition_disk(&self) -> Result<()> { + pub fn partition_disk(&self) -> Result<(), Box> { self.header("Partitioning target disk")?; self.cmd_list(PARTITION_COMMANDS, &[ ("$TARGET", self.target_str()) ]) } - pub fn setup_luks(&self) -> Result<()> { + pub fn setup_luks(&self) -> Result<(), Box> { self.header("Setting up LUKS disk encryption")?; util::create_dir(INSTALL_MOUNT)?; util::write_file(LUKS_PASSPHRASE_FILE, self.passphrase().as_bytes())?; @@ -281,15 +282,16 @@ impl Installer { ("$LUKS_PASSFILE", LUKS_PASSPHRASE_FILE), ])?; - util::remove_file(LUKS_PASSPHRASE_FILE) + util::remove_file(LUKS_PASSPHRASE_FILE)?; + Ok(()) } - pub fn setup_lvm(&self) -> Result<()> { + pub fn setup_lvm(&self) -> Result<(), Box> { self.header("Setting up LVM volumes")?; self.cmd_list(LVM_COMMANDS, &[]) } - pub fn setup_boot(&self) -> Result<()> { + pub fn setup_boot(&self) -> Result<(), Box> { self.header("Setting up /boot partition")?; let boot_partition = self.target_partition(1); self.cmd(format!("/sbin/mkfs.vfat -F 32 {}", boot_partition))?; @@ -323,11 +325,11 @@ impl Installer { Ok(()) } - fn setup_syslinux(&self) -> Result<()> { + fn setup_syslinux(&self) -> Result<(), Box> { self.header("Installing syslinux")?; let syslinux_src = self.artifact_path("syslinux"); if !syslinux_src.exists() { - bail!("no syslinux directory found in artifact directory, cannot install syslinux"); + panic!("no syslinux directory found in artifact directory, cannot install syslinux"); } let dst = Path::new(INSTALL_MOUNT).join("syslinux"); util::create_dir(&dst)?; @@ -345,17 +347,17 @@ impl Installer { self.cmd(format!("/sbin/extlinux --install {}", dst.display())) } - fn setup_syslinux_post_umount(&self) -> Result<()> { + fn setup_syslinux_post_umount(&self) -> Result<(), Box> { let mbrbin = self.artifact_path("syslinux/gptmbr.bin"); if !mbrbin.exists() { - bail!("could not find MBR image: {:?}", mbrbin); + panic!("could not find MBR image: {:?}", mbrbin); } self.cmd(format!("/bin/dd bs=440 count=1 conv=notrunc if={} of={}", mbrbin.display(), self.target().display()))?; self.cmd(format!("/sbin/parted -s {} set 1 legacy_boot on", self.target_str())) } - pub fn create_storage(&self) -> Result<()> { + pub fn create_storage(&self) -> Result<(), Box> { self.header("Setting up /storage partition")?; self.cmd_list(CREATE_STORAGE_COMMANDS, @@ -365,7 +367,7 @@ impl Installer { self.cmd(format!("/bin/umount {}", INSTALL_MOUNT)) } - fn setup_storage(&self) -> Result<()> { + fn setup_storage(&self) -> Result<(), Box> { if self._type == InstallType::Install { self.create_keyring()?; self.setup_storage_resources()?; @@ -389,33 +391,33 @@ impl Installer { Ok(()) } - fn create_keyring(&self) -> Result<()> { + fn create_keyring(&self) -> Result<(), Box> { self.info("Creating initial keyring")?; let keyring = KeyRing::create_new(); - keyring.write(self.storage().join("keyring"), self.passphrase.as_ref().unwrap()) + Ok(keyring.write(self.storage().join("keyring"), self.passphrase.as_ref().unwrap())?) } - - fn setup_base_realmfs(&self) -> Result<()> { + fn setup_base_realmfs(&self) -> Result<(), Box> { let realmfs_dir = self.storage().join("realms/realmfs-images"); util::create_dir(&realmfs_dir)?; self.sparse_copy_artifact("base-realmfs.img", &realmfs_dir)?; self.cmd(format!("/usr/bin/citadel-image decompress {}/base-realmfs.img", realmfs_dir.display())) } - fn setup_realm_skel(&self) -> Result<()> { + fn setup_realm_skel(&self) -> Result<(), Box> { let realm_skel = self.storage().join("realms/skel"); util::create_dir(&realm_skel)?; - util::copy_tree_with_chown(&self.skel(), &realm_skel, (1000,1000)) + util::copy_tree_with_chown(&self.skel(), &realm_skel, (1000, 1000))?; + Ok(()) } - fn create_realmlock(&self, dir: &Path) -> Result<()> { + fn create_realmlock(&self, dir: &Path) -> Result<(), Box> { fs::File::create(dir.join(".realmlock")) .map_err(context!("failed to create {:?}/.realmlock file", dir))?; Ok(()) } - fn setup_main_realm(&self) -> Result<()> { + fn setup_main_realm(&self) -> Result<(), Box> { self.header("Creating main realm")?; let realm = self.storage().join("realms/realm-main"); @@ -440,7 +442,7 @@ impl Installer { self.create_realmlock(&realm) } - fn setup_apt_cacher_realm(&self) -> Result<()> { + fn setup_apt_cacher_realm(&self) -> Result<(), Box> { self.header("Creating apt-cacher realm")?; let realm_base = self.storage().join("realms/realm-apt-cacher"); @@ -460,7 +462,7 @@ impl Installer { self.create_realmlock(&realm_base) } - fn setup_storage_resources(&self) -> Result<()> { + fn setup_storage_resources(&self) -> Result<(), Box> { let channel = match OsRelease::citadel_channel() { Some(channel) => channel, None => "dev", @@ -474,7 +476,7 @@ impl Installer { self.sparse_copy_artifact(&kernel_img, &resources) } - fn setup_citadel_passphrase(&self) -> Result<()> { + fn setup_citadel_passphrase(&self) -> Result<(), Box> { if self._type == InstallType::LiveSetup { self.info("Creating temporary citadel passphrase file for live mode")?; let path = self.storage().join("citadel-state/passwd"); @@ -497,17 +499,15 @@ impl Installer { Ok(()) } - pub fn install_rootfs_partitions(&self) -> Result<()> { + pub fn install_rootfs_partitions(&self) -> Result<(), Box> { self.header("Installing rootfs partitions")?; let rootfs = self.artifact_path("citadel-rootfs.img"); self.cmd(format!("/usr/bin/citadel-image install-rootfs --skip-sha {}", rootfs.display()))?; self.cmd(format!("/usr/bin/citadel-image install-rootfs --skip-sha --no-prefer {}", rootfs.display())) } - pub fn finish_install(&self) -> Result<()> { - self.cmd_list(FINISH_COMMANDS, &[ - ("$TARGET", self.target_str()) - ]) + pub fn finish_install(&self) -> Result<(), Box> { + self.cmd_list(FINISH_COMMANDS, &[("$TARGET", self.target_str())]) } fn global_realm_config(&self) -> &str { @@ -546,16 +546,33 @@ impl Installer { Path::new(&self.artifact_directory).join(filename) } - fn copy_artifact>(&self, filename: &str, target: P) -> Result<()> { + fn copy_artifact>( + &self, + filename: &str, + target: P, + ) -> Result<(), Box> { self._copy_artifact(filename, target, false) } - fn sparse_copy_artifact>(&self, filename: &str, target: P) -> Result<()> { + fn sparse_copy_artifact>( + &self, + filename: &str, + target: P, + ) -> Result<(), Box> { self._copy_artifact(filename, target, true) } - fn _copy_artifact>(&self, filename: &str, target: P, sparse: bool) -> Result<()> { - self.info(format!("Copying {} to {}", filename, target.as_ref().display()))?; + fn _copy_artifact>( + &self, + filename: &str, + target: P, + sparse: bool, + ) -> Result<(), Box> { + self.info(format!( + "Copying {} to {}", + filename, + target.as_ref().display() + ))?; let src = self.artifact_path(filename); let target = target.as_ref(); util::create_dir(target)?; @@ -568,20 +585,19 @@ impl Installer { Ok(()) } - fn header>(&self, s: S) -> Result<()> { + fn header>(&self, s: S) -> Result<(), Box> { self.output(format!("\n[+] {}\n", s.as_ref())) } - fn info>(&self, s: S) -> Result<()> { + fn info>(&self, s: S) -> Result<(), Box> { self.output(format!(" [>] {}", s.as_ref())) } - - fn output>(&self, s: S) -> Result<()> { - self.write_output(s.as_ref()).map_err(context!("error writing output")) + fn output>(&self, s: S) -> Result<(), Box> { + self.write_output(s.as_ref()) } - fn write_output(&self, s: &str) -> io::Result<()> { + fn write_output(&self, s: &str) -> Result<(), Box> { println!("{}", s); io::stdout().flush()?; @@ -592,7 +608,11 @@ impl Installer { Ok(()) } - fn cmd_list, S: AsRef>(&self, cmd_lines: I, subs: &[(&str,&str)]) -> Result<()> { + fn cmd_list, S: AsRef>( + &self, + cmd_lines: I, + subs: &[(&str, &str)], + ) -> Result<(), Box> { for line in cmd_lines { let line = line.as_ref(); let line = subs.iter().fold(line.to_string(), |acc, (from,to)| acc.replace(from,to)); @@ -602,12 +622,12 @@ impl Installer { Ok(()) } - fn cmd>(&self, args: S) -> Result<()> { + fn cmd>(&self, args: S) -> Result<(), Box> { let args: Vec<&str> = args.as_ref().split_whitespace().collect::>(); self.run_cmd(args, false) } - fn run_cmd(&self, args: Vec<&str>, as_user: bool) -> Result<()> { + fn run_cmd(&self, args: Vec<&str>, as_user: bool) -> Result<(), Box> { self.output(format!(" # {}", args.join(" ")))?; let mut command = Command::new(args[0]); @@ -632,8 +652,8 @@ impl Installer { if !result.status.success() { match result.status.code() { - Some(code) => bail!("command {} failed with exit code: {}", args[0], code), - None => bail!("command {} failed with no exit code", args[0]), + Some(code) => panic!("command {} failed with exit code: {}", args[0], code), + None => panic!("command {} failed with no exit code", args[0]), } } Ok(()) diff --git a/citadel-tool/src/install/mod.rs b/citadel-tool/src/install/mod.rs index 5a39656..7a1f39f 100644 --- a/citadel-tool/src/install/mod.rs +++ b/citadel-tool/src/install/mod.rs @@ -4,7 +4,7 @@ pub(crate) mod installer; mod cli; mod disk; -pub fn main(args: Vec) { +pub fn main(args: Vec) -> Result<(), Box> { let mut args = args.iter().skip(1); let result = if let Some(dev) = args.next() { cli::run_cli_install_with(dev) @@ -17,10 +17,11 @@ pub fn main(args: Vec) { Err(ref err) => { println!("Install failed: {}", err); exit(1); - }, + } }; if !ok { println!("Install cancelled..."); } -} + Ok(()) +} diff --git a/citadel-tool/src/install_backend/dbus.rs b/citadel-tool/src/install_backend/dbus.rs index 6247d91..a08e5cf 100644 --- a/citadel-tool/src/install_backend/dbus.rs +++ b/citadel-tool/src/install_backend/dbus.rs @@ -7,7 +7,6 @@ use std::sync::mpsc::{Sender}; use dbus::tree::{self, Factory, MTFn, MethodResult, Tree}; use dbus::{Message}; use dbus::blocking::LocalConnection; -use libcitadel::{Result}; // Use local version of disk.rs since we added some methods use crate::install_backend::disk::*; use crate::install::installer::*; @@ -15,7 +14,6 @@ use std::fmt; type MethodInfo<'a> = tree::MethodInfo<'a, MTFn, TData>; - const OBJECT_PATH: &str = "/com/subgraph/installer"; const INTERFACE_NAME: &str = "com.subgraph.installer.Manager"; const BUS_NAME: &str = "com.subgraph.installer"; @@ -37,8 +35,7 @@ pub struct DbusServer { } impl DbusServer { - - pub fn connect() -> Result { + pub fn connect() -> Result> { let connection = LocalConnection::new_system() .map_err(|e| format_err!("Failed to connect to DBUS system bus: {}", e))?; let connection = Arc::new(connection); @@ -80,7 +77,7 @@ impl DbusServer { Ok(vec![m.msg.method_return().append1(list)]) } - fn run_install(path: String, citadel_passphrase: String, luks_passphrase: String, sender: Sender) -> Result<()> { + fn run_install(path: String, citadel_passphrase: String, luks_passphrase: String, sender: Sender) -> Result<(), Box> { let mut install = Installer::new(path, &citadel_passphrase, &luks_passphrase); install.set_install_syslinux(true); install.verify()?; @@ -174,12 +171,12 @@ impl DbusServer { Message::signal(&path, &iface, &member).append1(text) } - pub fn start(&self) -> Result<()> { - let (sender, receiver) = mpsc::channel::(); + pub fn start(&self) -> Result<(), Box> { + let (sender, receiver) = mpsc::channel::(); let sender_clone = sender.clone(); let tree = self.build_tree(sender); if let Err(_err) = self.connection.request_name(BUS_NAME, false, true, false) { - bail!("Failed to request name"); + panic!("Failed to request name"); } tree.start_receive(self.connection.as_ref()); @@ -231,7 +228,6 @@ impl DbusServer { } } } - } #[derive(Clone)] @@ -243,7 +239,6 @@ impl TreeData { TreeData {} } - fn disks(&self) -> HashMap> { let disks = Disk::probe_all().unwrap(); @@ -257,7 +252,6 @@ impl TreeData { } disk_map } - } impl fmt::Debug for TreeData { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/citadel-tool/src/install_backend/mod.rs b/citadel-tool/src/install_backend/mod.rs index 7ba77f6..f000d8a 100644 --- a/citadel-tool/src/install_backend/mod.rs +++ b/citadel-tool/src/install_backend/mod.rs @@ -1,24 +1,20 @@ -use libcitadel::Result; use std::process::exit; mod disk; mod dbus; use libcitadel::CommandLine; -pub fn main() { +pub fn main() -> Result<(), Box> { if CommandLine::install_mode() { - if let Err(e) = run_dbus_server() { - warn!("Error: {}", e); - } + run_dbus_server() } else { println!("Citadel installer backend will only run in install or live mode"); exit(1); } } -fn run_dbus_server() -> Result<()> { +fn run_dbus_server() -> Result<(), Box> { let server = dbus::DbusServer::connect()?; server.start()?; Ok(()) } - diff --git a/citadel-tool/src/main.rs b/citadel-tool/src/main.rs index b07feda..2f29664 100644 --- a/citadel-tool/src/main.rs +++ b/citadel-tool/src/main.rs @@ -17,42 +17,37 @@ mod realmfs; mod sync; mod update; -fn main() { - let exe = match env::current_exe() { - Ok(path) => path, - Err(_e) => { - return; - }, - }; +fn main() -> Result<(), Box> { + let exe = env::current_exe()?; let args = env::args().collect::>(); if exe == Path::new("/usr/libexec/citadel-boot") { - boot::main(args); + boot::main(args) } else if exe == Path::new("/usr/libexec/citadel-install") { - install::main(args); + install::main(args) } else if exe == Path::new("/usr/libexec/citadel-install-backend") { - install_backend::main(); + install_backend::main() } else if exe == Path::new("/usr/bin/citadel-image") { - image::main(args); + image::main(args) } else if exe == Path::new("/usr/bin/citadel-realmfs") { - realmfs::main(args); + realmfs::main(args) } else if exe == Path::new("/usr/bin/citadel-update") { - update::main(args); + update::main(args) } else if exe == Path::new("/usr/libexec/citadel-desktop-sync") { - sync::main(args); + sync::main(args) } else if exe == Path::new("/usr/libexec/citadel-run") { - do_citadel_run(args); + do_citadel_run(args) } else if exe.file_name() == Some(OsStr::new("citadel-mkimage")) { - mkimage::main(args); + mkimage::main(args) } else if exe.file_name() == Some(OsStr::new("citadel-tool")) { - dispatch_command(args); + dispatch_command(args) } else { - println!("Error: unknown executable {}", exe.display()); + Result::Err(format!("Error: unknown executable {}", exe.display()).into()) } } -fn dispatch_command(args: Vec) { +fn dispatch_command(args: Vec) -> Result<(), Box> { if let Some(command) = args.get(1) { match command.as_str() { "boot" => boot::main(rebuild_args("citadel-boot", args)), @@ -63,22 +58,33 @@ fn dispatch_command(args: Vec) { "mkimage" => mkimage::main(rebuild_args("citadel-mkimage", args)), "sync" => sync::main(rebuild_args("citadel-desktop-sync", args)), "run" => do_citadel_run(rebuild_args("citadel-run", args)), - _ => println!("Error: unknown command {}", command), + _ => throw_err(command), } } else { - println!("Must provide an argument"); + Result::Err("Must provide an argument".into()) } } +fn throw_err(command: &String) -> Result<(), Box> { + Result::Err(format!("Error: unknown command {}", command).into()) +} + fn rebuild_args(command: &str, args: Vec) -> Vec { iter::once(command.to_string()) .chain(args.into_iter().skip(2)) .collect() } -fn do_citadel_run(args: Vec) { +fn do_citadel_run(args: Vec) -> Result<(), Box> { if let Err(e) = RealmManager::run_in_current(&args[1..], true) { - println!("RealmManager::run_in_current({:?}) failed: {}", &args[1..], e); + return Result::Err( + format!( + "RealmManager::run_in_current({:?}) failed: {}", + &args[1..], + e + ) + .into(), + ); } + Ok(()) } - diff --git a/citadel-tool/src/mkimage/mod.rs b/citadel-tool/src/mkimage/mod.rs index 0efa3cb..34244e1 100644 --- a/citadel-tool/src/mkimage/mod.rs +++ b/citadel-tool/src/mkimage/mod.rs @@ -1,13 +1,10 @@ use std::process::exit; -use libcitadel::Result; - mod config; mod build; -pub fn main(args: Vec) { - +pub fn main(args: Vec) -> Result<(), Box> { let config_path = match args.get(1) { Some(arg) => arg, None => { @@ -21,11 +18,11 @@ pub fn main(args: Vec) { exit(1); } - + Ok(()) } -fn build_image(config_path: &str) -> Result<()> { +fn build_image(config_path: &str) -> Result<(), Box> { let conf = config::BuildConfig::load(config_path)?; let mut builder = build::UpdateBuilder::new(conf); - builder.build() -} \ No newline at end of file + Ok(builder.build()?) +} diff --git a/citadel-tool/src/realmfs/mod.rs b/citadel-tool/src/realmfs/mod.rs index 376b04b..4a23af3 100644 --- a/citadel-tool/src/realmfs/mod.rs +++ b/citadel-tool/src/realmfs/mod.rs @@ -1,16 +1,14 @@ use clap::App; use clap::ArgMatches; -use libcitadel::{Result,RealmFS,Logger,LogLevel}; +use libcitadel::{RealmFS, Logger, LogLevel}; use libcitadel::util::is_euid_root; use clap::SubCommand; use clap::AppSettings::*; use clap::Arg; use libcitadel::ResizeSize; -use std::process::exit; - -pub fn main(args: Vec) { +pub fn main(args: Vec) -> Result<(), Box> { Logger::set_log_level(LogLevel::Debug); let app = App::new("citadel-realmfs") @@ -83,18 +81,15 @@ is the final absolute size of the image.") ("activate", Some(m)) => activate(m), ("deactivate", Some(m)) => deactivate(m), _ => image_info(&matches), - }; + }?; - if let Err(ref e) = result { - eprintln!("Error: {}", e); - exit(1); - } + Ok(()) } -fn realmfs_image(arg_matches: &ArgMatches) -> Result { +fn realmfs_image(arg_matches: &ArgMatches) -> Result> { let image = match arg_matches.value_of("image") { Some(s) => s, - None => bail!("Image argument required."), + None => panic!("Image argument required."), }; let realmfs = if RealmFS::is_valid_name(image) { @@ -102,93 +97,100 @@ fn realmfs_image(arg_matches: &ArgMatches) -> Result { } else if RealmFS::is_valid_realmfs_image(image) { RealmFS::load_from_path(image)? } else { - bail!("Not a valid realmfs name or path to realmfs image file: {}", image); + panic!( + "Not a valid realmfs name or path to realmfs image file: {}", + image + ); }; Ok(realmfs) } -fn image_info(arg_matches: &ArgMatches) -> Result<()> { +fn image_info(arg_matches: &ArgMatches) -> Result<(), Box> { let img = realmfs_image(arg_matches)?; print!("{}", String::from_utf8(img.header().metainfo_bytes())?); Ok(()) } -fn parse_resize_size(s: &str) -> Result { +fn parse_resize_size(s: &str) -> Result> { let unit = s.chars().last().filter(|c| c.is_alphabetic()); let skip = if s.starts_with('+') { 1 } else { 0 }; - let size = s.chars() + let size = s + .chars() .skip(skip) .take_while(|c| c.is_numeric()) .collect::() .parse::() - .map_err(|_| format_err!("Unable to parse size value '{}'",s))?; + .map_err(|_| format_err!("Unable to parse size value '{}'", s))?; let sz = match unit { Some('g') | Some('G') => ResizeSize::gigs(size), Some('m') | Some('M') => ResizeSize::megs(size), - Some(c) => bail!("Unknown size unit '{}'", c), + Some(c) => panic!("Unknown size unit '{}'", c), None => ResizeSize::blocks(size), }; Ok(sz) } -fn resize(arg_matches: &ArgMatches) -> Result<()> { +fn resize(arg_matches: &ArgMatches) -> Result<(), Box> { let img = realmfs_image(arg_matches)?; info!("image is {}", img.path().display()); let size_arg = match arg_matches.value_of("size") { Some(size) => size, None => "No size argument", - }; info!("Size is {}", size_arg); let mode_add = size_arg.starts_with('+'); let size = parse_resize_size(size_arg)?; if mode_add { - img.resize_grow_by(size) + img.resize_grow_by(size)?; } else { - img.resize_grow_to(size) + img.resize_grow_to(size)?; } + Ok(()) } -fn autoresize(arg_matches: &ArgMatches) -> Result<()> { +fn autoresize(arg_matches: &ArgMatches) -> Result<(), Box> { let img = realmfs_image(arg_matches)?; if let Some(size) = img.auto_resize_size() { - img.resize_grow_to(size) + img.resize_grow_to(size)?; } else { - info!("RealmFS image {} has sufficient free space, doing nothing", img.path().display()); - Ok(()) + info!( + "RealmFS image {} has sufficient free space, doing nothing", + img.path().display() + ); } + Ok(()) } -fn fork(arg_matches: &ArgMatches) -> Result<()> { +fn fork(arg_matches: &ArgMatches) -> Result<(), Box> { let img = realmfs_image(arg_matches)?; let forkname = match arg_matches.value_of("forkname") { Some(name) => name, - None => bail!("No fork name argument"), + None => panic!("No fork name argument"), }; if !RealmFS::is_valid_name(forkname) { - bail!("Not a valid RealmFS image name '{}'", forkname); + panic!("Not a valid RealmFS image name '{}'", forkname); } if RealmFS::named_image_exists(forkname) { - bail!("A RealmFS image named '{}' already exists", forkname); + panic!("A RealmFS image named '{}' already exists", forkname); } img.fork(forkname)?; Ok(()) } -fn update(arg_matches: &ArgMatches) -> Result<()> { +fn update(arg_matches: &ArgMatches) -> Result<(), Box> { if !is_euid_root() { - bail!("RealmFS updates must be run as root"); + panic!("RealmFS updates must be run as root"); } let img = realmfs_image(arg_matches)?; img.interactive_update(Some("icy"))?; Ok(()) } -fn activate(arg_matches: &ArgMatches) -> Result<()> { +fn activate(arg_matches: &ArgMatches) -> Result<(), Box> { let img = realmfs_image(arg_matches)?; let img_arg = arg_matches.value_of("image").unwrap(); @@ -201,7 +203,7 @@ fn activate(arg_matches: &ArgMatches) -> Result<()> { Ok(()) } -fn deactivate(arg_matches: &ArgMatches) -> Result<()> { +fn deactivate(arg_matches: &ArgMatches) -> Result<(), Box> { let img = realmfs_image(arg_matches)?; let img_arg = arg_matches.value_of("image").unwrap(); if !img.is_activated() { diff --git a/citadel-tool/src/sync/desktop_sync.rs b/citadel-tool/src/sync/desktop_sync.rs index e7b889b..cd39b0b 100644 --- a/citadel-tool/src/sync/desktop_sync.rs +++ b/citadel-tool/src/sync/desktop_sync.rs @@ -1,9 +1,9 @@ use std::collections::HashSet; use std::ffi::OsStr; -use std::path::{Path,PathBuf}; +use std::path::{Path, PathBuf}; use std::time::SystemTime; -use libcitadel::{Realm, Realms, Result, util}; +use libcitadel::{Realm, Realms, util}; use crate::sync::parser::DesktopFileParser; use std::fs::DirEntry; use crate::sync::desktop_file::DesktopFile; @@ -17,14 +17,13 @@ pub struct DesktopFileSync { icons: Option, } -#[derive(Eq,PartialEq,Hash)] +#[derive(Eq, PartialEq, Hash)] struct DesktopItem { path: PathBuf, mtime: SystemTime, } impl DesktopItem { - fn new(path: PathBuf, mtime: SystemTime) -> Self { DesktopItem { path, mtime } } @@ -46,7 +45,7 @@ impl DesktopItem { impl DesktopFileSync { pub const CITADEL_APPLICATIONS: &'static str = "/home/citadel/.local/share/applications"; - pub fn sync_active_realms() -> Result<()> { + pub fn sync_active_realms() -> Result<(), Box> { let realms = Realms::load()?; for realm in realms.active(true) { let mut sync = DesktopFileSync::new(realm); @@ -72,7 +71,7 @@ impl DesktopFileSync { DesktopFileSync { realm, items: HashSet::new(), icons } } - pub fn run_sync(&mut self, clear: bool) -> Result<()> { + pub fn run_sync(&mut self, clear: bool) -> Result<(), Box> { IconSync::ensure_theme_index_exists()?; @@ -98,7 +97,7 @@ impl DesktopFileSync { Ok(()) } - fn collect_source_files(&mut self, directory: impl AsRef) -> Result<()> { + fn collect_source_files(&mut self, directory: impl AsRef) -> Result<(), Box> { let mut directory = Realms::current_realm_symlink().join(directory.as_ref()); directory.push("share/applications"); if directory.exists() { @@ -119,16 +118,16 @@ impl DesktopFileSync { } } - pub fn clear_target_files() -> Result<()> { - util::read_directory(Self::CITADEL_APPLICATIONS, |dent| { + pub fn clear_target_files() -> Result<(), Box> { + Ok(util::read_directory(Self::CITADEL_APPLICATIONS, |dent| { util::remove_file(dent.path()) - }) + })?) } - fn remove_missing_target_files(&mut self) -> Result<()> { + fn remove_missing_target_files(&mut self) -> Result<(), Box> { let sources = self.source_filenames(); let prefix = format!("realm-{}.", self.realm.name()); - util::read_directory(Self::CITADEL_APPLICATIONS, |dent| { + Ok(util::read_directory(Self::CITADEL_APPLICATIONS, |dent| { if let Some(filename) = dent.file_name().to_str() { if filename.starts_with(&prefix) && !sources.contains(filename) { let path = dent.path(); @@ -137,7 +136,7 @@ impl DesktopFileSync { } } Ok(()) - }) + })?) } fn mtime(path: &Path) -> Option { @@ -156,7 +155,7 @@ impl DesktopFileSync { .collect() } - fn synchronize_items(&self) -> Result<()> { + fn synchronize_items(&self) -> Result<(), Box> { for item in &self.items { let target = Path::new(Self::CITADEL_APPLICATIONS).join(item.filename()); if item.is_newer_than(&target) { @@ -180,7 +179,7 @@ impl DesktopFileSync { } } - fn sync_item(&self, item: &DesktopItem) -> Result<()> { + fn sync_item(&self, item: &DesktopItem) -> Result<(), Box> { let mut dfp = DesktopFileParser::parse_from_path(&item.path, "/usr/libexec/citadel-run ")?; if dfp.is_showable() { self.sync_item_icon(&mut dfp); diff --git a/citadel-tool/src/sync/mod.rs b/citadel-tool/src/sync/mod.rs index 6956027..587347a 100644 --- a/citadel-tool/src/sync/mod.rs +++ b/citadel-tool/src/sync/mod.rs @@ -1,4 +1,4 @@ -use libcitadel::{Result, Logger, LogLevel}; +use libcitadel::{Logger, LogLevel}; mod desktop_file; mod parser; @@ -19,8 +19,7 @@ pub const REALM_BASE_PATHS:&[&str] = &[ "home/.local/share/flatpak/exports" ]; -pub fn main(args: Vec) { - +pub fn main(args: Vec) -> Result<(), Box> { if has_arg(&args, "-v") { Logger::set_log_level(LogLevel::Debug); } else { @@ -37,12 +36,14 @@ pub fn main(args: Vec) { println!("Desktop file sync failed: {}", e); } } + Ok(()) } -fn sync(clear: bool) -> Result<()> { +fn sync(clear: bool) -> Result<(), Box> { if let Some(mut sync) = DesktopFileSync::new_current() { - sync.run_sync(clear) + sync.run_sync(clear)? } else { - DesktopFileSync::clear_target_files() + DesktopFileSync::clear_target_files()? } + Ok(()) } diff --git a/citadel-tool/src/update/mod.rs b/citadel-tool/src/update/mod.rs index 69844ae..2e8307d 100644 --- a/citadel-tool/src/update/mod.rs +++ b/citadel-tool/src/update/mod.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use libcitadel::{Result, Partition, ResourceImage, ImageHeader, LogLevel, Logger, util}; +use libcitadel::{Partition, ResourceImage, ImageHeader, LogLevel, Logger, util}; use crate::update::kernel::{KernelInstaller, KernelVersion}; use std::collections::HashSet; use std::fs::{DirEntry, File}; @@ -16,7 +16,7 @@ const FLAG_QUIET: u32 = 0x04; const RESOURCES_DIRECTORY: &str = "/storage/resources"; const TEMP_DIRECTORY: &str = "/storage/resources/tmp"; -pub fn main(args: Vec) { +pub fn main(args: Vec) -> std::result::Result<(), Box> { let mut args = args.iter().skip(1); let mut flags = 0; @@ -34,7 +34,7 @@ pub fn main(args: Vec) { Logger::set_log_level(LogLevel::Debug); } else if arg == "--choose-rootfs" { let _ = choose_install_partition(true); - return; + return Ok(()) } else { let path = Path::new(arg); if let Err(e) = install_image(path, flags) { @@ -42,12 +42,13 @@ pub fn main(args: Vec) { } } } + Ok(()) } // Search directory containing installed image files for an // image file that has an identical shasum and abort the installation // if a duplicate is found. -fn detect_duplicates(header: &ImageHeader) -> Result<()> { +fn detect_duplicates(header: &ImageHeader) -> Result<(), Box> { let metainfo = header.metainfo(); let channel = metainfo.channel(); let shasum = metainfo.shasum(); @@ -61,17 +62,20 @@ fn detect_duplicates(header: &ImageHeader) -> Result<()> { return Ok(()) } - util::read_directory(&resource_dir, |dent| { + Ok(util::read_directory(&resource_dir, |dent| { if let Ok(hdr) = ImageHeader::from_file(dent.path()) { if hdr.metainfo().shasum() == shasum { - bail!("A duplicate image file with the same shasum already exists at {}", dent.path().display()); + panic!( + "A duplicate image file with the same shasum already exists at {}", + dent.path().display() + ); } } Ok(()) - }) + })?) } -fn create_tmp_copy(path: &Path) -> Result { +fn create_tmp_copy(path: &Path) -> Result> { if !Path::new(TEMP_DIRECTORY).exists() { util::create_dir(TEMP_DIRECTORY)?; } @@ -93,12 +97,12 @@ fn create_tmp_copy(path: &Path) -> Result { Ok(path) } -fn install_image(path: &Path, flags: u32) -> Result<()> { +fn install_image(path: &Path, flags: u32) -> Result<(), Box> { if !path.exists() || path.file_name().is_none() { - bail!("file path {} does not exist", path.display()); + panic!("file path {} does not exist", path.display()); } if !util::is_euid_root() { - bail!("Image updates must be installed by root user"); + panic!("Image updates must be installed by root user"); } let header = ImageHeader::from_file(path)?; @@ -113,14 +117,14 @@ fn install_image(path: &Path, flags: u32) -> Result<()> { match image.metainfo().image_type() { "kernel" => install_kernel_image(&mut image), "extra" => install_extra_image(&image), - "rootfs" => install_rootfs_image(&image, flags), - image_type => bail!("Unknown image type: {}", image_type), + "rootfs" => install_rootfs_image(&image, flags), + image_type => panic!("Unknown image type: {}", image_type), } } // Prepare the image file for installation by decompressing and generating // dmverity hash tree. -fn prepare_image(image: &ResourceImage, flags: u32) -> Result<()> { +fn prepare_image(image: &ResourceImage, flags: u32) -> Result<(), Box> { if image.is_compressed() { image.decompress(false)?; } @@ -129,7 +133,7 @@ fn prepare_image(image: &ResourceImage, flags: u32) -> Result<()> { info!("Verifying sha256 hash of image"); let shasum = image.generate_shasum()?; if shasum != image.metainfo().shasum() { - bail!("image file does not have expected sha256 value"); + panic!("image file does not have expected sha256 value"); } } @@ -139,24 +143,28 @@ fn prepare_image(image: &ResourceImage, flags: u32) -> Result<()> { Ok(()) } -fn install_extra_image(image: &ResourceImage) -> Result<()> { +fn install_extra_image(image: &ResourceImage) -> Result<(), Box> { let filename = format!("citadel-extra-{:03}.img", image.header().metainfo().version()); install_image_file(image, filename.as_str())?; remove_old_extra_images(image)?; Ok(()) } -fn remove_old_extra_images(image: &ResourceImage) -> Result<()> { +fn remove_old_extra_images(image: &ResourceImage) -> Result<(), Box> { let new_meta = image.header().metainfo(); let shasum = new_meta.shasum(); let target_dir = target_directory(image)?; - util::read_directory(&target_dir, |dent| { + Ok(util::read_directory(&target_dir, |dent| { let path = dent.path(); - maybe_remove_old_extra_image(&path, shasum) - }) + maybe_remove_old_extra_image(&path, shasum).unwrap(); + Ok(()) + })?) } -fn maybe_remove_old_extra_image(path: &Path, shasum: &str) -> Result<()> { +fn maybe_remove_old_extra_image( + path: &Path, + shasum: &str, +) -> Result<(), Box> { let header = ImageHeader::from_file(&path)?; if !header.is_magic_valid() { return Ok(()); @@ -172,16 +180,16 @@ fn maybe_remove_old_extra_image(path: &Path, shasum: &str) -> Result<()> { Ok(()) } -fn install_kernel_image(image: &mut ResourceImage) -> Result<()> { +fn install_kernel_image(image: &mut ResourceImage) -> Result<(), Box> { if !Path::new("/boot/loader/loader.conf").exists() { - bail!("failed to automount /boot partition. Please manually mount correct partition."); + panic!("failed to automount /boot partition. Please manually mount correct partition."); } let metainfo = image.header().metainfo(); let version = metainfo.version(); let kernel_version = match metainfo.kernel_version() { Some(kv) => kv, - None => bail!("kernel image does not have kernel version field"), + None => panic!("kernel image does not have kernel version field"), }; info!("kernel version is {}", kernel_version); install_kernel_file(image, &kernel_version)?; @@ -194,7 +202,7 @@ fn install_kernel_image(image: &mut ResourceImage) -> Result<()> { let mut remove_paths = Vec::new(); util::read_directory(&image_dir, |dent| { let path = dent.path(); - if is_unused_kernel_image(&path, &all_versions)? { + if is_unused_kernel_image(&path, &all_versions).unwrap() { remove_paths.push(path); } Ok(()) @@ -206,7 +214,7 @@ fn install_kernel_image(image: &mut ResourceImage) -> Result<()> { Ok(()) } -fn is_unused_kernel_image(path: &Path, versions: &HashSet) -> Result { +fn is_unused_kernel_image(path: &Path, versions: &HashSet) -> Result> { let header = ImageHeader::from_file(path)?; if !header.is_magic_valid() { return Ok(false); @@ -226,23 +234,25 @@ fn is_unused_kernel_image(path: &Path, versions: &HashSet) -> Result Result<()> { +fn install_kernel_file( + image: &mut ResourceImage, + kernel_version: &str, +) -> Result<(), Box> { let mountpoint = Path::new("/run/citadel/images/kernel-install.mountpoint"); info!("Temporarily mounting kernel resource image"); let mut handle = image.mount_at(mountpoint)?; let kernel_path = mountpoint.join("kernel/bzImage"); if !kernel_path.exists() { handle.unmount()?; - bail!("kernel not found in kernel resource image at /kernel/bzImage") + panic!("kernel not found in kernel resource image at /kernel/bzImage") } - let result = KernelInstaller::install_kernel(&kernel_path, kernel_version); + KernelInstaller::install_kernel(&kernel_path, kernel_version)?; info!("Unmounting kernel resource image"); - handle.unmount()?; - result + Ok(handle.unmount()?) } -fn all_boot_kernel_versions() -> Result> { +fn all_boot_kernel_versions() -> Result, Box> { let mut result = HashSet::new(); util::read_directory("/boot", |dent| { if is_kernel_dirent(&dent) { @@ -264,7 +274,10 @@ fn is_kernel_dirent(dirent: &DirEntry) -> bool { } } -fn install_image_file(image: &ResourceImage, filename: &str) -> Result<()> { +fn install_image_file( + image: &ResourceImage, + filename: &str, +) -> Result<(), Box> { let image_dir = target_directory(image)?; let image_dest = image_dir.join(filename); if image_dest.exists() { @@ -275,14 +288,14 @@ fn install_image_file(image: &ResourceImage, filename: &str) -> Result<()> { Ok(()) } -fn target_directory(image: &ResourceImage) -> Result { +fn target_directory(image: &ResourceImage) -> Result> { let metainfo = image.header().metainfo(); let channel = metainfo.channel(); validate_channel_name(channel)?; Ok(Path::new("/storage/resources").join(channel)) } -fn rotate(path: &Path) -> Result<()> { +fn rotate(path: &Path) -> Result<(), Box> { if !path.exists() || path.file_name().is_none() { return Ok(()); } @@ -293,14 +306,17 @@ fn rotate(path: &Path) -> Result<()> { Ok(()) } -fn validate_channel_name(channel: &str) -> Result<()> { +fn validate_channel_name(channel: &str) -> Result<(), Box> { if !channel.chars().all(|c| c.is_ascii_lowercase()) { - bail!("image has invalid channel name '{}'", channel); + panic!("image has invalid channel name '{}'", channel); } Ok(()) } -fn install_rootfs_image(image: &ResourceImage, flags: u32) -> Result<()> { +fn install_rootfs_image( + image: &ResourceImage, + flags: u32, +) -> Result<(), Box> { let quiet = flags & FLAG_QUIET != 0; let partition = choose_install_partition(!quiet)?; @@ -315,7 +331,7 @@ fn install_rootfs_image(image: &ResourceImage, flags: u32) -> Result<()> { Ok(()) } -fn clear_prefer_boot() -> Result<()> { +fn clear_prefer_boot() -> Result<(), Box> { for mut p in Partition::rootfs_partitions()? { if p.is_initialized() && p.header().has_flag(ImageHeader::FLAG_PREFER_BOOT) { p.clear_flag_and_write(ImageHeader::FLAG_PREFER_BOOT)?; @@ -332,7 +348,7 @@ fn bool_to_yesno(val: bool) -> &'static str { } } -fn choose_install_partition(verbose: bool) -> Result { +fn choose_install_partition(verbose: bool) -> Result> { let partitions = Partition::rootfs_partitions()?; if verbose { @@ -362,5 +378,5 @@ fn choose_install_partition(verbose: bool) -> Result { return Ok(p.clone()) } } - bail!("no suitable install partition found") + panic!("no suitable install partition found") }