diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/qemu-option.c | 111 |
1 files changed, 59 insertions, 52 deletions
diff --git a/util/qemu-option.c b/util/qemu-option.c index fa1a9f17fc..58d1c23893 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -70,25 +70,37 @@ static const char *get_opt_name(const char *p, char **option, char delim) * delimiter is fixed to be comma which starts a new option. To specify an * option value that contains commas, double each comma. */ -const char *get_opt_value(char *buf, int buf_size, const char *p) +const char *get_opt_value(const char *p, char **value) { - char *q; + size_t capacity = 0, length; + const char *offset; + + *value = NULL; + while (1) { + offset = strchr(p, ','); + if (!offset) { + offset = p + strlen(p); + } - q = buf; - while (*p != '\0') { - if (*p == ',') { - if (*(p + 1) != ',') - break; - p++; + length = offset - p; + if (*offset != '\0' && *(offset + 1) == ',') { + length++; + } + if (value) { + *value = g_renew(char, *value, capacity + length + 1); + strncpy(*value + capacity, p, length); + (*value)[capacity + length] = '\0'; + } + capacity += length; + if (*offset == '\0' || + *(offset + 1) != ',') { + break; } - if (q && (q - buf) < buf_size - 1) - *q++ = *p; - p++; + + p += (offset - p) + 2; } - if (q) - *q = '\0'; - return p; + return offset; } static void parse_option_bool(const char *name, const char *value, bool *ret, @@ -162,50 +174,43 @@ void parse_option_size(const char *name, const char *value, bool has_help_option(const char *param) { - size_t buflen = strlen(param) + 1; - char *buf = g_malloc(buflen); const char *p = param; bool result = false; - while (*p) { - p = get_opt_value(buf, buflen, p); + while (*p && !result) { + char *value; + + p = get_opt_value(p, &value); if (*p) { p++; } - if (is_help_option(buf)) { - result = true; - goto out; - } + result = is_help_option(value); + g_free(value); } -out: - g_free(buf); return result; } -bool is_valid_option_list(const char *param) +bool is_valid_option_list(const char *p) { - size_t buflen = strlen(param) + 1; - char *buf = g_malloc(buflen); - const char *p = param; - bool result = true; + char *value = NULL; + bool result = false; while (*p) { - p = get_opt_value(buf, buflen, p); - if (*p && !*++p) { - result = false; + p = get_opt_value(p, &value); + if ((*p && !*++p) || + (!*value || *value == ',')) { goto out; } - if (!*buf || *buf == ',') { - result = false; - goto out; - } + g_free(value); + value = NULL; } + result = true; out: - g_free(buf); + g_free(value); return result; } @@ -487,7 +492,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name) } } -static void opt_set(QemuOpts *opts, const char *name, const char *value, +static void opt_set(QemuOpts *opts, const char *name, char *value, bool prepend, Error **errp) { QemuOpt *opt; @@ -496,6 +501,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, desc = find_desc_by_name(opts->list->desc, name); if (!desc && !opts_accepts_any(opts)) { + g_free(value); error_setg(errp, QERR_INVALID_PARAMETER, name); return; } @@ -509,8 +515,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, QTAILQ_INSERT_TAIL(&opts->head, opt, next); } opt->desc = desc; - opt->str = g_strdup(value); - assert(opt->str); + opt->str = value; qemu_opt_parse(opt, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -521,7 +526,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, void qemu_opt_set(QemuOpts *opts, const char *name, const char *value, Error **errp) { - opt_set(opts, name, value, false, errp); + opt_set(opts, name, g_strdup(value), false, errp); } void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, @@ -755,7 +760,7 @@ static void opts_do_parse(QemuOpts *opts, const char *params, const char *firstname, bool prepend, Error **errp) { char *option = NULL; - char value[1024]; + char *value = NULL; const char *p,*pe,*pc; Error *local_err = NULL; @@ -767,15 +772,15 @@ static void opts_do_parse(QemuOpts *opts, const char *params, if (p == params && firstname) { /* implicitly named first option */ option = g_strdup(firstname); - p = get_opt_value(value, sizeof(value), p); + p = get_opt_value(p, &value); } else { /* option without value, probably a flag */ p = get_opt_name(p, &option, ','); if (strncmp(option, "no", 2) == 0) { memmove(option, option+2, strlen(option+2)+1); - pstrcpy(value, sizeof(value), "off"); + value = g_strdup("off"); } else { - pstrcpy(value, sizeof(value), "on"); + value = g_strdup("on"); } } } else { @@ -783,11 +788,12 @@ static void opts_do_parse(QemuOpts *opts, const char *params, p = get_opt_name(p, &option, '='); assert(*p == '='); p++; - p = get_opt_value(value, sizeof(value), p); + p = get_opt_value(p, &value); } if (strcmp(option, "id") != 0) { /* store and parse */ opt_set(opts, option, value, prepend, &local_err); + value = NULL; if (local_err) { error_propagate(errp, local_err); goto cleanup; @@ -797,11 +803,13 @@ static void opts_do_parse(QemuOpts *opts, const char *params, break; } g_free(option); - option = NULL; + g_free(value); + option = value = NULL; } cleanup: g_free(option); + g_free(value); } /** @@ -820,7 +828,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, bool permit_abbrev, bool defaults, Error **errp) { const char *firstname; - char value[1024], *id = NULL; + char *id = NULL; const char *p; QemuOpts *opts; Error *local_err = NULL; @@ -829,11 +837,9 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, firstname = permit_abbrev ? list->implied_opt_name : NULL; if (strncmp(params, "id=", 3) == 0) { - get_opt_value(value, sizeof(value), params+3); - id = value; + get_opt_value(params + 3, &id); } else if ((p = strstr(params, ",id=")) != NULL) { - get_opt_value(value, sizeof(value), p+4); - id = value; + get_opt_value(p + 4, &id); } /* @@ -845,6 +851,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, */ assert(!defaults || list->merge_lists); opts = qemu_opts_create(list, id, !defaults, &local_err); + g_free(id); if (opts == NULL) { error_propagate(errp, local_err); return NULL; |