postprocess: Move more code into Rust
Previously we carefully ported functionality bit by bit here. Now take the last step and move it all in to Rust. A reason I didn't do this in one go before is around the incredibly twisted handling of the `/etc` vs `/usr/etc`. I think longer term we should aim to basically have all of our code keep it as `/etc` up until the very end. For now we just do a rename dance around some of the add/remove files code.
This commit is contained in:
parent
86f9612395
commit
46728cfd99
@ -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");
|
||||
|
||||
let mut created = false;
|
||||
for unit in treefile.parsed.units.iter().flatten() {
|
||||
if !created {
|
||||
rootfs_dfd.ensure_dir_all(multiuser_wants, 0o755)?;
|
||||
created = true;
|
||||
// Sanity check
|
||||
if !rootfs_dfd.exists("usr/etc")? {
|
||||
return Err(anyhow!("Missing usr/etc in rootfs"));
|
||||
}
|
||||
rootfs_dfd.ensure_dir_all(multiuser_wants, 0o755)?;
|
||||
|
||||
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/)
|
||||
|
@ -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<String>;
|
||||
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<String>;
|
||||
fn get_ostree_ref(&self) -> String;
|
||||
|
@ -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)?;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
*
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user