qemu-config.c 5.2 KB

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