qemu-option.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  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, bool *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. /* fall through */
  198. case 'G':
  199. sizef *= 1024;
  200. /* fall through */
  201. case 'M':
  202. sizef *= 1024;
  203. /* fall through */
  204. case 'K':
  205. case 'k':
  206. sizef *= 1024;
  207. /* fall through */
  208. case 'b':
  209. case '\0':
  210. *ret = (uint64_t) sizef;
  211. break;
  212. default:
  213. qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
  214. error_printf_unless_qmp("You may use k, M, G or T suffixes for "
  215. "kilobytes, megabytes, gigabytes and terabytes.\n");
  216. return -1;
  217. }
  218. } else {
  219. qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
  220. return -1;
  221. }
  222. return 0;
  223. }
  224. /*
  225. * Sets the value of a parameter in a given option list. The parsing of the
  226. * value depends on the type of option:
  227. *
  228. * OPT_FLAG (uses value.n):
  229. * If no value is given, the flag is set to 1.
  230. * Otherwise the value must be "on" (set to 1) or "off" (set to 0)
  231. *
  232. * OPT_STRING (uses value.s):
  233. * value is strdup()ed and assigned as option value
  234. *
  235. * OPT_SIZE (uses value.n):
  236. * The value is converted to an integer. Suffixes for kilobytes etc. are
  237. * allowed (powers of 1024).
  238. *
  239. * Returns 0 on succes, -1 in error cases
  240. */
  241. int set_option_parameter(QEMUOptionParameter *list, const char *name,
  242. const char *value)
  243. {
  244. bool flag;
  245. // Find a matching parameter
  246. list = get_option_parameter(list, name);
  247. if (list == NULL) {
  248. fprintf(stderr, "Unknown option '%s'\n", name);
  249. return -1;
  250. }
  251. // Process parameter
  252. switch (list->type) {
  253. case OPT_FLAG:
  254. if (parse_option_bool(name, value, &flag) == -1)
  255. return -1;
  256. list->value.n = flag;
  257. break;
  258. case OPT_STRING:
  259. if (value != NULL) {
  260. list->value.s = g_strdup(value);
  261. } else {
  262. fprintf(stderr, "Option '%s' needs a parameter\n", name);
  263. return -1;
  264. }
  265. break;
  266. case OPT_SIZE:
  267. if (parse_option_size(name, value, &list->value.n) == -1)
  268. return -1;
  269. break;
  270. default:
  271. fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
  272. return -1;
  273. }
  274. return 0;
  275. }
  276. /*
  277. * Sets the given parameter to an integer instead of a string.
  278. * This function cannot be used to set string options.
  279. *
  280. * Returns 0 on success, -1 in error cases
  281. */
  282. int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
  283. uint64_t value)
  284. {
  285. // Find a matching parameter
  286. list = get_option_parameter(list, name);
  287. if (list == NULL) {
  288. fprintf(stderr, "Unknown option '%s'\n", name);
  289. return -1;
  290. }
  291. // Process parameter
  292. switch (list->type) {
  293. case OPT_FLAG:
  294. case OPT_NUMBER:
  295. case OPT_SIZE:
  296. list->value.n = value;
  297. break;
  298. default:
  299. return -1;
  300. }
  301. return 0;
  302. }
  303. /*
  304. * Frees a option list. If it contains strings, the strings are freed as well.
  305. */
  306. void free_option_parameters(QEMUOptionParameter *list)
  307. {
  308. QEMUOptionParameter *cur = list;
  309. while (cur && cur->name) {
  310. if (cur->type == OPT_STRING) {
  311. g_free(cur->value.s);
  312. }
  313. cur++;
  314. }
  315. g_free(list);
  316. }
  317. /*
  318. * Count valid options in list
  319. */
  320. static size_t count_option_parameters(QEMUOptionParameter *list)
  321. {
  322. size_t num_options = 0;
  323. while (list && list->name) {
  324. num_options++;
  325. list++;
  326. }
  327. return num_options;
  328. }
  329. /*
  330. * Append an option list (list) to an option list (dest).
  331. *
  332. * If dest is NULL, a new copy of list is created.
  333. *
  334. * Returns a pointer to the first element of dest (or the newly allocated copy)
  335. */
  336. QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
  337. QEMUOptionParameter *list)
  338. {
  339. size_t num_options, num_dest_options;
  340. num_options = count_option_parameters(dest);
  341. num_dest_options = num_options;
  342. num_options += count_option_parameters(list);
  343. dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
  344. dest[num_dest_options].name = NULL;
  345. while (list && list->name) {
  346. if (get_option_parameter(dest, list->name) == NULL) {
  347. dest[num_dest_options++] = *list;
  348. dest[num_dest_options].name = NULL;
  349. }
  350. list++;
  351. }
  352. return dest;
  353. }
  354. /*
  355. * Parses a parameter string (param) into an option list (dest).
  356. *
  357. * list is the template option list. If dest is NULL, a new copy of list is
  358. * created. If list is NULL, this function fails.
  359. *
  360. * A parameter string consists of one or more parameters, separated by commas.
  361. * Each parameter consists of its name and possibly of a value. In the latter
  362. * case, the value is delimited by an = character. To specify a value which
  363. * contains commas, double each comma so it won't be recognized as the end of
  364. * the parameter.
  365. *
  366. * For more details of the parsing see above.
  367. *
  368. * Returns a pointer to the first element of dest (or the newly allocated copy)
  369. * or NULL in error cases
  370. */
  371. QEMUOptionParameter *parse_option_parameters(const char *param,
  372. QEMUOptionParameter *list, QEMUOptionParameter *dest)
  373. {
  374. QEMUOptionParameter *allocated = NULL;
  375. char name[256];
  376. char value[256];
  377. char *param_delim, *value_delim;
  378. char next_delim;
  379. if (list == NULL) {
  380. return NULL;
  381. }
  382. if (dest == NULL) {
  383. dest = allocated = append_option_parameters(NULL, list);
  384. }
  385. while (*param) {
  386. // Find parameter name and value in the string
  387. param_delim = strchr(param, ',');
  388. value_delim = strchr(param, '=');
  389. if (value_delim && (value_delim < param_delim || !param_delim)) {
  390. next_delim = '=';
  391. } else {
  392. next_delim = ',';
  393. value_delim = NULL;
  394. }
  395. param = get_opt_name(name, sizeof(name), param, next_delim);
  396. if (value_delim) {
  397. param = get_opt_value(value, sizeof(value), param + 1);
  398. }
  399. if (*param != '\0') {
  400. param++;
  401. }
  402. // Set the parameter
  403. if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
  404. goto fail;
  405. }
  406. }
  407. return dest;
  408. fail:
  409. // Only free the list if it was newly allocated
  410. free_option_parameters(allocated);
  411. return NULL;
  412. }
  413. /*
  414. * Prints all options of a list that have a value to stdout
  415. */
  416. void print_option_parameters(QEMUOptionParameter *list)
  417. {
  418. while (list && list->name) {
  419. switch (list->type) {
  420. case OPT_STRING:
  421. if (list->value.s != NULL) {
  422. printf("%s='%s' ", list->name, list->value.s);
  423. }
  424. break;
  425. case OPT_FLAG:
  426. printf("%s=%s ", list->name, list->value.n ? "on" : "off");
  427. break;
  428. case OPT_SIZE:
  429. case OPT_NUMBER:
  430. printf("%s=%" PRId64 " ", list->name, list->value.n);
  431. break;
  432. default:
  433. printf("%s=(unknown type) ", list->name);
  434. break;
  435. }
  436. list++;
  437. }
  438. }
  439. /*
  440. * Prints an overview of all available options
  441. */
  442. void print_option_help(QEMUOptionParameter *list)
  443. {
  444. printf("Supported options:\n");
  445. while (list && list->name) {
  446. printf("%-16s %s\n", list->name,
  447. list->help ? list->help : "No description available");
  448. list++;
  449. }
  450. }
  451. /* ------------------------------------------------------------------ */
  452. struct QemuOpt {
  453. const char *name;
  454. const char *str;
  455. const QemuOptDesc *desc;
  456. union {
  457. bool boolean;
  458. uint64_t uint;
  459. } value;
  460. QemuOpts *opts;
  461. QTAILQ_ENTRY(QemuOpt) next;
  462. };
  463. struct QemuOpts {
  464. char *id;
  465. QemuOptsList *list;
  466. Location loc;
  467. QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
  468. QTAILQ_ENTRY(QemuOpts) next;
  469. };
  470. static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
  471. {
  472. QemuOpt *opt;
  473. QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
  474. if (strcmp(opt->name, name) != 0)
  475. continue;
  476. return opt;
  477. }
  478. return NULL;
  479. }
  480. const char *qemu_opt_get(QemuOpts *opts, const char *name)
  481. {
  482. QemuOpt *opt = qemu_opt_find(opts, name);
  483. return opt ? opt->str : NULL;
  484. }
  485. bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
  486. {
  487. QemuOpt *opt = qemu_opt_find(opts, name);
  488. if (opt == NULL)
  489. return defval;
  490. assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
  491. return opt->value.boolean;
  492. }
  493. uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
  494. {
  495. QemuOpt *opt = qemu_opt_find(opts, name);
  496. if (opt == NULL)
  497. return defval;
  498. assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
  499. return opt->value.uint;
  500. }
  501. uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
  502. {
  503. QemuOpt *opt = qemu_opt_find(opts, name);
  504. if (opt == NULL)
  505. return defval;
  506. assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
  507. return opt->value.uint;
  508. }
  509. static int qemu_opt_parse(QemuOpt *opt)
  510. {
  511. if (opt->desc == NULL)
  512. return 0;
  513. switch (opt->desc->type) {
  514. case QEMU_OPT_STRING:
  515. /* nothing */
  516. return 0;
  517. case QEMU_OPT_BOOL:
  518. return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
  519. case QEMU_OPT_NUMBER:
  520. return parse_option_number(opt->name, opt->str, &opt->value.uint);
  521. case QEMU_OPT_SIZE:
  522. return parse_option_size(opt->name, opt->str, &opt->value.uint);
  523. default:
  524. abort();
  525. }
  526. }
  527. static void qemu_opt_del(QemuOpt *opt)
  528. {
  529. QTAILQ_REMOVE(&opt->opts->head, opt, next);
  530. g_free((/* !const */ char*)opt->name);
  531. g_free((/* !const */ char*)opt->str);
  532. g_free(opt);
  533. }
  534. static int opt_set(QemuOpts *opts, const char *name, const char *value,
  535. bool prepend)
  536. {
  537. QemuOpt *opt;
  538. const QemuOptDesc *desc = opts->list->desc;
  539. int i;
  540. for (i = 0; desc[i].name != NULL; i++) {
  541. if (strcmp(desc[i].name, name) == 0) {
  542. break;
  543. }
  544. }
  545. if (desc[i].name == NULL) {
  546. if (i == 0) {
  547. /* empty list -> allow any */;
  548. } else {
  549. qerror_report(QERR_INVALID_PARAMETER, name);
  550. return -1;
  551. }
  552. }
  553. opt = g_malloc0(sizeof(*opt));
  554. opt->name = g_strdup(name);
  555. opt->opts = opts;
  556. if (prepend) {
  557. QTAILQ_INSERT_HEAD(&opts->head, opt, next);
  558. } else {
  559. QTAILQ_INSERT_TAIL(&opts->head, opt, next);
  560. }
  561. if (desc[i].name != NULL) {
  562. opt->desc = desc+i;
  563. }
  564. if (value) {
  565. opt->str = g_strdup(value);
  566. }
  567. if (qemu_opt_parse(opt) < 0) {
  568. qemu_opt_del(opt);
  569. return -1;
  570. }
  571. return 0;
  572. }
  573. int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
  574. {
  575. return opt_set(opts, name, value, false);
  576. }
  577. int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
  578. {
  579. QemuOpt *opt;
  580. const QemuOptDesc *desc = opts->list->desc;
  581. int i;
  582. for (i = 0; desc[i].name != NULL; i++) {
  583. if (strcmp(desc[i].name, name) == 0) {
  584. break;
  585. }
  586. }
  587. if (desc[i].name == NULL) {
  588. if (i == 0) {
  589. /* empty list -> allow any */;
  590. } else {
  591. qerror_report(QERR_INVALID_PARAMETER, name);
  592. return -1;
  593. }
  594. }
  595. opt = g_malloc0(sizeof(*opt));
  596. opt->name = g_strdup(name);
  597. opt->opts = opts;
  598. QTAILQ_INSERT_TAIL(&opts->head, opt, next);
  599. if (desc[i].name != NULL) {
  600. opt->desc = desc+i;
  601. }
  602. opt->value.boolean = !!val;
  603. return 0;
  604. }
  605. int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
  606. int abort_on_failure)
  607. {
  608. QemuOpt *opt;
  609. int rc = 0;
  610. QTAILQ_FOREACH(opt, &opts->head, next) {
  611. rc = func(opt->name, opt->str, opaque);
  612. if (abort_on_failure && rc != 0)
  613. break;
  614. }
  615. return rc;
  616. }
  617. QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
  618. {
  619. QemuOpts *opts;
  620. QTAILQ_FOREACH(opts, &list->head, next) {
  621. if (!opts->id) {
  622. if (!id) {
  623. return opts;
  624. }
  625. continue;
  626. }
  627. if (strcmp(opts->id, id) != 0) {
  628. continue;
  629. }
  630. return opts;
  631. }
  632. return NULL;
  633. }
  634. static int id_wellformed(const char *id)
  635. {
  636. int i;
  637. if (!qemu_isalpha(id[0])) {
  638. return 0;
  639. }
  640. for (i = 1; id[i]; i++) {
  641. if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
  642. return 0;
  643. }
  644. }
  645. return 1;
  646. }
  647. QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
  648. {
  649. QemuOpts *opts = NULL;
  650. if (id) {
  651. if (!id_wellformed(id)) {
  652. qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
  653. error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
  654. return NULL;
  655. }
  656. opts = qemu_opts_find(list, id);
  657. if (opts != NULL) {
  658. if (fail_if_exists && !list->merge_lists) {
  659. qerror_report(QERR_DUPLICATE_ID, id, list->name);
  660. return NULL;
  661. } else {
  662. return opts;
  663. }
  664. }
  665. } else if (list->merge_lists) {
  666. opts = qemu_opts_find(list, NULL);
  667. if (opts) {
  668. return opts;
  669. }
  670. }
  671. opts = g_malloc0(sizeof(*opts));
  672. if (id) {
  673. opts->id = g_strdup(id);
  674. }
  675. opts->list = list;
  676. loc_save(&opts->loc);
  677. QTAILQ_INIT(&opts->head);
  678. QTAILQ_INSERT_TAIL(&list->head, opts, next);
  679. return opts;
  680. }
  681. void qemu_opts_reset(QemuOptsList *list)
  682. {
  683. QemuOpts *opts, *next_opts;
  684. QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
  685. qemu_opts_del(opts);
  686. }
  687. }
  688. void qemu_opts_loc_restore(QemuOpts *opts)
  689. {
  690. loc_restore(&opts->loc);
  691. }
  692. int qemu_opts_set(QemuOptsList *list, const char *id,
  693. const char *name, const char *value)
  694. {
  695. QemuOpts *opts;
  696. opts = qemu_opts_create(list, id, 1);
  697. if (opts == NULL) {
  698. return -1;
  699. }
  700. return qemu_opt_set(opts, name, value);
  701. }
  702. const char *qemu_opts_id(QemuOpts *opts)
  703. {
  704. return opts->id;
  705. }
  706. void qemu_opts_del(QemuOpts *opts)
  707. {
  708. QemuOpt *opt;
  709. for (;;) {
  710. opt = QTAILQ_FIRST(&opts->head);
  711. if (opt == NULL)
  712. break;
  713. qemu_opt_del(opt);
  714. }
  715. QTAILQ_REMOVE(&opts->list->head, opts, next);
  716. g_free(opts->id);
  717. g_free(opts);
  718. }
  719. int qemu_opts_print(QemuOpts *opts, void *dummy)
  720. {
  721. QemuOpt *opt;
  722. fprintf(stderr, "%s: %s:", opts->list->name,
  723. opts->id ? opts->id : "<noid>");
  724. QTAILQ_FOREACH(opt, &opts->head, next) {
  725. fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
  726. }
  727. fprintf(stderr, "\n");
  728. return 0;
  729. }
  730. static int opts_do_parse(QemuOpts *opts, const char *params,
  731. const char *firstname, bool prepend)
  732. {
  733. char option[128], value[1024];
  734. const char *p,*pe,*pc;
  735. for (p = params; *p != '\0'; p++) {
  736. pe = strchr(p, '=');
  737. pc = strchr(p, ',');
  738. if (!pe || (pc && pc < pe)) {
  739. /* found "foo,more" */
  740. if (p == params && firstname) {
  741. /* implicitly named first option */
  742. pstrcpy(option, sizeof(option), firstname);
  743. p = get_opt_value(value, sizeof(value), p);
  744. } else {
  745. /* option without value, probably a flag */
  746. p = get_opt_name(option, sizeof(option), p, ',');
  747. if (strncmp(option, "no", 2) == 0) {
  748. memmove(option, option+2, strlen(option+2)+1);
  749. pstrcpy(value, sizeof(value), "off");
  750. } else {
  751. pstrcpy(value, sizeof(value), "on");
  752. }
  753. }
  754. } else {
  755. /* found "foo=bar,more" */
  756. p = get_opt_name(option, sizeof(option), p, '=');
  757. if (*p != '=') {
  758. break;
  759. }
  760. p++;
  761. p = get_opt_value(value, sizeof(value), p);
  762. }
  763. if (strcmp(option, "id") != 0) {
  764. /* store and parse */
  765. if (opt_set(opts, option, value, prepend) == -1) {
  766. return -1;
  767. }
  768. }
  769. if (*p != ',') {
  770. break;
  771. }
  772. }
  773. return 0;
  774. }
  775. int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
  776. {
  777. return opts_do_parse(opts, params, firstname, false);
  778. }
  779. static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
  780. int permit_abbrev, bool defaults)
  781. {
  782. const char *firstname;
  783. char value[1024], *id = NULL;
  784. const char *p;
  785. QemuOpts *opts;
  786. assert(!permit_abbrev || list->implied_opt_name);
  787. firstname = permit_abbrev ? list->implied_opt_name : NULL;
  788. if (strncmp(params, "id=", 3) == 0) {
  789. get_opt_value(value, sizeof(value), params+3);
  790. id = value;
  791. } else if ((p = strstr(params, ",id=")) != NULL) {
  792. get_opt_value(value, sizeof(value), p+4);
  793. id = value;
  794. }
  795. if (defaults) {
  796. if (!id && !QTAILQ_EMPTY(&list->head)) {
  797. opts = qemu_opts_find(list, NULL);
  798. } else {
  799. opts = qemu_opts_create(list, id, 0);
  800. }
  801. } else {
  802. opts = qemu_opts_create(list, id, 1);
  803. }
  804. if (opts == NULL)
  805. return NULL;
  806. if (opts_do_parse(opts, params, firstname, defaults) != 0) {
  807. qemu_opts_del(opts);
  808. return NULL;
  809. }
  810. return opts;
  811. }
  812. QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
  813. int permit_abbrev)
  814. {
  815. return opts_parse(list, params, permit_abbrev, false);
  816. }
  817. void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
  818. int permit_abbrev)
  819. {
  820. QemuOpts *opts;
  821. opts = opts_parse(list, params, permit_abbrev, true);
  822. assert(opts);
  823. }
  824. static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
  825. {
  826. char buf[32];
  827. const char *value;
  828. int n;
  829. if (!strcmp(key, "id")) {
  830. return;
  831. }
  832. switch (qobject_type(obj)) {
  833. case QTYPE_QSTRING:
  834. value = qstring_get_str(qobject_to_qstring(obj));
  835. break;
  836. case QTYPE_QINT:
  837. n = snprintf(buf, sizeof(buf), "%" PRId64,
  838. qint_get_int(qobject_to_qint(obj)));
  839. assert(n < sizeof(buf));
  840. value = buf;
  841. break;
  842. case QTYPE_QFLOAT:
  843. n = snprintf(buf, sizeof(buf), "%.17g",
  844. qfloat_get_double(qobject_to_qfloat(obj)));
  845. assert(n < sizeof(buf));
  846. value = buf;
  847. break;
  848. case QTYPE_QBOOL:
  849. pstrcpy(buf, sizeof(buf),
  850. qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
  851. value = buf;
  852. break;
  853. default:
  854. return;
  855. }
  856. qemu_opt_set(opaque, key, value);
  857. }
  858. /*
  859. * Create QemuOpts from a QDict.
  860. * Use value of key "id" as ID if it exists and is a QString.
  861. * Only QStrings, QInts, QFloats and QBools are copied. Entries with
  862. * other types are silently ignored.
  863. */
  864. QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
  865. {
  866. QemuOpts *opts;
  867. opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
  868. if (opts == NULL)
  869. return NULL;
  870. qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
  871. return opts;
  872. }
  873. /*
  874. * Convert from QemuOpts to QDict.
  875. * The QDict values are of type QString.
  876. * TODO We'll want to use types appropriate for opt->desc->type, but
  877. * this is enough for now.
  878. */
  879. QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
  880. {
  881. QemuOpt *opt;
  882. QObject *val;
  883. if (!qdict) {
  884. qdict = qdict_new();
  885. }
  886. if (opts->id) {
  887. qdict_put(qdict, "id", qstring_from_str(opts->id));
  888. }
  889. QTAILQ_FOREACH(opt, &opts->head, next) {
  890. val = QOBJECT(qstring_from_str(opt->str));
  891. qdict_put_obj(qdict, opt->name, val);
  892. }
  893. return qdict;
  894. }
  895. /* Validate parsed opts against descriptions where no
  896. * descriptions were provided in the QemuOptsList.
  897. */
  898. int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
  899. {
  900. QemuOpt *opt;
  901. assert(opts->list->desc[0].name == NULL);
  902. QTAILQ_FOREACH(opt, &opts->head, next) {
  903. int i;
  904. for (i = 0; desc[i].name != NULL; i++) {
  905. if (strcmp(desc[i].name, opt->name) == 0) {
  906. break;
  907. }
  908. }
  909. if (desc[i].name == NULL) {
  910. qerror_report(QERR_INVALID_PARAMETER, opt->name);
  911. return -1;
  912. }
  913. opt->desc = &desc[i];
  914. if (qemu_opt_parse(opt) < 0) {
  915. return -1;
  916. }
  917. }
  918. return 0;
  919. }
  920. int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
  921. int abort_on_failure)
  922. {
  923. Location loc;
  924. QemuOpts *opts;
  925. int rc = 0;
  926. loc_push_none(&loc);
  927. QTAILQ_FOREACH(opts, &list->head, next) {
  928. loc_restore(&opts->loc);
  929. rc |= func(opts, opaque);
  930. if (abort_on_failure && rc != 0)
  931. break;
  932. }
  933. loc_pop(&loc);
  934. return rc;
  935. }