* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#define PACKAGE_REENC "crypt_reencrypt"
-
-#define _LARGEFILE64_SOURCE
-#define _FILE_OFFSET_BITS 64
-#define SECTOR_SIZE 512
-#define NO_UUID "cafecafe-cafe-cafe-cafe-cafecafeeeee"
-#define MAX_BCK_SECTORS 8192
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <inttypes.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/stat.h>
+#include "cryptsetup.h"
#include <sys/ioctl.h>
#include <sys/time.h>
#include <linux/fs.h>
#include <arpa/inet.h>
-#include <fcntl.h>
#include <signal.h>
-#include <popt.h>
-#include "cryptsetup.h"
+#define PACKAGE_REENC "crypt_reencrypt"
+
+#define NO_UUID "cafecafe-cafe-cafe-cafe-cafecafeeeee"
+#define MAX_BCK_SECTORS 8192
-static int opt_verbose = 0;
-static int opt_debug = 0;
static const char *opt_cipher = NULL;
static const char *opt_hash = NULL;
static const char *opt_key_file = NULL;
static long opt_keyfile_size = 0;
static long opt_keyfile_offset = 0;
static int opt_iteration_time = 1000;
-static int opt_batch_mode = 0;
static int opt_version_mode = 0;
static int opt_random = 0;
static int opt_urandom = 0;
static int opt_bsize = 4;
-static int opt_reduce_device_size = 0;
static int opt_directio = 0;
static int opt_fsync = 0;
static int opt_write_log = 0;
static int opt_key_size = 0;
static int opt_new = 0;
+static const char *opt_reduce_size_str = NULL;
+static uint64_t opt_reduce_size = 0;
+
+static const char *opt_device_size_str = NULL;
+static uint64_t opt_device_size = 0;
+
static const char **action_argv;
static volatile int quit = 0;
struct reenc_ctx {
char *device;
char *device_uuid;
- uint64_t device_size;
+ uint64_t device_size; /* overrided by parameter */
+ uint64_t device_size_real;
uint64_t device_offset;
uint64_t device_shift;
int keyslot;
struct timeval start_time, end_time;
- uint64_t restart_bytes;
+ uint64_t resume_bytes;
};
char MAGIC[] = {'L','U','K','S', 0xba, 0xbe};
CHECK_OPEN,
} header_magic;
-__attribute__((format(printf, 5, 6)))
-static void clogger(struct crypt_device *cd, int level, const char *file,
- int line, const char *format, ...)
-{
- va_list argp;
- char *target = NULL;
-
- va_start(argp, format);
-
- if (vasprintf(&target, format, argp) > 0) {
- if (level >= 0) {
- crypt_log(cd, level, target);
- } else if (opt_debug)
- printf("# %s\n", target);
- }
-
- va_end(argp);
- free(target);
-}
-
-static void _log(int level, const char *msg, void *usrptr __attribute__((unused)))
-{
- switch(level) {
-
- case CRYPT_LOG_NORMAL:
- fputs(msg, stdout);
- break;
- case CRYPT_LOG_VERBOSE:
- if (opt_verbose)
- fputs(msg, stdout);
- break;
- case CRYPT_LOG_ERROR:
- fputs(msg, stderr);
- break;
- case CRYPT_LOG_DEBUG:
- if (opt_debug)
- printf("# %s\n", msg);
- break;
- default:
- fprintf(stderr, "Internal error on logging class for msg: %s", msg);
- break;
- }
-}
-
static void _quiet_log(int level, const char *msg, void *usrptr)
{
if (!opt_debug)
return;
- _log(level, msg, usrptr);
+ tool_log(level, msg, usrptr);
}
static void int_handler(int sig __attribute__((__unused__)))
s = read(devfd, buf, SECTOR_SIZE);
if (s < 0 || s != SECTOR_SIZE) {
log_err(_("Cannot read device %s.\n"), rc->device);
- close(devfd);
- return -EIO;
+ r = -EIO;
+ goto out;
}
/* Be sure that we do not process new version of header */
size = data_sector * SECTOR_SIZE;
/* if reducing size, be sure we have enough space */
- if (opt_reduce_device_size)
- size += (opt_reduce_device_size * SECTOR_SIZE);
+ if (opt_reduce_size)
+ size += opt_reduce_size;
log_dbg("Creating empty file %s of size %lu.", new_file, (unsigned long)size);
1, rc->device_uuid, rc->reencrypt_direction,
rc->device_offset, rc->device_shift);
- lseek(rc->log_fd, 0, SEEK_SET);
+ if (lseek(rc->log_fd, 0, SEEK_SET) == -1)
+ return -EIO;
+
r = write(rc->log_fd, rc->log_buf, SECTOR_SIZE);
if (r < 0 || r != SECTOR_SIZE) {
log_err(_("Cannot write reencryption log file.\n"));
if (rc->log_fd == -1)
return -EINVAL;
} else {
- log_std(_("Log file %s exists, restarting reencryption.\n"), rc->log_file);
+ log_std(_("Log file %s exists, resuming reencryption.\n"), rc->log_file);
flags = opt_directio ? O_RDWR|O_DIRECT : O_RDWR;
rc->log_fd = open(rc->log_file, flags);
if (rc->log_fd == -1)
params.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
params.data_alignment = crypt_get_data_offset(cd);
- params.data_alignment += opt_reduce_device_size;
+ params.data_alignment += ROUND_SECTOR(opt_reduce_size);
params.data_device = rc->device;
if (opt_cipher) {
if (r < 0)
goto out;
- params.data_alignment = opt_reduce_device_size;
+ params.data_alignment = ROUND_SECTOR(opt_reduce_size);
r = create_new_header(rc,
opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER,
opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE,
if (!tdiff)
return;
- mbytes = (bytes - rc->restart_bytes) / 1024 / 1024;
+ mbytes = (bytes - rc->resume_bytes) / 1024 / 1024;
mib = (double)(mbytes) / tdiff;
if (!mib)
return;
return -EIO;
}
- rc->restart_bytes = *bytes = rc->device_offset;
+ rc->resume_bytes = *bytes = rc->device_offset;
if (write_log(rc) < 0)
return -EIO;
return -EIO;
}
+ /* If device_size is forced, never write more than limit */
+ if ((s1 + rc->device_offset) > rc->device_size)
+ s1 = rc->device_size - rc->device_offset;
+
s2 = write(fd_new, buf, s1);
if (s2 < 0) {
log_dbg("Write error, expecting %d, got %d.",
if (!rc->in_progress) {
rc->device_offset = rc->device_size;
- rc->restart_bytes = 0;
+ rc->resume_bytes = 0;
*bytes = 0;
} else {
- rc->restart_bytes = rc->device_size - rc->device_offset;
- *bytes = rc->restart_bytes;
+ rc->resume_bytes = rc->device_size - rc->device_offset;
+ *bytes = rc->resume_bytes;
}
if (write_log(rc) < 0)
}
/* Check size */
- if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size) < 0) {
+ if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size_real) < 0) {
log_err(_("Cannot get device size.\n"));
goto out;
}
+ rc->device_size = opt_device_size ?: rc->device_size_real;
+
if (posix_memalign((void *)&buf, alignment(fd_new), block_size)) {
log_err(_("Allocation of aligned memory failed.\n"));
r = -ENOMEM;
}
if (!rc->in_progress) {
- if (!opt_reduce_device_size)
+ if (!opt_reduce_size)
rc->reencrypt_direction = FORWARD;
else {
rc->reencrypt_direction = BACKWARD;
return r;
}
-static __attribute__ ((noreturn)) void usage(poptContext popt_context,
- int exitcode, const char *error,
- const char *more)
-{
- poptPrintUsage(popt_context, stderr, 0);
- if (error)
- log_err("%s: %s\n", more, error);
- poptFreeContext(popt_context);
- exit(exitcode);
-}
-
static void help(poptContext popt_context,
enum poptCallbackReason reason __attribute__((unused)),
struct poptOption *key,
usage(popt_context, EXIT_SUCCESS, NULL, NULL);
}
-static void _dbg_version_and_cmd(int argc, const char **argv)
-{
- int i;
-
- log_std("# %s %s processing \"", PACKAGE_REENC, PACKAGE_VERSION);
- for (i = 0; i < argc; i++) {
- if (i)
- log_std(" ");
- log_std("%s", argv[i]);
- }
- log_std("\"\n");
-}
-
int main(int argc, const char **argv)
{
static struct poptOption popt_help_options[] = {
{ "key-slot", 'S', POPT_ARG_INT, &opt_key_slot, 0, N_("Use only this slot (others will be disabled)."), NULL },
{ "keyfile-offset", '\0', POPT_ARG_LONG, &opt_keyfile_offset, 0, N_("Number of bytes to skip in keyfile"), N_("bytes") },
{ "keyfile-size", 'l', POPT_ARG_LONG, &opt_keyfile_size, 0, N_("Limits the read from keyfile"), N_("bytes") },
- { "reduce-device-size",'\0', POPT_ARG_INT, &opt_reduce_device_size, 0, N_("Reduce data device size (move data offset). DANGEROUS!"), N_("SECTORS") },
+ { "reduce-device-size",'\0', POPT_ARG_STRING, &opt_reduce_size_str, 0, N_("Reduce data device size (move data offset). DANGEROUS!"), N_("bytes") },
+ { "device-size", '\0', POPT_ARG_STRING, &opt_device_size_str, 0, N_("Use only specified device size (ignore rest of device). DANGEROUS!"), N_("bytes") },
{ "new", 'N', POPT_ARG_NONE,&opt_new, 0, N_("Create new header on not encrypted device."), NULL },
POPT_TABLEEND
};
poptContext popt_context;
int r;
- crypt_set_log_callback(NULL, _log, NULL);
+ crypt_set_log_callback(NULL, tool_log, NULL);
set_int_block(1);
popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0);
poptSetOtherOptionHelp(popt_context,
- N_("[OPTION...] <device>"));
+ _("[OPTION...] <device>"));
while((r = poptGetNextOpt(popt_context)) > 0) ;
if (r < -1)
poptGetInvocationName(popt_context));
if (opt_bsize < 0 || opt_key_size < 0 || opt_iteration_time < 0 ||
- opt_tries < 0 || opt_keyfile_offset < 0 || opt_key_size < 0 ||
- opt_reduce_device_size < 0) {
+ opt_tries < 0 || opt_keyfile_offset < 0 || opt_key_size < 0) {
usage(popt_context, EXIT_FAILURE,
_("Negative number for option not permitted."),
poptGetInvocationName(popt_context));
if (opt_bsize < 1 || opt_bsize > 64)
usage(popt_context, EXIT_FAILURE,
- _("Only values between 1MiB and 64 MiB allowed for reencryption block size."),
- poptGetInvocationName(popt_context));
-
- if (opt_reduce_device_size > (64 * 1024 * 1024 / SECTOR_SIZE))
- usage(popt_context, EXIT_FAILURE,
- _("Maximum device reduce size is 64 MiB."),
+ _("Only values between 1 MiB and 64 MiB allowed for reencryption block size."),
poptGetInvocationName(popt_context));
if (opt_key_size % 8)
usage(popt_context, EXIT_FAILURE, _("Only one of --use-[u]random options is allowed."),
poptGetInvocationName(popt_context));
- if (opt_new && !opt_reduce_device_size)
- usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce_device_size."),
+ if (opt_device_size_str &&
+ crypt_string_to_size(NULL, opt_device_size_str, &opt_device_size))
+ usage(popt_context, EXIT_FAILURE, _("Invalid device size specification."),
+ poptGetInvocationName(popt_context));
+
+ if (opt_reduce_size_str &&
+ crypt_string_to_size(NULL, opt_reduce_size_str, &opt_reduce_size))
+ usage(popt_context, EXIT_FAILURE, _("Invalid device size specification."),
+ poptGetInvocationName(popt_context));
+ if (opt_reduce_size > 64 * 1024 * 1024)
+ usage(popt_context, EXIT_FAILURE, _("Maximum device reduce size is 64 MiB."),
+ poptGetInvocationName(popt_context));
+ if (opt_reduce_size % SECTOR_SIZE)
+ usage(popt_context, EXIT_FAILURE, _("Reduce size must be multiple of 512 bytes sector."),
+ poptGetInvocationName(popt_context));
+
+ if (opt_new && !opt_reduce_size)
+ usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce-device-size."),
poptGetInvocationName(popt_context));
if (opt_debug) {
opt_verbose = 1;
crypt_set_debug_level(-1);
- _dbg_version_and_cmd(argc, argv);
+ dbg_version_and_cmd(argc, argv);
}
r = run_reencrypt(action_argv[0]);
poptFreeContext(popt_context);
- /* Translate exit code to simple codes */
- switch (r) {
- case 0: r = EXIT_SUCCESS; break;
- case -EEXIST:
- case -EBUSY: r = 5; break;
- case -ENOTBLK:
- case -ENODEV: r = 4; break;
- case -ENOMEM: r = 3; break;
- case -EPERM: r = 2; break;
- default: r = EXIT_FAILURE;
- }
- return r;
+ return translate_errno(r);
}