summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus/busctl-introspect.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-03-31 22:49:02 -0400
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-04-04 20:36:09 -0400
commit3bcaf458f6d823f81399dfbc6fcd452d54c1cd32 (patch)
treea7496b87290b42fe3b1a4c345a33b5b5800450c0 /src/libsystemd/sd-bus/busctl-introspect.c
parentb0b46a2c12c4ba04ea2425d7930b14ca48bc6545 (diff)
Move busctl sources to src/busctl
busctl is not part of libsystemd, and should not be stored under libsystemd. In particular this is confusing because busctl is linked with libshared, but stuff in libsystemd is not supposed to depend on libshared.
Diffstat (limited to 'src/libsystemd/sd-bus/busctl-introspect.c')
-rw-r--r--src/libsystemd/sd-bus/busctl-introspect.c782
1 files changed, 0 insertions, 782 deletions
diff --git a/src/libsystemd/sd-bus/busctl-introspect.c b/src/libsystemd/sd-bus/busctl-introspect.c
deleted file mode 100644
index a05794941f..0000000000
--- a/src/libsystemd/sd-bus/busctl-introspect.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "busctl-introspect.h"
-#include "string-util.h"
-#include "util.h"
-#include "xml.h"
-
-#define NODE_DEPTH_MAX 16
-
-typedef struct Context {
- const XMLIntrospectOps *ops;
- void *userdata;
-
- char *interface_name;
- uint64_t interface_flags;
-
- char *member_name;
- char *member_signature;
- char *member_result;
- uint64_t member_flags;
- bool member_writable;
-
- const char *current;
- void *xml_state;
-} Context;
-
-static void context_reset_member(Context *c) {
- free(c->member_name);
- free(c->member_signature);
- free(c->member_result);
-
- c->member_name = c->member_signature = c->member_result = NULL;
- c->member_flags = 0;
- c->member_writable = false;
-}
-
-static void context_reset_interface(Context *c) {
- c->interface_name = mfree(c->interface_name);
- c->interface_flags = 0;
-
- context_reset_member(c);
-}
-
-static int parse_xml_annotation(Context *context, uint64_t *flags) {
-
- enum {
- STATE_ANNOTATION,
- STATE_NAME,
- STATE_VALUE
- } state = STATE_ANNOTATION;
-
- _cleanup_free_ char *field = NULL, *value = NULL;
-
- assert(context);
-
- for (;;) {
- _cleanup_free_ char *name = NULL;
-
- int t;
-
- t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
- if (t < 0) {
- log_error("XML parse error.");
- return t;
- }
-
- if (t == XML_END) {
- log_error("Premature end of XML data.");
- return -EBADMSG;
- }
-
- switch (state) {
-
- case STATE_ANNOTATION:
-
- if (t == XML_ATTRIBUTE_NAME) {
-
- if (streq_ptr(name, "name"))
- state = STATE_NAME;
-
- else if (streq_ptr(name, "value"))
- state = STATE_VALUE;
-
- else {
- log_error("Unexpected <annotation> attribute %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "annotation"))) {
-
- if (flags) {
- if (streq_ptr(field, "org.freedesktop.DBus.Deprecated")) {
-
- if (streq_ptr(value, "true"))
- *flags |= SD_BUS_VTABLE_DEPRECATED;
-
- } else if (streq_ptr(field, "org.freedesktop.DBus.Method.NoReply")) {
-
- if (streq_ptr(value, "true"))
- *flags |= SD_BUS_VTABLE_METHOD_NO_REPLY;
-
- } else if (streq_ptr(field, "org.freedesktop.DBus.Property.EmitsChangedSignal")) {
-
- if (streq_ptr(value, "const"))
- *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) | SD_BUS_VTABLE_PROPERTY_CONST;
- else if (streq_ptr(value, "invalidates"))
- *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST)) | SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION;
- else if (streq_ptr(value, "false"))
- *flags = *flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION);
- }
- }
-
- return 0;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <annotation>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free_and_replace(field, name);
-
- state = STATE_ANNOTATION;
- } else {
- log_error("Unexpected token in <annotation>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_VALUE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free_and_replace(value, name);
-
- state = STATE_ANNOTATION;
- } else {
- log_error("Unexpected token in <annotation>. (3)");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Bad state");
- }
- }
-}
-
-static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth) {
-
- enum {
- STATE_NODE,
- STATE_NODE_NAME,
- STATE_INTERFACE,
- STATE_INTERFACE_NAME,
- STATE_METHOD,
- STATE_METHOD_NAME,
- STATE_METHOD_ARG,
- STATE_METHOD_ARG_NAME,
- STATE_METHOD_ARG_TYPE,
- STATE_METHOD_ARG_DIRECTION,
- STATE_SIGNAL,
- STATE_SIGNAL_NAME,
- STATE_SIGNAL_ARG,
- STATE_SIGNAL_ARG_NAME,
- STATE_SIGNAL_ARG_TYPE,
- STATE_SIGNAL_ARG_DIRECTION,
- STATE_PROPERTY,
- STATE_PROPERTY_NAME,
- STATE_PROPERTY_TYPE,
- STATE_PROPERTY_ACCESS,
- } state = STATE_NODE;
-
- _cleanup_free_ char *node_path = NULL, *argument_type = NULL, *argument_direction = NULL;
- const char *np = prefix;
- int r;
-
- assert(context);
- assert(prefix);
-
- if (n_depth > NODE_DEPTH_MAX) {
- log_error("<node> depth too high.");
- return -EINVAL;
- }
-
- for (;;) {
- _cleanup_free_ char *name = NULL;
- int t;
-
- t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
- if (t < 0) {
- log_error("XML parse error.");
- return t;
- }
-
- if (t == XML_END) {
- log_error("Premature end of XML data.");
- return -EBADMSG;
- }
-
- switch (state) {
-
- case STATE_NODE:
- if (t == XML_ATTRIBUTE_NAME) {
-
- if (streq_ptr(name, "name"))
- state = STATE_NODE_NAME;
- else {
- log_error("Unexpected <node> attribute %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_OPEN) {
-
- if (streq_ptr(name, "interface"))
- state = STATE_INTERFACE;
- else if (streq_ptr(name, "node")) {
-
- r = parse_xml_node(context, np, n_depth+1);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <node> tag %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) {
-
- if (context->ops->on_path) {
- r = context->ops->on_path(node_path ? node_path : np, context->userdata);
- if (r < 0)
- return r;
- }
-
- return 0;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <node>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_NODE_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- free(node_path);
-
- if (name[0] == '/') {
- node_path = name;
- name = NULL;
- } else {
-
- if (endswith(prefix, "/"))
- node_path = strappend(prefix, name);
- else
- node_path = strjoin(prefix, "/", name);
- if (!node_path)
- return log_oom();
- }
-
- np = node_path;
- state = STATE_NODE;
- } else {
- log_error("Unexpected token in <node>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_INTERFACE:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_INTERFACE_NAME;
- else {
- log_error("Unexpected <interface> attribute %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "method"))
- state = STATE_METHOD;
- else if (streq_ptr(name, "signal"))
- state = STATE_SIGNAL;
- else if (streq_ptr(name, "property")) {
- context->member_flags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE;
- state = STATE_PROPERTY;
- } else if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->interface_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <interface> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "interface"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_interface) {
- r = context->ops->on_interface(context->interface_name, context->interface_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_interface(context);
- }
-
- state = STATE_NODE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <interface>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_INTERFACE_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- if (n_depth == 0)
- free_and_replace(context->interface_name, name);
-
- state = STATE_INTERFACE;
- } else {
- log_error("Unexpected token in <interface>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_METHOD_NAME;
- else {
- log_error("Unexpected <method> attribute %s", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "arg"))
- state = STATE_METHOD_ARG;
- else if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->member_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <method> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "method"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_method) {
- r = context->ops->on_method(context->interface_name, context->member_name, context->member_signature, context->member_result, context->member_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_member(context);
- }
-
- state = STATE_INTERFACE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <method> (1).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- if (n_depth == 0)
- free_and_replace(context->member_name, name);
-
- state = STATE_METHOD;
- } else {
- log_error("Unexpected token in <method> (2).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_METHOD_ARG_NAME;
- else if (streq_ptr(name, "type"))
- state = STATE_METHOD_ARG_TYPE;
- else if (streq_ptr(name, "direction"))
- state = STATE_METHOD_ARG_DIRECTION;
- else {
- log_error("Unexpected method <arg> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, NULL);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected method <arg> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
-
- if (n_depth == 0) {
-
- if (argument_type) {
- if (!argument_direction || streq(argument_direction, "in")) {
- if (!strextend(&context->member_signature, argument_type, NULL))
- return log_oom();
- } else if (streq(argument_direction, "out")) {
- if (!strextend(&context->member_result, argument_type, NULL))
- return log_oom();
- } else
- log_error("Unexpected method <arg> direction value '%s'.", argument_direction);
- }
-
- argument_type = mfree(argument_type);
- argument_direction = mfree(argument_direction);
- }
-
- state = STATE_METHOD;
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in method <arg>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE)
- state = STATE_METHOD_ARG;
- else {
- log_error("Unexpected token in method <arg>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG_TYPE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free_and_replace(argument_type, name);
-
- state = STATE_METHOD_ARG;
- } else {
- log_error("Unexpected token in method <arg>. (3)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG_DIRECTION:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free_and_replace(argument_direction, name);
-
- state = STATE_METHOD_ARG;
- } else {
- log_error("Unexpected token in method <arg>. (4)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_SIGNAL_NAME;
- else {
- log_error("Unexpected <signal> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "arg"))
- state = STATE_SIGNAL_ARG;
- else if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->member_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <signal> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "signal"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_signal) {
- r = context->ops->on_signal(context->interface_name, context->member_name, context->member_signature, context->member_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_member(context);
- }
-
- state = STATE_INTERFACE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <signal>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- if (n_depth == 0)
- free_and_replace(context->member_name, name);
-
- state = STATE_SIGNAL;
- } else {
- log_error("Unexpected token in <signal>. (2)");
- return -EINVAL;
- }
-
- break;
-
-
- case STATE_SIGNAL_ARG:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_SIGNAL_ARG_NAME;
- else if (streq_ptr(name, "type"))
- state = STATE_SIGNAL_ARG_TYPE;
- else if (streq_ptr(name, "direction"))
- state = STATE_SIGNAL_ARG_DIRECTION;
- else {
- log_error("Unexpected signal <arg> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, NULL);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected signal <arg> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
-
- if (argument_type) {
- if (!argument_direction || streq(argument_direction, "out")) {
- if (!strextend(&context->member_signature, argument_type, NULL))
- return log_oom();
- } else
- log_error("Unexpected signal <arg> direction value '%s'.", argument_direction);
-
- argument_type = mfree(argument_type);
- }
-
- state = STATE_SIGNAL;
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in signal <arg> (1).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL_ARG_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE)
- state = STATE_SIGNAL_ARG;
- else {
- log_error("Unexpected token in signal <arg> (2).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL_ARG_TYPE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free_and_replace(argument_type, name);
-
- state = STATE_SIGNAL_ARG;
- } else {
- log_error("Unexpected token in signal <arg> (3).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL_ARG_DIRECTION:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free_and_replace(argument_direction, name);
-
- state = STATE_SIGNAL_ARG;
- } else {
- log_error("Unexpected token in signal <arg>. (4)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_PROPERTY_NAME;
- else if (streq_ptr(name, "type"))
- state = STATE_PROPERTY_TYPE;
- else if (streq_ptr(name, "access"))
- state = STATE_PROPERTY_ACCESS;
- else {
- log_error("Unexpected <property> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
-
- if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->member_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <property> tag %s.", name);
- return -EINVAL;
- }
-
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "property"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_property) {
- r = context->ops->on_property(context->interface_name, context->member_name, context->member_signature, context->member_writable, context->member_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_member(context);
- }
-
- state = STATE_INTERFACE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <property>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- if (n_depth == 0)
- free_and_replace(context->member_name, name);
-
- state = STATE_PROPERTY;
- } else {
- log_error("Unexpected token in <property>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY_TYPE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- if (n_depth == 0)
- free_and_replace(context->member_signature, name);
-
- state = STATE_PROPERTY;
- } else {
- log_error("Unexpected token in <property>. (3)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY_ACCESS:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- if (streq(name, "readwrite") || streq(name, "write"))
- context->member_writable = true;
-
- state = STATE_PROPERTY;
- } else {
- log_error("Unexpected token in <property>. (4)");
- return -EINVAL;
- }
-
- break;
- }
- }
-}
-
-int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata) {
- Context context = {
- .ops = ops,
- .userdata = userdata,
- .current = xml,
- };
-
- int r;
-
- assert(prefix);
- assert(xml);
- assert(ops);
-
- for (;;) {
- _cleanup_free_ char *name = NULL;
-
- r = xml_tokenize(&context.current, &name, &context.xml_state, NULL);
- if (r < 0) {
- log_error("XML parse error");
- goto finish;
- }
-
- if (r == XML_END) {
- r = 0;
- break;
- }
-
- if (r == XML_TAG_OPEN) {
-
- if (streq(name, "node")) {
- r = parse_xml_node(&context, prefix, 0);
- if (r < 0)
- goto finish;
- } else {
- log_error("Unexpected tag '%s' in introspection data.", name);
- r = -EBADMSG;
- goto finish;
- }
- } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token.");
- r = -EBADMSG;
- goto finish;
- }
- }
-
-finish:
- context_reset_interface(&context);
-
- return r;
-}