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))?)
|
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;
|
/// The treefile format has two kinds of postprocessing scripts;
|
||||||
/// there's a single `postprocess-script` as well as inline (anonymous)
|
/// there's a single `postprocess-script` as well as inline (anonymous)
|
||||||
/// scripts. This function executes both kinds in bwrap containers.
|
/// scripts. This function executes both kinds in bwrap containers.
|
||||||
|
@ -88,6 +88,7 @@ pub mod ffi {
|
|||||||
// composepost.rs
|
// composepost.rs
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn composepost_nsswitch_altfiles(rootfs_dfd: i32) -> Result<()>;
|
fn composepost_nsswitch_altfiles(rootfs_dfd: i32) -> Result<()>;
|
||||||
|
fn compose_postprocess_targets(rootfs_dfd: i32, treefile: &mut Treefile) -> Result<()>;
|
||||||
fn compose_postprocess(
|
fn compose_postprocess(
|
||||||
rootfs_dfd: i32,
|
rootfs_dfd: i32,
|
||||||
treefile: &mut Treefile,
|
treefile: &mut Treefile,
|
||||||
|
@ -1012,10 +1012,10 @@ pub(crate) struct TreeComposeConfig {
|
|||||||
|
|
||||||
// systemd
|
// systemd
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[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(skip_serializing_if = "Option::is_none")]
|
||||||
#[serde(rename = "default-target")]
|
#[serde(rename = "default-target")]
|
||||||
default_target: Option<String>,
|
pub(crate) default_target: Option<String>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
#[serde(rename = "machineid-compat")]
|
#[serde(rename = "machineid-compat")]
|
||||||
// Defaults to `true`
|
// 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))
|
if (!rename_if_exists (rootfs_fd, "etc", rootfs_fd, "usr/etc", error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
JsonArray *units = NULL;
|
rpmostreecxx::compose_postprocess_targets(rootfs_fd, treefile_rs);
|
||||||
if (json_object_has_member (treefile, "units"))
|
|
||||||
units = json_object_get_array_member (treefile, "units");
|
|
||||||
|
|
||||||
guint len;
|
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;
|
JsonArray *remove = NULL;
|
||||||
if (json_object_has_member (treefile, "remove-files"))
|
if (json_object_has_member (treefile, "remove-files"))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user