summaryrefslogtreecommitdiff
path: root/c_src/cmd_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'c_src/cmd_dump.c')
-rw-r--r--c_src/cmd_dump.c82
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;
+}