qemu

Форк
0
/
qemu-config.c 
295 строк · 7.7 Кб
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.