Add --device-size option for reencryption tool.

This commit is contained in:
Milan Broz
2012-06-25 15:34:11 +02:00
parent c469e458b7
commit fb3b62ca02
5 changed files with 103 additions and 2 deletions

View File

@@ -1,3 +1,6 @@
2012-06-25 Milan Broz <gmazyland@gmail.com>
* Add --device-size option for reencryption tool.
2012-06-20 Milan Broz <gmazyland@gmail.com> 2012-06-20 Milan Broz <gmazyland@gmail.com>
* Version 1.5.0-rc2. * Version 1.5.0-rc2.

View File

@@ -23,6 +23,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
@@ -423,3 +425,65 @@ ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
*result = bytes; *result = bytes;
return i; 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;
}

View File

@@ -44,5 +44,6 @@ void crypt_safe_free(void *data);
void *crypt_safe_realloc(void *data, size_t size); void *crypt_safe_realloc(void *data, size_t size);
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc); 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 */ #endif /* _UTILS_CRYPT_H */

View File

@@ -122,6 +122,23 @@ partition (so last sectors contains no data).
WARNING: This is destructive operation and cannot be reverted. WARNING: This is destructive operation and cannot be reverted.
Use with extreme care - shrinked filesystems are usually unrecoverable. 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). You cannot shrink device more than by 64 MiB (131072 sectors).
.TP .TP
.B "\-\-new, N" .B "\-\-new, N"

View File

@@ -67,6 +67,9 @@ static int opt_key_slot = CRYPT_ANY_SLOT;
static int opt_key_size = 0; static int opt_key_size = 0;
static int opt_new = 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 const char **action_argv;
static volatile int quit = 0; static volatile int quit = 0;
@@ -75,7 +78,8 @@ static volatile int quit = 0;
struct reenc_ctx { struct reenc_ctx {
char *device; char *device;
char *device_uuid; 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_offset;
uint64_t device_shift; 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; 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); s2 = write(fd_new, buf, s1);
if (s2 < 0) { if (s2 < 0) {
log_dbg("Write error, expecting %d, got %d.", log_dbg("Write error, expecting %d, got %d.",
@@ -861,11 +869,13 @@ static int copy_data(struct reenc_ctx *rc)
} }
/* Check size */ /* 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")); log_err(_("Cannot get device size.\n"));
goto out; goto out;
} }
rc->device_size = opt_device_size ?: rc->device_size_real;
if (posix_memalign((void *)&buf, alignment(fd_new), block_size)) { if (posix_memalign((void *)&buf, alignment(fd_new), block_size)) {
log_err(_("Allocation of aligned memory failed.\n")); log_err(_("Allocation of aligned memory failed.\n"));
r = -ENOMEM; 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-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") }, { "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_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 }, { "new", 'N', POPT_ARG_NONE,&opt_new, 0, N_("Create new header on not encrypted device."), NULL },
POPT_TABLEEND 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."), usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce_device_size."),
poptGetInvocationName(popt_context)); 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) { if (opt_debug) {
opt_verbose = 1; opt_verbose = 1;
crypt_set_debug_level(-1); crypt_set_debug_level(-1);