1 #include "qemu/osdep.h" 2 #include "block/qdict.h" /* for qdict_extract_subqdict() */ 3 #include "qapi/error.h" 4 #include "qapi/qmp/qdict.h" 5 #include "qapi/qmp/qlist.h" 6 #include "qemu/error-report.h" 7 #include "qemu/option.h" 8 #include "qemu/config-file.h" 9 10 QemuOptsList *vm_config_groups[48]; 11 QemuOptsList *drive_config_groups[5]; 12 13 static QemuOptsList *find_list(QemuOptsList **lists, const char *group, 14 Error **errp) 15 { 16 int i; 17 18 qemu_load_module_for_opts(group); 19 for (i = 0; lists[i] != NULL; i++) { 20 if (strcmp(lists[i]->name, group) == 0) 21 break; 22 } 23 if (lists[i] == NULL) { 24 error_setg(errp, "There is no option group '%s'", group); 25 } 26 return lists[i]; 27 } 28 29 QemuOptsList *qemu_find_opts(const char *group) 30 { 31 QemuOptsList *ret; 32 Error *local_err = NULL; 33 34 ret = find_list(vm_config_groups, group, &local_err); 35 if (local_err) { 36 error_report_err(local_err); 37 } 38 39 return ret; 40 } 41 42 QemuOpts *qemu_find_opts_singleton(const char *group) 43 { 44 QemuOptsList *list; 45 QemuOpts *opts; 46 47 list = qemu_find_opts(group); 48 assert(list); 49 opts = qemu_opts_find(list, NULL); 50 if (!opts) { 51 opts = qemu_opts_create(list, NULL, 0, &error_abort); 52 } 53 return opts; 54 } 55 56 QemuOptsList *qemu_find_opts_err(const char *group, Error **errp) 57 { 58 return find_list(vm_config_groups, group, errp); 59 } 60 61 void qemu_add_drive_opts(QemuOptsList *list) 62 { 63 int entries, i; 64 65 entries = ARRAY_SIZE(drive_config_groups); 66 entries--; /* keep list NULL terminated */ 67 for (i = 0; i < entries; i++) { 68 if (drive_config_groups[i] == NULL) { 69 drive_config_groups[i] = list; 70 return; 71 } 72 } 73 fprintf(stderr, "ran out of space in drive_config_groups"); 74 abort(); 75 } 76 77 void qemu_add_opts(QemuOptsList *list) 78 { 79 int entries, i; 80 81 entries = ARRAY_SIZE(vm_config_groups); 82 entries--; /* keep list NULL terminated */ 83 for (i = 0; i < entries; i++) { 84 if (vm_config_groups[i] == NULL) { 85 vm_config_groups[i] = list; 86 return; 87 } 88 } 89 fprintf(stderr, "ran out of space in vm_config_groups"); 90 abort(); 91 } 92 93 /* Returns number of config groups on success, -errno on error */ 94 static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque, 95 const char *fname, Error **errp) 96 { 97 ERRP_GUARD(); 98 char line[1024], prev_group[64], group[64], arg[64], value[1024]; 99 Location loc; 100 QDict *qdict = NULL; 101 int res = -EINVAL, lno = 0; 102 int count = 0; 103 104 loc_push_none(&loc); 105 while (fgets(line, sizeof(line), fp) != NULL) { 106 ++lno; 107 if (line[0] == '\n') { 108 /* skip empty lines */ 109 continue; 110 } 111 if (line[0] == '#') { 112 /* comment */ 113 continue; 114 } 115 if (line[0] == '[') { 116 QDict *prev = qdict; 117 if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) { 118 qdict = qdict_new(); 119 qdict_put_str(qdict, "id", value); 120 count++; 121 } else if (sscanf(line, "[%63[^]]]", group) == 1) { 122 qdict = qdict_new(); 123 count++; 124 } 125 if (qdict != prev) { 126 if (prev) { 127 cb(prev_group, prev, opaque, errp); 128 qobject_unref(prev); 129 if (*errp) { 130 goto out; 131 } 132 } 133 strcpy(prev_group, group); 134 continue; 135 } 136 } 137 loc_set_file(fname, lno); 138 value[0] = '\0'; 139 if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 || 140 sscanf(line, " %63s = \"\"", arg) == 1) { 141 /* arg = value */ 142 if (qdict == NULL) { 143 error_setg(errp, "no group defined"); 144 goto out; 145 } 146 qdict_put_str(qdict, arg, value); 147 continue; 148 } 149 error_setg(errp, "parse error"); 150 goto out; 151 } 152 if (ferror(fp)) { 153 loc_pop(&loc); 154 error_setg_errno(errp, errno, "Cannot read config file"); 155 goto out_no_loc; 156 } 157 res = count; 158 if (qdict) { 159 cb(group, qdict, opaque, errp); 160 } 161 out: 162 loc_pop(&loc); 163 out_no_loc: 164 qobject_unref(qdict); 165 return res; 166 } 167 168 void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp) 169 { 170 QemuOptsList **lists = opaque; 171 QemuOptsList *list; 172 173 list = find_list(lists, group, errp); 174 if (!list) { 175 return; 176 } 177 178 qemu_opts_from_qdict(list, qdict, errp); 179 } 180 181 int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp) 182 { 183 return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp); 184 } 185 186 int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp) 187 { 188 FILE *f = fopen(filename, "r"); 189 int ret; 190 191 if (f == NULL) { 192 error_setg_file_open(errp, errno, filename); 193 return -errno; 194 } 195 196 ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp); 197 fclose(f); 198 return ret; 199 } 200 201 static bool config_parse_qdict_section(QDict *options, QemuOptsList *opts, 202 Error **errp) 203 { 204 QemuOpts *subopts; 205 g_autoptr(QDict) subqdict = NULL; 206 g_autoptr(QList) list = NULL; 207 size_t orig_size, enum_size; 208 char *prefix; 209 210 prefix = g_strdup_printf("%s.", opts->name); 211 qdict_extract_subqdict(options, &subqdict, prefix); 212 g_free(prefix); 213 orig_size = qdict_size(subqdict); 214 if (!orig_size) { 215 return true; 216 } 217 218 subopts = qemu_opts_create(opts, NULL, 0, errp); 219 if (!subopts) { 220 return false; 221 } 222 223 if (!qemu_opts_absorb_qdict(subopts, subqdict, errp)) { 224 return false; 225 } 226 227 enum_size = qdict_size(subqdict); 228 if (enum_size < orig_size && enum_size) { 229 error_setg(errp, "Unknown option '%s' for [%s]", 230 qdict_first(subqdict)->key, opts->name); 231 return false; 232 } 233 234 if (enum_size) { 235 /* Multiple, enumerated sections */ 236 QListEntry *list_entry; 237 unsigned i = 0; 238 239 /* Not required anymore */ 240 qemu_opts_del(subopts); 241 242 qdict_array_split(subqdict, &list); 243 if (qdict_size(subqdict)) { 244 error_setg(errp, "Unused option '%s' for [%s]", 245 qdict_first(subqdict)->key, opts->name); 246 return false; 247 } 248 249 QLIST_FOREACH_ENTRY(list, list_entry) { 250 QDict *section = qobject_to(QDict, qlist_entry_obj(list_entry)); 251 char *opt_name; 252 253 if (!section) { 254 error_setg(errp, "[%s] section (index %u) does not consist of " 255 "keys", opts->name, i); 256 return false; 257 } 258 259 opt_name = g_strdup_printf("%s.%u", opts->name, i++); 260 subopts = qemu_opts_create(opts, opt_name, 1, errp); 261 g_free(opt_name); 262 if (!subopts) { 263 return false; 264 } 265 266 if (!qemu_opts_absorb_qdict(subopts, section, errp)) { 267 qemu_opts_del(subopts); 268 return false; 269 } 270 271 if (qdict_size(section)) { 272 error_setg(errp, "[%s] section doesn't support the option '%s'", 273 opts->name, qdict_first(section)->key); 274 qemu_opts_del(subopts); 275 return false; 276 } 277 } 278 } 279 280 return true; 281 } 282 283 bool qemu_config_parse_qdict(QDict *options, QemuOptsList **lists, 284 Error **errp) 285 { 286 int i; 287 288 for (i = 0; lists[i]; i++) { 289 if (!config_parse_qdict_section(options, lists[i], errp)) { 290 return false; 291 } 292 } 293 294 return true; 295 } 296