diff options
Diffstat (limited to 'c_src/cmd_dump.c')
-rw-r--r-- | c_src/cmd_dump.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/c_src/cmd_dump.c b/c_src/cmd_dump.c index 5f354272..93e7d743 100644 --- a/c_src/cmd_dump.c +++ b/c_src/cmd_dump.c @@ -386,3 +386,85 @@ int cmd_dump(int argc, char *argv[]) darray_exit(&dev_names); return ret; } + +static void undump_usage(void) +{ + puts("bcachefs undump - turn qcow2 images from 'bcachefs dump' back into sparse raw images\n" + "Usage: bcachefs undump [OPTION]... <files>\n" + "\n" + "Options:\n" + " -f, --force Force; overwrite when needed\n" + " -h, --help Display this help and exit\n" + "Report bugs to <linux-bcachefs@vger.kernel.org>"); +} + +struct undump { + char *in, *out; + int infd, outfd; +}; + +int cmd_undump(int argc, char *argv[]) +{ + static const struct option longopts[] = { + { "force", no_argument, NULL, 'f' }, + { "help", no_argument, NULL, 'h' }, + { NULL } + }; + bool force = false; + int opt; + + while ((opt = getopt_long(argc, argv, "fh", + longopts, NULL)) != -1) + switch (opt) { + case 'f': + force = true; + break; + case 'h': + undump_usage(); + exit(EXIT_SUCCESS); + } + args_shift(optind); + + if (!argc) { + undump_usage(); + die("Please supply file(s) to convert"); + } + + DARRAY(struct undump) files = {}; + + for (unsigned i = 0; i < argc; i++) { + unsigned len = strlen(argv[i]); + const char *suffix = ".qcow2"; + unsigned suffixlen = strlen(suffix); + + if (len <= suffixlen || + strcmp(suffix, argv[i] + len - suffixlen)) { + die("%s not a qcow2 image?", argv[i]); + } + + char *out = strdup(argv[i]); + out[len - suffixlen] = '\0'; + + if (!force && !access(out, F_OK)) + die("%s already exists", out); + + darray_push(&files, ((struct undump) { + .in = argv[i], + .out = out, + .infd = xopen(argv[i], O_RDONLY), + })); + } + + darray_for_each(files, i) + i->outfd = xopen(i->out, O_WRONLY|O_CREAT|(!force ? O_EXCL : 0), 0600); + + darray_for_each(files, i) { + qcow2_to_raw(i->infd, i->outfd); + close(i->infd); + close(i->outfd); + free(i->out); + } + + darray_exit(&files); + return 0; +} |