diff --git a/rust/src/composepost.rs b/rust/src/composepost.rs index 68f1f032..fd193965 100644 --- a/rust/src/composepost.rs +++ b/rust/src/composepost.rs @@ -128,22 +128,25 @@ pub(crate) fn compose_postprocess_final(rootfs_dfd: i32) -> CxxResult<()> { #[context("Handling treefile 'units'")] fn compose_postprocess_units(rootfs_dfd: &openat::Dir, treefile: &mut Treefile) -> Result<()> { + let units = if let Some(u) = treefile.parsed.units.as_ref() { + u + } else { + return Ok(()); + }; let multiuser_wants = Path::new("usr/etc/systemd/system/multi-user.target.wants"); + // Sanity check + if !rootfs_dfd.exists("usr/etc")? { + return Err(anyhow!("Missing usr/etc in rootfs")); + } + rootfs_dfd.ensure_dir_all(multiuser_wants, 0o755)?; - let mut created = false; - for unit in treefile.parsed.units.iter().flatten() { - if !created { - rootfs_dfd.ensure_dir_all(multiuser_wants, 0o755)?; - created = true; - } - + for unit in units { let dest = multiuser_wants.join(unit); if rootfs_dfd.exists(&dest)? { continue; } println!("Adding {} to multi-user.target.wants", unit); - let target = format!("/usr/lib/systemd/system/{}", unit); rootfs_dfd.symlink(&dest, &target)?; } @@ -165,21 +168,6 @@ fn compose_postprocess_default_target(rootfs_dfd: &openat::Dir, target: &str) -> Ok(()) } -#[context("Handling targets")] -pub(crate) fn compose_postprocess_targets( - rootfs_dfd: i32, - treefile: &mut Treefile, -) -> CxxResult<()> { - let rootfs_dfd = crate::ffiutil::ffi_view_openat_dir(rootfs_dfd); - - compose_postprocess_units(&rootfs_dfd, treefile)?; - if let Some(t) = treefile.parsed.default_target.as_deref() { - compose_postprocess_default_target(&rootfs_dfd, t)?; - } - - Ok(()) -} - /// The treefile format has two kinds of postprocessing scripts; /// there's a single `postprocess-script` as well as inline (anonymous) /// scripts. This function executes both kinds in bwrap containers. @@ -227,11 +215,9 @@ fn compose_postprocess_scripts( #[context("Handling `remove-files`")] pub(crate) fn compose_postprocess_remove_files( - rootfs_dfd: i32, + rootfs_dfd: &openat::Dir, treefile: &mut Treefile, -) -> CxxResult<()> { - let rootfs_dfd = crate::ffiutil::ffi_view_openat_dir(rootfs_dfd); - +) -> Result<()> { for name in treefile.parsed.remove_files.iter().flatten() { let p = Path::new(name); if p.is_absolute() { @@ -307,13 +293,33 @@ fn compose_postprocess_rpmdb(rootfs_dfd: &openat::Dir) -> Result<()> { pub(crate) fn compose_postprocess( rootfs_dfd: i32, treefile: &mut Treefile, + next_version: &str, unified_core: bool, ) -> CxxResult<()> { let rootfs_dfd = &crate::ffiutil::ffi_view_openat_dir(rootfs_dfd); - compose_postprocess_add_files(rootfs_dfd, treefile)?; - compose_postprocess_scripts(rootfs_dfd, treefile, unified_core)?; + // One of several dances we do around this that really needs to be completely + // reworked. + if rootfs_dfd.exists("etc")? { + rootfs_dfd.local_rename("etc", "usr/etc")?; + } + compose_postprocess_rpmdb(rootfs_dfd)?; + compose_postprocess_units(&rootfs_dfd, treefile)?; + if let Some(t) = treefile.parsed.default_target.as_deref() { + compose_postprocess_default_target(&rootfs_dfd, t)?; + } + + compose_postprocess_mutate_os_release(rootfs_dfd, treefile, next_version)?; + treefile.write_compose_json(rootfs_dfd)?; + + let etc_guard = crate::core::prepare_tempetc_guard(rootfs_dfd.as_raw_fd())?; + // These ones depend on the /etc path + compose_postprocess_remove_files(rootfs_dfd, treefile)?; + compose_postprocess_add_files(rootfs_dfd, treefile)?; + etc_guard.undo()?; + + compose_postprocess_scripts(rootfs_dfd, treefile, unified_core)?; Ok(()) } @@ -321,7 +327,7 @@ pub(crate) fn compose_postprocess( /// Implementation of the treefile `mutate-os-release` field. #[context("Updating os-release with commit version")] pub(crate) fn compose_postprocess_mutate_os_release( - rootfs_dfd: i32, + rootfs_dfd: &openat::Dir, treefile: &mut Treefile, next_version: &str, ) -> Result<()> { @@ -334,7 +340,6 @@ pub(crate) fn compose_postprocess_mutate_os_release( println!("Ignoring mutate-os-release: no commit version specified."); return Ok(()); } - let rootfs_dfd = &crate::ffiutil::ffi_view_openat_dir(rootfs_dfd); // find the real path to os-release using bwrap; this is an overkill but safer way // of resolving a symlink relative to a rootfs (see discussions in // https://github.com/projectatomic/rpm-ostree/pull/410/) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 5a8f9c6e..ce01f8e0 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -133,17 +133,10 @@ pub mod ffi { // composepost.rs extern "Rust" { fn composepost_nsswitch_altfiles(rootfs_dfd: i32) -> Result<()>; - fn compose_postprocess_targets(rootfs_dfd: i32, treefile: &mut Treefile) -> Result<()>; - fn compose_postprocess_mutate_os_release( - rootfs_dfd: i32, - treefile: &mut Treefile, - next_version: &str, - ) -> Result<()>; - fn compose_postprocess_remove_files(rootfs_dfd: i32, treefile: &mut Treefile) - -> Result<()>; fn compose_postprocess( rootfs_dfd: i32, treefile: &mut Treefile, + next_version: &str, unified_core: bool, ) -> Result<()>; fn compose_postprocess_final(rootfs_dfd: i32) -> Result<()>; @@ -260,7 +253,6 @@ pub mod ffi { fn get_rpmdb(&self) -> String; fn get_files_remove_regex(&self, package: &str) -> Vec; fn print_deprecation_warnings(&self); - fn write_compose_json(&self, rootfs_dfd: i32) -> Result<()>; fn sanitycheck_externals(&self) -> Result<()>; fn get_checksum(&self, repo: Pin<&mut OstreeRepo>) -> Result; fn get_ostree_ref(&self) -> String; diff --git a/rust/src/treefile.rs b/rust/src/treefile.rs index 1010fbe9..2a656175 100644 --- a/rust/src/treefile.rs +++ b/rust/src/treefile.rs @@ -746,8 +746,7 @@ for x in *; do mv ${{x}} %{{buildroot}}%{{_prefix}}/lib/ostree-jigdo/%{{name}}; } /// Write the serialized treefile into /usr/share on the target filesystem. - pub(crate) fn write_compose_json(&self, rootfs_dfd: i32) -> CxxResult<()> { - let rootfs_dfd = crate::ffiutil::ffi_view_openat_dir(rootfs_dfd); + pub(crate) fn write_compose_json(&self, rootfs_dfd: &openat::Dir) -> Result<()> { let target = Path::new(COMPOSE_JSON_PATH); rootfs_dfd.ensure_dir_all(target.parent().unwrap(), 0o755)?; rootfs_dfd.write_file_contents(target, 0o644, self.serialized.as_bytes())?; @@ -1626,7 +1625,7 @@ arch-include: { let workdir = tempfile::tempdir()?; let tf = new_test_treefile(workdir.path(), VALID_PRELUDE, None).unwrap(); - tf.write_compose_json(rootdir.as_raw_fd())?; + tf.write_compose_json(rootdir)?; } let mut src = std::io::BufReader::new(rootdir.open_file(COMPOSE_JSON_PATH)?); let cfg = treefile_parse_stream(utils::InputFormat::JSON, &mut src, None)?; diff --git a/src/app/rpmostree-compose-builtin-tree.cxx b/src/app/rpmostree-compose-builtin-tree.cxx index 2c14d3e1..5e648efc 100644 --- a/src/app/rpmostree-compose-builtin-tree.cxx +++ b/src/app/rpmostree-compose-builtin-tree.cxx @@ -954,10 +954,7 @@ impl_install_tree (RpmOstreeTreeComposeContext *self, return FALSE; /* Start postprocessing */ - if (!rpmostree_treefile_postprocessing (self->rootfs_dfd, **self->treefile_rs, self->treefile, - next_version.length() > 0 ? next_version.c_str() : NULL, self->unified_core_and_fuse, - cancellable, error)) - return glnx_prefix_error (error, "Postprocessing"); + rpmostreecxx::compose_postprocess(self->rootfs_dfd, **self->treefile_rs, next_version, self->unified_core_and_fuse); /* Until here, we targeted "rootfs.tmp" in the working directory. Most * user-configured postprocessing has run. Now, we need to perform required diff --git a/src/libpriv/rpmostree-postprocess.cxx b/src/libpriv/rpmostree-postprocess.cxx index fd56993e..07f1f565 100644 --- a/src/libpriv/rpmostree-postprocess.cxx +++ b/src/libpriv/rpmostree-postprocess.cxx @@ -1132,43 +1132,6 @@ rpmostree_rootfs_postprocess_common (int rootfs_fd, return TRUE; } -/* Move etc -> usr/etc in the rootfs, and run through treefile - * postprocessing. - */ -gboolean -rpmostree_treefile_postprocessing (int rootfs_fd, - rpmostreecxx::Treefile &treefile_rs, - JsonObject *treefile, - const char *next_version, - gboolean unified_core_mode, - GCancellable *cancellable, - GError **error) -{ - g_assert (treefile); - - treefile_rs.write_compose_json(rootfs_fd); - - if (!rename_if_exists (rootfs_fd, "etc", rootfs_fd, "usr/etc", error)) - return FALSE; - - rpmostreecxx::compose_postprocess_targets(rootfs_fd, treefile_rs); - - /* Put /etc back for backwards compatibility */ - if (!rename_if_exists (rootfs_fd, "usr/etc", rootfs_fd, "etc", error)) - return FALSE; - - rpmostreecxx::compose_postprocess_remove_files(rootfs_fd, treefile_rs); - rpmostreecxx::compose_postprocess_mutate_os_release(rootfs_fd, treefile_rs, next_version ?: ""); - - /* Undo etc move again */ - if (!rename_if_exists (rootfs_fd, "etc", rootfs_fd, "usr/etc", error)) - return FALSE; - - rpmostreecxx::compose_postprocess(rootfs_fd, treefile_rs, (bool)unified_core_mode); - - return TRUE; -} - /** * rpmostree_prepare_rootfs_for_commit: * diff --git a/src/libpriv/rpmostree-postprocess.h b/src/libpriv/rpmostree-postprocess.h index 5dfd9676..b2819e58 100644 --- a/src/libpriv/rpmostree-postprocess.h +++ b/src/libpriv/rpmostree-postprocess.h @@ -26,16 +26,6 @@ G_BEGIN_DECLS - -gboolean -rpmostree_treefile_postprocessing (int rootfs_fd, - rpmostreecxx::Treefile &treefile_rs, - JsonObject *treefile, - const char *next_version, - gboolean unified_core_mode, - GCancellable *cancellable, - GError **error); - gboolean rpmostree_rootfs_symlink_emptydir_at (int rootfs_fd, const char *dest,