a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering/***
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering This file is part of systemd.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering Copyright 2014 Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering systemd is free software; you can redistribute it and/or modify it
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering under the terms of the GNU Lesser General Public License as published by
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering (at your option) any later version.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering systemd is distributed in the hope that it will be useful, but
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering Lesser General Public License for more details.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering You should have received a copy of the GNU Lesser General Public License
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering***/
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sd-bus.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "busctl-introspect.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "string-util.h"
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include "util.h"
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#include "xml.h"
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering#define NODE_DEPTH_MAX 16
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringtypedef struct Context {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const XMLIntrospectOps *ops;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering void *userdata;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *interface_name;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering uint64_t interface_flags;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *member_name;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *member_signature;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering char *member_result;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering uint64_t member_flags;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering bool member_writable;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *current;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering void *xml_state;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering} Context;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poetteringstatic void context_reset_member(Context *c) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(c->member_name);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(c->member_signature);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(c->member_result);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering c->member_name = c->member_signature = c->member_result = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering c->member_flags = 0;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering c->member_writable = false;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering}
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poetteringstatic void context_reset_interface(Context *c) {
a1e58e8ee1c84b633d6d6d651d5328d4dd4eba5bLennart Poettering c->interface_name = mfree(c->interface_name);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering c->interface_flags = 0;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context_reset_member(c);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering}
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int parse_xml_annotation(Context *context, uint64_t *flags) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering enum {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_ANNOTATION,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_VALUE
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } state = STATE_ANNOTATION;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering _cleanup_free_ char *field = NULL, *value = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(context);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering for (;;) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering _cleanup_free_ char *name = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int t;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t < 0) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("XML parse error.");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return t;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_END) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Premature end of XML data.");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering switch (state) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_ANNOTATION:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "value"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_VALUE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <annotation> attribute %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "annotation"))) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (flags) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(field, "org.freedesktop.DBus.Deprecated")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(value, "true"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *flags |= SD_BUS_VTABLE_DEPRECATED;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (streq_ptr(field, "org.freedesktop.DBus.Method.NoReply")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(value, "true"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering *flags |= SD_BUS_VTABLE_METHOD_NO_REPLY;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (streq_ptr(field, "org.freedesktop.DBus.Property.EmitsChangedSignal")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(value, "const"))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) | SD_BUS_VTABLE_PROPERTY_CONST;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(value, "invalidates"))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST)) | SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(value, "false"))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering *flags = *flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <annotation>. (1)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering free(field);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering field = name;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering name = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_ANNOTATION;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <annotation>. (2)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_VALUE:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering free(value);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering value = name;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering name = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_ANNOTATION;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <annotation>. (3)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering default:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert_not_reached("Bad state");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringstatic int parse_xml_node(Context *context, const char *prefix, unsigned n_depth) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering enum {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_NODE,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_NODE_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_INTERFACE,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_INTERFACE_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_METHOD,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_METHOD_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_METHOD_ARG,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_METHOD_ARG_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_METHOD_ARG_TYPE,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_METHOD_ARG_DIRECTION,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_SIGNAL,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_SIGNAL_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_SIGNAL_ARG,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_SIGNAL_ARG_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_SIGNAL_ARG_TYPE,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_PROPERTY,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_PROPERTY_NAME,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_PROPERTY_TYPE,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering STATE_PROPERTY_ACCESS,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } state = STATE_NODE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering _cleanup_free_ char *node_path = NULL, *argument_type = NULL, *argument_direction = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering const char *np = prefix;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(context);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(prefix);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (n_depth > NODE_DEPTH_MAX) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("<node> depth too high.");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering for (;;) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering _cleanup_free_ char *name = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int t;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t < 0) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("XML parse error.");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return t;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_END) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Premature end of XML data.");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering switch (state) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_NODE:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_NODE_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <node> attribute %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "interface"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_INTERFACE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "node")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_node(context, np, n_depth+1);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <node> tag %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (context->ops->on_path) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = context->ops->on_path(node_path ? node_path : np, context->userdata);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <node>. (1)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_NODE_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering free(node_path);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (name[0] == '/') {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering node_path = name;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering name = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (endswith(prefix, "/"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering node_path = strappend(prefix, name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering node_path = strjoin(prefix, "/", name, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (!node_path)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return log_oom();
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering np = node_path;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_NODE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <node>. (2)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_INTERFACE:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_INTERFACE_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <interface> attribute %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "method"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "signal"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering else if (streq_ptr(name, "property")) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context->member_flags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_PROPERTY;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (streq_ptr(name, "annotation")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_annotation(context, &context->interface_flags);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <interface> tag %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "interface"))) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (context->ops->on_interface) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering r = context->ops->on_interface(context->interface_name, context->interface_flags, context->userdata);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (r < 0)
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return r;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context_reset_interface(context);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_NODE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <interface>. (1)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_INTERFACE_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(context->interface_name);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context->interface_name = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_INTERFACE;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <interface>. (2)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_METHOD:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <method> attribute %s", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "arg"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_ARG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "annotation")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_annotation(context, &context->member_flags);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <method> tag %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "method"))) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (context->ops->on_method) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering r = context->ops->on_method(context->interface_name, context->member_name, context->member_signature, context->member_result, context->member_flags, context->userdata);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (r < 0)
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return r;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context_reset_member(context);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_INTERFACE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <method> (1).");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_METHOD_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(context->member_name);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context->member_name = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <method> (2).");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_METHOD_ARG:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_ARG_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "type"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_ARG_TYPE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "direction"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_ARG_DIRECTION;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected method <arg> attribute %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "annotation")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_annotation(context, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected method <arg> tag %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (argument_type) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (!argument_direction || streq(argument_direction, "in")) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (!strextend(&context->member_signature, argument_type, NULL))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return log_oom();
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (streq(argument_direction, "out")) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (!strextend(&context->member_result, argument_type, NULL))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return log_oom();
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
97b11eedff9d2e17101ad453caf9e48b73246719David Herrmann argument_type = mfree(argument_type);
97b11eedff9d2e17101ad453caf9e48b73246719David Herrmann argument_direction = mfree(argument_direction);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering state = STATE_METHOD;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in method <arg>. (1)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_METHOD_ARG_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_VALUE)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_ARG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in method <arg>. (2)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_METHOD_ARG_TYPE:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(argument_type);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering argument_type = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_ARG;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in method <arg>. (3)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_METHOD_ARG_DIRECTION:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(argument_direction);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering argument_direction = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_METHOD_ARG;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in method <arg>. (4)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_SIGNAL:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <signal> attribute %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "arg"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL_ARG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "annotation")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_annotation(context, &context->member_flags);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <signal> tag %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "signal"))) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (context->ops->on_signal) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering r = context->ops->on_signal(context->interface_name, context->member_name, context->member_signature, context->member_flags, context->userdata);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (r < 0)
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return r;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context_reset_member(context);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_INTERFACE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <signal>. (1)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_SIGNAL_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(context->member_name);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context->member_name = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <signal>. (2)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_SIGNAL_ARG:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL_ARG_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "type"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL_ARG_TYPE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected signal <arg> attribute %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "annotation")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_annotation(context, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected signal <arg> tag %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (argument_type) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (!strextend(&context->member_signature, argument_type, NULL))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return log_oom();
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
97b11eedff9d2e17101ad453caf9e48b73246719David Herrmann argument_type = mfree(argument_type);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering state = STATE_SIGNAL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in signal <arg> (1).");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_SIGNAL_ARG_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_VALUE)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL_ARG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in signal <arg> (2).");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_SIGNAL_ARG_TYPE:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(argument_type);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering argument_type = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_SIGNAL_ARG;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in signal <arg> (3).");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_PROPERTY:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (t == XML_ATTRIBUTE_NAME) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "name"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_PROPERTY_NAME;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "type"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_PROPERTY_TYPE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else if (streq_ptr(name, "access"))
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_PROPERTY_ACCESS;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <property> attribute %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EBADMSG;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq_ptr(name, "annotation")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_annotation(context, &context->member_flags);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected <property> tag %s.", name);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (t == XML_TAG_CLOSE_EMPTY ||
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering (t == XML_TAG_CLOSE && streq_ptr(name, "property"))) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (context->ops->on_property) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering r = context->ops->on_property(context->interface_name, context->member_name, context->member_signature, context->member_writable, context->member_flags, context->userdata);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (r < 0)
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return r;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context_reset_member(context);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_INTERFACE;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <property>. (1)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_PROPERTY_NAME:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(context->member_name);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context->member_name = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_PROPERTY;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <property>. (2)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_PROPERTY_TYPE:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (n_depth == 0) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering free(context->member_signature);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context->member_signature = name;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering name = NULL;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_PROPERTY;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <property>. (3)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering case STATE_PROPERTY_ACCESS:
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (t == XML_ATTRIBUTE_VALUE) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (streq(name, "readwrite") || streq(name, "write"))
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context->member_writable = true;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering state = STATE_PROPERTY;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token in <property>. (4)");
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering return -EINVAL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poetteringint parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering Context context = {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering .ops = ops,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering .userdata = userdata,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering .current = xml,
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering };
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering int r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(prefix);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(xml);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering assert(ops);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering for (;;) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering _cleanup_free_ char *name = NULL;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = xml_tokenize(&context.current, &name, &context.xml_state, NULL);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("XML parse error");
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering goto finish;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering if (r == XML_END) {
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering r = 0;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering break;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r == XML_TAG_OPEN) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (streq(name, "node")) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering r = parse_xml_node(&context, prefix, 0);
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering if (r < 0)
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering goto finish;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected tag '%s' in introspection data.", name);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering r = -EBADMSG;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering goto finish;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) {
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering log_error("Unexpected token.");
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering r = -EBADMSG;
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering goto finish;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering }
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poetteringfinish:
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering context_reset_interface(&context);
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering
0171da06ef8bb19c175c5aa8aff8cf95f3de7dc1Lennart Poettering return r;
a1ad376761af16da46c9ad90fd8df41c8c5c0976Lennart Poettering}