qemu/qapi/qapi-util.c
Markus Armbruster 57df0dff1a qapi: Extend -compat to set policy for unstable interfaces
New option parameters unstable-input and unstable-output set policy
for unstable interfaces just like deprecated-input and
deprecated-output set policy for deprecated interfaces (see commit
6dd75472d5 "qemu-options: New -compat to set policy for deprecated
interfaces").  This is intended for testing users of the management
interfaces.  It is experimental.

For now, this covers only syntactic aspects of QMP, i.e. stuff tagged
with feature 'unstable'.  We may want to extend it to cover semantic
aspects, or the command line.

Note that there is no good way for management application to detect
presence of these new option parameters: they are not visible output
of query-qmp-schema or query-command-line-options.  Tolerable, because
it's meant for testing.  If running with -compat fails, skip the test.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: John Snow <jsnow@redhat.com>
Message-Id: <20211028102520.747396-10-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
[Doc comments fixed up]
2021-10-29 21:28:01 +02:00

155 lines
4.1 KiB
C

/*
* QAPI util functions
*
* Authors:
* Hu Tao <hutao@cn.fujitsu.com>
* Peter Lieven <pl@kamp.de>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "qapi/compat-policy.h"
#include "qapi/error.h"
#include "qemu/ctype.h"
#include "qapi/qmp/qerror.h"
CompatPolicy compat_policy;
static bool compat_policy_input_ok1(const char *adjective,
CompatPolicyInput policy,
ErrorClass error_class,
const char *kind, const char *name,
Error **errp)
{
switch (policy) {
case COMPAT_POLICY_INPUT_ACCEPT:
return true;
case COMPAT_POLICY_INPUT_REJECT:
error_set(errp, error_class, "%s %s %s disabled by policy",
adjective, kind, name);
return false;
case COMPAT_POLICY_INPUT_CRASH:
default:
abort();
}
}
bool compat_policy_input_ok(unsigned special_features,
const CompatPolicy *policy,
ErrorClass error_class,
const char *kind, const char *name,
Error **errp)
{
if ((special_features & 1u << QAPI_DEPRECATED)
&& !compat_policy_input_ok1("Deprecated",
policy->deprecated_input,
error_class, kind, name, errp)) {
return false;
}
if ((special_features & (1u << QAPI_UNSTABLE))
&& !compat_policy_input_ok1("Unstable",
policy->unstable_input,
error_class, kind, name, errp)) {
return false;
}
return true;
}
const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
{
assert(val >= 0 && val < lookup->size);
return lookup->array[val];
}
int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
int def, Error **errp)
{
int i;
if (!buf) {
return def;
}
for (i = 0; i < lookup->size; i++) {
if (!strcmp(buf, lookup->array[i])) {
return i;
}
}
error_setg(errp, "invalid parameter value: %s", buf);
return def;
}
bool qapi_bool_parse(const char *name, const char *value, bool *obj, Error **errp)
{
if (g_str_equal(value, "on") ||
g_str_equal(value, "yes") ||
g_str_equal(value, "true") ||
g_str_equal(value, "y")) {
*obj = true;
return true;
}
if (g_str_equal(value, "off") ||
g_str_equal(value, "no") ||
g_str_equal(value, "false") ||
g_str_equal(value, "n")) {
*obj = false;
return true;
}
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
"'on' or 'off'");
return false;
}
/*
* Parse a valid QAPI name from @str.
* A valid name consists of letters, digits, hyphen and underscore.
* It may be prefixed by __RFQDN_ (downstream extension), where RFQDN
* may contain only letters, digits, hyphen and period.
* The special exception for enumeration names is not implemented.
* See docs/devel/qapi-code-gen.txt for more on QAPI naming rules.
* Keep this consistent with scripts/qapi.py!
* If @complete, the parse fails unless it consumes @str completely.
* Return its length on success, -1 on failure.
*/
int parse_qapi_name(const char *str, bool complete)
{
const char *p = str;
if (*p == '_') { /* Downstream __RFQDN_ */
p++;
if (*p != '_') {
return -1;
}
while (*++p) {
if (!qemu_isalnum(*p) && *p != '-' && *p != '.') {
break;
}
}
if (*p != '_') {
return -1;
}
p++;
}
if (!qemu_isalpha(*p)) {
return -1;
}
while (*++p) {
if (!qemu_isalnum(*p) && *p != '-' && *p != '_') {
break;
}
}
if (complete && *p) {
return -1;
}
return p - str;
}