2
0

qemu-option.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  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 "error.h"
  31. #include "qerror.h"
  32. #include "qemu-option-internal.h"
  33. /*
  34. * Extracts the name of an option from the parameter string (p points at the
  35. * first byte of the option name)
  36. *
  37. * The option name is delimited by delim (usually , or =) or the string end
  38. * and is copied into buf. If the option name is longer than buf_size, it is
  39. * truncated. buf is always zero terminated.
  40. *
  41. * The return value is the position of the delimiter/zero byte after the option
  42. * name in p.
  43. */
  44. const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
  45. {
  46. char *q;
  47. q = buf;
  48. while (*p != '\0' && *p != delim) {
  49. if (q && (q - buf) < buf_size - 1)
  50. *q++ = *p;
  51. p++;
  52. }
  53. if (q)
  54. *q = '\0';
  55. return p;
  56. }
  57. /*
  58. * Extracts the value of an option from the parameter string p (p points at the
  59. * first byte of the option value)
  60. *
  61. * This function is comparable to get_opt_name with the difference that the
  62. * delimiter is fixed to be comma which starts a new option. To specify an
  63. * option value that contains commas, double each comma.
  64. */
  65. const char *get_opt_value(char *buf, int buf_size, const char *p)
  66. {
  67. char *q;
  68. q = buf;
  69. while (*p != '\0') {
  70. if (*p == ',') {
  71. if (*(p + 1) != ',')
  72. break;
  73. p++;
  74. }
  75. if (q && (q - buf) < buf_size - 1)
  76. *q++ = *p;
  77. p++;
  78. }
  79. if (q)
  80. *q = '\0';
  81. return p;
  82. }
  83. int get_next_param_value(char *buf, int buf_size,
  84. const char *tag, const char **pstr)
  85. {
  86. const char *p;
  87. char option[128];
  88. p = *pstr;
  89. for(;;) {
  90. p = get_opt_name(option, sizeof(option), p, '=');
  91. if (*p != '=')
  92. break;
  93. p++;
  94. if (!strcmp(tag, option)) {
  95. *pstr = get_opt_value(buf, buf_size, p);
  96. if (**pstr == ',') {
  97. (*pstr)++;
  98. }
  99. return strlen(buf);
  100. } else {
  101. p = get_opt_value(NULL, 0, p);
  102. }
  103. if (*p != ',')
  104. break;
  105. p++;
  106. }
  107. return 0;
  108. }
  109. int get_param_value(char *buf, int buf_size,
  110. const char *tag, const char *str)
  111. {
  112. return get_next_param_value(buf, buf_size, tag, &str);
  113. }
  114. int check_params(char *buf, int buf_size,
  115. const char * const *params, const char *str)
  116. {
  117. const char *p;
  118. int i;
  119. p = str;
  120. while (*p != '\0') {
  121. p = get_opt_name(buf, buf_size, p, '=');
  122. if (*p != '=') {
  123. return -1;
  124. }
  125. p++;
  126. for (i = 0; params[i] != NULL; i++) {
  127. if (!strcmp(params[i], buf)) {
  128. break;
  129. }
  130. }
  131. if (params[i] == NULL) {
  132. return -1;
  133. }
  134. p = get_opt_value(NULL, 0, p);
  135. if (*p != ',') {
  136. break;
  137. }
  138. p++;
  139. }
  140. return 0;
  141. }
  142. /*
  143. * Searches an option list for an option with the given name
  144. */
  145. QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
  146. const char *name)
  147. {
  148. while (list && list->name) {
  149. if (!strcmp(list->name, name)) {
  150. return list;
  151. }
  152. list++;
  153. }
  154. return NULL;
  155. }
  156. static void parse_option_bool(const char *name, const char *value, bool *ret,
  157. Error **errp)
  158. {
  159. if (value != NULL) {
  160. if (!strcmp(value, "on")) {
  161. *ret = 1;
  162. } else if (!strcmp(value, "off")) {
  163. *ret = 0;
  164. } else {
  165. error_set(errp,QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
  166. }
  167. } else {
  168. *ret = 1;
  169. }
  170. }
  171. static void parse_option_number(const char *name, const char *value,
  172. uint64_t *ret, Error **errp)
  173. {
  174. char *postfix;
  175. uint64_t number;
  176. if (value != NULL) {
  177. number = strtoull(value, &postfix, 0);
  178. if (*postfix != '\0') {
  179. error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
  180. return;
  181. }
  182. *ret = number;
  183. } else {
  184. error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
  185. }
  186. }
  187. static void parse_option_size(const char *name, const char *value,
  188. uint64_t *ret, Error **errp)
  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. error_set(errp, 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;
  217. }
  218. } else {
  219. error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
  220. }
  221. }
  222. /*
  223. * Sets the value of a parameter in a given option list. The parsing of the
  224. * value depends on the type of option:
  225. *
  226. * OPT_FLAG (uses value.n):
  227. * If no value is given, the flag is set to 1.
  228. * Otherwise the value must be "on" (set to 1) or "off" (set to 0)
  229. *
  230. * OPT_STRING (uses value.s):
  231. * value is strdup()ed and assigned as option value
  232. *
  233. * OPT_SIZE (uses value.n):
  234. * The value is converted to an integer. Suffixes for kilobytes etc. are
  235. * allowed (powers of 1024).
  236. *
  237. * Returns 0 on succes, -1 in error cases
  238. */
  239. int set_option_parameter(QEMUOptionParameter *list, const char *name,
  240. const char *value)
  241. {
  242. bool flag;
  243. Error *local_err = NULL;
  244. // Find a matching parameter
  245. list = get_option_parameter(list, name);
  246. if (list == NULL) {
  247. fprintf(stderr, "Unknown option '%s'\n", name);
  248. return -1;
  249. }
  250. // Process parameter
  251. switch (list->type) {
  252. case OPT_FLAG:
  253. parse_option_bool(name, value, &flag, &local_err);
  254. if (!error_is_set(&local_err)) {
  255. list->value.n = flag;
  256. }
  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. parse_option_size(name, value, &list->value.n, &local_err);
  268. break;
  269. default:
  270. fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
  271. return -1;
  272. }
  273. if (error_is_set(&local_err)) {
  274. qerror_report_err(local_err);
  275. error_free(local_err);
  276. return -1;
  277. }
  278. return 0;
  279. }
  280. /*
  281. * Sets the given parameter to an integer instead of a string.
  282. * This function cannot be used to set string options.
  283. *
  284. * Returns 0 on success, -1 in error cases
  285. */
  286. int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
  287. uint64_t value)
  288. {
  289. // Find a matching parameter
  290. list = get_option_parameter(list, name);
  291. if (list == NULL) {
  292. fprintf(stderr, "Unknown option '%s'\n", name);
  293. return -1;
  294. }
  295. // Process parameter
  296. switch (list->type) {
  297. case OPT_FLAG:
  298. case OPT_NUMBER:
  299. case OPT_SIZE:
  300. list->value.n = value;
  301. break;
  302. default:
  303. return -1;
  304. }
  305. return 0;
  306. }
  307. /*
  308. * Frees a option list. If it contains strings, the strings are freed as well.
  309. */
  310. void free_option_parameters(QEMUOptionParameter *list)
  311. {
  312. QEMUOptionParameter *cur = list;
  313. while (cur && cur->name) {
  314. if (cur->type == OPT_STRING) {
  315. g_free(cur->value.s);
  316. }
  317. cur++;
  318. }
  319. g_free(list);
  320. }
  321. /*
  322. * Count valid options in list
  323. */
  324. static size_t count_option_parameters(QEMUOptionParameter *list)
  325. {
  326. size_t num_options = 0;
  327. while (list && list->name) {
  328. num_options++;
  329. list++;
  330. }
  331. return num_options;
  332. }
  333. /*
  334. * Append an option list (list) to an option list (dest).
  335. *
  336. * If dest is NULL, a new copy of list is created.
  337. *
  338. * Returns a pointer to the first element of dest (or the newly allocated copy)
  339. */
  340. QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
  341. QEMUOptionParameter *list)
  342. {
  343. size_t num_options, num_dest_options;
  344. num_options = count_option_parameters(dest);
  345. num_dest_options = num_options;
  346. num_options += count_option_parameters(list);
  347. dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
  348. dest[num_dest_options].name = NULL;
  349. while (list && list->name) {
  350. if (get_option_parameter(dest, list->name) == NULL) {
  351. dest[num_dest_options++] = *list;
  352. dest[num_dest_options].name = NULL;
  353. }
  354. list++;
  355. }
  356. return dest;
  357. }
  358. /*
  359. * Parses a parameter string (param) into an option list (dest).
  360. *
  361. * list is the template option list. If dest is NULL, a new copy of list is
  362. * created. If list is NULL, this function fails.
  363. *
  364. * A parameter string consists of one or more parameters, separated by commas.
  365. * Each parameter consists of its name and possibly of a value. In the latter
  366. * case, the value is delimited by an = character. To specify a value which
  367. * contains commas, double each comma so it won't be recognized as the end of
  368. * the parameter.
  369. *
  370. * For more details of the parsing see above.
  371. *
  372. * Returns a pointer to the first element of dest (or the newly allocated copy)
  373. * or NULL in error cases
  374. */
  375. QEMUOptionParameter *parse_option_parameters(const char *param,
  376. QEMUOptionParameter *list, QEMUOptionParameter *dest)
  377. {
  378. QEMUOptionParameter *allocated = NULL;
  379. char name[256];
  380. char value[256];
  381. char *param_delim, *value_delim;
  382. char next_delim;
  383. if (list == NULL) {
  384. return NULL;
  385. }
  386. if (dest == NULL) {
  387. dest = allocated = append_option_parameters(NULL, list);
  388. }
  389. while (*param) {
  390. // Find parameter name and value in the string
  391. param_delim = strchr(param, ',');
  392. value_delim = strchr(param, '=');
  393. if (value_delim && (value_delim < param_delim || !param_delim)) {
  394. next_delim = '=';
  395. } else {
  396. next_delim = ',';
  397. value_delim = NULL;
  398. }
  399. param = get_opt_name(name, sizeof(name), param, next_delim);
  400. if (value_delim) {
  401. param = get_opt_value(value, sizeof(value), param + 1);
  402. }
  403. if (*param != '\0') {
  404. param++;
  405. }
  406. // Set the parameter
  407. if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
  408. goto fail;
  409. }
  410. }
  411. return dest;
  412. fail:
  413. // Only free the list if it was newly allocated
  414. free_option_parameters(allocated);
  415. return NULL;
  416. }
  417. /*
  418. * Prints all options of a list that have a value to stdout
  419. */
  420. void print_option_parameters(QEMUOptionParameter *list)
  421. {
  422. while (list && list->name) {
  423. switch (list->type) {
  424. case OPT_STRING:
  425. if (list->value.s != NULL) {
  426. printf("%s='%s' ", list->name, list->value.s);
  427. }
  428. break;
  429. case OPT_FLAG:
  430. printf("%s=%s ", list->name, list->value.n ? "on" : "off");
  431. break;
  432. case OPT_SIZE:
  433. case OPT_NUMBER:
  434. printf("%s=%" PRId64 " ", list->name, list->value.n);
  435. break;
  436. default:
  437. printf("%s=(unknown type) ", list->name);
  438. break;
  439. }
  440. list++;
  441. }
  442. }
  443. /*
  444. * Prints an overview of all available options
  445. */
  446. void print_option_help(QEMUOptionParameter *list)
  447. {
  448. printf("Supported options:\n");
  449. while (list && list->name) {
  450. printf("%-16s %s\n", list->name,
  451. list->help ? list->help : "No description available");
  452. list++;
  453. }
  454. }
  455. /* ------------------------------------------------------------------ */
  456. static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
  457. {
  458. QemuOpt *opt;
  459. QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
  460. if (strcmp(opt->name, name) != 0)
  461. continue;
  462. return opt;
  463. }
  464. return NULL;
  465. }
  466. const char *qemu_opt_get(QemuOpts *opts, const char *name)
  467. {
  468. QemuOpt *opt = qemu_opt_find(opts, name);
  469. return opt ? opt->str : NULL;
  470. }
  471. bool qemu_opt_has_help_opt(QemuOpts *opts)
  472. {
  473. QemuOpt *opt;
  474. QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
  475. if (is_help_option(opt->name)) {
  476. return true;
  477. }
  478. }
  479. return false;
  480. }
  481. bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool 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 void qemu_opt_parse(QemuOpt *opt, Error **errp)
  506. {
  507. if (opt->desc == NULL)
  508. return;
  509. switch (opt->desc->type) {
  510. case QEMU_OPT_STRING:
  511. /* nothing */
  512. return;
  513. case QEMU_OPT_BOOL:
  514. parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
  515. break;
  516. case QEMU_OPT_NUMBER:
  517. parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
  518. break;
  519. case QEMU_OPT_SIZE:
  520. parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
  521. break;
  522. default:
  523. abort();
  524. }
  525. }
  526. static void qemu_opt_del(QemuOpt *opt)
  527. {
  528. QTAILQ_REMOVE(&opt->opts->head, opt, next);
  529. g_free((/* !const */ char*)opt->name);
  530. g_free((/* !const */ char*)opt->str);
  531. g_free(opt);
  532. }
  533. static void opt_set(QemuOpts *opts, const char *name, const char *value,
  534. bool prepend, Error **errp)
  535. {
  536. QemuOpt *opt;
  537. const QemuOptDesc *desc = opts->list->desc;
  538. Error *local_err = NULL;
  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. error_set(errp, QERR_INVALID_PARAMETER, name);
  550. return;
  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. qemu_opt_parse(opt, &local_err);
  568. if (error_is_set(&local_err)) {
  569. error_propagate(errp, local_err);
  570. qemu_opt_del(opt);
  571. }
  572. }
  573. int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
  574. {
  575. Error *local_err = NULL;
  576. opt_set(opts, name, value, false, &local_err);
  577. if (error_is_set(&local_err)) {
  578. qerror_report_err(local_err);
  579. error_free(local_err);
  580. return -1;
  581. }
  582. return 0;
  583. }
  584. void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
  585. Error **errp)
  586. {
  587. opt_set(opts, name, value, false, errp);
  588. }
  589. int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
  590. {
  591. QemuOpt *opt;
  592. const QemuOptDesc *desc = opts->list->desc;
  593. int i;
  594. for (i = 0; desc[i].name != NULL; i++) {
  595. if (strcmp(desc[i].name, name) == 0) {
  596. break;
  597. }
  598. }
  599. if (desc[i].name == NULL) {
  600. if (i == 0) {
  601. /* empty list -> allow any */;
  602. } else {
  603. qerror_report(QERR_INVALID_PARAMETER, name);
  604. return -1;
  605. }
  606. }
  607. opt = g_malloc0(sizeof(*opt));
  608. opt->name = g_strdup(name);
  609. opt->opts = opts;
  610. QTAILQ_INSERT_TAIL(&opts->head, opt, next);
  611. if (desc[i].name != NULL) {
  612. opt->desc = desc+i;
  613. }
  614. opt->value.boolean = !!val;
  615. return 0;
  616. }
  617. int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
  618. int abort_on_failure)
  619. {
  620. QemuOpt *opt;
  621. int rc = 0;
  622. QTAILQ_FOREACH(opt, &opts->head, next) {
  623. rc = func(opt->name, opt->str, opaque);
  624. if (abort_on_failure && rc != 0)
  625. break;
  626. }
  627. return rc;
  628. }
  629. QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
  630. {
  631. QemuOpts *opts;
  632. QTAILQ_FOREACH(opts, &list->head, next) {
  633. if (!opts->id) {
  634. if (!id) {
  635. return opts;
  636. }
  637. continue;
  638. }
  639. if (strcmp(opts->id, id) != 0) {
  640. continue;
  641. }
  642. return opts;
  643. }
  644. return NULL;
  645. }
  646. static int id_wellformed(const char *id)
  647. {
  648. int i;
  649. if (!qemu_isalpha(id[0])) {
  650. return 0;
  651. }
  652. for (i = 1; id[i]; i++) {
  653. if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
  654. return 0;
  655. }
  656. }
  657. return 1;
  658. }
  659. QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
  660. int fail_if_exists, Error **errp)
  661. {
  662. QemuOpts *opts = NULL;
  663. if (id) {
  664. if (!id_wellformed(id)) {
  665. error_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
  666. error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
  667. return NULL;
  668. }
  669. opts = qemu_opts_find(list, id);
  670. if (opts != NULL) {
  671. if (fail_if_exists && !list->merge_lists) {
  672. error_set(errp, QERR_DUPLICATE_ID, id, list->name);
  673. return NULL;
  674. } else {
  675. return opts;
  676. }
  677. }
  678. } else if (list->merge_lists) {
  679. opts = qemu_opts_find(list, NULL);
  680. if (opts) {
  681. return opts;
  682. }
  683. }
  684. opts = g_malloc0(sizeof(*opts));
  685. if (id) {
  686. opts->id = g_strdup(id);
  687. }
  688. opts->list = list;
  689. loc_save(&opts->loc);
  690. QTAILQ_INIT(&opts->head);
  691. QTAILQ_INSERT_TAIL(&list->head, opts, next);
  692. return opts;
  693. }
  694. void qemu_opts_reset(QemuOptsList *list)
  695. {
  696. QemuOpts *opts, *next_opts;
  697. QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
  698. qemu_opts_del(opts);
  699. }
  700. }
  701. void qemu_opts_loc_restore(QemuOpts *opts)
  702. {
  703. loc_restore(&opts->loc);
  704. }
  705. int qemu_opts_set(QemuOptsList *list, const char *id,
  706. const char *name, const char *value)
  707. {
  708. QemuOpts *opts;
  709. Error *local_err = NULL;
  710. opts = qemu_opts_create(list, id, 1, &local_err);
  711. if (error_is_set(&local_err)) {
  712. qerror_report_err(local_err);
  713. error_free(local_err);
  714. return -1;
  715. }
  716. return qemu_opt_set(opts, name, value);
  717. }
  718. const char *qemu_opts_id(QemuOpts *opts)
  719. {
  720. return opts->id;
  721. }
  722. void qemu_opts_del(QemuOpts *opts)
  723. {
  724. QemuOpt *opt;
  725. for (;;) {
  726. opt = QTAILQ_FIRST(&opts->head);
  727. if (opt == NULL)
  728. break;
  729. qemu_opt_del(opt);
  730. }
  731. QTAILQ_REMOVE(&opts->list->head, opts, next);
  732. g_free(opts->id);
  733. g_free(opts);
  734. }
  735. int qemu_opts_print(QemuOpts *opts, void *dummy)
  736. {
  737. QemuOpt *opt;
  738. fprintf(stderr, "%s: %s:", opts->list->name,
  739. opts->id ? opts->id : "<noid>");
  740. QTAILQ_FOREACH(opt, &opts->head, next) {
  741. fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
  742. }
  743. fprintf(stderr, "\n");
  744. return 0;
  745. }
  746. static int opts_do_parse(QemuOpts *opts, const char *params,
  747. const char *firstname, bool prepend)
  748. {
  749. char option[128], value[1024];
  750. const char *p,*pe,*pc;
  751. Error *local_err = NULL;
  752. for (p = params; *p != '\0'; p++) {
  753. pe = strchr(p, '=');
  754. pc = strchr(p, ',');
  755. if (!pe || (pc && pc < pe)) {
  756. /* found "foo,more" */
  757. if (p == params && firstname) {
  758. /* implicitly named first option */
  759. pstrcpy(option, sizeof(option), firstname);
  760. p = get_opt_value(value, sizeof(value), p);
  761. } else {
  762. /* option without value, probably a flag */
  763. p = get_opt_name(option, sizeof(option), p, ',');
  764. if (strncmp(option, "no", 2) == 0) {
  765. memmove(option, option+2, strlen(option+2)+1);
  766. pstrcpy(value, sizeof(value), "off");
  767. } else {
  768. pstrcpy(value, sizeof(value), "on");
  769. }
  770. }
  771. } else {
  772. /* found "foo=bar,more" */
  773. p = get_opt_name(option, sizeof(option), p, '=');
  774. if (*p != '=') {
  775. break;
  776. }
  777. p++;
  778. p = get_opt_value(value, sizeof(value), p);
  779. }
  780. if (strcmp(option, "id") != 0) {
  781. /* store and parse */
  782. opt_set(opts, option, value, prepend, &local_err);
  783. if (error_is_set(&local_err)) {
  784. qerror_report_err(local_err);
  785. error_free(local_err);
  786. return -1;
  787. }
  788. }
  789. if (*p != ',') {
  790. break;
  791. }
  792. }
  793. return 0;
  794. }
  795. int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
  796. {
  797. return opts_do_parse(opts, params, firstname, false);
  798. }
  799. static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
  800. int permit_abbrev, bool defaults)
  801. {
  802. const char *firstname;
  803. char value[1024], *id = NULL;
  804. const char *p;
  805. QemuOpts *opts;
  806. Error *local_err = NULL;
  807. assert(!permit_abbrev || list->implied_opt_name);
  808. firstname = permit_abbrev ? list->implied_opt_name : NULL;
  809. if (strncmp(params, "id=", 3) == 0) {
  810. get_opt_value(value, sizeof(value), params+3);
  811. id = value;
  812. } else if ((p = strstr(params, ",id=")) != NULL) {
  813. get_opt_value(value, sizeof(value), p+4);
  814. id = value;
  815. }
  816. if (defaults) {
  817. if (!id && !QTAILQ_EMPTY(&list->head)) {
  818. opts = qemu_opts_find(list, NULL);
  819. } else {
  820. opts = qemu_opts_create(list, id, 0, &local_err);
  821. }
  822. } else {
  823. opts = qemu_opts_create(list, id, 1, &local_err);
  824. }
  825. if (opts == NULL) {
  826. if (error_is_set(&local_err)) {
  827. qerror_report_err(local_err);
  828. error_free(local_err);
  829. }
  830. return NULL;
  831. }
  832. if (opts_do_parse(opts, params, firstname, defaults) != 0) {
  833. qemu_opts_del(opts);
  834. return NULL;
  835. }
  836. return opts;
  837. }
  838. QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
  839. int permit_abbrev)
  840. {
  841. return opts_parse(list, params, permit_abbrev, false);
  842. }
  843. void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
  844. int permit_abbrev)
  845. {
  846. QemuOpts *opts;
  847. opts = opts_parse(list, params, permit_abbrev, true);
  848. assert(opts);
  849. }
  850. typedef struct OptsFromQDictState {
  851. QemuOpts *opts;
  852. Error **errp;
  853. } OptsFromQDictState;
  854. static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
  855. {
  856. OptsFromQDictState *state = opaque;
  857. char buf[32];
  858. const char *value;
  859. int n;
  860. if (!strcmp(key, "id") || error_is_set(state->errp)) {
  861. return;
  862. }
  863. switch (qobject_type(obj)) {
  864. case QTYPE_QSTRING:
  865. value = qstring_get_str(qobject_to_qstring(obj));
  866. break;
  867. case QTYPE_QINT:
  868. n = snprintf(buf, sizeof(buf), "%" PRId64,
  869. qint_get_int(qobject_to_qint(obj)));
  870. assert(n < sizeof(buf));
  871. value = buf;
  872. break;
  873. case QTYPE_QFLOAT:
  874. n = snprintf(buf, sizeof(buf), "%.17g",
  875. qfloat_get_double(qobject_to_qfloat(obj)));
  876. assert(n < sizeof(buf));
  877. value = buf;
  878. break;
  879. case QTYPE_QBOOL:
  880. pstrcpy(buf, sizeof(buf),
  881. qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
  882. value = buf;
  883. break;
  884. default:
  885. return;
  886. }
  887. qemu_opt_set_err(state->opts, key, value, state->errp);
  888. }
  889. /*
  890. * Create QemuOpts from a QDict.
  891. * Use value of key "id" as ID if it exists and is a QString.
  892. * Only QStrings, QInts, QFloats and QBools are copied. Entries with
  893. * other types are silently ignored.
  894. */
  895. QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
  896. Error **errp)
  897. {
  898. OptsFromQDictState state;
  899. Error *local_err = NULL;
  900. QemuOpts *opts;
  901. opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
  902. &local_err);
  903. if (error_is_set(&local_err)) {
  904. error_propagate(errp, local_err);
  905. return NULL;
  906. }
  907. assert(opts != NULL);
  908. state.errp = &local_err;
  909. state.opts = opts;
  910. qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
  911. if (error_is_set(&local_err)) {
  912. error_propagate(errp, local_err);
  913. qemu_opts_del(opts);
  914. return NULL;
  915. }
  916. return opts;
  917. }
  918. /*
  919. * Convert from QemuOpts to QDict.
  920. * The QDict values are of type QString.
  921. * TODO We'll want to use types appropriate for opt->desc->type, but
  922. * this is enough for now.
  923. */
  924. QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
  925. {
  926. QemuOpt *opt;
  927. QObject *val;
  928. if (!qdict) {
  929. qdict = qdict_new();
  930. }
  931. if (opts->id) {
  932. qdict_put(qdict, "id", qstring_from_str(opts->id));
  933. }
  934. QTAILQ_FOREACH(opt, &opts->head, next) {
  935. val = QOBJECT(qstring_from_str(opt->str));
  936. qdict_put_obj(qdict, opt->name, val);
  937. }
  938. return qdict;
  939. }
  940. /* Validate parsed opts against descriptions where no
  941. * descriptions were provided in the QemuOptsList.
  942. */
  943. void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
  944. {
  945. QemuOpt *opt;
  946. Error *local_err = NULL;
  947. assert(opts->list->desc[0].name == NULL);
  948. QTAILQ_FOREACH(opt, &opts->head, next) {
  949. int i;
  950. for (i = 0; desc[i].name != NULL; i++) {
  951. if (strcmp(desc[i].name, opt->name) == 0) {
  952. break;
  953. }
  954. }
  955. if (desc[i].name == NULL) {
  956. error_set(errp, QERR_INVALID_PARAMETER, opt->name);
  957. return;
  958. }
  959. opt->desc = &desc[i];
  960. qemu_opt_parse(opt, &local_err);
  961. if (error_is_set(&local_err)) {
  962. error_propagate(errp, local_err);
  963. return;
  964. }
  965. }
  966. }
  967. int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
  968. int abort_on_failure)
  969. {
  970. Location loc;
  971. QemuOpts *opts;
  972. int rc = 0;
  973. loc_push_none(&loc);
  974. QTAILQ_FOREACH(opts, &list->head, next) {
  975. loc_restore(&opts->loc);
  976. rc |= func(opts, opaque);
  977. if (abort_on_failure && rc != 0)
  978. break;
  979. }
  980. loc_pop(&loc);
  981. return rc;
  982. }