qemu-option.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. /*
  2. * Commandline option parsing functions
  3. *
  4. * Copyright (c) 2003-2008 Fabrice Bellard
  5. * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "qemu-common.h"
  28. #include "qemu-error.h"
  29. #include "qemu-objects.h"
  30. #include "qemu-option.h"
  31. #include "qerror.h"
  32. /*
  33. * Extracts the name of an option from the parameter string (p points at the
  34. * first byte of the option name)
  35. *
  36. * The option name is delimited by delim (usually , or =) or the string end
  37. * and is copied into buf. If the option name is longer than buf_size, it is
  38. * truncated. buf is always zero terminated.
  39. *
  40. * The return value is the position of the delimiter/zero byte after the option
  41. * name in p.
  42. */
  43. const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
  44. {
  45. char *q;
  46. q = buf;
  47. while (*p != '\0' && *p != delim) {
  48. if (q && (q - buf) < buf_size - 1)
  49. *q++ = *p;
  50. p++;
  51. }
  52. if (q)
  53. *q = '\0';
  54. return p;
  55. }
  56. /*
  57. * Extracts the value of an option from the parameter string p (p points at the
  58. * first byte of the option value)
  59. *
  60. * This function is comparable to get_opt_name with the difference that the
  61. * delimiter is fixed to be comma which starts a new option. To specify an
  62. * option value that contains commas, double each comma.
  63. */
  64. const char *get_opt_value(char *buf, int buf_size, const char *p)
  65. {
  66. char *q;
  67. q = buf;
  68. while (*p != '\0') {
  69. if (*p == ',') {
  70. if (*(p + 1) != ',')
  71. break;
  72. p++;
  73. }
  74. if (q && (q - buf) < buf_size - 1)
  75. *q++ = *p;
  76. p++;
  77. }
  78. if (q)
  79. *q = '\0';
  80. return p;
  81. }
  82. int get_next_param_value(char *buf, int buf_size,
  83. const char *tag, const char **pstr)
  84. {
  85. const char *p;
  86. char option[128];
  87. p = *pstr;
  88. for(;;) {
  89. p = get_opt_name(option, sizeof(option), p, '=');
  90. if (*p != '=')
  91. break;
  92. p++;
  93. if (!strcmp(tag, option)) {
  94. *pstr = get_opt_value(buf, buf_size, p);
  95. if (**pstr == ',') {
  96. (*pstr)++;
  97. }
  98. return strlen(buf);
  99. } else {
  100. p = get_opt_value(NULL, 0, p);
  101. }
  102. if (*p != ',')
  103. break;
  104. p++;
  105. }
  106. return 0;
  107. }
  108. int get_param_value(char *buf, int buf_size,
  109. const char *tag, const char *str)
  110. {
  111. return get_next_param_value(buf, buf_size, tag, &str);
  112. }
  113. int check_params(char *buf, int buf_size,
  114. const char * const *params, const char *str)
  115. {
  116. const char *p;
  117. int i;
  118. p = str;
  119. while (*p != '\0') {
  120. p = get_opt_name(buf, buf_size, p, '=');
  121. if (*p != '=') {
  122. return -1;
  123. }
  124. p++;
  125. for (i = 0; params[i] != NULL; i++) {
  126. if (!strcmp(params[i], buf)) {
  127. break;
  128. }
  129. }
  130. if (params[i] == NULL) {
  131. return -1;
  132. }
  133. p = get_opt_value(NULL, 0, p);
  134. if (*p != ',') {
  135. break;
  136. }
  137. p++;
  138. }
  139. return 0;
  140. }
  141. /*
  142. * Searches an option list for an option with the given name
  143. */
  144. QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
  145. const char *name)
  146. {
  147. while (list && list->name) {
  148. if (!strcmp(list->name, name)) {
  149. return list;
  150. }
  151. list++;
  152. }
  153. return NULL;
  154. }
  155. static int parse_option_bool(const char *name, const char *value, int *ret)
  156. {
  157. if (value != NULL) {
  158. if (!strcmp(value, "on")) {
  159. *ret = 1;
  160. } else if (!strcmp(value, "off")) {
  161. *ret = 0;
  162. } else {
  163. qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
  164. return -1;
  165. }
  166. } else {
  167. *ret = 1;
  168. }
  169. return 0;
  170. }
  171. static int parse_option_number(const char *name, const char *value, uint64_t *ret)
  172. {
  173. char *postfix;
  174. uint64_t number;
  175. if (value != NULL) {
  176. number = strtoull(value, &postfix, 0);
  177. if (*postfix != '\0') {
  178. qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
  179. return -1;
  180. }
  181. *ret = number;
  182. } else {
  183. qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
  184. return -1;
  185. }
  186. return 0;
  187. }
  188. static int parse_option_size(const char *name, const char *value, uint64_t *ret)
  189. {
  190. char *postfix;
  191. double sizef;
  192. if (value != NULL) {
  193. sizef = strtod(value, &postfix);
  194. switch (*postfix) {
  195. case 'T':
  196. sizef *= 1024;
  197. case 'G':
  198. sizef *= 1024;
  199. case 'M':
  200. sizef *= 1024;
  201. case 'K':
  202. case 'k':
  203. sizef *= 1024;
  204. case 'b':
  205. case '\0':
  206. *ret = (uint64_t) sizef;
  207. break;
  208. default:
  209. qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
  210. error_printf_unless_qmp("You may use k, M, G or T suffixes for "
  211. "kilobytes, megabytes, gigabytes and terabytes.\n");
  212. return -1;
  213. }
  214. } else {
  215. qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
  216. return -1;
  217. }
  218. return 0;
  219. }
  220. /*
  221. * Sets the value of a parameter in a given option list. The parsing of the
  222. * value depends on the type of option:
  223. *
  224. * OPT_FLAG (uses value.n):
  225. * If no value is given, the flag is set to 1.
  226. * Otherwise the value must be "on" (set to 1) or "off" (set to 0)
  227. *
  228. * OPT_STRING (uses value.s):
  229. * value is strdup()ed and assigned as option value
  230. *
  231. * OPT_SIZE (uses value.n):
  232. * The value is converted to an integer. Suffixes for kilobytes etc. are
  233. * allowed (powers of 1024).
  234. *
  235. * Returns 0 on succes, -1 in error cases
  236. */
  237. int set_option_parameter(QEMUOptionParameter *list, const char *name,
  238. const char *value)
  239. {
  240. int flag;
  241. // Find a matching parameter
  242. list = get_option_parameter(list, name);
  243. if (list == NULL) {
  244. fprintf(stderr, "Unknown option '%s'\n", name);
  245. return -1;
  246. }
  247. // Process parameter
  248. switch (list->type) {
  249. case OPT_FLAG:
  250. if (parse_option_bool(name, value, &flag) == -1)
  251. return -1;
  252. list->value.n = flag;
  253. break;
  254. case OPT_STRING:
  255. if (value != NULL) {
  256. list->value.s = qemu_strdup(value);
  257. } else {
  258. fprintf(stderr, "Option '%s' needs a parameter\n", name);
  259. return -1;
  260. }
  261. break;
  262. case OPT_SIZE:
  263. if (parse_option_size(name, value, &list->value.n) == -1)
  264. return -1;
  265. break;
  266. default:
  267. fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
  268. return -1;
  269. }
  270. return 0;
  271. }
  272. /*
  273. * Sets the given parameter to an integer instead of a string.
  274. * This function cannot be used to set string options.
  275. *
  276. * Returns 0 on success, -1 in error cases
  277. */
  278. int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
  279. uint64_t value)
  280. {
  281. // Find a matching parameter
  282. list = get_option_parameter(list, name);
  283. if (list == NULL) {
  284. fprintf(stderr, "Unknown option '%s'\n", name);
  285. return -1;
  286. }
  287. // Process parameter
  288. switch (list->type) {
  289. case OPT_FLAG:
  290. case OPT_NUMBER:
  291. case OPT_SIZE:
  292. list->value.n = value;
  293. break;
  294. default:
  295. return -1;
  296. }
  297. return 0;
  298. }
  299. /*
  300. * Frees a option list. If it contains strings, the strings are freed as well.
  301. */
  302. void free_option_parameters(QEMUOptionParameter *list)
  303. {
  304. QEMUOptionParameter *cur = list;
  305. while (cur && cur->name) {
  306. if (cur->type == OPT_STRING) {
  307. qemu_free(cur->value.s);
  308. }
  309. cur++;
  310. }
  311. qemu_free(list);
  312. }
  313. /*
  314. * Count valid options in list
  315. */
  316. static size_t count_option_parameters(QEMUOptionParameter *list)
  317. {
  318. size_t num_options = 0;
  319. while (list && list->name) {
  320. num_options++;
  321. list++;
  322. }
  323. return num_options;
  324. }
  325. /*
  326. * Append an option list (list) to an option list (dest).
  327. *
  328. * If dest is NULL, a new copy of list is created.
  329. *
  330. * Returns a pointer to the first element of dest (or the newly allocated copy)
  331. */
  332. QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
  333. QEMUOptionParameter *list)
  334. {
  335. size_t num_options, num_dest_options;
  336. num_options = count_option_parameters(dest);
  337. num_dest_options = num_options;
  338. num_options += count_option_parameters(list);
  339. dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
  340. dest[num_dest_options].name = NULL;
  341. while (list && list->name) {
  342. if (get_option_parameter(dest, list->name) == NULL) {
  343. dest[num_dest_options++] = *list;
  344. dest[num_dest_options].name = NULL;
  345. }
  346. list++;
  347. }
  348. return dest;
  349. }
  350. /*
  351. * Parses a parameter string (param) into an option list (dest).
  352. *
  353. * list is the template option list. If dest is NULL, a new copy of list is
  354. * created. If list is NULL, this function fails.
  355. *
  356. * A parameter string consists of one or more parameters, separated by commas.
  357. * Each parameter consists of its name and possibly of a value. In the latter
  358. * case, the value is delimited by an = character. To specify a value which
  359. * contains commas, double each comma so it won't be recognized as the end of
  360. * the parameter.
  361. *
  362. * For more details of the parsing see above.
  363. *
  364. * Returns a pointer to the first element of dest (or the newly allocated copy)
  365. * or NULL in error cases
  366. */
  367. QEMUOptionParameter *parse_option_parameters(const char *param,
  368. QEMUOptionParameter *list, QEMUOptionParameter *dest)
  369. {
  370. QEMUOptionParameter *allocated = NULL;
  371. char name[256];
  372. char value[256];
  373. char *param_delim, *value_delim;
  374. char next_delim;
  375. if (list == NULL) {
  376. return NULL;
  377. }
  378. if (dest == NULL) {
  379. dest = allocated = append_option_parameters(NULL, list);
  380. }
  381. while (*param) {
  382. // Find parameter name and value in the string
  383. param_delim = strchr(param, ',');
  384. value_delim = strchr(param, '=');
  385. if (value_delim && (value_delim < param_delim || !param_delim)) {
  386. next_delim = '=';
  387. } else {
  388. next_delim = ',';
  389. value_delim = NULL;
  390. }
  391. param = get_opt_name(name, sizeof(name), param, next_delim);
  392. if (value_delim) {
  393. param = get_opt_value(value, sizeof(value), param + 1);
  394. }
  395. if (*param != '\0') {
  396. param++;
  397. }
  398. // Set the parameter
  399. if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
  400. goto fail;
  401. }
  402. }
  403. return dest;
  404. fail:
  405. // Only free the list if it was newly allocated
  406. free_option_parameters(allocated);
  407. return NULL;
  408. }
  409. /*
  410. * Prints all options of a list that have a value to stdout
  411. */
  412. void print_option_parameters(QEMUOptionParameter *list)
  413. {
  414. while (list && list->name) {
  415. switch (list->type) {
  416. case OPT_STRING:
  417. if (list->value.s != NULL) {
  418. printf("%s='%s' ", list->name, list->value.s);
  419. }
  420. break;
  421. case OPT_FLAG:
  422. printf("%s=%s ", list->name, list->value.n ? "on" : "off");
  423. break;
  424. case OPT_SIZE:
  425. case OPT_NUMBER:
  426. printf("%s=%" PRId64 " ", list->name, list->value.n);
  427. break;
  428. default:
  429. printf("%s=(unkown type) ", list->name);
  430. break;
  431. }
  432. list++;
  433. }
  434. }
  435. /*
  436. * Prints an overview of all available options
  437. */
  438. void print_option_help(QEMUOptionParameter *list)
  439. {
  440. printf("Supported options:\n");
  441. while (list && list->name) {
  442. printf("%-16s %s\n", list->name,
  443. list->help ? list->help : "No description available");
  444. list++;
  445. }
  446. }
  447. /* ------------------------------------------------------------------ */
  448. struct QemuOpt {
  449. const char *name;
  450. const char *str;
  451. const QemuOptDesc *desc;
  452. union {
  453. int boolean;
  454. uint64_t uint;
  455. } value;
  456. QemuOpts *opts;
  457. QTAILQ_ENTRY(QemuOpt) next;
  458. };
  459. struct QemuOpts {
  460. char *id;
  461. QemuOptsList *list;
  462. Location loc;
  463. QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
  464. QTAILQ_ENTRY(QemuOpts) next;
  465. };
  466. static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
  467. {
  468. QemuOpt *opt;
  469. QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
  470. if (strcmp(opt->name, name) != 0)
  471. continue;
  472. return opt;
  473. }
  474. return NULL;
  475. }
  476. const char *qemu_opt_get(QemuOpts *opts, const char *name)
  477. {
  478. QemuOpt *opt = qemu_opt_find(opts, name);
  479. return opt ? opt->str : NULL;
  480. }
  481. int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
  482. {
  483. QemuOpt *opt = qemu_opt_find(opts, name);
  484. if (opt == NULL)
  485. return defval;
  486. assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
  487. return opt->value.boolean;
  488. }
  489. uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
  490. {
  491. QemuOpt *opt = qemu_opt_find(opts, name);
  492. if (opt == NULL)
  493. return defval;
  494. assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
  495. return opt->value.uint;
  496. }
  497. uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
  498. {
  499. QemuOpt *opt = qemu_opt_find(opts, name);
  500. if (opt == NULL)
  501. return defval;
  502. assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
  503. return opt->value.uint;
  504. }
  505. static int qemu_opt_parse(QemuOpt *opt)
  506. {
  507. if (opt->desc == NULL)
  508. return 0;
  509. switch (opt->desc->type) {
  510. case QEMU_OPT_STRING:
  511. /* nothing */
  512. return 0;
  513. case QEMU_OPT_BOOL:
  514. return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
  515. case QEMU_OPT_NUMBER:
  516. return parse_option_number(opt->name, opt->str, &opt->value.uint);
  517. case QEMU_OPT_SIZE:
  518. return parse_option_size(opt->name, opt->str, &opt->value.uint);
  519. default:
  520. abort();
  521. }
  522. }
  523. static void qemu_opt_del(QemuOpt *opt)
  524. {
  525. QTAILQ_REMOVE(&opt->opts->head, opt, next);
  526. qemu_free((/* !const */ char*)opt->name);
  527. qemu_free((/* !const */ char*)opt->str);
  528. qemu_free(opt);
  529. }
  530. int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
  531. {
  532. QemuOpt *opt;
  533. const QemuOptDesc *desc = opts->list->desc;
  534. int i;
  535. for (i = 0; desc[i].name != NULL; i++) {
  536. if (strcmp(desc[i].name, name) == 0) {
  537. break;
  538. }
  539. }
  540. if (desc[i].name == NULL) {
  541. if (i == 0) {
  542. /* empty list -> allow any */;
  543. } else {
  544. qerror_report(QERR_INVALID_PARAMETER, name);
  545. return -1;
  546. }
  547. }
  548. opt = qemu_mallocz(sizeof(*opt));
  549. opt->name = qemu_strdup(name);
  550. opt->opts = opts;
  551. QTAILQ_INSERT_TAIL(&opts->head, opt, next);
  552. if (desc[i].name != NULL) {
  553. opt->desc = desc+i;
  554. }
  555. if (value) {
  556. opt->str = qemu_strdup(value);
  557. }
  558. if (qemu_opt_parse(opt) < 0) {
  559. qemu_opt_del(opt);
  560. return -1;
  561. }
  562. return 0;
  563. }
  564. int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
  565. int abort_on_failure)
  566. {
  567. QemuOpt *opt;
  568. int rc = 0;
  569. QTAILQ_FOREACH(opt, &opts->head, next) {
  570. rc = func(opt->name, opt->str, opaque);
  571. if (abort_on_failure && rc != 0)
  572. break;
  573. }
  574. return rc;
  575. }
  576. QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
  577. {
  578. QemuOpts *opts;
  579. QTAILQ_FOREACH(opts, &list->head, next) {
  580. if (!opts->id) {
  581. continue;
  582. }
  583. if (strcmp(opts->id, id) != 0) {
  584. continue;
  585. }
  586. return opts;
  587. }
  588. return NULL;
  589. }
  590. static int id_wellformed(const char *id)
  591. {
  592. int i;
  593. if (!qemu_isalpha(id[0])) {
  594. return 0;
  595. }
  596. for (i = 1; id[i]; i++) {
  597. if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
  598. return 0;
  599. }
  600. }
  601. return 1;
  602. }
  603. QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
  604. {
  605. QemuOpts *opts = NULL;
  606. if (id) {
  607. if (!id_wellformed(id)) {
  608. qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
  609. error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
  610. return NULL;
  611. }
  612. opts = qemu_opts_find(list, id);
  613. if (opts != NULL) {
  614. if (fail_if_exists) {
  615. qerror_report(QERR_DUPLICATE_ID, id, list->name);
  616. return NULL;
  617. } else {
  618. return opts;
  619. }
  620. }
  621. }
  622. opts = qemu_mallocz(sizeof(*opts));
  623. if (id) {
  624. opts->id = qemu_strdup(id);
  625. }
  626. opts->list = list;
  627. loc_save(&opts->loc);
  628. QTAILQ_INIT(&opts->head);
  629. QTAILQ_INSERT_TAIL(&list->head, opts, next);
  630. return opts;
  631. }
  632. void qemu_opts_reset(QemuOptsList *list)
  633. {
  634. QemuOpts *opts, *next_opts;
  635. QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
  636. qemu_opts_del(opts);
  637. }
  638. }
  639. void qemu_opts_loc_restore(QemuOpts *opts)
  640. {
  641. loc_restore(&opts->loc);
  642. }
  643. int qemu_opts_set(QemuOptsList *list, const char *id,
  644. const char *name, const char *value)
  645. {
  646. QemuOpts *opts;
  647. opts = qemu_opts_create(list, id, 1);
  648. if (opts == NULL) {
  649. return -1;
  650. }
  651. return qemu_opt_set(opts, name, value);
  652. }
  653. const char *qemu_opts_id(QemuOpts *opts)
  654. {
  655. return opts->id;
  656. }
  657. void qemu_opts_del(QemuOpts *opts)
  658. {
  659. QemuOpt *opt;
  660. for (;;) {
  661. opt = QTAILQ_FIRST(&opts->head);
  662. if (opt == NULL)
  663. break;
  664. qemu_opt_del(opt);
  665. }
  666. QTAILQ_REMOVE(&opts->list->head, opts, next);
  667. qemu_free(opts->id);
  668. qemu_free(opts);
  669. }
  670. int qemu_opts_print(QemuOpts *opts, void *dummy)
  671. {
  672. QemuOpt *opt;
  673. fprintf(stderr, "%s: %s:", opts->list->name,
  674. opts->id ? opts->id : "<noid>");
  675. QTAILQ_FOREACH(opt, &opts->head, next) {
  676. fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
  677. }
  678. fprintf(stderr, "\n");
  679. return 0;
  680. }
  681. int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
  682. {
  683. char option[128], value[1024];
  684. const char *p,*pe,*pc;
  685. for (p = params; *p != '\0'; p++) {
  686. pe = strchr(p, '=');
  687. pc = strchr(p, ',');
  688. if (!pe || (pc && pc < pe)) {
  689. /* found "foo,more" */
  690. if (p == params && firstname) {
  691. /* implicitly named first option */
  692. pstrcpy(option, sizeof(option), firstname);
  693. p = get_opt_value(value, sizeof(value), p);
  694. } else {
  695. /* option without value, probably a flag */
  696. p = get_opt_name(option, sizeof(option), p, ',');
  697. if (strncmp(option, "no", 2) == 0) {
  698. memmove(option, option+2, strlen(option+2)+1);
  699. pstrcpy(value, sizeof(value), "off");
  700. } else {
  701. pstrcpy(value, sizeof(value), "on");
  702. }
  703. }
  704. } else {
  705. /* found "foo=bar,more" */
  706. p = get_opt_name(option, sizeof(option), p, '=');
  707. if (*p != '=') {
  708. break;
  709. }
  710. p++;
  711. p = get_opt_value(value, sizeof(value), p);
  712. }
  713. if (strcmp(option, "id") != 0) {
  714. /* store and parse */
  715. if (qemu_opt_set(opts, option, value) == -1) {
  716. return -1;
  717. }
  718. }
  719. if (*p != ',') {
  720. break;
  721. }
  722. }
  723. return 0;
  724. }
  725. QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
  726. int permit_abbrev)
  727. {
  728. const char *firstname;
  729. char value[1024], *id = NULL;
  730. const char *p;
  731. QemuOpts *opts;
  732. assert(!permit_abbrev || list->implied_opt_name);
  733. firstname = permit_abbrev ? list->implied_opt_name : NULL;
  734. if (strncmp(params, "id=", 3) == 0) {
  735. get_opt_value(value, sizeof(value), params+3);
  736. id = value;
  737. } else if ((p = strstr(params, ",id=")) != NULL) {
  738. get_opt_value(value, sizeof(value), p+4);
  739. id = value;
  740. }
  741. opts = qemu_opts_create(list, id, 1);
  742. if (opts == NULL)
  743. return NULL;
  744. if (qemu_opts_do_parse(opts, params, firstname) != 0) {
  745. qemu_opts_del(opts);
  746. return NULL;
  747. }
  748. return opts;
  749. }
  750. static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
  751. {
  752. char buf[32];
  753. const char *value;
  754. int n;
  755. if (!strcmp(key, "id")) {
  756. return;
  757. }
  758. switch (qobject_type(obj)) {
  759. case QTYPE_QSTRING:
  760. value = qstring_get_str(qobject_to_qstring(obj));
  761. break;
  762. case QTYPE_QINT:
  763. n = snprintf(buf, sizeof(buf), "%" PRId64,
  764. qint_get_int(qobject_to_qint(obj)));
  765. assert(n < sizeof(buf));
  766. value = buf;
  767. break;
  768. case QTYPE_QFLOAT:
  769. n = snprintf(buf, sizeof(buf), "%.17g",
  770. qfloat_get_double(qobject_to_qfloat(obj)));
  771. assert(n < sizeof(buf));
  772. value = buf;
  773. break;
  774. case QTYPE_QBOOL:
  775. pstrcpy(buf, sizeof(buf),
  776. qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
  777. value = buf;
  778. break;
  779. default:
  780. return;
  781. }
  782. qemu_opt_set(opaque, key, value);
  783. }
  784. /*
  785. * Create QemuOpts from a QDict.
  786. * Use value of key "id" as ID if it exists and is a QString.
  787. * Only QStrings, QInts, QFloats and QBools are copied. Entries with
  788. * other types are silently ignored.
  789. */
  790. QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
  791. {
  792. QemuOpts *opts;
  793. opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
  794. if (opts == NULL)
  795. return NULL;
  796. qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
  797. return opts;
  798. }
  799. /*
  800. * Convert from QemuOpts to QDict.
  801. * The QDict values are of type QString.
  802. * TODO We'll want to use types appropriate for opt->desc->type, but
  803. * this is enough for now.
  804. */
  805. QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
  806. {
  807. QemuOpt *opt;
  808. QObject *val;
  809. if (!qdict) {
  810. qdict = qdict_new();
  811. }
  812. if (opts->id) {
  813. qdict_put(qdict, "id", qstring_from_str(opts->id));
  814. }
  815. QTAILQ_FOREACH(opt, &opts->head, next) {
  816. val = QOBJECT(qstring_from_str(opt->str));
  817. qdict_put_obj(qdict, opt->name, val);
  818. }
  819. return qdict;
  820. }
  821. /* Validate parsed opts against descriptions where no
  822. * descriptions were provided in the QemuOptsList.
  823. */
  824. int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
  825. {
  826. QemuOpt *opt;
  827. assert(opts->list->desc[0].name == NULL);
  828. QTAILQ_FOREACH(opt, &opts->head, next) {
  829. int i;
  830. for (i = 0; desc[i].name != NULL; i++) {
  831. if (strcmp(desc[i].name, opt->name) == 0) {
  832. break;
  833. }
  834. }
  835. if (desc[i].name == NULL) {
  836. qerror_report(QERR_INVALID_PARAMETER, opt->name);
  837. return -1;
  838. }
  839. opt->desc = &desc[i];
  840. if (qemu_opt_parse(opt) < 0) {
  841. return -1;
  842. }
  843. }
  844. return 0;
  845. }
  846. int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
  847. int abort_on_failure)
  848. {
  849. Location loc;
  850. QemuOpts *opts;
  851. int rc = 0;
  852. loc_push_none(&loc);
  853. QTAILQ_FOREACH(opts, &list->head, next) {
  854. loc_restore(&opts->loc);
  855. rc |= func(opts, opaque);
  856. if (abort_on_failure && rc != 0)
  857. break;
  858. }
  859. loc_pop(&loc);
  860. return rc;
  861. }