/** * Handles a firm option. */ int firm_option(char const *const opt) { char const* val; if ((val = strstart(opt, "dump-filter="))) { set_dump_filter(val); return 1; } else if ((val = strstart(opt, "clone-threshold="))) { sscanf(val, "%d", &firm_opt.clone_threshold); return 1; } else if ((val = strstart(opt, "inline-max-size="))) { sscanf(val, "%u", &firm_opt.inline_maxsize); return 1; } else if ((val = strstart(opt, "inline-threshold="))) { sscanf(val, "%u", &firm_opt.inline_threshold); return 1; } else if (streq(opt, "no-opt")) { disable_opts(); return 1; } size_t const len = strlen(opt); for (size_t i = lengthof(firm_options); i != 0;) { struct params const* const o = &firm_options[--i]; if (len == o->opt_len && strncmp(opt, o->option, len) == 0) { if (!o->flag) { /* help option */ print_option_help(firm_options[0].option, firm_options[0].description); firm_opt_option_help(); for (size_t k = 1; k != lengthof(firm_options); ++k) { print_option_help(firm_options[k].option, firm_options[k].description); } return -1; } /* statistic options do accumulate */ if (o->flag == &firm_dump.statistic) *o->flag = (bool) (*o->flag | o->set); else *o->flag = o->set; return 1; } } /* maybe this enables/disables optimisations */ if (firm_opt_option(opt)) return 1; return 0; }
int usage_with_options_internal(const char * const *usagestr, const struct option *opts, int full) { if (!usagestr) return PARSE_OPT_HELP; fprintf(stderr, "\n usage: %s\n", *usagestr++); while (*usagestr && **usagestr) fprintf(stderr, " or: %s\n", *usagestr++); while (*usagestr) { fprintf(stderr, "%s%s\n", **usagestr ? " " : "", *usagestr); usagestr++; } if (opts->type != OPTION_GROUP) fputc('\n', stderr); for ( ; opts->type != OPTION_END; opts++) print_option_help(opts, full); fputc('\n', stderr); return PARSE_OPT_HELP; }
static int print_block_option_help(const char *filename, const char *fmt) { BlockDriver *drv, *proto_drv; QEMUOptionParameter *create_options = NULL; /* Find driver and parse its options */ drv = bdrv_find_format(fmt); if (!drv) { error_report("Unknown file format '%s'", fmt); return 1; } proto_drv = bdrv_find_protocol(filename); if (!proto_drv) { error_report("Unknown protocol '%s'", filename); return 1; } create_options = append_option_parameters(create_options, drv->create_options); create_options = append_option_parameters(create_options, proto_drv->create_options); print_option_help(create_options); free_option_parameters(create_options); return 0; }
int parse_options_usage(const char * const *usagestr, const struct option *opts, const char *optstr, bool short_opt) { if (!usagestr) goto opt; fprintf(stderr, "\n Usage: %s\n", *usagestr++); while (*usagestr && **usagestr) fprintf(stderr, " or: %s\n", *usagestr++); while (*usagestr) { fprintf(stderr, "%s%s\n", **usagestr ? " " : "", *usagestr); usagestr++; } fputc('\n', stderr); opt: for ( ; opts->type != OPTION_END; opts++) { if (short_opt) { if (opts->short_name == *optstr) { print_option_help(opts, 0); break; } continue; } if (opts->long_name == NULL) continue; if (strstarts(opts->long_name, optstr)) print_option_help(opts, 0); if (strstarts("no-", optstr) && strstarts(opts->long_name, optstr + 3)) print_option_help(opts, 0); } return PARSE_OPT_HELP; }
static int usage_with_options_internal(const char * const *usagestr, const struct option *opts, int full, struct parse_opt_ctx_t *ctx) { struct option *ordered; if (!usagestr) return PARSE_OPT_HELP; setup_pager(); if (error_buf) { fprintf(stderr, " Error: %s\n", error_buf); zfree(&error_buf); } fprintf(stderr, "\n Usage: %s\n", *usagestr++); while (*usagestr && **usagestr) fprintf(stderr, " or: %s\n", *usagestr++); while (*usagestr) { fprintf(stderr, "%s%s\n", **usagestr ? " " : "", *usagestr); usagestr++; } if (opts->type != OPTION_GROUP) fputc('\n', stderr); ordered = options__order(opts); if (ordered) opts = ordered; for ( ; opts->type != OPTION_END; opts++) { if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx)) continue; print_option_help(opts, full); } fputc('\n', stderr); free(ordered); return PARSE_OPT_HELP; }
static int img_convert(int argc, char **argv) { int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors; const char *fmt, *out_fmt, *out_baseimg, *out_filename; BlockDriver *drv; BlockDriverState **bs, *out_bs; int64_t total_sectors, nb_sectors, sector_num, bs_offset; uint64_t bs_sectors; uint8_t * buf; const uint8_t *buf1; BlockDriverInfo bdi; QEMUOptionParameter *param = NULL; char *options = NULL; fmt = NULL; out_fmt = "raw"; out_baseimg = NULL; flags = 0; for(;;) { c = getopt(argc, argv, "f:O:B:hce6o:"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'B': out_baseimg = optarg; break; case 'c': flags |= BLOCK_FLAG_COMPRESS; break; case 'e': flags |= BLOCK_FLAG_ENCRYPT; break; case '6': flags |= BLOCK_FLAG_COMPAT6; break; case 'o': options = optarg; break; } } bs_n = argc - optind - 1; if (bs_n < 1) help(); out_filename = argv[argc - 1]; if (bs_n > 1 && out_baseimg) error("-B makes no sense when concatenating multiple input images"); bs = calloc(bs_n, sizeof(BlockDriverState *)); if (!bs) error("Out of memory"); total_sectors = 0; for (bs_i = 0; bs_i < bs_n; bs_i++) { bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS); if (!bs[bs_i]) error("Could not open '%s'", argv[optind + bs_i]); bdrv_get_geometry(bs[bs_i], &bs_sectors); total_sectors += bs_sectors; } /* Find driver and parse its options */ drv = bdrv_find_format(out_fmt); if (!drv) error("Unknown file format '%s'", out_fmt); if (options && !strcmp(options, "?")) { print_option_help(drv->create_options); free(bs); return 0; } if (options) { param = parse_option_parameters(options, drv->create_options, param); if (param == NULL) { error("Invalid options for file format '%s'.", out_fmt); } } else { param = parse_option_parameters("", drv->create_options, param); } set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512); add_old_style_options(out_fmt, param, flags, out_baseimg, NULL); /* Check if compression is supported */ if (flags & BLOCK_FLAG_COMPRESS) { QEMUOptionParameter *encryption = get_option_parameter(param, BLOCK_OPT_ENCRYPT); if (!drv->bdrv_write_compressed) { error("Compression not supported for this file format"); } if (encryption && encryption->value.n) { error("Compression and encryption not supported at the same time"); } } /* Create the new image */ ret = bdrv_create(drv, out_filename, param); free_option_parameters(param); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting not supported for file format '%s'", out_fmt); } else if (ret == -EFBIG) { error("The image size is too large for file format '%s'", out_fmt); } else { error("%s: error while converting %s: %s", out_filename, out_fmt, strerror(-ret)); } } out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_FLAGS | BDRV_O_RDWR); bs_i = 0; bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); buf = qemu_malloc(IO_BUF_SIZE); if (flags & BLOCK_FLAG_COMPRESS) { if (bdrv_get_info(out_bs, &bdi) < 0) error("could not get block driver info"); cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) error("invalid cluster size"); cluster_sectors = cluster_size >> 9; sector_num = 0; for(;;) { int64_t bs_num; int remainder; uint8_t *buf2; nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; bs_num = sector_num - bs_offset; assert (bs_num >= 0); remainder = n; buf2 = buf; while (remainder > 0) { int nlow; while (bs_num == bs_sectors) { bs_i++; assert (bs_i < bs_n); bs_offset += bs_sectors; bdrv_get_geometry(bs[bs_i], &bs_sectors); bs_num = 0; /* printf("changing part: sector_num=%lld, " "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n", sector_num, bs_i, bs_offset, bs_sectors); */ } assert (bs_num < bs_sectors); nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder; if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) error("error while reading"); buf2 += nlow * 512; bs_num += nlow; remainder -= nlow; } assert (remainder == 0); if (n < cluster_sectors) memset(buf + n * 512, 0, cluster_size - n * 512); if (is_not_zero(buf, cluster_size)) { if (bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors) != 0) error("error while compressing sector %" PRId64, sector_num); } sector_num += n; } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {
static int img_create(int argc, char **argv) { int c, ret, flags; const char *fmt = "raw"; const char *base_fmt = NULL; const char *filename; const char *base_filename = NULL; BlockDriver *drv; QEMUOptionParameter *param = NULL; char *options = NULL; flags = 0; for(;;) { c = getopt(argc, argv, "F:b:f:he6o:"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'F': base_fmt = optarg; break; case 'b': base_filename = optarg; break; case 'f': fmt = optarg; break; case 'e': flags |= BLOCK_FLAG_ENCRYPT; break; case '6': flags |= BLOCK_FLAG_COMPAT6; break; case 'o': options = optarg; break; } } /* Find driver and parse its options */ drv = bdrv_find_format(fmt); if (!drv) error("Unknown file format '%s'", fmt); if (options && !strcmp(options, "?")) { print_option_help(drv->create_options); return 0; } /* Create parameter list with default values */ param = parse_option_parameters("", drv->create_options, param); set_option_parameter_int(param, BLOCK_OPT_SIZE, -1); /* Parse -o options */ if (options) { param = parse_option_parameters(options, drv->create_options, param); if (param == NULL) { error("Invalid options for file format '%s'.", fmt); } } /* Get the filename */ if (optind >= argc) help(); filename = argv[optind++]; /* Add size to parameters */ if (optind < argc) { set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]); } /* Add old-style options to parameters */ add_old_style_options(fmt, param, flags, base_filename, base_fmt); // The size for the image must always be specified, with one exception: // If we are using a backing file, we can obtain the size from there if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) { QEMUOptionParameter *backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); QEMUOptionParameter *backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT); if (backing_file && backing_file->value.s) { BlockDriverState *bs; uint64_t size; const char *fmt = NULL; char buf[32]; if (backing_fmt && backing_fmt->value.s) { if (bdrv_find_format(backing_fmt->value.s)) { fmt = backing_fmt->value.s; } else { error("Unknown backing file format '%s'", backing_fmt->value.s); } } bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS); bdrv_get_geometry(bs, &size); size *= 512; bdrv_delete(bs); snprintf(buf, sizeof(buf), "%" PRId64, size); set_option_parameter(param, BLOCK_OPT_SIZE, buf); } else { error("Image creation needs a size parameter"); } } printf("Formatting '%s', fmt=%s ", filename, fmt); print_option_parameters(param); puts(""); ret = bdrv_create(drv, filename, param); free_option_parameters(param); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting or formatting option not supported for file format '%s'", fmt); } else if (ret == -EFBIG) { error("The image size is too large for file format '%s'", fmt); } else { error("%s: error while creating %s: %s", filename, fmt, strerror(-ret)); } } return 0; }