From 88f4d6e68f0910254b862330685e849416d8ab5f Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sun, 19 Mar 2023 19:04:05 +0000 Subject: [PATCH] transaction: Automatically create system users Signed-off-by: Michael Tremer --- src/libpakfire/archive.c | 86 ++++++++++++++++++++++++ src/libpakfire/include/pakfire/archive.h | 2 + src/libpakfire/packager.c | 11 +++ src/libpakfire/pakfire.c | 1 + src/libpakfire/transaction.c | 19 ++++++ 5 files changed, 119 insertions(+) diff --git a/src/libpakfire/archive.c b/src/libpakfire/archive.c index 69849ec7..c3a028ad 100644 --- a/src/libpakfire/archive.c +++ b/src/libpakfire/archive.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -1147,3 +1148,88 @@ struct pakfire_scriptlet* pakfire_archive_get_scriptlet( return NULL; } + +/* + systemd sysusers +*/ +static int __pakfire_archive_filter_systemd_sysusers(struct pakfire* pakfire, + struct archive* a, struct archive_entry* e, void* data) { + const char* path = archive_entry_pathname(e); + + if (!pakfire_path_match("/usr/lib/sysusers.d/*.conf", path)) + return PAKFIRE_WALK_SKIP; + + return PAKFIRE_WALK_OK; +} + +static int pakfire_archive_stream_payload(struct pakfire* pakfire, void* data, int fd) { + char buffer[1024]; + + struct archive* a = (struct archive*)data; + + // Read a block from the input archive + ssize_t bytes_read = archive_read_data(a, buffer, sizeof(buffer)); + if (bytes_read < 0) { + ERROR(pakfire, "Could not read from archive: %s\n", archive_error_string(a)); + return 1; + } + + // We have consumed everything + if (bytes_read == 0) + return EOF; + + // Write the data to the output file descriptor + ssize_t bytes_written = write(fd, buffer, bytes_read); + if (bytes_written < 0) { + ERROR(pakfire, "Could not stream output: %m\n"); + return 1; + } + + return 0; +} + +static int __pakfire_archive_handle_systemd_sysusers(struct pakfire* pakfire, + struct archive* a, struct archive_entry* e, void* data) { + struct pakfire_jail* jail = NULL; + char replace[PATH_MAX]; + int r; + + // Fetch path + const char* path = archive_entry_pathname(e); + + // Format --replace + r = pakfire_string_format(replace, "--replace=/%s", path); + if (r) + goto ERROR; + + const char* argv[] = { "/usr/bin/systemd-sysusers", replace, "-", NULL }; + + // Create a new jail + r = pakfire_jail_create(&jail, pakfire, 0); + if (r) + goto ERROR; + + r = pakfire_jail_exec(jail, argv, pakfire_archive_stream_payload, NULL, a); + switch (r) { + // If the command does not exist, we silently ignore this error + case 127: + r = 0; + break; + + default: + goto ERROR; + } + +ERROR: + if (jail) + pakfire_jail_unref(jail); + + return r; +} + +int pakfire_archive_apply_systemd_sysusers(struct pakfire_archive* archive) { + pakfire_archive_walk(archive, + __pakfire_archive_filter_systemd_sysusers, __pakfire_archive_handle_systemd_sysusers, NULL); + + return 0; +} diff --git a/src/libpakfire/include/pakfire/archive.h b/src/libpakfire/include/pakfire/archive.h index 8f8dc272..fed3f572 100644 --- a/src/libpakfire/include/pakfire/archive.h +++ b/src/libpakfire/include/pakfire/archive.h @@ -64,6 +64,8 @@ int pakfire_archive_check_digest(struct pakfire_archive* archive, struct pakfire_scriptlet* pakfire_archive_get_scriptlet( struct pakfire_archive* archive, const char* type); +int pakfire_archive_apply_systemd_sysusers(struct pakfire_archive* archive); + #endif #endif /* PAKFIRE_ARCHIVE_H */ diff --git a/src/libpakfire/packager.c b/src/libpakfire/packager.c index dc503837..04b41436 100644 --- a/src/libpakfire/packager.c +++ b/src/libpakfire/packager.c @@ -579,6 +579,17 @@ int pakfire_packager_add_file(struct pakfire_packager* packager, struct pakfire_ pakfire_file_set_gname(file, "root"); } + // Handle systemd sysusers + if (pakfire_file_matches(file, "/usr/lib/sysusers.d/*.conf")) { + pakfire_package_add_dep(packager->pkg, + PAKFIRE_PKG_REQUIRES, "pakfire(systemd-sysusers)"); + + // Ask to pre-install /usr/bin/systemd-sysusers + pakfire_package_add_dep(packager->pkg, + PAKFIRE_PKG_PREREQUIRES, "/usr/bin/systemd-sysusers"); + } + + // Handle systemd tmpfiles if (pakfire_file_matches(file, "/usr/lib/tmpfiles.d/*.conf")) { pakfire_package_add_dep(packager->pkg, PAKFIRE_PKG_REQUIRES, "pakfire(systemd-tmpfiles)"); diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index ad1093ac..765f075b 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -156,6 +156,7 @@ static const struct pakfire_feature { { "Digest-SHA2-256" }, // Systemd + { "systemd-sysusers" }, { "systemd-tmpfiles" }, // The end diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c index d8a39b8e..8a2f1b4d 100644 --- a/src/libpakfire/transaction.c +++ b/src/libpakfire/transaction.c @@ -814,6 +814,15 @@ static int pakfire_transaction_package_is_userinstalled( return 0; } +static int pakfire_transaction_apply_systemd_sysusers(struct pakfire_transaction* transaction, + struct pakfire_package* pkg, struct pakfire_archive* archive) { + // Walk through the archive and find all sysuser files + if (pakfire_package_matches_dep(pkg, PAKFIRE_PKG_REQUIRES, "pakfire(systemd-sysusers)")) + return pakfire_archive_apply_systemd_sysusers(archive); + + return 0; +} + static int pakfire_transaction_apply_systemd_tmpfiles( struct pakfire_transaction* transaction, struct pakfire_package* pkg) { // Apply any tmpfiles (ignore any errors) @@ -905,6 +914,11 @@ static int pakfire_transaction_run_step(struct pakfire_transaction* transaction, switch (type) { case PAKFIRE_STEP_INSTALL: case PAKFIRE_STEP_REINSTALL: + // Apply systemd sysusers + r = pakfire_transaction_apply_systemd_sysusers(transaction, pkg, archive); + if (r) + break; + r = pakfire_transaction_run_script(transaction, db, "prein", pkg, archive); if (r) @@ -937,6 +951,11 @@ static int pakfire_transaction_run_step(struct pakfire_transaction* transaction, case PAKFIRE_STEP_UPGRADE: case PAKFIRE_STEP_DOWNGRADE: + // Apply systemd sysusers + r = pakfire_transaction_apply_systemd_sysusers(transaction, pkg, archive); + if (r) + break; + r = pakfire_transaction_run_script(transaction, db, "preup", pkg, archive); if (r) -- 2.47.3