]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/machine-id-setup/machine-id-setup-main.c
machine-id-setup: support --image= mode
[thirdparty/systemd.git] / src / machine-id-setup / machine-id-setup-main.c
index 69fb71cdc2d7f837e96f4ddaa1e3c738a8231ab0..9539c39c4e7cf5a7edeae66534e4759be1866186 100644 (file)
@@ -6,20 +6,25 @@
 #include <stdlib.h>
 
 #include "alloc-util.h"
+#include "dissect-image.h"
 #include "id128-util.h"
 #include "log.h"
 #include "machine-id-setup.h"
 #include "main-func.h"
+#include "mount-util.h"
 #include "parse-argument.h"
 #include "path-util.h"
 #include "pretty-print.h"
+#include "terminal-util.h"
 #include "util.h"
 
 static char *arg_root = NULL;
+static char *arg_image = NULL;
 static bool arg_commit = false;
 static bool arg_print = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
 
 static int help(void) {
         _cleanup_free_ char *link = NULL;
@@ -29,15 +34,18 @@ static int help(void) {
         if (r < 0)
                 return log_oom();
 
-        printf("%s [OPTIONS...]\n\n"
-               "Initialize /etc/machine-id from a random source.\n\n"
+        printf("%s [OPTIONS...]\n"
+               "\n%sInitialize /etc/machine-id from a random source.%s\n\n"
                "  -h --help             Show this help\n"
                "     --version          Show package version\n"
-               "     --root=ROOT        Filesystem root\n"
+               "     --root=PATH        Operate relative to root path\n"
+               "     --image=PATH       Operate relative to image file\n"
                "     --commit           Commit transient ID\n"
                "     --print            Print used machine ID\n"
                "\nSee the %s for details.\n",
                program_invocation_short_name,
+               ansi_highlight(),
+               ansi_normal(),
                link);
 
         return 0;
@@ -48,6 +56,7 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_ROOT,
+                ARG_IMAGE,
                 ARG_COMMIT,
                 ARG_PRINT,
         };
@@ -56,6 +65,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "help",      no_argument,       NULL, 'h'           },
                 { "version",   no_argument,       NULL, ARG_VERSION   },
                 { "root",      required_argument, NULL, ARG_ROOT      },
+                { "image",     required_argument, NULL, ARG_IMAGE     },
                 { "commit",    no_argument,       NULL, ARG_COMMIT    },
                 { "print",     no_argument,       NULL, ARG_PRINT     },
                 {}
@@ -82,6 +92,12 @@ static int parse_argv(int argc, char *argv[]) {
                                 return r;
                         break;
 
+                case ARG_IMAGE:
+                        r = parse_path_argument(optarg, false, &arg_image);
+                        if (r < 0)
+                                return r;
+                        break;
+
                 case ARG_COMMIT:
                         arg_commit = true;
                         break;
@@ -101,10 +117,16 @@ static int parse_argv(int argc, char *argv[]) {
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Extraneous arguments");
 
+        if (arg_image && arg_root)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
+
         return 1;
 }
 
 static int run(int argc, char *argv[]) {
+        _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
+        _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
+        _cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
         char buf[SD_ID128_STRING_MAX];
         sd_id128_t id;
         int r;
@@ -116,6 +138,26 @@ static int run(int argc, char *argv[]) {
         if (r <= 0)
                 return r;
 
+        if (arg_image) {
+                assert(!arg_root);
+
+                r = mount_image_privately_interactively(
+                                arg_image,
+                                DISSECT_IMAGE_REQUIRE_ROOT |
+                                DISSECT_IMAGE_VALIDATE_OS |
+                                DISSECT_IMAGE_RELAX_VAR_CHECK |
+                                DISSECT_IMAGE_FSCK,
+                                &unlink_dir,
+                                &loop_device,
+                                &decrypted_image);
+                if (r < 0)
+                        return r;
+
+                arg_root = strdup(unlink_dir);
+                if (!arg_root)
+                        return log_oom();
+        }
+
         if (arg_commit) {
                 const char *etc_machine_id;