static const char *opt_new_file = NULL;
static const char **action_argv;
-sigset_t signals_open;
+
+static volatile int quit = 0;
struct {
char *device;
_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);
+}
+
/* The difference in seconds between two times in "timeval" format. */
double time_diff(struct timeval start, struct timeval end)
{
{
ssize_t s1, s2;
- *bytes = 0;
- while (rnc.device_offset < rnc.device_size) {
+ *bytes = rnc.device_offset;
+ while (!quit && rnc.device_offset < rnc.device_size) {
s1 = read(fd_old, buf, block_size);
if (s1 < 0 || (s1 != block_size && (rnc.device_offset + s1) != rnc.device_size)) {
log_err("Read error, expecting %d, got %d.\n", (int)block_size, (int)s1);
print_progress(*bytes, 0);
}
- return 0;
+ return quit ? -EAGAIN : 0;
}
static int copy_data_backward(int fd_old, int fd_new, size_t block_size, void *buf, uint64_t *bytes)
ssize_t s1, s2, working_block;
off64_t working_offset;
- *bytes = 0;
- while (rnc.device_offset) {
+ *bytes = rnc.device_size - rnc.device_offset;
+ while (!quit && rnc.device_offset) {
if (rnc.device_offset < block_size) {
working_offset = 0;
working_block = rnc.device_offset;
log_err("Cannot seek to device offset.\n");
return -EIO;
}
-//log_err("off: %06d, size %06d\n", working_offset, block_size);
s1 = read(fd_old, buf, working_block);
if (s1 < 0 || (s1 != working_block)) {
print_progress(*bytes, 0);
}
- return 0;
+ return quit ? -EAGAIN : 0;
}
static int copy_data(void)
goto out;
}
+ set_int_handler();
// FIXME: all this should be in init
if (!rnc.in_progress && rnc.reencrypt_direction == BACKWARD)
rnc.device_offset = rnc.device_size;
r = copy_data_forward(fd_old, fd_new, block_size, buf, &bytes);
else
r = copy_data_backward(fd_old, fd_new, block_size, buf, &bytes);
+
+ set_int_block(1);
print_progress(bytes, 1);
if (r < 0)
remove_headers();
- /* Block ctrl+c */
- // FIXME: add some routine to handle it
- sigemptyset(&signals_open);
- sigaddset(&signals_open, SIGINT);
- sigprocmask(SIG_SETMASK, &signals_open, NULL);
-
return open_log();
}
free(rnc.device);
free(rnc.device_uuid);
-
- sigprocmask(SIG_UNBLOCK, &signals_open, NULL);
}
int run_reencrypt(const char *device)
{
int r = -EINVAL;
-
if (initialize_context(device))
goto out;
crypt_set_log_callback(NULL, _log, NULL);
log_err("WARNING: this is experimental code, it can completely break your data.\n");
+ set_int_block(1);
+
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
case -ENODEV: r = 4; break;
case -ENOMEM: r = 3; break;
case -EPERM: r = 2; break;
+ case -EAGAIN: log_err(_("Interrupted by a signal.\n"));
case -EINVAL:
case -ENOENT:
case -ENOSYS: