From 3cd5d83ee95d4873735df14d1556ff6e642c7a75 Mon Sep 17 00:00:00 2001 From: Ondrej Kozina Date: Tue, 15 Feb 2022 12:33:59 +0100 Subject: [PATCH] Add --progress-json parameter to utilities. Progress data can now be printed out in json format suitable for machine processing. --- man/cryptsetup.8 | 19 +++++++++++ man/integritysetup.8 | 20 +++++++++++- src/cryptsetup.c | 15 ++++++--- src/cryptsetup.h | 3 ++ src/cryptsetup_arg_list.h | 2 ++ src/cryptsetup_args.h | 1 + src/integritysetup.c | 15 ++++++--- src/integritysetup_arg_list.h | 2 ++ src/integritysetup_args.h | 1 + src/utils_arg_names.h | 1 + src/utils_progress.c | 61 +++++++++++++++++++++++++++++++++-- src/utils_reencrypt.c | 44 +++++++++++++++++-------- src/utils_reencrypt_luks1.c | 46 +++++++++++++++++--------- 13 files changed, 188 insertions(+), 42 deletions(-) diff --git a/man/cryptsetup.8 b/man/cryptsetup.8 index 8935bfcd..f3294701 100644 --- a/man/cryptsetup.8 +++ b/man/cryptsetup.8 @@ -1201,6 +1201,25 @@ the passphrase verification for \fIluksFormat\fR. .B "\-\-progress-frequency " Print separate line every with wipe progress. .TP +.B "\-\-progress-json" +Prints progress data in json format suitable mostly for machine processing. +It prints separate line every half second (or based on \fI\-\-progress\-frequency\fR value). +The json output looks as follows during progress (except it's compact single line): + +.EX +{ + "device":"/dev/sda" // backing device or file + "device_bytes":"8192", // bytes of I/O so far + "device_size":"44040192", // total bytes of I/O to go + "speed":"126877696", // calculated speed in bytes per second (based on progress so far) + "eta_ms":"2520012" // estimated time to finish an operation in milliseconds + "time_ms":"5561235" // total time spent in IO operation in milliseconds +} +.EE + +Note on numbers in json output: Due to json parsers limitations all numbers are represented in a string format +due to need of full 64bit unsigned integers. +.TP .B "\-\-timeout, \-t " The number of seconds to wait before timeout on passphrase input via terminal. It is relevant every time a passphrase is asked, diff --git a/man/integritysetup.8 b/man/integritysetup.8 index ff3e1dce..4c919bcc 100644 --- a/man/integritysetup.8 +++ b/man/integritysetup.8 @@ -21,7 +21,7 @@ Formats (calculates space and dm-integrity superblock and wipes the dev \fB\fR can be [\-\-data\-device, \-\-batch\-mode, \-\-no\-wipe, \-\-journal\-size, \-\-interleave\-sectors, \-\-tag\-size, \-\-integrity, \-\-integrity\-key\-size, -\-\-integrity\-key\-file, \-\-sector\-size, \-\-progress-frequency] +\-\-integrity\-key\-file, \-\-sector\-size, \-\-progress\-frequency, \-\-progress\-json] .PP \fIopen\fR @@ -72,6 +72,24 @@ Do not ask for confirmation. .B "\-\-progress-frequency " Print separate line every with wipe progress. .TP +.B "\-\-progress-json" +Prints wipe progress data in json format suitable mostly for machine processing. +It prints separate line every half second (or based on \fI\-\-progress\-frequency\fR value). +The json output looks as follows during wipe progress (except it's compact single line): +.EX +{ + "device":"/dev/sda" // backing device or file + "device_bytes":"8192", // bytes wiped so far + "device_size":"44040192", // total bytes to wipe + "speed":"126877696", // calculated speed in bytes per second (based on progress so far) + "eta_ms":"2520012" // estimated time to finish wipe in milliseconds + "time_ms":"5561235" // total time spent wiping device in milliseconds +} +.EE + +Note on numbers in json output: Due to json parsers limitations all numbers are represented in a string format +due to need of full 64bit unsigned integers. +.TP .B "\-\-no\-wipe" Do not wipe the device after format. A device that is not initially wiped will contain invalid checksums. .TP diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 72df92b4..c681c9d9 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -1179,11 +1179,14 @@ static int _wipe_data_device(struct crypt_device *cd) { char tmp_name[64], tmp_path[128], tmp_uuid[40]; uuid_t tmp_uuid_bin; - int r; + int r = -EINVAL; + char *backing_file = NULL; struct tools_progress_params prog_parms = { .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID), .batch_mode = ARG_SET(OPT_BATCH_MODE_ID), - .interrupt_message = _("\nWipe interrupted.") + .json_output = ARG_SET(OPT_PROGRESS_JSON_ID), + .interrupt_message = _("\nWipe interrupted."), + .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file) }; if (!ARG_SET(OPT_BATCH_MODE_ID)) @@ -1195,14 +1198,14 @@ static int _wipe_data_device(struct crypt_device *cd) uuid_generate(tmp_uuid_bin); uuid_unparse(tmp_uuid_bin, tmp_uuid); if (snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid) < 0) - return -EINVAL; + goto out; if (snprintf(tmp_path, sizeof(tmp_path), "%s/%s", crypt_get_dir(), tmp_name) < 0) - return -EINVAL; + goto out; r = crypt_activate_by_volume_key(cd, tmp_name, NULL, 0, CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL); if (r < 0) - return r; + goto out; /* Wipe the device */ set_int_handler(0); @@ -1212,6 +1215,8 @@ static int _wipe_data_device(struct crypt_device *cd) log_err(_("Cannot deactivate temporary device %s."), tmp_path); set_int_block(0); +out: + free(backing_file); return r; } diff --git a/src/cryptsetup.h b/src/cryptsetup.h index cce4515c..f7f89586 100644 --- a/src/cryptsetup.h +++ b/src/cryptsetup.h @@ -96,10 +96,13 @@ struct tools_progress_params { struct timeval end_time; uint64_t start_offset; bool batch_mode; + bool json_output; const char *interrupt_message; + const char *device; }; int tools_progress(uint64_t size, uint64_t offset, void *usrptr); +const char *tools_get_device_name(const char *device, char **r_backing_file); int tools_read_mk(const char *file, char **key, int keysize); int tools_write_mk(const char *file, const char *key, int keysize); diff --git a/src/cryptsetup_arg_list.h b/src/cryptsetup_arg_list.h index addbf1c2..2b1ca14b 100644 --- a/src/cryptsetup_arg_list.h +++ b/src/cryptsetup_arg_list.h @@ -135,6 +135,8 @@ ARG(OPT_PERSISTENT, '\0', POPT_ARG_NONE, N_("Set activation flags persistent for ARG(OPT_PRIORITY, '\0', POPT_ARG_STRING, N_("Keyslot priority: ignore, normal, prefer"), NULL, CRYPT_ARG_STRING, {}, OPT_PRIORITY_ACTIONS) +ARG(OPT_PROGRESS_JSON, '\0', POPT_ARG_NONE, N_("Print progress data in json format (suitable for machine processing)"), NULL, CRYPT_ARG_BOOL, {}, OPT_PROGRESS_JSON_ACTIONS) + ARG(OPT_PROGRESS_FREQUENCY, '\0', POPT_ARG_STRING, N_("Progress line update (in seconds)"), N_("secs"), CRYPT_ARG_UINT32, {}, {}) ARG(OPT_READONLY, 'r', POPT_ARG_NONE, N_("Create a readonly mapping"), NULL, CRYPT_ARG_BOOL, {}, {}) diff --git a/src/cryptsetup_args.h b/src/cryptsetup_args.h index 05254da1..abcc5d7f 100644 --- a/src/cryptsetup_args.h +++ b/src/cryptsetup_args.h @@ -76,6 +76,7 @@ #define OPT_PBKDF_FORCE_ITERATIONS_ACTIONS { FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, REENCRYPT_ACTION } #define OPT_PERSISTENT_ACTIONS { OPEN_ACTION } #define OPT_PRIORITY_ACTIONS { CONFIG_ACTION } +#define OPT_PROGRESS_JSON_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION } #define OPT_REFRESH_ACTIONS { OPEN_ACTION } #define OPT_SECTOR_SIZE_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, FORMAT_ACTION } #define OPT_SERIALIZE_MEMORY_HARD_PBKDF_ACTIONS { OPEN_ACTION } diff --git a/src/integritysetup.c b/src/integritysetup.c index e738e2a3..e0400a7c 100644 --- a/src/integritysetup.c +++ b/src/integritysetup.c @@ -80,11 +80,14 @@ static int _wipe_data_device(struct crypt_device *cd, const char *integrity_key) { char tmp_name[64], tmp_path[128], tmp_uuid[40]; uuid_t tmp_uuid_bin; - int r; + int r = -EINVAL; + char *backing_file = NULL; struct tools_progress_params prog_parms = { .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID), .batch_mode = ARG_SET(OPT_BATCH_MODE_ID), - .interrupt_message = _("\nWipe interrupted.") + .json_output = ARG_SET(OPT_PROGRESS_JSON_ID), + .interrupt_message = _("\nWipe interrupted."), + .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file) }; if (!ARG_SET(OPT_BATCH_MODE_ID)) @@ -96,14 +99,14 @@ static int _wipe_data_device(struct crypt_device *cd, const char *integrity_key) uuid_generate(tmp_uuid_bin); uuid_unparse(tmp_uuid_bin, tmp_uuid); if (snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid) < 0) - return -EINVAL; + goto out; if (snprintf(tmp_path, sizeof(tmp_path), "%s/%s", crypt_get_dir(), tmp_name) < 0) - return -EINVAL; + goto out; r = crypt_activate_by_volume_key(cd, tmp_name, integrity_key, ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID), CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL); if (r < 0) - return r; + goto out; /* Wipe the device */ set_int_handler(0); @@ -113,6 +116,8 @@ static int _wipe_data_device(struct crypt_device *cd, const char *integrity_key) log_err(_("Cannot deactivate temporary device %s."), tmp_path); set_int_block(0); +out: + free(backing_file); return r; } diff --git a/src/integritysetup_arg_list.h b/src/integritysetup_arg_list.h index f2f88353..10e0dec0 100644 --- a/src/integritysetup_arg_list.h +++ b/src/integritysetup_arg_list.h @@ -77,6 +77,8 @@ ARG(OPT_NO_WIPE, '\0', POPT_ARG_NONE, N_("Do not wipe device after format"), NUL ARG(OPT_PROGRESS_FREQUENCY, '\0', POPT_ARG_STRING, N_("Progress line update (in seconds)"), N_("secs"), CRYPT_ARG_UINT32, {}, {}) +ARG(OPT_PROGRESS_JSON, '\0', POPT_ARG_NONE, N_("Print wipe progress data in json format (suitable for machine processing)"), NULL, CRYPT_ARG_BOOL, {}, OPT_PROGRESS_JSON_ACTIONS) + ARG(OPT_INTEGRITY_BITMAP_MODE, 'B', POPT_ARG_NONE, N_("Use bitmap to track changes and disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {}) ARG(OPT_INTEGRITY_RECALCULATE, '\0', POPT_ARG_NONE, N_("Recalculate initial tags automatically."), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS) diff --git a/src/integritysetup_args.h b/src/integritysetup_args.h index e77324fb..6f919fc4 100644 --- a/src/integritysetup_args.h +++ b/src/integritysetup_args.h @@ -37,6 +37,7 @@ #define OPT_JOURNAL_SIZE_ACTIONS { FORMAT_ACTION } #define OPT_NO_WIPE_ACTIONS { FORMAT_ACTION } #define OPT_INTERLEAVE_SECTORS_ACTIONS { FORMAT_ACTION } +#define OPT_PROGRESS_JSON_ACTIONS { FORMAT_ACTION } #define OPT_SECTOR_SIZE_ACTIONS { FORMAT_ACTION } #define OPT_TAG_SIZE_ACTIONS { FORMAT_ACTION } diff --git a/src/utils_arg_names.h b/src/utils_arg_names.h index ff4bdaea..bd4899f1 100644 --- a/src/utils_arg_names.h +++ b/src/utils_arg_names.h @@ -118,6 +118,7 @@ #define OPT_PERSISTENT "persistent" #define OPT_PLUGIN "plugin" #define OPT_PRIORITY "priority" +#define OPT_PROGRESS_JSON "progress-json" #define OPT_PROGRESS_FREQUENCY "progress-frequency" #define OPT_READONLY "readonly" #define OPT_REDUCE_DEVICE_SIZE "reduce-device-size" diff --git a/src/utils_progress.c b/src/utils_progress.c index f55b3bc4..55a3f497 100644 --- a/src/utils_progress.c +++ b/src/utils_progress.c @@ -224,17 +224,59 @@ static void tools_time_progress(uint64_t device_size, uint64_t bytes, struct too fflush(stdout); } +static void log_progress_json(const char *device, uint64_t bytes, uint64_t device_size, uint64_t eta, uint64_t uib, uint64_t time_spent) +{ + int r; + char json[PATH_MAX+256]; + + r = snprintf(json, sizeof(json) - 1, + "{\"device\":\"%s\"," + "\"device_bytes\":\"%" PRIu64 "\"," /* in bytes */ + "\"device_size\":\"%" PRIu64 "\"," /* in bytes */ + "\"speed\":\"%" PRIu64 "\"," /* in bytes per second */ + "\"eta_ms\":\"%" PRIu64 "\"," /* in milliseconds */ + "\"time_ms\":\"%" PRIu64 "\"}\n", /* in milliseconds */ + device, bytes, device_size, uib, eta, time_spent); + + if (r < 0 || (size_t)r >= sizeof(json) - 1) + return; + + log_std(json); +} + +static void tools_time_progress_json(uint64_t device_size, uint64_t bytes, struct tools_progress_params *parms) +{ + double tdiff, uib; + bool final = (bytes == device_size); + + if (!calculate_tdiff(final, bytes, parms, &tdiff)) + return; + + uib = (double)(bytes - parms->start_offset) / tdiff; + + log_progress_json(parms->device, + bytes, + device_size, + final ? UINT64_C(0) : (uint64_t)((device_size / uib - tdiff) * 1E3), + (uint64_t)uib, + (uint64_t)(tdiff * 1E3)); + + fflush(stdout); +} + int tools_progress(uint64_t size, uint64_t offset, void *usrptr) { int r = 0; struct tools_progress_params *parms = (struct tools_progress_params *)usrptr; - if (parms && !parms->batch_mode) + if (parms && parms->json_output) + tools_time_progress_json(size, offset, parms); + else if (parms && !parms->batch_mode) tools_time_progress(size, offset, parms); check_signal(&r); if (r) { - if (!parms || !parms->frequency) + if (!parms || (!parms->frequency && !parms->json_output)) tools_clear_line(); if (parms && parms->interrupt_message) log_err("%s", parms->interrupt_message); @@ -242,3 +284,18 @@ int tools_progress(uint64_t size, uint64_t offset, void *usrptr) return r; } + +const char *tools_get_device_name(const char *device, char **r_backing_file) +{ + char *bfile; + + assert(r_backing_file); + + bfile = crypt_loop_backing_file(device); + if (bfile) { + *r_backing_file = bfile; + return bfile; + } + + return device; +} diff --git a/src/utils_reencrypt.c b/src/utils_reencrypt.c index d65dd95f..99759434 100644 --- a/src/utils_reencrypt.c +++ b/src/utils_reencrypt.c @@ -849,12 +849,15 @@ static int luks2_reencrypt_in_progress(struct crypt_device *cd) static int encrypt_luks2(int action_argc, const char **action_argv) { enum device_status_info dev_st; - int r = 0; + int r = -EINVAL; struct crypt_device *cd = NULL; + char *backing_file = NULL; struct tools_progress_params prog_parms = { .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID), .batch_mode = ARG_SET(OPT_BATCH_MODE_ID), - .interrupt_message = _("\nReencryption interrupted.") + .json_output = ARG_SET(OPT_PROGRESS_JSON_ID), + .interrupt_message = _("\nReencryption interrupted."), + .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file) }; if (ARG_SET(OPT_RESUME_ONLY_ID)) { @@ -864,7 +867,7 @@ static int encrypt_luks2(int action_argc, const char **action_argv) dev_st = load_luks(&cd, CRYPT_LUKS2, ARG_STR(OPT_HEADER_ID), action_argv[0]); if (dev_st != DEVICE_LUKS2) - return -EINVAL; + goto out; r = luks2_reencrypt_in_progress(cd); if (r < 0) @@ -886,38 +889,44 @@ static int encrypt_luks2(int action_argc, const char **action_argv) } out: crypt_free(cd); + free(backing_file); return r; } static int decrypt_luks2(struct crypt_device *cd, int action_argc, const char **action_argv) { - int r = 0; + int r = -EINVAL; + char *backing_file = NULL; struct tools_progress_params prog_parms = { .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID), .batch_mode = ARG_SET(OPT_BATCH_MODE_ID), - .interrupt_message = _("\nReencryption interrupted.") + .json_output = ARG_SET(OPT_PROGRESS_JSON_ID), + .interrupt_message = _("\nReencryption interrupted."), + .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file) }; if (!ARG_SET(OPT_HEADER_ID)) { log_err(_("LUKS2 decryption requires option --header.")); - return -EINVAL; + goto out; } r = luks2_reencrypt_in_progress(cd); if (r < 0) /* error */ - return r; + goto out; if (r > 0) { /* in progress */ if (ARG_SET(OPT_INIT_ONLY_ID)) { log_err(_("LUKS2 reencryption already initialized. Aborting operation.")); - return -EINVAL; + r = -EINVAL; + goto out; } r = action_reencrypt_load(cd, action_argv[0]); } else { if (ARG_SET(OPT_RESUME_ONLY_ID)) { log_err(_("Device reencryption not in progress.")); - return -EINVAL; + r = -EINVAL; + goto out; } r = action_decrypt_luks2(cd, action_argv[0]); } @@ -927,32 +936,39 @@ static int decrypt_luks2(struct crypt_device *cd, int action_argc, const char ** r = crypt_reencrypt_run(cd, tools_progress, &prog_parms); } +out: + free(backing_file); return r; } static int reencrypt_luks2(struct crypt_device *cd, int action_argc, const char **action_argv) { int r; + char *backing_file = NULL; struct tools_progress_params prog_parms = { .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID), .batch_mode = ARG_SET(OPT_BATCH_MODE_ID), - .interrupt_message = _("\nReencryption interrupted.") + .json_output = ARG_SET(OPT_PROGRESS_JSON_ID), + .interrupt_message = _("\nReencryption interrupted."), + .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file) }; r = luks2_reencrypt_in_progress(cd); if (r < 0) /* error */ - return r; + goto out; if (r > 0) { /* in progress */ if (ARG_SET(OPT_INIT_ONLY_ID)) { log_err(_("LUKS2 reencryption already initialized. Aborting operation.")); - return -EINVAL; + r = -EINVAL; + goto out; } r = action_reencrypt_load(cd, action_argv[0]); } else { if (ARG_SET(OPT_RESUME_ONLY_ID)) { log_err(_("Device reencryption not in progress.")); - return -EINVAL; + r = -EINVAL; + goto out; } r = action_reencrypt_luks2(cd, action_argv[0]); } @@ -962,6 +978,8 @@ static int reencrypt_luks2(struct crypt_device *cd, int action_argc, const char r = crypt_reencrypt_run(cd, tools_progress, &prog_parms); } +out: + free(backing_file); return r; } diff --git a/src/utils_reencrypt_luks1.c b/src/utils_reencrypt_luks1.c index 5544fdb7..341ce0e6 100644 --- a/src/utils_reencrypt_luks1.c +++ b/src/utils_reencrypt_luks1.c @@ -717,10 +717,14 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new, size_t block_size, void *buf, uint64_t *bytes) { ssize_t s1, s2; + int r = -EIO; + char *backing_file = NULL; struct tools_progress_params prog_parms = { .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID), .batch_mode = ARG_SET(OPT_BATCH_MODE_ID), - .interrupt_message = _("\nReencryption interrupted.") + .json_output = ARG_SET(OPT_PROGRESS_JSON_ID), + .interrupt_message = _("\nReencryption interrupted."), + .device = tools_get_device_name(rc->device, &backing_file) }; log_dbg("Reencrypting in forward direction."); @@ -728,7 +732,7 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new, if (lseek64(fd_old, rc->device_offset, SEEK_SET) < 0 || lseek64(fd_new, rc->device_offset, SEEK_SET) < 0) { log_err(_("Cannot seek to device offset.")); - return -EIO; + goto out; } rc->resume_bytes = *bytes = rc->device_offset; @@ -736,7 +740,7 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new, tools_progress(rc->device_size, *bytes, &prog_parms); if (write_log(rc) < 0) - return -EIO; + goto out; while (!quit && rc->device_offset < rc->device_size) { if ((rc->device_size - rc->device_offset) < (uint64_t)block_size) @@ -746,7 +750,7 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new, (rc->device_offset + s1) != rc->device_size)) { log_dbg("Read error, expecting %zu, got %zd.", block_size, s1); - return -EIO; + goto out; } /* If device_size is forced, never write more than limit */ @@ -757,16 +761,16 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new, if (s2 < 0) { log_dbg("Write error, expecting %zu, got %zd.", block_size, s2); - return -EIO; + goto out; } rc->device_offset += s1; if (ARG_SET(OPT_WRITE_LOG_ID) && write_log(rc) < 0) - return -EIO; + goto out; if (ARG_SET(OPT_USE_FSYNC_ID) && fsync(fd_new) < 0) { log_dbg("Write error, fsync."); - return -EIO; + goto out; } *bytes += (uint64_t)s2; @@ -774,7 +778,10 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new, tools_progress(rc->device_size, *bytes, &prog_parms); } - return quit ? -EAGAIN : 0; + r = 0; +out: + free(backing_file); + return quit ? -EAGAIN : r; } static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new, @@ -782,10 +789,14 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new, { ssize_t s1, s2, working_block; off64_t working_offset; + int r = -EIO; + char *backing_file = NULL; struct tools_progress_params prog_parms = { .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID), .batch_mode = ARG_SET(OPT_BATCH_MODE_ID), - .interrupt_message = _("\nReencryption interrupted.") + .json_output = ARG_SET(OPT_PROGRESS_JSON_ID), + .interrupt_message = _("\nReencryption interrupted."), + .device = tools_get_device_name(rc->device, &backing_file) }; log_dbg("Reencrypting in backward direction."); @@ -802,7 +813,7 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new, tools_progress(rc->device_size, *bytes, &prog_parms); if (write_log(rc) < 0) - return -EIO; + goto out; /* dirty the device during ENCRYPT mode */ rc->stained = 1; @@ -819,30 +830,30 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new, if (lseek64(fd_old, working_offset, SEEK_SET) < 0 || lseek64(fd_new, working_offset, SEEK_SET) < 0) { log_err(_("Cannot seek to device offset.")); - return -EIO; + goto out; } s1 = read_buf(fd_old, buf, working_block); if (s1 < 0 || (s1 != working_block)) { log_dbg("Read error, expecting %zu, got %zd.", block_size, s1); - return -EIO; + goto out; } s2 = write(fd_new, buf, working_block); if (s2 < 0) { log_dbg("Write error, expecting %zu, got %zd.", block_size, s2); - return -EIO; + goto out; } rc->device_offset -= s1; if (ARG_SET(OPT_WRITE_LOG_ID) && write_log(rc) < 0) - return -EIO; + goto out; if (ARG_SET(OPT_USE_FSYNC_ID) && fsync(fd_new) < 0) { log_dbg("Write error, fsync."); - return -EIO; + goto out; } *bytes += (uint64_t)s2; @@ -850,7 +861,10 @@ static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new, tools_progress(rc->device_size, *bytes, &prog_parms); } - return quit ? -EAGAIN : 0; + r = 0; +out: + free(backing_file); + return quit ? -EAGAIN : r; } static void zero_rest_of_device(int fd, size_t block_size, void *buf,