const char *qemu_opt_get(QemuOpts *opts, const char *name)
{
- QemuOpt *opt = qemu_opt_find(opts, name);
+ QemuOpt *opt;
+
+ if (opts == NULL) {
+ return NULL;
+ }
+ opt = qemu_opt_find(opts, name);
if (!opt) {
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
if (desc && desc->def_value_str) {
static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
bool defval, bool del)
{
- QemuOpt *opt = qemu_opt_find(opts, name);
+ QemuOpt *opt;
bool ret = defval;
+ if (opts == NULL) {
+ return ret;
+ }
+
+ opt = qemu_opt_find(opts, name);
if (opt == NULL) {
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
if (desc && desc->def_value_str) {
static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
uint64_t defval, bool del)
{
- QemuOpt *opt = qemu_opt_find(opts, name);
+ QemuOpt *opt;
uint64_t ret = defval;
+ if (opts == NULL) {
+ return ret;
+ }
+
+ opt = qemu_opt_find(opts, name);
if (opt == NULL) {
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
if (desc && desc->def_value_str) {
static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
uint64_t defval, bool del)
{
- QemuOpt *opt = qemu_opt_find(opts, name);
+ QemuOpt *opt;
uint64_t ret = defval;
+ if (opts == NULL) {
+ return ret;
+ }
+
+ opt = qemu_opt_find(opts, name);
if (opt == NULL) {
const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
if (desc && desc->def_value_str) {
return NULL;
}
-static int id_wellformed(const char *id)
-{
- int i;
-
- if (!qemu_isalpha(id[0])) {
- return 0;
- }
- for (i = 1; id[i]; i++) {
- if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
- return 0;
- }
- }
- return 1;
-}
-
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
int fail_if_exists, Error **errp)
{
g_free(opts);
}
-void qemu_opts_print(QemuOpts *opts)
+void qemu_opts_print(QemuOpts *opts, const char *sep)
{
QemuOpt *opt;
QemuOptDesc *desc = opts->list->desc;
if (desc[0].name == NULL) {
QTAILQ_FOREACH(opt, &opts->head, next) {
- printf("%s=\"%s\" ", opt->name, opt->str);
+ printf("%s%s=\"%s\"", sep, opt->name, opt->str);
}
return;
}
continue;
}
if (desc->type == QEMU_OPT_STRING) {
- printf("%s='%s' ", desc->name, value);
+ printf("%s%s='%s'", sep, desc->name, value);
} else if ((desc->type == QEMU_OPT_SIZE ||
desc->type == QEMU_OPT_NUMBER) && opt) {
- printf("%s=%" PRId64 " ", desc->name, opt->value.uint);
+ printf("%s%s=%" PRId64, sep, desc->name, opt->value.uint);
} else {
- printf("%s=%s ", desc->name, value);
+ printf("%s%s=%s", sep, desc->name, value);
}
}
}
void qemu_opts_free(QemuOptsList *list)
{
- /* List members point to new malloced space and need to be freed.
- * FIXME:
- * Introduced for QEMUOptionParamter->QemuOpts conversion.
- * Will remove after all drivers switch to QemuOpts.
- */
- if (list && list->allocated) {
- QemuOptDesc *desc = list->desc;
- while (desc && desc->name) {
- g_free((char *)desc->name);
- g_free((char *)desc->help);
- g_free((char *)desc->def_value_str);
- desc++;
- }
- }
-
g_free(list);
}
/* Realloc dst option list and append options from an option list (list)
* to it. dst could be NULL or a malloced list.
+ * The lifetime of dst must be shorter than the input list because the
+ * QemuOptDesc->name, ->help, and ->def_value_str strings are shared.
*/
QemuOptsList *qemu_opts_append(QemuOptsList *dst,
QemuOptsList *list)
size_t num_opts, num_dst_opts;
QemuOptDesc *desc;
bool need_init = false;
+ bool need_head_update;
if (!list) {
return dst;
*/
if (!dst) {
need_init = true;
+ need_head_update = true;
+ } else {
+ /* Moreover, even if dst is not NULL, the realloc may move it to a
+ * different address in which case we may get a stale tail pointer
+ * in dst->head. */
+ need_head_update = QTAILQ_EMPTY(&dst->head);
}
num_opts = count_opts_list(dst);
if (need_init) {
dst->name = NULL;
dst->implied_opt_name = NULL;
- QTAILQ_INIT(&dst->head);
- dst->allocated = true;
dst->merge_lists = false;
}
+ if (need_head_update) {
+ QTAILQ_INIT(&dst->head);
+ }
dst->desc[num_dst_opts].name = NULL;
- /* (const char *) members of result dst are malloced, need free. */
- assert(dst->allocated);
/* append list->desc to dst->desc */
if (list) {
desc = list->desc;
while (desc && desc->name) {
if (find_desc_by_name(dst->desc, desc->name) == NULL) {
- dst->desc[num_dst_opts].name = g_strdup(desc->name);
- dst->desc[num_dst_opts].type = desc->type;
- dst->desc[num_dst_opts].help = g_strdup(desc->help);
- dst->desc[num_dst_opts].def_value_str =
- g_strdup(desc->def_value_str);
- num_dst_opts++;
+ dst->desc[num_dst_opts++] = *desc;
dst->desc[num_dst_opts].name = NULL;
}
desc++;