Ejemplo n.º 1
0
static int driver_remove_match(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {

        struct bus_match_component *components = NULL;
        _cleanup_free_ char *normalized = NULL;
        Context *context = userdata;
        unsigned n_components = 0;
        Client *c = NULL;
        Match *m = NULL;
        char *arg0;
        uint64_t id;
        int r;

        assert(bus);
        assert(message);
        assert(context);

        r = sd_bus_message_read(message, "s", &arg0);
        if (r < 0)
                return r;

        r = bus_kernel_parse_unique_name(message->sender, &id);
        if (r < 0)
                return r;

        c = hashmap_get(context->clients, &id);
        if (!c)
                return sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "You have not registered any matches.");

        r = bus_match_parse(arg0, &components, &n_components);
        if (r < 0) {
                r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_INVALID, "Match rule \"%s\" is not valid", arg0);
                goto finish;
        }

        normalized = bus_match_to_string(components, n_components);
        if (!normalized) {
                r = -ENOMEM;
                goto finish;
        }

        m = hashmap_get(c->matches, normalized);
        if (!m) {
                r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule \"%s\" not found.", normalized);
                goto finish;
        }

        bus_remove_match_internal_kernel(bus, id, m->cookie);
        match_free(m);

        r = sd_bus_reply_method_return(message, NULL);

finish:
        bus_match_parse_free(components, n_components);

        if (c->n_matches <= 0)
                client_free(c);

        return r;
}
Ejemplo n.º 2
0
static void test_match_scope(const char *match, enum bus_match_scope scope) {
    struct bus_match_component *components = NULL;
    unsigned n_components = 0;

    assert_se(bus_match_parse(match, &components, &n_components) >= 0);
    assert_se(bus_match_get_scope(components, n_components) == scope);
    bus_match_parse_free(components, n_components);
}
Ejemplo n.º 3
0
static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) {
    struct bus_match_component *components = NULL;
    unsigned n_components = 0;
    sd_bus_slot *s;
    int r;

    s = slots + value;
    zero(*s);

    r = bus_match_parse(match, &components, &n_components);
    if (r < 0)
        return r;

    s->userdata = INT_TO_PTR(value);
    s->match_callback.callback = filter;

    r = bus_match_add(root, components, n_components, &s->match_callback);
    bus_match_parse_free(components, n_components);

    return r;
}
Ejemplo n.º 4
0
static int driver_add_match(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {

        struct bus_match_component *components = NULL;
        Context *context = userdata;
        unsigned n_components = 0;
        Match *m = NULL;
        Client *c = NULL;
        char *arg0;
        uint64_t id;
        int r;

        assert(bus);
        assert(message);
        assert(context);

        r = sd_bus_message_read(message, "s", &arg0);
        if (r < 0)
                return r;

        r = bus_kernel_parse_unique_name(message->sender, &id);
        if (r < 0)
                return r;

        r = client_acquire(context, id, &c);
        if (r == -ENOBUFS)
                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Reached limit of %u clients", CLIENTS_MAX);
        if (r < 0)
                return r;

        if (c->n_matches >= MATCHES_MAX) {
                r = sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Reached limit of %u matches per client", MATCHES_MAX);
                goto fail;
        }

        r = bus_match_parse(arg0, &components, &n_components);
        if (r < 0) {
                r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_INVALID, "Match rule \"%s\" is not valid", arg0);
                goto fail;
        }

        r = match_new(c, components, n_components, &m);
        if (r < 0)
                goto fail;

        r = bus_add_match_internal_kernel(bus, id, components, n_components, m->cookie);
        if (r < 0)
                goto fail;

        bus_match_parse_free(components, n_components);

        return sd_bus_reply_method_return(message, NULL);

fail:
        bus_match_parse_free(components, n_components);

        match_free(m);

        if (c->n_matches <= 0)
                client_free(c);

        return r;
}
Ejemplo n.º 5
0
int bus_match_parse(
                const char *match,
                struct bus_match_component **_components,
                unsigned *_n_components) {

        const char *p = match;
        struct bus_match_component *components = NULL;
        size_t components_allocated = 0;
        unsigned n_components = 0, i;
        _cleanup_free_ char *value = NULL;
        int r;

        assert(match);
        assert(_components);
        assert(_n_components);

        while (*p != 0) {
                const char *eq, *q;
                enum bus_match_node_type t;
                unsigned j = 0;
                size_t value_allocated = 0;
                bool escaped = false;
                uint8_t u;

                eq = strchr(p, '=');
                if (!eq)
                        return -EINVAL;

                if (eq[1] != '\'')
                        return -EINVAL;

                t = bus_match_node_type_from_string(p, eq - p);
                if (t < 0)
                        return -EINVAL;

                for (q = eq + 2;; q++) {

                        if (*q == 0) {
                                r = -EINVAL;
                                goto fail;
                        }

                        if (!escaped) {
                                if (*q == '\\') {
                                        escaped = true;
                                        continue;
                                }
                                if (*q == '\'') {
                                        if (value)
                                                value[j] = 0;
                                        break;
                                }
                        }

                        if (!GREEDY_REALLOC(value, value_allocated, j + 2)) {
                                r = -ENOMEM;
                                goto fail;
                        }

                        value[j++] = *q;
                        escaped = false;
                }

                if (t == BUS_MATCH_MESSAGE_TYPE) {
                        r = bus_message_type_from_string(value, &u);
                        if (r < 0)
                                goto fail;

                        free(value);
                        value = NULL;
                } else
                        u = 0;

                if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) {
                        r = -ENOMEM;
                        goto fail;
                }

                components[n_components].type = t;
                components[n_components].value_str = value;
                components[n_components].value_u8 = u;
                n_components++;

                value = NULL;

                if (q[1] == 0)
                        break;

                if (q[1] != ',') {
                        r = -EINVAL;
                        goto fail;
                }

                p = q + 2;
        }

        /* Order the whole thing, so that we always generate the same tree */
        qsort_safe(components, n_components, sizeof(struct bus_match_component), match_component_compare);

        /* Check for duplicates */
        for (i = 0; i+1 < n_components; i++)
                if (components[i].type == components[i+1].type) {
                        r = -EINVAL;
                        goto fail;
                }

        *_components = components;
        *_n_components = n_components;

        return 0;

fail:
        bus_match_parse_free(components, n_components);
        return r;
}