]> git.ipfire.org Git - pakfire.git/commitdiff
transaction: Automatically create system users
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 19 Mar 2023 19:04:05 +0000 (19:04 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 19 Mar 2023 19:04:31 +0000 (19:04 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/archive.c
src/libpakfire/include/pakfire/archive.h
src/libpakfire/packager.c
src/libpakfire/pakfire.c
src/libpakfire/transaction.c

index 69849ec760d5aaf563d65d02eedf9092d3e70163..c3a028adde4cfa6839d0ad3b85dca7deac879d9c 100644 (file)
@@ -40,6 +40,7 @@
 #include <pakfire/file.h>
 #include <pakfire/filelist.h>
 #include <pakfire/i18n.h>
+#include <pakfire/jail.h>
 #include <pakfire/logging.h>
 #include <pakfire/package.h>
 #include <pakfire/pakfire.h>
@@ -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;
+}
index 8f8dc272901d586a091351556bf149a20096cd1f..fed3f5727e333b8822eb0ee5bd1284b7ae966ed1 100644 (file)
@@ -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 */
index dc5038376a06dd85797732efc3d1a30659bcab21..04b41436aba6643adcb7220be6f4c10615a02e71 100644 (file)
@@ -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)");
index ad1093ac946e7582ed6a0d1e7f902033332695e3..765f075b3b244ac9c7b673abbd469965e52b44b1 100644 (file)
@@ -156,6 +156,7 @@ static const struct pakfire_feature {
        { "Digest-SHA2-256" },
 
        // Systemd
+       { "systemd-sysusers" },
        { "systemd-tmpfiles" },
 
        // The end
index d8a39b8e894e27231cd52dd540b5d1a38b71d38e..8a2f1b4df19c100c6733b54f23f2640a91753c6a 100644 (file)
@@ -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)