qemu-config: add error propagation to qemu_config_parse

This enables some simplification of vl.c via error_fatal, and improves
error messages.  Before:

  $ ./qemu-system-x86_64 -readconfig .
  qemu-system-x86_64: error reading file
  qemu-system-x86_64: -readconfig .: read config .: Invalid argument
  $ /usr/libexec/qemu-kvm -readconfig foo
  qemu-kvm: -readconfig foo: read config foo: No such file or directory

After:

  $ ./qemu-system-x86_64 -readconfig .
  qemu-system-x86_64: -readconfig .: Cannot read config file: Is a directory
  $ ./qemu-system-x86_64 -readconfig foo
  qemu-system-x86_64: -readconfig foo: Could not open 'foo': No such file or directory

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20210226170816.231173-1-pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2021-02-26 12:08:16 -05:00
parent e20e182ea0
commit f7544edcd3
4 changed files with 27 additions and 33 deletions

View file

@ -279,9 +279,8 @@ static int read_config(BDRVBlkdebugState *s, const char *filename,
return -errno; return -errno;
} }
ret = qemu_config_parse(f, config_groups, filename); ret = qemu_config_parse(f, config_groups, filename, errp);
if (ret < 0) { if (ret < 0) {
error_setg(errp, "Could not parse blkdebug config file");
goto fail; goto fail;
} }
} }

View file

@ -11,9 +11,10 @@ void qemu_add_drive_opts(QemuOptsList *list);
int qemu_global_option(const char *str); int qemu_global_option(const char *str);
void qemu_config_write(FILE *fp); void qemu_config_write(FILE *fp);
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname); int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname,
Error **errp);
int qemu_read_config_file(const char *filename); int qemu_read_config_file(const char *filename, Error **errp);
/* Parse QDict options as a replacement for a config file (allowing multiple /* Parse QDict options as a replacement for a config file (allowing multiple
enumerated (0..(n-1)) configuration "sections") */ enumerated (0..(n-1)) configuration "sections") */

View file

@ -2062,17 +2062,19 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
return 0; return 0;
} }
static int qemu_read_default_config_file(void) static void qemu_read_default_config_file(Error **errp)
{ {
ERRP_GUARD();
int ret; int ret;
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf"); g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
ret = qemu_read_config_file(file); ret = qemu_read_config_file(file, errp);
if (ret < 0 && ret != -ENOENT) { if (ret < 0) {
return ret; if (ret == -ENOENT) {
error_free(*errp);
*errp = NULL;
}
} }
return 0;
} }
static int qemu_set_option(const char *str) static int qemu_set_option(const char *str)
@ -2633,9 +2635,7 @@ void qemu_init(int argc, char **argv, char **envp)
} }
if (userconfig) { if (userconfig) {
if (qemu_read_default_config_file() < 0) { qemu_read_default_config_file(&error_fatal);
exit(1);
}
} }
/* second pass of option parsing */ /* second pass of option parsing */
@ -3323,15 +3323,8 @@ void qemu_init(int argc, char **argv, char **envp)
qemu_plugin_opt_parse(optarg, &plugin_list); qemu_plugin_opt_parse(optarg, &plugin_list);
break; break;
case QEMU_OPTION_readconfig: case QEMU_OPTION_readconfig:
{ qemu_read_config_file(optarg, &error_fatal);
int ret = qemu_read_config_file(optarg); break;
if (ret < 0) {
error_report("read config %s: %s", optarg,
strerror(-ret));
exit(1);
}
break;
}
case QEMU_OPTION_spice: case QEMU_OPTION_spice:
olist = qemu_find_opts_err("spice", NULL); olist = qemu_find_opts_err("spice", NULL);
if (!olist) { if (!olist) {

View file

@ -350,7 +350,7 @@ void qemu_config_write(FILE *fp)
} }
/* Returns number of config groups on success, -errno on error */ /* Returns number of config groups on success, -errno on error */
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
{ {
char line[1024], group[64], id[64], arg[64], value[1024]; char line[1024], group[64], id[64], arg[64], value[1024];
Location loc; Location loc;
@ -375,7 +375,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
/* group with id */ /* group with id */
list = find_list(lists, group, &local_err); list = find_list(lists, group, &local_err);
if (local_err) { if (local_err) {
error_report_err(local_err); error_propagate(errp, local_err);
goto out; goto out;
} }
opts = qemu_opts_create(list, id, 1, NULL); opts = qemu_opts_create(list, id, 1, NULL);
@ -386,7 +386,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
/* group without id */ /* group without id */
list = find_list(lists, group, &local_err); list = find_list(lists, group, &local_err);
if (local_err) { if (local_err) {
error_report_err(local_err); error_propagate(errp, local_err);
goto out; goto out;
} }
opts = qemu_opts_create(list, NULL, 0, &error_abort); opts = qemu_opts_create(list, NULL, 0, &error_abort);
@ -398,21 +398,21 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
sscanf(line, " %63s = \"\"", arg) == 1) { sscanf(line, " %63s = \"\"", arg) == 1) {
/* arg = value */ /* arg = value */
if (opts == NULL) { if (opts == NULL) {
error_report("no group defined"); error_setg(errp, "no group defined");
goto out; goto out;
} }
if (!qemu_opt_set(opts, arg, value, &local_err)) { if (!qemu_opt_set(opts, arg, value, errp)) {
error_report_err(local_err);
goto out; goto out;
} }
continue; continue;
} }
error_report("parse error"); error_setg(errp, "parse error");
goto out; goto out;
} }
if (ferror(fp)) { if (ferror(fp)) {
error_report("error reading file"); loc_pop(&loc);
goto out; error_setg_errno(errp, errno, "Cannot read config file");
return res;
} }
res = count; res = count;
out: out:
@ -420,16 +420,17 @@ out:
return res; return res;
} }
int qemu_read_config_file(const char *filename) int qemu_read_config_file(const char *filename, Error **errp)
{ {
FILE *f = fopen(filename, "r"); FILE *f = fopen(filename, "r");
int ret; int ret;
if (f == NULL) { if (f == NULL) {
error_setg_file_open(errp, errno, filename);
return -errno; return -errno;
} }
ret = qemu_config_parse(f, vm_config_groups, filename); ret = qemu_config_parse(f, vm_config_groups, filename, errp);
fclose(f); fclose(f);
return ret; return ret;
} }