1 #include "qemu-common.h" 2 #include "qemu/error-report.h" 3 #include "qemu/option.h" 4 #include "qemu/config-file.h" 5 #include "hw/qdev.h" 6 #include "qapi/error.h" 7 8 static QemuOptsList *vm_config_groups[32]; 9 10 static QemuOptsList *find_list(QemuOptsList **lists, const char *group, 11 Error **errp) 12 { 13 int i; 14 15 for (i = 0; lists[i] != NULL; i++) { 16 if (strcmp(lists[i]->name, group) == 0) 17 break; 18 } 19 if (lists[i] == NULL) { 20 error_set(errp, QERR_INVALID_OPTION_GROUP, group); 21 } 22 return lists[i]; 23 } 24 25 QemuOptsList *qemu_find_opts(const char *group) 26 { 27 QemuOptsList *ret; 28 Error *local_err = NULL; 29 30 ret = find_list(vm_config_groups, group, &local_err); 31 if (error_is_set(&local_err)) { 32 error_report("%s", error_get_pretty(local_err)); 33 error_free(local_err); 34 } 35 36 return ret; 37 } 38 39 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp) 40 { 41 return find_list(vm_config_groups, group, errp); 42 } 43 44 void qemu_add_opts(QemuOptsList *list) 45 { 46 int entries, i; 47 48 entries = ARRAY_SIZE(vm_config_groups); 49 entries--; /* keep list NULL terminated */ 50 for (i = 0; i < entries; i++) { 51 if (vm_config_groups[i] == NULL) { 52 vm_config_groups[i] = list; 53 return; 54 } 55 } 56 fprintf(stderr, "ran out of space in vm_config_groups"); 57 abort(); 58 } 59 60 int qemu_set_option(const char *str) 61 { 62 char group[64], id[64], arg[64]; 63 QemuOptsList *list; 64 QemuOpts *opts; 65 int rc, offset; 66 67 rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset); 68 if (rc < 3 || str[offset] != '=') { 69 error_report("can't parse: \"%s\"", str); 70 return -1; 71 } 72 73 list = qemu_find_opts(group); 74 if (list == NULL) { 75 return -1; 76 } 77 78 opts = qemu_opts_find(list, id); 79 if (!opts) { 80 error_report("there is no %s \"%s\" defined", 81 list->name, id); 82 return -1; 83 } 84 85 if (qemu_opt_set(opts, arg, str+offset+1) == -1) { 86 return -1; 87 } 88 return 0; 89 } 90 91 struct ConfigWriteData { 92 QemuOptsList *list; 93 FILE *fp; 94 }; 95 96 static int config_write_opt(const char *name, const char *value, void *opaque) 97 { 98 struct ConfigWriteData *data = opaque; 99 100 fprintf(data->fp, " %s = \"%s\"\n", name, value); 101 return 0; 102 } 103 104 static int config_write_opts(QemuOpts *opts, void *opaque) 105 { 106 struct ConfigWriteData *data = opaque; 107 const char *id = qemu_opts_id(opts); 108 109 if (id) { 110 fprintf(data->fp, "[%s \"%s\"]\n", data->list->name, id); 111 } else { 112 fprintf(data->fp, "[%s]\n", data->list->name); 113 } 114 qemu_opt_foreach(opts, config_write_opt, data, 0); 115 fprintf(data->fp, "\n"); 116 return 0; 117 } 118 119 void qemu_config_write(FILE *fp) 120 { 121 struct ConfigWriteData data = { .fp = fp }; 122 QemuOptsList **lists = vm_config_groups; 123 int i; 124 125 fprintf(fp, "# qemu config file\n\n"); 126 for (i = 0; lists[i] != NULL; i++) { 127 data.list = lists[i]; 128 qemu_opts_foreach(data.list, config_write_opts, &data, 0); 129 } 130 } 131 132 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) 133 { 134 char line[1024], group[64], id[64], arg[64], value[1024]; 135 Location loc; 136 QemuOptsList *list = NULL; 137 Error *local_err = NULL; 138 QemuOpts *opts = NULL; 139 int res = -1, lno = 0; 140 141 loc_push_none(&loc); 142 while (fgets(line, sizeof(line), fp) != NULL) { 143 loc_set_file(fname, ++lno); 144 if (line[0] == '\n') { 145 /* skip empty lines */ 146 continue; 147 } 148 if (line[0] == '#') { 149 /* comment */ 150 continue; 151 } 152 if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { 153 /* group with id */ 154 list = find_list(lists, group, &local_err); 155 if (error_is_set(&local_err)) { 156 error_report("%s", error_get_pretty(local_err)); 157 error_free(local_err); 158 goto out; 159 } 160 opts = qemu_opts_create(list, id, 1, NULL); 161 continue; 162 } 163 if (sscanf(line, "[%63[^]]]", group) == 1) { 164 /* group without id */ 165 list = find_list(lists, group, &local_err); 166 if (error_is_set(&local_err)) { 167 error_report("%s", error_get_pretty(local_err)); 168 error_free(local_err); 169 goto out; 170 } 171 opts = qemu_opts_create_nofail(list); 172 continue; 173 } 174 if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { 175 /* arg = value */ 176 if (opts == NULL) { 177 error_report("no group defined"); 178 goto out; 179 } 180 if (qemu_opt_set(opts, arg, value) != 0) { 181 goto out; 182 } 183 continue; 184 } 185 error_report("parse error"); 186 goto out; 187 } 188 if (ferror(fp)) { 189 error_report("error reading file"); 190 goto out; 191 } 192 res = 0; 193 out: 194 loc_pop(&loc); 195 return res; 196 } 197 198 int qemu_read_config_file(const char *filename) 199 { 200 FILE *f = fopen(filename, "r"); 201 int ret; 202 203 if (f == NULL) { 204 return -errno; 205 } 206 207 ret = qemu_config_parse(f, vm_config_groups, filename); 208 fclose(f); 209 210 if (ret == 0) { 211 return 0; 212 } else { 213 return -EINVAL; 214 } 215 } 216