summaryrefslogtreecommitdiffstats
path: root/qemu-img.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu-img.c')
-rw-r--r--qemu-img.c87
1 files changed, 51 insertions, 36 deletions
diff --git a/qemu-img.c b/qemu-img.c
index 821cbf610e..a2369766f0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -223,6 +223,53 @@ static bool qemu_img_object_print_help(const char *type, QemuOpts *opts)
return true;
}
+/*
+ * Is @optarg safe for accumulate_options()?
+ * It is when multiple of them can be joined together separated by ','.
+ * To make that work, @optarg must not start with ',' (or else a
+ * separating ',' preceding it gets escaped), and it must not end with
+ * an odd number of ',' (or else a separating ',' following it gets
+ * escaped), or be empty (or else a separating ',' preceding it can
+ * escape a separating ',' following it).
+ *
+ */
+static bool is_valid_option_list(const char *optarg)
+{
+ size_t len = strlen(optarg);
+ size_t i;
+
+ if (!optarg[0] || optarg[0] == ',') {
+ return false;
+ }
+
+ for (i = len; i > 0 && optarg[i - 1] == ','; i--) {
+ }
+ if ((len - i) % 2) {
+ return false;
+ }
+
+ return true;
+}
+
+static int accumulate_options(char **options, char *optarg)
+{
+ char *new_options;
+
+ if (!is_valid_option_list(optarg)) {
+ error_report("Invalid option list: %s", optarg);
+ return -1;
+ }
+
+ if (!*options) {
+ *options = g_strdup(optarg);
+ } else {
+ new_options = g_strdup_printf("%s,%s", *options, optarg);
+ g_free(*options);
+ *options = new_options;
+ }
+ return 0;
+}
+
static QemuOptsList qemu_source_opts = {
.name = "source",
.implied_opt_name = "file",
@@ -482,17 +529,9 @@ static int img_create(int argc, char **argv)
fmt = optarg;
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
goto fail;
}
- 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 'q':
quiet = true;
@@ -2127,17 +2166,9 @@ static int img_convert(int argc, char **argv)
s.compressed = true;
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
goto fail_getopt;
}
- 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 'l':
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
@@ -3953,18 +3984,10 @@ static int img_amend(int argc, char **argv)
help();
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
ret = -1;
goto out_no_progress;
}
- 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;
@@ -4855,17 +4878,9 @@ static int img_measure(int argc, char **argv)
out_fmt = optarg;
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
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 'l':
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {