*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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 ROUND_SECTOR(x) (((x) + SECTOR_SIZE - 1) / SECTOR_SIZE)
-#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 const char **action_argv;
-static volatile int quit = 0;
-
#define MAX_SLOT 8
struct reenc_ctx {
char *device;
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);
-}
-
-static void int_handler(int sig __attribute__((__unused__)))
-{
- quit++;
-}
-
-static void set_int_block(int block)
-{
- sigset_t signals_open;
-
- sigemptyset(&signals_open);
- sigaddset(&signals_open, SIGINT);
- sigaddset(&signals_open, SIGTERM);
- sigprocmask(block ? SIG_SETMASK : SIG_UNBLOCK, &signals_open, NULL);
-}
-
-static void set_int_handler(void)
-{
- struct sigaction sigaction_open;
-
- memset(&sigaction_open, 0, sizeof(struct sigaction));
- sigaction_open.sa_handler = int_handler;
- sigaction(SIGINT, &sigaction_open, 0);
- sigaction(SIGTERM, &sigaction_open, 0);
- set_int_block(0);
+ tool_log(level, msg, usrptr);
}
/* The difference in seconds between two times in "timeval" format. */
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 */
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"));
static int open_log(struct reenc_ctx *rc)
{
- int flags, create_new;
- struct stat st;
+ int flags = opt_directio ? O_DIRECT : 0;
- if (!stat(rc->log_file, &st))
- create_new = 0;
- else if (errno == ENOENT)
- create_new = 1;
- else
- return -EINVAL;
-
- if (create_new) {
- log_dbg("Creating LUKS reencryption log file %s.", rc->log_file);
- flags = opt_directio ? O_RDWR|O_CREAT|O_DIRECT : O_RDWR|O_CREAT;
- rc->log_fd = open(rc->log_file, flags, S_IRUSR|S_IWUSR);
- if (rc->log_fd == -1)
- return -EINVAL;
- } else {
+ rc->log_fd = open(rc->log_file, O_RDWR|O_EXCL|O_CREAT|flags, S_IRUSR|S_IWUSR);
+ if (rc->log_fd != -1) {
+ log_dbg("Created LUKS reencryption log file %s.", rc->log_file);
+ } else if (errno == EEXIST) {
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)
- return -EINVAL;
+ rc->log_fd = open(rc->log_file, O_RDWR|flags);
rc->in_progress = 1;
}
+ if (rc->log_fd == -1)
+ return -EINVAL;
+
if (posix_memalign((void *)&rc->log_buf, alignment(rc->log_fd), SECTOR_SIZE)) {
log_err(_("Allocation of aligned memory failed.\n"));
close_log(rc);
return -ENOMEM;
}
- if (create_new && write_log(rc) < 0) {
+ if (!rc->in_progress && write_log(rc) < 0) {
close_log(rc);
return -EIO;
}
(r = crypt_set_data_device(cd, rc->device)))
goto out;
+ log_verbose(_("Activating temporary device using old LUKS header.\n"));
if ((r = crypt_activate_by_passphrase(cd, rc->header_file_org,
opt_key_slot, rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen,
CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_PRIVATE)) < 0)
(r = crypt_set_data_device(cd_new, rc->device)))
goto out;
+ log_verbose(_("Activating temporary device using new LUKS header.\n"));
if ((r = crypt_activate_by_passphrase(cd_new, rc->header_file_new,
opt_key_slot, rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen,
CRYPT_ACTIVATE_SHARED|CRYPT_ACTIVATE_PRIVATE)) < 0)
if (!mib)
return;
+ /* FIXME: calculate this from last minute only and remaining space */
eta = (unsigned long long)(rc->device_size / 1024 / 1024 / mib - tdiff);
/* vt100 code clear line */
goto out;
}
- set_int_handler();
+ set_int_handler(0);
gettimeofday(&rc->start_time, NULL);
if (rc->reencrypt_direction == FORWARD)
retry_count = opt_tries ?: 1;
while (retry_count--) {
- set_int_handler();
+ set_int_handler(0);
r = crypt_get_key(msg, &rc->p[slot].password,
&rc->p[slot].passwordLen,
0, 0, NULL /*opt_key_file*/,
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[] = {
poptContext popt_context;
int r;
- crypt_set_log_callback(NULL, _log, NULL);
+ crypt_set_log_callback(NULL, tool_log, NULL);
set_int_block(1);
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);
}