Move units
and default-target
processing to Rust
More oxidation.
This commit is contained in:
parent
ef931e20b0
commit
4c5bb4f216
@ -125,6 +125,60 @@ pub(crate) fn compose_postprocess_final(rootfs_dfd: i32) -> CxxResult<()> {
|
||||
Ok(tasks.par_iter().try_for_each(|f| f(&rootfs_dfd))?)
|
||||
}
|
||||
|
||||
#[context("Handling treefile 'units'")]
|
||||
fn compose_postprocess_units(rootfs_dfd: &openat::Dir, treefile: &mut Treefile) -> Result<()> {
|
||||
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;
|
||||
}
|
||||
|
||||
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)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[context("Handling treefile 'default-target'")]
|
||||
fn compose_postprocess_default_target(rootfs_dfd: &openat::Dir, target: &str) -> Result<()> {
|
||||
/* This used to be in /etc, but doing it in /usr makes more sense, as it's
|
||||
* part of the OS defaults. This was changed in particular to work with
|
||||
* ConditionFirstBoot= which runs `systemctl preset-all`:
|
||||
* https://github.com/projectatomic/rpm-ostree/pull/1425
|
||||
*/
|
||||
let default_target_path = "usr/lib/systemd/system/default.target";
|
||||
rootfs_dfd.remove_file_optional(default_target_path)?;
|
||||
let dest = format!("/usr/lib/systemd/system/{}", target);
|
||||
rootfs_dfd.symlink(default_target_path, dest)?;
|
||||
|
||||
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.
|
||||
|
@ -88,6 +88,7 @@ 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(
|
||||
rootfs_dfd: i32,
|
||||
treefile: &mut Treefile,
|
||||
|
@ -1012,10 +1012,10 @@ pub(crate) struct TreeComposeConfig {
|
||||
|
||||
// systemd
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
units: Option<Vec<String>>,
|
||||
pub(crate) units: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(rename = "default-target")]
|
||||
default_target: Option<String>,
|
||||
pub(crate) default_target: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(rename = "machineid-compat")]
|
||||
// Defaults to `true`
|
||||
|
@ -1213,74 +1213,9 @@ rpmostree_treefile_postprocessing (int rootfs_fd,
|
||||
if (!rename_if_exists (rootfs_fd, "etc", rootfs_fd, "usr/etc", error))
|
||||
return FALSE;
|
||||
|
||||
JsonArray *units = NULL;
|
||||
if (json_object_has_member (treefile, "units"))
|
||||
units = json_object_get_array_member (treefile, "units");
|
||||
rpmostreecxx::compose_postprocess_targets(rootfs_fd, treefile_rs);
|
||||
|
||||
guint len;
|
||||
if (units)
|
||||
len = json_array_get_length (units);
|
||||
else
|
||||
len = 0;
|
||||
|
||||
{
|
||||
glnx_autofd int multiuser_wants_dfd = -1;
|
||||
|
||||
if (!glnx_shutil_mkdir_p_at (rootfs_fd, "usr/etc/systemd/system/multi-user.target.wants", 0755,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
if (!glnx_opendirat (rootfs_fd, "usr/etc/systemd/system/multi-user.target.wants", TRUE,
|
||||
&multiuser_wants_dfd, error))
|
||||
return FALSE;
|
||||
|
||||
for (guint i = 0; i < len; i++)
|
||||
{
|
||||
const char *unitname = _rpmostree_jsonutil_array_require_string_element (units, i, error);
|
||||
g_autofree char *symlink_target = NULL;
|
||||
struct stat stbuf;
|
||||
|
||||
if (!unitname)
|
||||
return FALSE;
|
||||
|
||||
symlink_target = g_strconcat ("/usr/lib/systemd/system/", unitname, NULL);
|
||||
|
||||
if (fstatat (multiuser_wants_dfd, unitname, &stbuf, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return glnx_throw_errno_prefix (error, "fstatat(%s)", unitname);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
g_print ("Adding %s to multi-user.target.wants\n", unitname);
|
||||
|
||||
if (symlinkat (symlink_target, multiuser_wants_dfd, unitname) < 0)
|
||||
return glnx_throw_errno_prefix (error, "symlinkat(%s)", unitname);
|
||||
}
|
||||
}
|
||||
|
||||
const char *default_target = NULL;
|
||||
if (!_rpmostree_jsonutil_object_get_optional_string_member (treefile, "default-target",
|
||||
&default_target, error))
|
||||
return FALSE;
|
||||
|
||||
if (default_target != NULL)
|
||||
{
|
||||
g_autofree char *dest_default_target_path =
|
||||
g_strconcat ("/usr/lib/systemd/system/", default_target, NULL);
|
||||
|
||||
/* This used to be in /etc, but doing it in /usr makes more sense, as it's
|
||||
* part of the OS defaults. This was changed in particular to work with
|
||||
* ConditionFirstBoot= which runs `systemctl preset-all`:
|
||||
* https://github.com/projectatomic/rpm-ostree/pull/1425
|
||||
*/
|
||||
static const char default_target_path[] = "usr/lib/systemd/system/default.target";
|
||||
(void) unlinkat (rootfs_fd, default_target_path, 0);
|
||||
|
||||
if (symlinkat (dest_default_target_path, rootfs_fd, default_target_path) < 0)
|
||||
return glnx_throw_errno_prefix (error, "symlinkat(%s)", default_target_path);
|
||||
}
|
||||
|
||||
JsonArray *remove = NULL;
|
||||
if (json_object_has_member (treefile, "remove-files"))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user