#include "process-util.h"
#include "string-util.h"
#include "terminal-util.h"
+#include "verbs.h"
static uint32_t arg_activate_flags;
static int arg_percent;
return "crc32c";
}
-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;
- char *verb, *volume;
+ crypt_status_info status;
+ _cleanup_(erase_and_freep) void *key_buf = NULL;
+ size_t key_buf_size = 0;
int r;
- if (argv_looks_like_help(argc, argv))
- return help();
+ /* attach name device optional_key_file optional_options */
- if (argc < 3)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires at least two arguments.");
+ assert(argc >= 3 && argc <= 5);
- verb = argv[1];
- volume = argv[2];
+ const char *volume = argv[1],
+ *device = argv[2],
+ *key_file = mangle_none(argc > 3 ? argv[3] : NULL),
+ *options = mangle_none(argc > 4 ? argv[4] : NULL);
- log_setup();
+ if (!filename_is_valid(volume))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
- cryptsetup_enable_logging(NULL);
+ if (key_file) {
+ r = load_key_file(key_file, &key_buf, &key_buf_size);
+ if (r < 0)
+ return r;
+ }
- umask(0022);
+ if (options) {
+ r = parse_integrity_options(options, &arg_activate_flags, &arg_percent,
+ &arg_commit_time, &arg_existing_data_device, &arg_integrity_algorithm);
+ if (r < 0)
+ return r;
+ }
- if (streq(verb, "attach")) {
- /* attach name device optional_key_file optional_options */
+ r = crypt_init(&cd, device);
+ if (r < 0)
+ return log_error_errno(r, "Failed to open integrity device %s: %m", device);
- crypt_status_info status;
- _cleanup_(erase_and_freep) void *key_buf = NULL;
- const char *device, *key_file, *options;
- size_t key_buf_size = 0;
+ cryptsetup_enable_logging(cd);
- if (argc < 4)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least three arguments.");
+ status = crypt_status(cd, volume);
+ if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) {
+ log_info("Volume %s already active.", volume);
+ return 0;
+ }
- if (argc > 6)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach has a maximum of five arguments.");
+ r = crypt_load(cd,
+ CRYPT_INTEGRITY,
+ &(struct crypt_params_integrity) {
+ .journal_watermark = arg_percent,
+ .journal_commit_time = DIV_ROUND_UP(arg_commit_time, USEC_PER_SEC),
+ .integrity = integrity_algorithm_select(key_buf),
+ });
+ if (r < 0)
+ return log_error_errno(r, "Failed to load integrity superblock: %m");
- device = argv[3];
- key_file = mangle_none(argc > 4 ? argv[4] : NULL);
- options = mangle_none(argc > 5 ? argv[5] : NULL);
+ if (!isempty(arg_existing_data_device)) {
+ r = crypt_set_data_device(cd, arg_existing_data_device);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add separate data device: %m");
+ }
- if (!filename_is_valid(volume))
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
+ r = crypt_activate_by_volume_key(cd, volume, key_buf, key_buf_size, arg_activate_flags);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set up integrity device: %m");
- if (key_file) {
- r = load_key_file(key_file, &key_buf, &key_buf_size);
- if (r < 0)
- return r;
- }
+ return 0;
+}
- if (options) {
- r = parse_integrity_options(options, &arg_activate_flags, &arg_percent,
- &arg_commit_time, &arg_existing_data_device, &arg_integrity_algorithm);
- if (r < 0)
- return r;
- }
+static int verb_detach(int argc, char *argv[], void *userdata) {
+ _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
+ int r;
- r = crypt_init(&cd, device);
- if (r < 0)
- return log_error_errno(r, "Failed to open integrity device %s: %m", 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;
- }
-
- r = crypt_load(cd,
- CRYPT_INTEGRITY,
- &(struct crypt_params_integrity) {
- .journal_watermark = arg_percent,
- .journal_commit_time = DIV_ROUND_UP(arg_commit_time, USEC_PER_SEC),
- .integrity = integrity_algorithm_select(key_buf),
- });
- if (r < 0)
- return log_error_errno(r, "Failed to load integrity superblock: %m");
+ assert(argc == 2);
- if (!isempty(arg_existing_data_device)) {
- r = crypt_set_data_device(cd, arg_existing_data_device);
- if (r < 0)
- return log_error_errno(r, "Failed to add separate data device: %m");
- }
+ const char *volume = argv[1];
- r = crypt_activate_by_volume_key(cd, volume, key_buf, key_buf_size, arg_activate_flags);
- if (r < 0)
- return log_error_errno(r, "Failed to set up integrity device: %m");
+ if (!filename_is_valid(volume))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Volume name '%s' is not valid.", volume);
- } else if (streq(verb, "detach")) {
+ 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() failed: %m");
- if (argc > 3)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "detach has a maximum of two arguments.");
+ 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: %m");
- 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() failed: %m");
+ return 0;
+}
- cryptsetup_enable_logging(cd);
+static int run(int argc, char *argv[]) {
+ if (argv_looks_like_help(argc, argv))
+ return help();
- r = crypt_deactivate(cd, volume);
- if (r < 0)
- return log_error_errno(r, "Failed to deactivate: %m");
+ log_setup();
- } else
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", verb);
+ cryptsetup_enable_logging(NULL);
- return 0;
+ umask(0022);
+
+ static const Verb verbs[] = {
+ { "attach", 3, 5, 0, verb_attach },
+ { "detach", 2, 2, 0, verb_detach },
+ {}
+ };
+
+ return dispatch_verb(argc, argv, verbs, NULL);
}
DEFINE_MAIN_FUNCTION(run);