diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 01bc9217..9ccee100 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -53,9 +53,11 @@ similar-asserts = { workspace = true } static_assertions = { workspace = true } [features] -default = ["install"] -# This feature enables `bootc install`. Disable if you always want to use an external installer. -install = [] +default = ["install-to-disk"] +# This feature enables `bootc install to-disk`, which is considered just a "demo" +# or reference installer; we expect most nontrivial use cases to be using +# `bootc install to-filesystem`. +install-to-disk = [] # This featuares enables `bootc internals publish-rhsm-facts` to integrate with # Red Hat Subscription Manager rhsm = [] diff --git a/lib/src/blockdev.rs b/lib/src/blockdev.rs index c086868d..d4b4ed65 100644 --- a/lib/src/blockdev.rs +++ b/lib/src/blockdev.rs @@ -1,15 +1,20 @@ use std::collections::HashMap; +#[cfg(feature = "install-to-disk")] use std::env; +#[cfg(feature = "install-to-disk")] use std::path::Path; use std::process::Command; use std::sync::OnceLock; use anyhow::{anyhow, Context, Result}; -use camino::{Utf8Path, Utf8PathBuf}; +use camino::Utf8Path; +#[cfg(feature = "install-to-disk")] +use camino::Utf8PathBuf; use fn_error_context::context; use regex::Regex; use serde::Deserialize; +#[cfg(feature = "install-to-disk")] use crate::install::run_in_host_mountns; use crate::task::Task; use bootc_utils::CommandRunExt; @@ -47,6 +52,7 @@ impl Device { self.path.clone().unwrap_or(format!("/dev/{}", &self.name)) } + #[allow(dead_code)] pub(crate) fn has_children(&self) -> bool { self.children.as_ref().map_or(false, |v| !v.is_empty()) } @@ -86,6 +92,7 @@ impl Device { } #[context("Failed to wipe {dev}")] +#[cfg(feature = "install-to-disk")] pub(crate) fn wipefs(dev: &Utf8Path) -> Result<()> { Task::new_and_run( format!("Wiping device {dev}"), @@ -161,6 +168,7 @@ impl PartitionTable { } // Find the partition with the given offset (starting at 1) + #[allow(dead_code)] pub(crate) fn find_partno(&self, partno: u32) -> Result<&Partition> { let r = self .partitions @@ -171,6 +179,7 @@ impl PartitionTable { } impl Partition { + #[allow(dead_code)] pub(crate) fn path(&self) -> &Utf8Path { self.node.as_str().into() } @@ -185,10 +194,12 @@ pub(crate) fn partitions_of(dev: &Utf8Path) -> Result { Ok(o.partitiontable) } +#[cfg(feature = "install-to-disk")] pub(crate) struct LoopbackDevice { pub(crate) dev: Option, } +#[cfg(feature = "install-to-disk")] impl LoopbackDevice { // Create a new loopback block device targeting the provided file path. pub(crate) fn new(path: &Path) -> Result { @@ -243,6 +254,7 @@ impl LoopbackDevice { } } +#[cfg(feature = "install-to-disk")] impl Drop for LoopbackDevice { fn drop(&mut self) { // Best effort to unmount if we're dropped without invoking `close` @@ -250,6 +262,7 @@ impl Drop for LoopbackDevice { } } +#[cfg(feature = "install-to-disk")] pub(crate) fn udev_settle() -> Result<()> { // There's a potential window after rereading the partition table where // udevd hasn't yet received updates from the kernel, settle will return @@ -311,6 +324,7 @@ pub(crate) fn find_parent_devices(device: &str) -> Result> { } /// Parse a string into mibibytes +#[cfg(feature = "install-to-disk")] pub(crate) fn parse_size_mib(mut s: &str) -> Result { let suffixes = [ ("MiB", 1u64), diff --git a/lib/src/bootloader.rs b/lib/src/bootloader.rs index 2a696f1f..c079552a 100644 --- a/lib/src/bootloader.rs +++ b/lib/src/bootloader.rs @@ -7,8 +7,11 @@ use crate::task::Task; /// The name of the mountpoint for efi (as a subdirectory of /boot, or at the toplevel) pub(crate) const EFI_DIR: &str = "efi"; +#[cfg(feature = "install-to-disk")] pub(crate) const ESP_GUID: &str = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"; +#[cfg(feature = "install-to-disk")] pub(crate) const PREPBOOT_GUID: &str = "9E1A2D38-C612-4316-AA26-8B49521E5A8B"; +#[cfg(feature = "install-to-disk")] pub(crate) const PREPBOOT_LABEL: &str = "PowerPC-PReP-boot"; #[cfg(target_arch = "powerpc64")] /// We make a best-effort to support MBR partitioning too. diff --git a/lib/src/boundimage.rs b/lib/src/boundimage.rs index 24fe8cb9..20e744e7 100644 --- a/lib/src/boundimage.rs +++ b/lib/src/boundimage.rs @@ -10,7 +10,6 @@ use camino::Utf8Path; use cap_std_ext::cap_std::fs::Dir; use cap_std_ext::dirext::CapStdExtDirExt; use fn_error_context::context; -#[cfg(feature = "install")] use ostree_ext::containers_image_proxy; use ostree_ext::ostree::Deployment; @@ -33,7 +32,6 @@ pub(crate) struct BoundImage { } #[derive(Debug, PartialEq, Eq)] -#[cfg(feature = "install")] pub(crate) struct ResolvedBoundImage { pub(crate) image: String, pub(crate) digest: String, @@ -104,7 +102,6 @@ pub(crate) fn query_bound_images(root: &Dir) -> Result> { Ok(bound_images) } -#[cfg(feature = "install")] impl ResolvedBoundImage { #[context("resolving bound image {}", src.image)] pub(crate) async fn from_image(src: &BoundImage) -> Result { diff --git a/lib/src/cli.rs b/lib/src/cli.rs index c3b44189..78669edd 100644 --- a/lib/src/cli.rs +++ b/lib/src/cli.rs @@ -184,7 +184,6 @@ pub(crate) struct StatusOpts { pub(crate) booted: bool, } -#[cfg(feature = "install")] #[derive(Debug, clap::Subcommand, PartialEq, Eq)] pub(crate) enum InstallOpts { /// Install to the target block device. @@ -197,6 +196,7 @@ pub(crate) enum InstallOpts { /// in the container image, alongside any required system partitions such as /// the EFI system partition. Use `install to-filesystem` for anything more /// complex such as RAID, LVM, LUKS etc. + #[cfg(feature = "install-to-disk")] ToDisk(crate::install::InstallToDiskOpts), /// Install to an externally created filesystem structure. /// @@ -384,7 +384,6 @@ pub(crate) enum InternalsOpts { #[clap(allow_hyphen_values = true)] args: Vec, }, - #[cfg(feature = "install")] /// Invoked from ostree-ext to complete an installation. BootcInstallCompletion { /// Path to the sysroot @@ -525,7 +524,6 @@ pub(crate) enum Opt { /// An installation is not simply a copy of the container filesystem, but includes /// other setup and metadata. #[clap(subcommand)] - #[cfg(feature = "install")] Install(InstallOpts), /// Operations which can be executed as part of a container build. #[clap(subcommand)] @@ -537,7 +535,6 @@ pub(crate) enum Opt { #[clap(subcommand, hide = true)] Image(ImageOpts), /// Execute the given command in the host mount namespace - #[cfg(feature = "install")] #[clap(hide = true)] ExecInHostMountNamespace { #[clap(trailing_var_arg = true, allow_hyphen_values = true)] @@ -1053,8 +1050,8 @@ async fn run_from_opt(opt: Opt) -> Result<()> { } } }, - #[cfg(feature = "install")] Opt::Install(opts) => match opts { + #[cfg(feature = "install-to-disk")] InstallOpts::ToDisk(opts) => crate::install::install_to_disk(opts).await, InstallOpts::ToFilesystem(opts) => { crate::install::install_to_filesystem(opts, false).await @@ -1068,7 +1065,6 @@ async fn run_from_opt(opt: Opt) -> Result<()> { crate::install::completion::run_from_anaconda(rootfs).await } }, - #[cfg(feature = "install")] Opt::ExecInHostMountNamespace { args } => { crate::install::exec_in_host_mountns(args.as_slice()) } @@ -1104,7 +1100,6 @@ async fn run_from_opt(opt: Opt) -> Result<()> { let sysroot = get_storage().await?; crate::deploy::cleanup(&sysroot).await } - #[cfg(feature = "install")] InternalsOpts::BootcInstallCompletion { sysroot, stateroot } => { let rootfs = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?; crate::install::completion::run_from_ostree(rootfs, &sysroot, &stateroot).await diff --git a/lib/src/install.rs b/lib/src/install.rs index d591672b..20cd7108 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -6,6 +6,7 @@ // This sub-module is the "basic" installer that handles creating basic block device // and filesystem setup. +#[cfg(feature = "install-to-disk")] pub(crate) mod baseline; pub(crate) mod completion; pub(crate) mod config; @@ -40,9 +41,12 @@ use ostree_ext::oci_spec; use ostree_ext::ostree; use ostree_ext::prelude::Cast; use ostree_ext::sysroot::SysrootLock; -use rustix::fs::{FileTypeExt, MetadataExt as _}; +#[cfg(feature = "install-to-disk")] +use rustix::fs::FileTypeExt; +use rustix::fs::MetadataExt as _; use serde::{Deserialize, Serialize}; +#[cfg(feature = "install-to-disk")] use self::baseline::InstallBlockDeviceOpts; use crate::boundimage::{BoundImage, ResolvedBoundImage}; use crate::containerenv::ContainerExecutionInfo; @@ -57,6 +61,7 @@ use crate::utils::sigpolicy_from_opts; /// The toplevel boot directory const BOOT: &str = "boot"; /// Directory for transient runtime state +#[cfg(feature = "install-to-disk")] const RUN_BOOTC: &str = "/run/bootc"; /// The default path for the host rootfs const ALONGSIDE_ROOT_MOUNT: &str = "/target"; @@ -65,10 +70,8 @@ const LOST_AND_FOUND: &str = "lost+found"; /// The filename of the composefs EROFS superblock; TODO move this into ostree const OSTREE_COMPOSEFS_SUPER: &str = ".ostree.cfs"; /// The mount path for selinux -#[cfg(feature = "install")] const SELINUXFS: &str = "/sys/fs/selinux"; /// The mount path for uefi -#[cfg(feature = "install")] const EFIVARFS: &str = "/sys/firmware/efi/efivars"; pub(crate) const ARCH_USES_EFI: bool = cfg!(any(target_arch = "x86_64", target_arch = "aarch64")); @@ -202,6 +205,7 @@ pub(crate) struct InstallConfigOpts { pub(crate) stateroot: Option, } +#[cfg(feature = "install-to-disk")] #[derive(Debug, Clone, clap::Parser, Serialize, Deserialize, PartialEq, Eq)] pub(crate) struct InstallToDiskOpts { #[clap(flatten)] @@ -375,6 +379,7 @@ impl State { } #[context("Finalizing state")] + #[allow(dead_code)] pub(crate) fn consume(self) -> Result<()> { self.tempdir.close()?; // If we had invoked `setenforce 0`, then let's re-enable it. @@ -880,6 +885,7 @@ pub(crate) fn exec_in_host_mountns(args: &[std::ffi::OsString]) -> Result<()> { } pub(crate) struct RootSetup { + #[cfg(feature = "install-to-disk")] luks_device: Option, device_info: crate::blockdev::PartitionTable, /// Absolute path to the location where we've mounted the physical @@ -907,12 +913,14 @@ impl RootSetup { } // Drop any open file descriptors and return just the mount path and backing luks device, if any + #[cfg(feature = "install-to-disk")] fn into_storage(self) -> (Utf8PathBuf, Option) { (self.physical_root_path, self.luks_device) } } #[derive(Debug)] +#[allow(dead_code)] pub(crate) enum SELinuxFinalState { /// Host and target both have SELinux, but user forced it off for target ForceTargetDisabled, @@ -1449,6 +1457,7 @@ fn installation_complete() { /// Implementation of the `bootc install to-disk` CLI command. #[context("Installing to disk")] +#[cfg(feature = "install-to-disk")] pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> { let mut block_opts = opts.block_opts; let target_blockdev_meta = block_opts @@ -1845,6 +1854,7 @@ pub(crate) async fn install_to_filesystem( let skip_finalize = matches!(fsopts.replace, Some(ReplaceMode::Alongside)) || fsopts.skip_finalize; let mut rootfs = RootSetup { + #[cfg(feature = "install-to-disk")] luks_device: None, device_info, physical_root_path: fsopts.root_path, diff --git a/lib/src/install/baseline.rs b/lib/src/install/baseline.rs index 5db2e221..66b4557c 100644 --- a/lib/src/install/baseline.rs +++ b/lib/src/install/baseline.rs @@ -21,12 +21,14 @@ use clap::ValueEnum; use fn_error_context::context; use serde::{Deserialize, Serialize}; +use super::config::Filesystem; use super::MountSpec; use super::RootSetup; use super::State; use super::RUN_BOOTC; use super::RW_KARG; use crate::mount; +#[cfg(feature = "install-to-disk")] use crate::mount::is_mounted_in_pid1_mountns; use crate::task::Task; @@ -36,20 +38,6 @@ pub(crate) const EFIPN_SIZE_MB: u32 = 512; /// The GPT type for "linux" pub(crate) const LINUX_PARTTYPE: &str = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"; -#[derive(clap::ValueEnum, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub(crate) enum Filesystem { - Xfs, - Ext4, - Btrfs, -} - -impl Display for Filesystem { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.to_possible_value().unwrap().get_name().fmt(f) - } -} - #[derive(clap::ValueEnum, Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub(crate) enum BlockSetup { @@ -104,6 +92,7 @@ impl BlockSetup { } } +#[cfg(feature = "install-to-disk")] fn mkfs<'a>( dev: &str, fs: Filesystem, @@ -143,6 +132,7 @@ fn mkfs<'a>( } #[context("Creating rootfs")] +#[cfg(feature = "install-to-disk")] pub(crate) fn install_create_rootfs( state: &State, opts: InstallBlockDeviceOpts, diff --git a/lib/src/install/config.rs b/lib/src/install/config.rs index b8c870ff..4736ca69 100644 --- a/lib/src/install/config.rs +++ b/lib/src/install/config.rs @@ -3,9 +3,11 @@ //! This module handles the TOML configuration file for `bootc install`. use anyhow::{Context, Result}; +use clap::ValueEnum; use fn_error_context::context; use serde::{Deserialize, Serialize}; +#[cfg(feature = "install-to-disk")] use super::baseline::BlockSetup; /// Properties of the environment, such as the system architecture @@ -14,6 +16,21 @@ pub(crate) struct EnvProperties { pub(crate) sys_arch: String, } +/// A well known filesystem type. +#[derive(clap::ValueEnum, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub(crate) enum Filesystem { + Xfs, + Ext4, + Btrfs, +} + +impl std::fmt::Display for Filesystem { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.to_possible_value().unwrap().get_name().fmt(f) + } +} + /// The toplevel config entry for installation configs stored /// in bootc/install (e.g. /etc/bootc/install/05-custom.toml) #[derive(Debug, Clone, Serialize, Deserialize, Default)] @@ -27,7 +44,7 @@ pub(crate) struct InstallConfigurationToplevel { #[serde(deny_unknown_fields)] pub(crate) struct RootFS { #[serde(rename = "type")] - pub(crate) fstype: Option, + pub(crate) fstype: Option, } /// This structure should only define "system" or "basic" filesystems; we are @@ -46,8 +63,9 @@ pub(crate) struct BasicFilesystems { #[serde(rename = "install", rename_all = "kebab-case", deny_unknown_fields)] pub(crate) struct InstallConfiguration { /// Root filesystem type - pub(crate) root_fs_type: Option, + pub(crate) root_fs_type: Option, /// Enabled block storage configurations + #[cfg(feature = "install-to-disk")] pub(crate) block: Option>, pub(crate) filesystem: Option, /// Kernel arguments, applied at installation time @@ -112,6 +130,7 @@ impl Mergeable for InstallConfiguration { .unwrap_or(true) { merge_basic(&mut self.root_fs_type, other.root_fs_type, env); + #[cfg(feature = "install-to-disk")] merge_basic(&mut self.block, other.block, env); self.filesystem.merge(other.filesystem, env); if let Some(other_kargs) = other.kargs { @@ -139,6 +158,7 @@ impl InstallConfiguration { root.fstype = Some(*rootfs); } + #[cfg(feature = "install-to-disk")] if self.block.is_none() { self.block = Some(vec![BlockSetup::Direct]); } @@ -154,6 +174,7 @@ impl InstallConfiguration { self.kargs.take(); } + #[cfg(feature = "install-to-disk")] pub(crate) fn get_block_setup(&self, default: Option) -> Result { let valid_block_setups = self.block.as_deref().unwrap_or_default(); let default_block = valid_block_setups.iter().next().ok_or_else(|| { @@ -217,8 +238,6 @@ pub(crate) fn load_config() -> Result> { mod tests { use super::*; - use super::super::baseline::Filesystem; - #[test] /// Verify that we can parse our default config file fn test_parse_config() { diff --git a/lib/src/kargs.rs b/lib/src/kargs.rs index af4410e8..5df1497c 100644 --- a/lib/src/kargs.rs +++ b/lib/src/kargs.rs @@ -53,7 +53,6 @@ pub(crate) fn get_kargs_in_root(d: &Dir, sys_arch: &str) -> Result> } /// Load kargs.d files from the target ostree commit root -#[cfg(feature = "install")] pub(crate) fn get_kargs_from_ostree_root( repo: &ostree::Repo, root: &ostree::RepoFile, diff --git a/lib/src/lib.rs b/lib/src/lib.rs index daa4bfc4..a661ba35 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -30,17 +30,11 @@ mod utils; #[cfg(feature = "docgen")] mod docgen; -#[cfg(feature = "install")] mod blockdev; -#[cfg(feature = "install")] mod bootloader; -#[cfg(feature = "install")] mod containerenv; -#[cfg(feature = "install")] mod install; -#[cfg(feature = "install")] mod kernel; -#[cfg(feature = "install")] pub(crate) mod mount; #[cfg(feature = "rhsm")] diff --git a/lib/src/lsm.rs b/lib/src/lsm.rs index c2deaea3..9365c7fc 100644 --- a/lib/src/lsm.rs +++ b/lib/src/lsm.rs @@ -1,4 +1,3 @@ -#[cfg(feature = "install")] use std::io::Write; use std::os::fd::AsRawFd; use std::os::unix::process::CommandExt; @@ -9,14 +8,10 @@ use anyhow::{Context, Result}; use bootc_utils::CommandRunExt; use camino::{Utf8Path, Utf8PathBuf}; use cap_std::fs::Dir; -#[cfg(feature = "install")] use cap_std::fs::{DirBuilder, OpenOptions}; -#[cfg(feature = "install")] use cap_std::io_lifetimes::AsFilelike; use cap_std_ext::cap_std; -#[cfg(feature = "install")] use cap_std_ext::cap_std::fs::{Metadata, MetadataExt}; -#[cfg(feature = "install")] use cap_std_ext::dirext::CapStdExtDirExt; use fn_error_context::context; use ostree_ext::gio; @@ -24,10 +19,8 @@ use ostree_ext::ostree; use rustix::fd::AsFd; /// The mount path for selinux -#[cfg(feature = "install")] const SELINUXFS: &str = "/sys/fs/selinux"; /// The SELinux xattr -#[cfg(feature = "install")] const SELINUX_XATTR: &[u8] = b"security.selinux\0"; const SELF_CURRENT: &str = "/proc/self/attr/current"; @@ -99,7 +92,6 @@ pub(crate) fn selinux_ensure_install() -> Result { } /// Query whether SELinux is apparently enabled in the target root -#[cfg(feature = "install")] pub(crate) fn have_selinux_policy(root: &Dir) -> Result { // TODO use ostree::SePolicy and query policy name root.try_exists("etc/selinux/config").map_err(Into::into) @@ -108,17 +100,17 @@ pub(crate) fn have_selinux_policy(root: &Dir) -> Result { /// A type which will reset SELinux back to enforcing mode when dropped. /// This is a workaround for the deep difficulties in trying to reliably /// gain the `mac_admin` permission (install_t). -#[cfg(feature = "install")] #[must_use] #[derive(Debug)] +#[allow(dead_code)] pub(crate) struct SetEnforceGuard(Option<()>); -#[cfg(feature = "install")] impl SetEnforceGuard { pub(crate) fn new() -> Self { SetEnforceGuard(Some(())) } + #[allow(dead_code)] pub(crate) fn consume(mut self) -> Result<()> { // SAFETY: The option cannot have been consumed until now self.0.take().unwrap(); @@ -127,7 +119,6 @@ impl SetEnforceGuard { } } -#[cfg(feature = "install")] impl Drop for SetEnforceGuard { fn drop(&mut self) { // A best-effort attempt to re-enable enforcement on drop (installation failure) @@ -140,7 +131,6 @@ impl Drop for SetEnforceGuard { /// Try to enter the install_t domain, but if we can't do that, then /// just setenforce 0. #[context("Ensuring selinux install_t type")] -#[cfg(feature = "install")] pub(crate) fn selinux_ensure_install_or_setenforce() -> Result> { // If the process already has install_t, exit early // Note that this may re-exec the entire process @@ -160,7 +150,6 @@ pub(crate) fn selinux_ensure_install_or_setenforce() -> Result Result<()> { let enforce_path = &Utf8Path::new(SELINUXFS).join("enforce"); if !enforce_path.exists() { @@ -179,7 +168,6 @@ pub(crate) fn selinux_set_permissive(permissive: bool) -> Result<()> { Ok(()) } -#[cfg(feature = "install")] /// Check if the ostree-formatted extended attributes include a security.selinux value. pub(crate) fn xattrs_have_selinux(xattrs: &ostree::glib::Variant) -> bool { let n = xattrs.n_children(); @@ -223,7 +211,6 @@ pub(crate) fn set_security_selinux(fd: std::os::fd::BorrowedFd, label: &[u8]) -> /// The labeling state; "unsupported" is distinct as we need to handle /// cases like the ESP which don't support labeling. -#[cfg(feature = "install")] pub(crate) enum SELinuxLabelState { Unlabeled, Unsupported, @@ -231,7 +218,6 @@ pub(crate) enum SELinuxLabelState { } /// Query the SELinux labeling for a particular path -#[cfg(feature = "install")] pub(crate) fn has_security_selinux(root: &Dir, path: &Utf8Path) -> Result { // TODO: avoid hardcoding a max size here let mut buf = [0u8; 2048]; @@ -244,7 +230,6 @@ pub(crate) fn has_security_selinux(root: &Dir, path: &Utf8Path) -> Result Result<()> { // TODO: avoid hardcoding a max size here let fdpath = format!("/proc/self/fd/{}/", root.as_raw_fd()); @@ -258,7 +243,6 @@ pub(crate) fn set_security_selinux_path(root: &Dir, path: &Utf8Path, label: &[u8 Ok(()) } -#[cfg(feature = "install")] pub(crate) fn ensure_labeled( root: &Dir, path: &Utf8Path, @@ -277,7 +261,6 @@ pub(crate) fn ensure_labeled( /// A wrapper for creating a directory, also optionally setting a SELinux label. /// The provided `skip` parameter is a device/inode that we will ignore (and not traverse). -#[cfg(feature = "install")] pub(crate) fn ensure_dir_labeled_recurse( root: &Dir, path: &mut Utf8PathBuf, @@ -340,7 +323,6 @@ pub(crate) fn ensure_dir_labeled_recurse( } /// A wrapper for creating a directory, also optionally setting a SELinux label. -#[cfg(feature = "install")] pub(crate) fn ensure_dir_labeled( root: &Dir, destname: impl AsRef, @@ -387,7 +369,6 @@ pub(crate) fn ensure_dir_labeled( } /// A wrapper for atomically writing a file, also optionally setting a SELinux label. -#[cfg(feature = "install")] pub(crate) fn atomic_replace_labeled( root: &Dir, destname: impl AsRef, diff --git a/lib/src/mount.rs b/lib/src/mount.rs index a1ad00e6..6c10165b 100644 --- a/lib/src/mount.rs +++ b/lib/src/mount.rs @@ -21,6 +21,7 @@ use rustix::{ }; use serde::Deserialize; +#[cfg(feature = "install-to-disk")] use crate::task::Task; /// Well known identifier for pid 1 @@ -90,6 +91,7 @@ pub(crate) fn inspect_filesystem_by_uuid(uuid: &str) -> Result { // Check if a specified device contains an already mounted filesystem // in the root mount namespace +#[cfg(feature = "install-to-disk")] pub(crate) fn is_mounted_in_pid1_mountns(path: &str) -> Result { let o = run_findmnt(&["-N"], "1")?; @@ -99,6 +101,7 @@ pub(crate) fn is_mounted_in_pid1_mountns(path: &str) -> Result { } // Recursively check a given filesystem to see if it contains an already mounted source +#[cfg(feature = "install-to-disk")] pub(crate) fn is_source_mounted(path: &str, mounted_fs: &Filesystem) -> bool { if mounted_fs.source.contains(path) { return true; @@ -116,6 +119,7 @@ pub(crate) fn is_source_mounted(path: &str, mounted_fs: &Filesystem) -> bool { } /// Mount a device to the target path. +#[cfg(feature = "install-to-disk")] pub(crate) fn mount(dev: &str, target: &Utf8Path) -> Result<()> { Task::new_and_run( format!("Mounting {target}"), diff --git a/lib/src/podman.rs b/lib/src/podman.rs index 058984ee..1731f586 100644 --- a/lib/src/podman.rs +++ b/lib/src/podman.rs @@ -1,19 +1,14 @@ -#[cfg(feature = "install")] use anyhow::Result; -#[cfg(feature = "install")] use camino::Utf8Path; -#[cfg(feature = "install")] use cap_std_ext::cap_std::fs::Dir; use serde::Deserialize; /// Where we look inside our container to find our own image /// for use with `bootc install`. -#[cfg(feature = "install")] pub(crate) const CONTAINER_STORAGE: &str = "/var/lib/containers"; #[derive(Deserialize)] #[serde(rename_all = "PascalCase")] -#[cfg(feature = "install")] pub(crate) struct Inspect { pub(crate) digest: String, } @@ -27,7 +22,6 @@ pub(crate) struct ImageListEntry { } /// Given an image ID, return its manifest digest -#[cfg(feature = "install")] pub(crate) fn imageid_to_digest(imgid: &str) -> Result { use bootc_utils::CommandRunExt; let o: Vec = crate::install::run_in_host_mountns("podman") @@ -41,7 +35,6 @@ pub(crate) fn imageid_to_digest(imgid: &str) -> Result { } /// Return true if there is apparently an active container store at the target path. -#[cfg(feature = "install")] pub(crate) fn storage_exists(root: &Dir, path: impl AsRef) -> Result { fn impl_storage_exists(root: &Dir, path: &Utf8Path) -> Result { let lock = "storage.lock"; @@ -55,7 +48,6 @@ pub(crate) fn storage_exists(root: &Dir, path: impl AsRef) -> Result Result { storage_exists(root, CONTAINER_STORAGE.trim_start_matches('/')) } diff --git a/lib/src/status.rs b/lib/src/status.rs index 8bc598eb..7f3e8290 100644 --- a/lib/src/status.rs +++ b/lib/src/status.rs @@ -102,7 +102,6 @@ pub(crate) struct Deployments { pub(crate) other: VecDeque, } -#[cfg(feature = "install")] pub(crate) fn try_deserialize_timestamp(t: &str) -> Option> { match chrono::DateTime::parse_from_rfc3339(t).context("Parsing timestamp") { Ok(t) => Some(t.into()), diff --git a/lib/src/utils.rs b/lib/src/utils.rs index 8e33ceef..42fbd165 100644 --- a/lib/src/utils.rs +++ b/lib/src/utils.rs @@ -7,14 +7,10 @@ use std::time::Duration; use anyhow::{Context, Result}; use bootc_utils::CommandRunExt; -#[cfg(feature = "install")] use camino::Utf8Path; use cap_std_ext::cap_std::fs::Dir; -#[cfg(feature = "install")] use cap_std_ext::dirext::CapStdExtDirExt; -#[cfg(feature = "install")] use cap_std_ext::prelude::CapStdExtCommandExt; -#[cfg(feature = "install")] use fn_error_context::context; use indicatif::HumanDuration; use libsystemd::logging::journal_print; @@ -88,7 +84,6 @@ pub fn openat2_with_retry( /// Given an mount option string list like foo,bar=baz,something=else,ro parse it and find /// the first entry like $optname= /// This will not match a bare `optname` without an equals. -#[cfg(feature = "install")] pub(crate) fn find_mount_option<'a>( option_string_list: &'a str, optname: &'_ str, @@ -102,7 +97,6 @@ pub(crate) fn find_mount_option<'a>( /// Given a target directory, if it's a read-only mount, then remount it writable #[context("Opening {target} with writable mount")] -#[cfg(feature = "install")] pub(crate) fn open_dir_remount_rw(root: &Dir, target: &Utf8Path) -> Result { if matches!(root.is_mountpoint(target), Ok(Some(true))) { tracing::debug!("Target {target} is a mountpoint, remounting rw"); @@ -118,7 +112,6 @@ pub(crate) fn open_dir_remount_rw(root: &Dir, target: &Utf8Path) -> Result /// Given a target path, remove its immutability if present #[context("Removing immutable flag from {target}")] -#[cfg(feature = "install")] pub(crate) fn remove_immutability(root: &Dir, target: &Utf8Path) -> Result<()> { use anyhow::ensure; @@ -175,7 +168,6 @@ pub(crate) fn sigpolicy_from_opts( /// Output a warning message that we want to be quite visible. /// The process (thread) execution will be delayed for a short time. -#[cfg(feature = "install")] pub(crate) fn medium_visibility_warning(s: &str) { anstream::eprintln!( "{}{s}{}",