Commit fb3b62ca authored by Milan Broz's avatar Milan Broz

Add --device-size option for reencryption tool.

parent c469e458
2012-06-25 Milan Broz <gmazyland@gmail.com>
* Add --device-size option for reencryption tool.
2012-06-20 Milan Broz <gmazyland@gmail.com>
* Version 1.5.0-rc2.
......
......@@ -23,6 +23,8 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
......@@ -423,3 +425,65 @@ ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
*result = bytes;
return i;
}
/*
* Device size string parsing, suffixes:
* s|S - 512 bytes sectors
* k |K |m |M |g |G |t |T - 1024 base
* kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
* kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
*/
int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size)
{
char *endp = NULL;
size_t len;
uint64_t mult_base, mult, tmp;
*size = strtoull(s, &endp, 10);
if (!isdigit(s[0]) ||
(errno == ERANGE && *size == ULLONG_MAX) ||
(errno != 0 && *size == 0))
return -EINVAL;
if (!endp)
return 0;
len = strlen(endp);
/* Allow "B" and "iB" suffixes */
if (len > 3 ||
(len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
(len == 2 && endp[1] != 'B'))
return -EINVAL;
if (len == 1 || len == 3)
mult_base = 1024;
else
mult_base = 1000;
mult = 1;
switch (endp[0]) {
case 's':
case 'S': mult = 512;
break;
case 't':
case 'T': mult *= mult_base;
case 'g':
case 'G': mult *= mult_base;
case 'm':
case 'M': mult *= mult_base;
case 'k':
case 'K': mult *= mult_base;
break;
default:
return -EINVAL;
}
tmp = *size * mult;
if ((tmp / *size) != mult) {
log_dbg("Device size overflow.");
return -EINVAL;
}
*size = tmp;
return 0;
}
......@@ -44,5 +44,6 @@ void crypt_safe_free(void *data);
void *crypt_safe_realloc(void *data, size_t size);
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);
int crypt_string_to_size(struct crypt_device *cd, const char *s, uint64_t *size);
#endif /* _UTILS_CRYPT_H */
......@@ -122,6 +122,23 @@ partition (so last sectors contains no data).
WARNING: This is destructive operation and cannot be reverted.
Use with extreme care - shrinked filesystems are usually unrecoverable.
You cannot shrink device more than by 64 MiB (131072 sectors).
.TP
.B "\-\-device-size \fIsize[units]\fR"
Instead of real device size, use specified value.
It means that only specified area (from the start of the device
to the specified size) will be reencrypted.
WARNING: This is destructive operation.
If no unit suffix is specified, the size is in bytes.
Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB)
for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale).
WARNING: This is destructive operation.
You cannot shrink device more than by 64 MiB (131072 sectors).
.TP
.B "\-\-new, N"
......
......@@ -67,6 +67,9 @@ static int opt_key_slot = CRYPT_ANY_SLOT;
static int opt_key_size = 0;
static int opt_new = 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;
......@@ -75,7 +78,8 @@ 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;
......@@ -750,6 +754,10 @@ static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
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.",
......@@ -861,11 +869,13 @@ static int copy_data(struct reenc_ctx *rc)
}
/* 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;
......@@ -1230,6 +1240,7 @@ int main(int argc, const char **argv)
{ "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") },
{ "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
};
......@@ -1311,6 +1322,11 @@ int main(int argc, const char **argv)
usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce_device_size."),
poptGetInvocationName(popt_context));
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_debug) {
opt_verbose = 1;
crypt_set_debug_level(-1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment