static int img_amend(int argc, char **argv)

{

    int c, ret = 0;

    char *options = NULL;

    QemuOptsList *create_opts = NULL;

    QemuOpts *opts = NULL;

    const char *fmt = NULL, *filename, *cache;

    int flags;

    bool quiet = false, progress = false;

    BlockBackend *blk = NULL;

    BlockDriverState *bs = NULL;



    cache = BDRV_DEFAULT_CACHE;

    for (;;) {

        c = getopt(argc, argv, "ho:f:t:pq");

        if (c == -1) {

            break;

        }



        switch (c) {

            case 'h':

            case '?':

                help();

                break;

            case 'o':

                if (!is_valid_option_list(optarg)) {

                    error_report("Invalid option list: %s", optarg);

                    ret = -1;

                    goto out;

                }

                if (!options) {

                    options = g_strdup(optarg);

                } else {

                    char *old_options = options;

                    options = g_strdup_printf("%s,%s", options, optarg);

                    g_free(old_options);

                }

                break;

            case 'f':

                fmt = optarg;

                break;

            case 't':

                cache = optarg;

                break;

            case 'p':

                progress = true;

                break;

            case 'q':

                quiet = true;

                break;

        }

    }



    if (!options) {

        error_exit("Must specify options (-o)");

    }



    if (quiet) {

        progress = false;

    }

    qemu_progress_init(progress, 1.0);



    filename = (optind == argc - 1) ? argv[argc - 1] : NULL;

    if (fmt && has_help_option(options)) {

        /* If a format is explicitly specified (and possibly no filename is

         * given), print option help here */

        ret = print_block_option_help(filename, fmt);

        goto out;

    }



    if (optind != argc - 1) {

        error_report("Expecting one image file name");

        ret = -1;

        goto out;

    }



    flags = BDRV_O_FLAGS | BDRV_O_RDWR;

    ret = bdrv_parse_cache_flags(cache, &flags);

    if (ret < 0) {

        error_report("Invalid cache option: %s", cache);

        goto out;

    }



    blk = img_open("image", filename, fmt, flags, true, quiet);

    if (!blk) {

        ret = -1;

        goto out;

    }

    bs = blk_bs(blk);



    fmt = bs->drv->format_name;



    if (has_help_option(options)) {

        /* If the format was auto-detected, print option help here */

        ret = print_block_option_help(filename, fmt);

        goto out;

    }



    if (!bs->drv->create_opts) {

        error_report("Format driver '%s' does not support any options to amend",

                     fmt);

        ret = -1;

        goto out;

    }



    create_opts = qemu_opts_append(create_opts, bs->drv->create_opts);

    opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);

    if (options && qemu_opts_do_parse(opts, options, NULL)) {

        error_report("Invalid options for file format '%s'", fmt);

        ret = -1;

        goto out;

    }



    /* In case the driver does not call amend_status_cb() */

    qemu_progress_print(0.f, 0);

    ret = bdrv_amend_options(bs, opts, &amend_status_cb);

    qemu_progress_print(100.f, 0);

    if (ret < 0) {

        error_report("Error while amending options: %s", strerror(-ret));

        goto out;

    }



out:

    qemu_progress_end();



    blk_unref(blk);

    qemu_opts_del(opts);

    qemu_opts_free(create_opts);

    g_free(options);



    if (ret) {

        return 1;

    }

    return 0;

}
