]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
veritysetup: use dispatch_verb()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 18 Jan 2025 20:10:04 +0000 (05:10 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 20 Jan 2025 18:42:38 +0000 (03:42 +0900)
src/veritysetup/veritysetup.c

index d133572464410187e04420861bd1d46dddc005aa..97f233c906e22bc1febaefda1787bb546c4dd4e4 100644 (file)
@@ -17,6 +17,7 @@
 #include "process-util.h"
 #include "string-util.h"
 #include "terminal-util.h"
+#include "verbs.h"
 
 static char *arg_hash = NULL;
 static bool arg_superblock = true;
@@ -274,158 +275,161 @@ static int parse_options(const char *options) {
         return r;
 }
 
-static int run(int argc, char *argv[]) {
+static int verb_attach(int argc, char *argv[], void *userdata) {
         _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
-        const char *verb;
+        _cleanup_free_ void *m = NULL;
+        struct crypt_params_verity p = {};
+        crypt_status_info status;
+        size_t l;
         int r;
 
-        if (argv_looks_like_help(argc, argv))
-                return help();
-
-        if (argc < 3)
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires at least two arguments.");
+        assert(argc >= 5);
 
-        log_setup();
+        const char *volume = argv[1],
+                *data_device = argv[2],
+                *verity_device = argv[3],
+                *root_hash = argv[4],
+                *options = mangle_none(argc > 5 ? argv[5] : NULL);
 
-        cryptsetup_enable_logging(NULL);
+        if (!filename_is_valid(volume))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
 
-        umask(0022);
+        r = unhexmem(root_hash, &m, &l);
+        if (r < 0)
+                return log_error_errno(r, "Failed to parse root hash: %m");
 
-        verb = argv[1];
+        r = crypt_init(&cd, verity_device);
+        if (r < 0)
+                return log_error_errno(r, "Failed to open verity device %s: %m", verity_device);
 
-        if (streq(verb, "attach")) {
-                const char *volume, *data_device, *verity_device, *root_hash, *options;
-                _cleanup_free_ void *m = NULL;
-                struct crypt_params_verity p = {};
-                crypt_status_info status;
-                size_t l;
+        cryptsetup_enable_logging(cd);
 
-                if (argc < 6)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least four arguments.");
+        status = crypt_status(cd, volume);
+        if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
+                log_info("Volume %s already active.", volume);
+                return 0;
+        }
 
-                volume = argv[2];
-                data_device = argv[3];
-                verity_device = argv[4];
-                root_hash = argv[5];
-                options = mangle_none(argc > 6 ? argv[6] : NULL);
+        if (options) {
+                r = parse_options(options);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse options: %m");
+        }
 
-                if (!filename_is_valid(volume))
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
+        if (arg_superblock) {
+                p = (struct crypt_params_verity) {
+                        .fec_device = arg_fec_what,
+                        .hash_area_offset = arg_hash_offset,
+                        .fec_area_offset = arg_fec_offset,
+                        .fec_roots = arg_fec_roots,
+                };
 
-                r = unhexmem(root_hash, &m, &l);
+                r = crypt_load(cd, CRYPT_VERITY, &p);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to parse root hash: %m");
-
-                r = crypt_init(&cd, verity_device);
+                        return log_error_errno(r, "Failed to load verity superblock: %m");
+        } else {
+                p = (struct crypt_params_verity) {
+                        .hash_name = arg_hash,
+                        .data_device = data_device,
+                        .fec_device = arg_fec_what,
+                        .salt = arg_salt,
+                        .salt_size = arg_salt_size,
+                        .hash_type = arg_format,
+                        .data_block_size = arg_data_block_size,
+                        .hash_block_size = arg_hash_block_size,
+                        .data_size = arg_data_blocks,
+                        .hash_area_offset = arg_hash_offset,
+                        .fec_area_offset = arg_fec_offset,
+                        .fec_roots = arg_fec_roots,
+                        .flags = CRYPT_VERITY_NO_HEADER,
+                };
+
+                r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, arg_uuid, NULL, 0, &p);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to open verity device %s: %m", verity_device);
-
-                cryptsetup_enable_logging(cd);
-
-                status = crypt_status(cd, volume);
-                if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
-                        log_info("Volume %s already active.", volume);
-                        return 0;
-                }
+                        return log_error_errno(r, "Failed to format verity superblock: %m");
+        }
 
-                if (options) {
-                        r = parse_options(options);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to parse options: %m");
-                }
+        r = crypt_set_data_device(cd, data_device);
+        if (r < 0)
+                return log_error_errno(r, "Failed to configure data device: %m");
 
-                if (arg_superblock) {
-                        p = (struct crypt_params_verity) {
-                                .fec_device = arg_fec_what,
-                                .hash_area_offset = arg_hash_offset,
-                                .fec_area_offset = arg_fec_offset,
-                                .fec_roots = arg_fec_roots,
-                        };
+        if (arg_root_hash_signature) {
+#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
+                _cleanup_free_ char *hash_sig = NULL;
+                size_t hash_sig_size;
+                char *value;
 
-                        r = crypt_load(cd, CRYPT_VERITY, &p);
+                if ((value = startswith(arg_root_hash_signature, "base64:"))) {
+                        r = unbase64mem(value, (void*) &hash_sig, &hash_sig_size);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to load verity superblock: %m");
+                                return log_error_errno(r, "Failed to parse root hash signature '%s': %m", arg_root_hash_signature);
                 } else {
-                        p = (struct crypt_params_verity) {
-                                .hash_name = arg_hash,
-                                .data_device = data_device,
-                                .fec_device = arg_fec_what,
-                                .salt = arg_salt,
-                                .salt_size = arg_salt_size,
-                                .hash_type = arg_format,
-                                .data_block_size = arg_data_block_size,
-                                .hash_block_size = arg_hash_block_size,
-                                .data_size = arg_data_blocks,
-                                .hash_area_offset = arg_hash_offset,
-                                .fec_area_offset = arg_fec_offset,
-                                .fec_roots = arg_fec_roots,
-                                .flags = CRYPT_VERITY_NO_HEADER,
-                        };
-
-                        r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, arg_uuid, NULL, 0, &p);
+                        r = read_full_file_full(
+                                        AT_FDCWD, arg_root_hash_signature, UINT64_MAX, SIZE_MAX,
+                                        READ_FULL_FILE_CONNECT_SOCKET,
+                                        NULL,
+                                        &hash_sig, &hash_sig_size);
                         if (r < 0)
-                                return log_error_errno(r, "Failed to format verity superblock: %m");
+                                return log_error_errno(r, "Failed to read root hash signature: %m");
                 }
 
-                r = crypt_set_data_device(cd, data_device);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to configure data device: %m");
-
-                if (arg_root_hash_signature) {
-#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
-                        _cleanup_free_ char *hash_sig = NULL;
-                        size_t hash_sig_size;
-                        char *value;
-
-                        if ((value = startswith(arg_root_hash_signature, "base64:"))) {
-                                r = unbase64mem(value, (void*) &hash_sig, &hash_sig_size);
-                                if (r < 0)
-                                        return log_error_errno(r, "Failed to parse root hash signature '%s': %m", arg_root_hash_signature);
-                        } else {
-                                r = read_full_file_full(
-                                                AT_FDCWD, arg_root_hash_signature, UINT64_MAX, SIZE_MAX,
-                                                READ_FULL_FILE_CONNECT_SOCKET,
-                                                NULL,
-                                                &hash_sig, &hash_sig_size);
-                                if (r < 0)
-                                        return log_error_errno(r, "Failed to read root hash signature: %m");
-                        }
-
-                        r = crypt_activate_by_signed_key(cd, volume, m, l, hash_sig, hash_sig_size, arg_activate_flags);
+                r = crypt_activate_by_signed_key(cd, volume, m, l, hash_sig, hash_sig_size, arg_activate_flags);
 #else
-                        assert_not_reached();
+                assert_not_reached();
 #endif
-                } else
-                        r = crypt_activate_by_volume_key(cd, volume, m, l, arg_activate_flags);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to set up verity device '%s': %m", volume);
+        } else
+                r = crypt_activate_by_volume_key(cd, volume, m, l, arg_activate_flags);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set up verity device '%s': %m", volume);
 
-        } else if (streq(verb, "detach")) {
-                const char *volume;
+        return 0;
+}
 
-                volume = argv[2];
+static int verb_detach(int argc, char *argv[], void *userdata) {
+        _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
+        int r;
 
-                if (!filename_is_valid(volume))
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
+        assert(argc == 2);
 
-                r = crypt_init_by_name(&cd, volume);
-                if (r == -ENODEV) {
-                        log_info("Volume %s 'already' inactive.", volume);
-                        return 0;
-                }
-                if (r < 0)
-                        return log_error_errno(r, "crypt_init_by_name() for volume '%s' failed: %m", volume);
+        const char *volume = argv[1];
 
-                cryptsetup_enable_logging(cd);
+        if (!filename_is_valid(volume))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
 
-                r = crypt_deactivate(cd, volume);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to deactivate volume '%s': %m", volume);
+        r = crypt_init_by_name(&cd, volume);
+        if (r == -ENODEV) {
+                log_info("Volume %s 'already' inactive.", volume);
+                return 0;
+        }
+        if (r < 0)
+                return log_error_errno(r, "crypt_init_by_name() for volume '%s' failed: %m", volume);
 
-        } else
-                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", verb);
+        cryptsetup_enable_logging(cd);
+
+        r = crypt_deactivate(cd, volume);
+        if (r < 0)
+                return log_error_errno(r, "Failed to deactivate volume '%s': %m", volume);
 
         return 0;
 }
 
+static int run(int argc, char *argv[]) {
+        if (argv_looks_like_help(argc, argv))
+                return help();
+
+        log_setup();
+
+        cryptsetup_enable_logging(NULL);
+
+        umask(0022);
+
+        static const Verb verbs[] = {
+                { "attach", 5, 6, 0, verb_attach },
+                { "detach", 2, 2, 0, verb_detach },
+                {}
+        };
+
+        return dispatch_verb(argc, argv, verbs, NULL);
+}
+
 DEFINE_MAIN_FUNCTION(run);