[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 16/23] QMP: New argument checker (first part)
From: |
Luiz Capitulino |
Subject: |
[Qemu-devel] [PATCH 16/23] QMP: New argument checker (first part) |
Date: |
Thu, 1 Jul 2010 16:21:44 -0300 |
Current QMP's argument checker is more complex than it should be
and has (at least) one serious bug: it ignores unknown arguments.
To solve both problems we introduce a new argument checker. It's
added on top of the existing one, so that there are no regressions
during the transition.
This commit introduces the first part of the new checker, which
is run by qmp_check_client_args() and does the following:
1. Check if all mandatory arguments were provided
2. Set flags for argument validation
In order to do that, we transform the args_type string (from
qemu-montor.hx) into a qdict and iterate over it.
Next commit adds the new checker's second part: type checking and
invalid argument detection.
Signed-off-by: Luiz Capitulino <address@hidden>
---
monitor.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 106 insertions(+), 0 deletions(-)
diff --git a/monitor.c b/monitor.c
index 568bfb2..222622b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -177,6 +177,9 @@ static inline void mon_print_count_init(Monitor *mon) { }
static inline int mon_print_count_get(const Monitor *mon) { return 0; }
#endif /* CONFIG_DEBUG_MONITOR */
+/* QMP checker flags */
+#define QMP_ACCEPT_UNKNOWNS 1
+
static QLIST_HEAD(mon_list, Monitor) mon_list;
static const mon_cmd_t mon_cmds[];
@@ -4147,6 +4150,104 @@ static int invalid_qmp_mode(const Monitor *mon, const
char *cmd_name)
return (qmp_cmd_mode(mon) ? is_cap : !is_cap);
}
+/*
+ * - Check if the client has passed all mandatory args
+ * - Set special flags for argument validation
+ */
+static int check_mandatory_args(const QDict *cmd_args,
+ const QDict *client_args, int *flags)
+{
+ const QDictEntry *ent;
+
+ for (ent = qdict_first(cmd_args); ent; ent = qdict_next(cmd_args, ent)) {
+ const char *cmd_arg_name = qdict_entry_key(ent);
+ QString *type = qobject_to_qstring(qdict_entry_value(ent));
+ assert(type != NULL);
+
+ if (qstring_get_str(type)[0] == 'O') {
+ assert((*flags & QMP_ACCEPT_UNKNOWNS) == 0);
+ *flags |= QMP_ACCEPT_UNKNOWNS;
+ } else if (qstring_get_str(type)[0] != '-' &&
+ qstring_get_str(type)[1] != '?' &&
+ !qdict_haskey(client_args, cmd_arg_name)) {
+ qerror_report(QERR_MISSING_PARAMETER, cmd_arg_name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static QDict *qdict_from_args_type(const char *args_type)
+{
+ int i;
+ QDict *qdict;
+ QString *key, *type, *cur_qs;
+
+ assert(args_type != NULL);
+
+ qdict = qdict_new();
+
+ if (args_type == NULL || args_type[0] == '\0') {
+ /* no args, empty qdict */
+ goto out;
+ }
+
+ key = qstring_new();
+ type = qstring_new();
+
+ cur_qs = key;
+
+ for (i = 0;; i++) {
+ switch (args_type[i]) {
+ case ',':
+ case '\0':
+ qdict_put(qdict, qstring_get_str(key), type);
+ QDECREF(key);
+ if (args_type[i] == '\0') {
+ goto out;
+ }
+ type = qstring_new(); /* qdict has ref */
+ cur_qs = key = qstring_new();
+ break;
+ case ':':
+ cur_qs = type;
+ break;
+ default:
+ qstring_append_chr(cur_qs, args_type[i]);
+ break;
+ }
+ }
+
+out:
+ return qdict;
+}
+
+/*
+ * Client argument checking rules:
+ *
+ * 1. Client must provide all mandatory arguments
+ */
+static int qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args)
+{
+ int flags, err;
+ QDict *cmd_args;
+
+ cmd_args = qdict_from_args_type(cmd->args_type);
+
+ flags = 0;
+ err = check_mandatory_args(cmd_args, client_args, &flags);
+ if (err) {
+ goto out;
+ }
+
+ /* TODO: Check client args type */
+
+out:
+ QDECREF(cmd_args);
+ return err;
+}
+
static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
{
int err;
@@ -4222,6 +4323,11 @@ static void handle_qmp_command(JSONMessageParser
*parser, QList *tokens)
QDECREF(input);
+ err = qmp_check_client_args(cmd, args);
+ if (err < 0) {
+ goto err_out;
+ }
+
err = monitor_check_qmp_args(cmd, args);
if (err < 0) {
goto err_out;
--
1.7.2.rc0
- [Qemu-devel] [PATCH 06/23] net: delete QemuOpts when net_client_init() fails., (continued)
- [Qemu-devel] [PATCH 06/23] net: delete QemuOpts when net_client_init() fails., Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 07/23] QMP: Fix error reporting in the async API, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 09/23] QDict: Rename 'err_value', Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 08/23] QError: Enhance QERR_DEVICE_NOT_ACTIVE's user desc, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 11/23] QDict: Introduce functions to retrieve QDictEntry values, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 10/23] QDict: Small terminology change, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 13/23] check-qdict: Introduce test for the new iteration API, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 14/23] QDict: Introduce qdict_get_try_bool(), Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 12/23] QDict: Introduce new iteration API, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 15/23] Monitor: handle optional '-' arg as a bool, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 16/23] QMP: New argument checker (first part),
Luiz Capitulino <=
- [Qemu-devel] [PATCH 17/23] QMP: New argument checker (second part), Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 18/23] QMP: Drop old client argument checker, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 19/23] QError: Introduce QERR_QMP_EXTRA_MEMBER, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 20/23] QMP: Introduce qmp_check_input_obj(), Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 21/23] QMP: Drop old input object checking, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 22/23] QMP: handle_qmp_command(): Small cleanup, Luiz Capitulino, 2010/07/01
- [Qemu-devel] [PATCH 23/23] monitor: Allow to exclude commands from QMP, Luiz Capitulino, 2010/07/01
- Re: [Qemu-devel] [PATCH 00/23][PULL]: QMP/Monitor queue, Anthony Liguori, 2010/07/06