static int plooptool_resize(int argc, char **argv) { int i, ret; off_t new_size = 0; /* in sectors */ int max_balloon_size = 0; /* make balloon file of max possible size */ struct ploop_resize_param param = { .size = 0, .offline_resize = 1, }; struct ploop_disk_images_data *di; while ((i = getopt(argc, argv, "s:b")) != EOF) { switch (i) { case 's': if (parse_size(optarg, &new_size, "-s")) { usage_resize(); return SYSEXIT_PARAM; } param.size = new_size; break; case 'b': max_balloon_size = 1; break; default: usage_resize(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc != 1 || (new_size == 0 && !max_balloon_size) || !is_xml_fname(argv[0])) { usage_resize(); return SYSEXIT_PARAM; } ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_resize_image(di, ¶m); ploop_close_dd(di); return ret; } static void usage_convert(void) { fprintf(stderr, "Usage: ploop convert {-f FORMAT | -v VERSION} DiskDescriptor.xml\n" " FORMAT := { raw | preallocated }\n" " VERSION := { 1 | 2 }\n" ); }
int ploop_read_disk_descr(struct ploop_disk_images_data **di, const char *file) { int ret; ret = ploop_open_dd(di, file); if (ret) return ret; return ploop_read_dd(*di); }
static int plooptool_snapshot(int argc, char **argv) { int i, ret; char *device = NULL; int syncfs = 0; struct ploop_snapshot_param param = {}; while ((i = getopt(argc, argv, "Fd:u:")) != EOF) { switch (i) { case 'd': device = optarg; break; case 'F': syncfs = 1; break; case 'u': param.guid = parse_uuid(optarg); if (!param.guid) return SYSEXIT_PARAM; break; default: usage_snapshot(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc != 1) { usage_snapshot(); return SYSEXIT_PARAM; } if (is_xml_fname(argv[0])) { struct ploop_disk_images_data *di; ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_create_snapshot(di, ¶m); ploop_close_dd(di); } else { if (!device) { usage_snapshot(); return SYSEXIT_PARAM; } ret = create_snapshot(device, argv[0], syncfs); } return ret; }
static int plooptool_convert(int argc, char **argv) { int i, ret; struct ploop_disk_images_data *di; int mode = -1; int version = -1; while ((i = getopt(argc, argv, "f:v:")) != EOF) { switch (i) { case 'f': mode = parse_format_opt(optarg); break; case 'v': version = parse_version_opt(optarg); if (version < 0) { usage_convert(); return SYSEXIT_PARAM; } break; default: usage_convert(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc == 0 || (mode == -1 && version == -1) || (mode != -1 && version != -1)) { usage_convert(); return SYSEXIT_PARAM; } ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; if (mode != -1) ret = ploop_convert_image(di, mode, 0); else if (version != -1) ret = ploop_change_fmt_version(di, version, 0); ploop_close_dd(di); return ret; }
static int plooptool_snapshot_merge(int argc, char ** argv) { int i, ret; struct ploop_merge_param param = {}; while ((i = getopt(argc, argv, "u:A")) != EOF) { switch (i) { case 'u': param.guid = parse_uuid(optarg); if (!param.guid) return SYSEXIT_PARAM; break; case 'A': param.merge_all = 1; break; default: usage_snapshot_merge(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (param.guid != NULL && param.merge_all != 0) { fprintf(stderr, "Options -u and -A can't be used together\n"); usage_snapshot_merge(); return SYSEXIT_PARAM; } if (argc == 1 && is_xml_fname(argv[0])) { struct ploop_disk_images_data *di; ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_merge_snapshot(di, ¶m); ploop_close_dd(di); } else { usage_snapshot_merge(); return SYSEXIT_PARAM; } return ret; }
static int plooptool_tsnapshot(int argc, char **argv) { int i, ret; struct ploop_disk_images_data *di; struct ploop_tsnapshot_param param = {}; while ((i = getopt(argc, argv, "u:c:m:")) != EOF) { switch (i) { case 'u': param.guid = parse_uuid(optarg); if (!param.guid) return SYSEXIT_PARAM; break; case 'c': param.component_name = optarg; break; case 'm': param.target = optarg; break; default: usage_snapshot(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc != 1 || !is_xml_fname(argv[0]) || param.guid == NULL || param.component_name == NULL) { usage_tsnapshot(); return SYSEXIT_PARAM; } ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_create_temporary_snapshot(di, ¶m, NULL); ploop_close_dd(di); return ret; }
static int plooptool_snapshot_switch(int argc, char **argv) { int i, ret; char *uuid = NULL; int flags = 0; struct ploop_disk_images_data *di = NULL; while ((i = getopt(argc, argv, "u:D")) != EOF) { switch (i) { case 'u': uuid = parse_uuid(optarg); if (!uuid) return SYSEXIT_PARAM; break; case 'D': /* for test purposes */ flags = PLOOP_SNAP_SKIP_TOPDELTA_DESTROY; break; default: usage_snapshot_switch(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if ((argc != 1 && !is_xml_fname(argv[0])) || uuid == NULL) { usage_snapshot_switch(); return SYSEXIT_PARAM; } ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_switch_snapshot(di, uuid, flags); ploop_close_dd(di); return ret; }
static int plooptool_snapshot_delete(int argc, char **argv) { int i, ret; char *uuid = NULL; struct ploop_disk_images_data *di = NULL; while ((i = getopt(argc, argv, "u:")) != EOF) { switch (i) { case 'u': uuid = parse_uuid(optarg); if (!uuid) return SYSEXIT_PARAM; break; default: usage_snapshot_delete(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc != 1 || !is_xml_fname(argv[0]) || uuid == NULL) { usage_snapshot_delete(); return SYSEXIT_PARAM; } ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_delete_snapshot(di, uuid); ploop_close_dd(di); return ret; }
static int ploop_get_spec_path(const char *dd_path, struct ploop_spec *spec) { struct ploop_disk_images_data *di; int rc; if ((rc = ploop_open_dd(&di, dd_path))) { rc = putErr(MIG_ERR_PLOOP, "ploop_read_diskdescriptor(%s) : %s [%d]", dd_path, ploop_get_last_error(), rc); goto cleanup; } memset((void *)spec, 0, sizeof(*spec)); if ((rc = ploop_get_spec(di, spec))) { rc = putErr(MIG_ERR_PLOOP, "ploop_get_spec() : %s [%d]", ploop_get_last_error(), rc); goto cleanup; } cleanup: if (di != NULL) ploop_close_dd(di); return rc; }
static int plooptool_info(int argc, char **argv) { int ret, i; int spec = 0; int device = 0; struct ploop_info info = {}; while ((i = getopt(argc, argv, "sd")) != EOF) { switch (i) { case 's': spec = 1; break; case 'd': device = 1; break; default: usage_info(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc != 1 || !is_xml_fname(argv[0])) { usage_info(); return SYSEXIT_PARAM; } if (spec || device) { struct ploop_disk_images_data *di; ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; if (spec) { struct ploop_spec spec = {}; ret = ploop_get_spec(di, &spec); if (ret) goto exit; printf("size:\t\t%llu\nblocksize:\t%d\nfmt_version:\t%d\n", (unsigned long long)spec.size, spec.blocksize, spec.fmt_version); } if (device) { char dev[PATH_MAX] = {}; if (ploop_get_dev(di, dev, sizeof(dev)) == -1) { ret = SYSEXIT_SYS; goto exit; } printf("device:\t\t%s\n", dev); } exit: ploop_close_dd(di); } else { ret = ploop_get_info_by_descr(argv[0], &info); if (ret == 0) print_info(&info); } return ret; }
static int plooptool_umount(int argc, char **argv) { int i, ret; char *mnt = NULL; char device[PATH_MAX]; struct { char * device; } umountopts = { }; const char *component_name = NULL; while ((i = getopt(argc, argv, "d:m:c:")) != EOF) { switch (i) { case 'd': umountopts.device = optarg; break; case 'm': mnt = optarg; break; case 'c': component_name = optarg; break; default: usage_umount(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc != 1 && !umountopts.device && !mnt) { usage_umount(); return SYSEXIT_PARAM; } if (umountopts.device != NULL) { int len = strlen(umountopts.device); /* if partition is provided, strip it */ if (strcmp(umountopts.device + len - 2, "p1") == 0 && isdigit(umountopts.device[len - 3])) umountopts.device[len - 2] = '\0'; ret = ploop_umount(umountopts.device, NULL); }else if (mnt != NULL) { if (ploop_get_dev_by_mnt(mnt, device, sizeof(device))) { fprintf(stderr, "Unable to find ploop device by %s\n", mnt); return SYSEXIT_PARAM; } ret = ploop_umount(device, NULL); } else if (is_xml_fname(argv[0])) { struct ploop_disk_images_data *di; ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; if (component_name != NULL) ploop_set_component_name(di, component_name); ret = ploop_umount_image(di); ploop_close_dd(di); } else { if (ploop_find_dev(component_name, argv[0], device, sizeof(device)) != 0) { fprintf(stderr, "Image %s is not mounted\n", argv[0]); return SYSEXIT_PARAM; } ret = ploop_umount(device, NULL); } return ret; }
static int plooptool_mount(int argc, char **argv) { int i, f, ret = 0; int raw = 0; struct ploop_mount_param mountopts = {}; const char *component_name = NULL; while ((i = getopt(argc, argv, "rFf:d:m:t:u:o:b:c:")) != EOF) { switch (i) { case 'd': strncpy(mountopts.device, optarg, sizeof(mountopts.device)-1); break; case 'r': mountopts.ro = 1; break; case 'F': mountopts.fsck = 1; break; case 'f': f = parse_format_opt(optarg); if (f < 0) { usage_mount(); return SYSEXIT_PARAM; } raw = (f == PLOOP_RAW_MODE); break; case 'm': mountopts.target = strdup(optarg); break; case 't': mountopts.fstype = strdup(optarg); break; case 'u': mountopts.guid = parse_uuid(optarg); if (!mountopts.guid) return SYSEXIT_PARAM; break; case 'o': mountopts.mount_data = strdup(optarg); break; case 'b': { char * endptr; mountopts.blocksize = strtoul(optarg, &endptr, 0); if (*endptr != '\0') { usage_mount(); return SYSEXIT_PARAM; } break; case 'c': component_name = optarg; break; } default: usage_mount(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (argc < 1) { usage_mount(); return SYSEXIT_PARAM; } if (argc == 1 && is_xml_fname(argv[0])) { struct ploop_disk_images_data *di; ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; if (component_name != NULL) ploop_set_component_name(di, component_name); ret = ploop_mount_image(di, &mountopts); ploop_close_dd(di); } else ret = ploop_mount(NULL, argv, &mountopts, raw); return ret; }
static int plooptool_replace(int argc, char **argv) { int i; char dev[PATH_MAX]; char *device = NULL; char *mnt = NULL; struct ploop_replace_param param = { .level = -1, }; while ((i = getopt(argc, argv, "d:m:l:i:u:o:")) != EOF) { switch (i) { case 'd': device = optarg; break; case 'm': mnt = optarg; break; case 'l': param.level = atoi(optarg); break; case 'u': param.guid = parse_uuid(optarg); if (!param.guid) return SYSEXIT_PARAM; break; case 'i': param.file = strdup(optarg); break; case 'o': param.cur_file = strdup(optarg); break; default: usage_replace(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (!param.file) { fprintf(stderr, "Error: image file not specified (use -i)\n"); usage_replace(); return SYSEXIT_PARAM; } if ((argc == 1) && is_xml_fname(argv[0])) { int ret; struct ploop_disk_images_data *di; /* only one way of choosing delta to replace */ if ( (!!param.guid) + (param.level != -1) + (!!param.cur_file) != 1) { fprintf(stderr, "Error: either one of uuid (-u), " "level (-l) or current file (-o) " "must be specified\n"); usage_replace(); return SYSEXIT_PARAM; } ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_replace_image(di, ¶m); ploop_close_dd(di); return ret; } else { int level = param.level; if (argc > 0) { usage_replace(); return SYSEXIT_PARAM; } if ((!!device) + (!!mnt) != 1) { fprintf(stderr, "Error: either device (-d), mount " "point (-m) or DiskDescriptor.xml " "must be specified\n"); usage_replace(); return SYSEXIT_PARAM; } if (mnt) { if (ploop_get_dev_by_mnt(mnt, dev, sizeof(dev))) { fprintf(stderr, "Unable to find ploop device " "by mount point %s\n", mnt); return SYSEXIT_PARAM; } device = dev; } /* Either level or current delta must be specified */ if ((level != -1) + (!!param.cur_file) != 1) { fprintf(stderr, "Error: either one of level (-l) or " "current delta file (-o) must be " "specified\n"); usage_replace(); return SYSEXIT_PARAM; } if (param.cur_file) { int ret; level = find_level_by_delta(device, param.cur_file); if (level < 0) { fprintf(stderr, "Can't find level by " "delta file name %s", param.cur_file); return SYSEXIT_PARAM; } ret = check_deltas_same(param.cur_file, param.file); if (ret) return ret; } return replace_delta(device, level, param.file); } } int main(int argc, char **argv) { char * cmd; int v = 3; /* global options */ while (argc > 1 && argv[1][0] == '-') { switch (argv[1][1]) { case 'v': switch (argv[1][2]) { case '\0': v++; break; case 'v': /* -vvv... */ v += strlen(&argv[1][1]); break; default: /* -vNN */ v = atoi(&argv[1][2]); } break; case '-': /* long option */ /* fall through */ default: fprintf(stderr, "Bad option %s\n", argv[1]); usage_summary(); return SYSEXIT_PARAM; } argc--; argv++; } if (argc < 2) { usage_summary(); return SYSEXIT_PARAM; } cmd = argv[1]; argc--; argv++; ploop_set_verbose_level(v); init_signals(); if (strcmp(cmd, "init") == 0) return plooptool_init(argc, argv); if (strcmp(cmd, "start") == 0) return plooptool_start(argc, argv); if (strcmp(cmd, "stop") == 0) return plooptool_stop(argc, argv); if (strcmp(cmd, "clear") == 0) return plooptool_clear(argc, argv); if (strcmp(cmd, "mount") == 0) return plooptool_mount(argc, argv); if (strcmp(cmd, "umount") == 0) return plooptool_umount(argc, argv); if (strcmp(cmd, "delete") == 0 || strcmp(cmd, "rm") == 0) return plooptool_rm(argc, argv); if (strcmp(cmd, "snapshot") == 0) return plooptool_snapshot(argc, argv); if (strcmp(cmd, "tsnapshot") == 0) return plooptool_tsnapshot(argc, argv); if (strcmp(cmd, "snapshot-switch") == 0) return plooptool_snapshot_switch(argc, argv); if (strcmp(cmd, "snapshot-delete") == 0) return plooptool_snapshot_delete(argc, argv); if (strcmp(cmd, "snapshot-merge") == 0) return plooptool_snapshot_merge(argc, argv); if (strcmp(cmd, "snapshot-list") == 0) return plooptool_snapshot_list(argc, argv); if (strcmp(cmd, "getdev") == 0) return plooptool_getdevice(argc, argv); if (strcmp(cmd, "resize") == 0) return plooptool_resize(argc, argv); if (strcmp(cmd, "convert") == 0) return plooptool_convert(argc, argv); if (strcmp(cmd, "info") == 0) return plooptool_info(argc, argv); if (strcmp(cmd, "list") == 0) return plooptool_list(argc, argv); if (strcmp(cmd, "check") == 0) return plooptool_check(argc, argv); if (strcmp(cmd, "fsck") == 0) { fprintf(stderr, "WARNING: ploop fsck command is obsoleted, " "please use ploop check\n"); return plooptool_check(argc, argv); } if (strcmp(cmd, "grow") == 0) return plooptool_grow(argc, argv); if (strcmp(cmd, "merge") == 0) return plooptool_merge(argc, argv); if (strcmp(cmd, "stat") == 0) return plooptool_stat(argc, argv); if (strcmp(cmd, "copy") == 0) return plooptool_copy(argc, argv); if (strcmp(cmd, "replace") == 0) return plooptool_replace(argc, argv); if (cmd[0] != '-') { char ** nargs; nargs = calloc(argc+1, sizeof(char*)); nargs[0] = malloc(sizeof("ploop-") + strlen(cmd)); sprintf(nargs[0], "ploop-%s", cmd); memcpy(nargs + 1, argv + 1, (argc - 1)*sizeof(char*)); nargs[argc] = NULL; execvp(nargs[0], nargs); } usage_summary(); return SYSEXIT_PARAM; }
int plooptool_grow(int argc, char **argv) { int i, f; off_t new_size = 0; /* in sectors */ int raw = 0, sparse = 0; char *device = NULL; static struct option long_opts[] = { { "sparse", no_argument, 0, 'S' }, {}, }; while ((i = getopt_long(argc, argv, "f:d:s:S", long_opts, NULL)) != EOF) { switch (i) { case 'f': f = parse_format_opt(optarg); if (f < 0) { usage(); return SYSEXIT_PARAM; } raw = (f == PLOOP_RAW_MODE); break; case 'd': device = optarg; break; case 'S': sparse = 1; break; case 's': if (parse_size(optarg, &new_size, "-s")) { usage(); return SYSEXIT_PARAM; } break; default: usage(); return SYSEXIT_PARAM; } } argc -= optind; argv += optind; if (((argc != 0 || !device) && (argc != 1 || device)) || (raw && device) || (new_size == 0)) { usage(); return SYSEXIT_PARAM; } if (argc == 1 && is_xml_fname(argv[0])) { int ret; struct ploop_disk_images_data *di; ret = ploop_open_dd(&di, argv[0]); if (ret) return ret; ret = ploop_grow_image(di, new_size, sparse); ploop_close_dd(di); return ret; } else if (device) return ploop_grow_device(device, new_size); else if (raw) return ploop_grow_raw_delta_offline(argv[0], new_size, sparse); else return ploop_grow_delta_offline(argv[0], new_size); }