bus: make sd_bus_request_name() and sd_bus_release_name() behave more like other...
authorLennart Poettering <lennart@poettering.net>
Tue, 3 Dec 2013 17:01:26 +0000 (18:01 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 3 Dec 2013 17:02:46 +0000 (18:02 +0100)
Instead of returning an enum of return codes, make them return error
codes like kdbus does internally.

Also, document this behaviour so that clients can stick to it.

(Also rework bus-control.c to always have to functions for dbus1 vs.
kernel implementation of the various calls.)

Makefile-man.am
TODO
man/sd_bus_request_name.xml [new file with mode: 0644]
src/core/dbus.c
src/hostname/hostnamed.c
src/libsystemd-bus/bus-control.c
src/locale/localed.c
src/login/logind.c
src/machine/machined.c
src/systemd/sd-bus.h
src/timedate/timedated.c

index 52275ce..3811949 100644 (file)
@@ -20,6 +20,7 @@ MANPAGES += \
        man/sd-id128.3 \
        man/sd-journal.3 \
        man/sd_booted.3 \
+       man/sd_bus_request_name.3 \
        man/sd_id128_get_machine.3 \
        man/sd_id128_randomize.3 \
        man/sd_id128_to_string.3 \
@@ -131,6 +132,7 @@ MANPAGES_ALIAS += \
        man/init.1 \
        man/poweroff.8 \
        man/reboot.8 \
+       man/sd_bus_release_name.3 \
        man/sd_id128_equal.3 \
        man/sd_id128_from_string.3 \
        man/sd_id128_get_boot.3 \
@@ -232,6 +234,7 @@ man/SD_WARNING.3: man/sd-daemon.3
 man/init.1: man/systemd.1
 man/poweroff.8: man/halt.8
 man/reboot.8: man/halt.8
+man/sd_bus_release_name.3: man/sd_bus_request_name.3
 man/sd_id128_equal.3: man/sd-id128.3
 man/sd_id128_from_string.3: man/sd_id128_to_string.3
 man/sd_id128_get_boot.3: man/sd_id128_get_machine.3
@@ -389,6 +392,9 @@ man/poweroff.html: man/halt.html
 man/reboot.html: man/halt.html
        $(html-alias)
 
+man/sd_bus_release_name.html: man/sd_bus_request_name.html
+       $(html-alias)
+
 man/sd_id128_equal.html: man/sd-id128.html
        $(html-alias)
 
diff --git a/TODO b/TODO
index 6773604..39c38dd 100644 (file)
--- a/TODO
+++ b/TODO
@@ -130,6 +130,7 @@ Features:
   - longer term:
     * priority queues
     * priority inheritance
+  - sort out error codes for sd_bus_release_name()
 
 * sd-event
   - allow multiple signal handlers per signal
diff --git a/man/sd_bus_request_name.xml b/man/sd_bus_request_name.xml
new file mode 100644 (file)
index 0000000..6e61a88
--- /dev/null
@@ -0,0 +1,213 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2013 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/>.
+-->
+
+<refentry id="sd_bus_request_name">
+
+        <refentryinfo>
+                <title>sd_bus_request_name</title>
+                <productname>systemd</productname>
+
+                <authorgroup>
+                        <author>
+                                <contrib>Developer</contrib>
+                                <firstname>Lennart</firstname>
+                                <surname>Poettering</surname>
+                                <email>lennart@poettering.net</email>
+                        </author>
+                </authorgroup>
+        </refentryinfo>
+
+        <refmeta>
+                <refentrytitle>sd_bus_request_name</refentrytitle>
+                <manvolnum>3</manvolnum>
+        </refmeta>
+
+        <refnamediv>
+                <refname>sd_bus_request_name</refname>
+                <refname>sd_bus_release_name</refname>
+                <refpurpose>Request or release a well-known name on a bus</refpurpose>
+        </refnamediv>
+
+        <refsynopsisdiv>
+                <funcsynopsis>
+                        <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+
+                        <funcprototype>
+                                <funcdef>int <function>sd_bus_request_name</function></funcdef>
+                                <paramdef>sd_bus* <parameter>bus</parameter></paramdef>
+                                <paramdef>const char *<parameter>name</parameter></paramdef>
+                                <paramdef>unsigned <parameter>flags</parameter></paramdef>
+                        </funcprototype>
+
+                        <funcprototype>
+                                <funcdef>int <function>sd_bus_release_name</function></funcdef>
+                                <paramdef>sd_bus* <parameter>bus</parameter></paramdef>
+                                <paramdef>const char *<parameter>name</parameter></paramdef>
+                        </funcprototype>
+
+
+                </funcsynopsis>
+        </refsynopsisdiv>
+
+        <refsect1>
+                <title>Description</title>
+
+                <para><function>sd_bus_request_name()</function> requests
+                a well-known name on a bus. It takes a bus connection,
+                a valid bus name and a flags parameter. The flags
+                parameter is a combination of the following
+                flags:</para>
+
+                <variablelist>
+                        <varlistentry>
+                                <term><varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname></term>
+
+                                <listitem><para>After acquiring the
+                                name successuflly, permit other peers
+                                to take over the name when they try to
+                                acquire it with the
+                                <varname>SD_BUS_NAME_REPLACE_EXISTING</varname>
+                                flag set. If
+                                <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname>
+                                is not set on the original request
+                                such a request by other peers will be
+                                denied.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>SD_BUS_NAME_REPLACE_EXISTING</varname></term>
+
+                                <listitem><para>Take over a the name
+                                if it is already acquired by a another
+                                peer, and that other peer permitted
+                                taking it over by setting
+                                <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname>
+                                while acquiring it.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>SD_BUS_NAME_DO_NOT_QUEUE</varname></term>
+
+                                <listitem><para>Do not queue name
+                                acquisition when the name is already
+                                taken.</para></listitem>
+                        </varlistentry>
+                </variablelist>
+
+                <para><function>sd_bus_release_name()</function> releases
+                an acquired well-known name. It takes a bus connection
+                and a valid bus name as parameters.</para>
+        </refsect1>
+
+        <refsect1>
+                <title>Return Value</title>
+
+                <para>On success, these calls return 0 or a positive
+                integer. On failure, these calls return a negative
+                errno-style error code.</para>
+
+                <para><function>sd_bus_request_name()</function> will
+                return 0 when the name is already taken by another
+                peer and the client has been added to the queue for
+                the name, unless
+                <varname>SD_BUS_NAME_DO_NOT_QUEUE</varname> has been
+                set. The caller can subscribe to
+                <literal>NameOwnerChanged</literal> signals to be
+                notified when the name is successfully
+                acquired. <function>sd_bus_request_name()</function> returns
+                &gt; 0 when the name has been
+                acquired successfully.</para>
+        </refsect1>
+
+        <refsect1>
+                <title>Errors</title>
+
+                <para>Returned errors may indicate the following problems:</para>
+
+                <variablelist>
+                        <varlistentry>
+                                <term><varname>-EALREADY</varname></term>
+
+                                <listitem><para>The caller already is
+                                the owner of the specified
+                                name.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>-EEXIST</varname></term>
+
+                                <listitem><para>The name has already
+                                been acquired by a different peer, and
+                                SD_BUS_NAME_REPLACE_EXISTING was not
+                                specified or the other peer did not
+                                specify SD_BUS_NAME_ALLOW_REPLACEMENT
+                                while acquiring the
+                                name.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>-EINVAL</varname></term>
+
+                                <listitem><para>A specified parameter
+                                is invalid.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>-ENOTCONN</varname></term>
+
+                                <listitem><para>The bus connection has
+                                been disconnected.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
+                                <term><varname>-ECHILD</varname></term>
+
+                                <listitem><para>The bus connection has
+                                been created in a different process
+                                than the current.</para></listitem>
+                        </varlistentry>
+                </variablelist>
+        </refsect1>
+
+        <refsect1>
+                <title>Notes</title>
+
+                <para>The <function>sd_bus_acquire_name()</function>
+                and <function>sd_bus_release_bame()</function>
+                interfaces are available as shared library, which can
+                be compiled and linked to with the
+                <constant>libsystemd-bus</constant> <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                file.</para>
+        </refsect1>
+
+        <refsect1>
+                <title>See Also</title>
+
+                <para>
+                        <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+                </para>
+        </refsect1>
+
+</refentry>
index 7d7c6cb..cda1c5d 100644 (file)
@@ -819,17 +819,12 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
          * after the new connection is set up and the name installed
          * to allow clients to synchronously wait for reexecution to
          * finish */
-        r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING);
+        r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_DO_NOT_QUEUE);
         if (r < 0) {
                 log_error("Failed to register name: %s", strerror(-r));
                 return r;
         }
 
-        if (r != SD_BUS_NAME_PRIMARY_OWNER) {
-                log_error("Failed to acquire name.");
-                return -EEXIST;
-        }
-
         bus_list_names(m, bus);
 
         log_debug("Successfully connected to API bus.");
index e98bd42..9082966 100644 (file)
@@ -574,17 +574,12 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
                 return r;
         }
 
-        r = sd_bus_request_name(bus, "org.freedesktop.hostname1", SD_BUS_NAME_DO_NOT_QUEUE);
+        r = sd_bus_request_name(bus, "org.freedesktop.hostname1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_DO_NOT_QUEUE);
         if (r < 0) {
                 log_error("Failed to register name: %s", strerror(-r));
                 return r;
         }
 
-        if (r != SD_BUS_NAME_PRIMARY_OWNER) {
-                log_error("Failed to acquire name.");
-                return -EEXIST;
-        }
-
         r = sd_bus_attach_event(bus, event, 0);
         if (r < 0) {
                 log_error("Failed to attach bus to event loop: %s", strerror(-r));
index 5cb32ea..de5c20e 100644 (file)
@@ -50,354 +50,254 @@ _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
         return 0;
 }
 
-_public_ int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
-        uint32_t ret;
+static int bus_request_name_kernel(sd_bus *bus, const char *name, unsigned flags) {
+        struct kdbus_cmd_name *n;
+        size_t l;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(name, -EINVAL);
-        assert_return(bus->bus_client, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        if (bus->is_kernel) {
-                struct kdbus_cmd_name *n;
-                size_t l;
+        assert(bus);
+        assert(name);
 
-                l = strlen(name);
-                n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
-                n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
-                kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
-                memcpy(n->name, name, l+1);
+        l = strlen(name);
+        n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
+        n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
+        kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
+        memcpy(n->name, name, l+1);
 
 #ifdef HAVE_VALGRIND_MEMCHECK_H
-                VALGRIND_MAKE_MEM_DEFINED(n, n->size);
+        VALGRIND_MAKE_MEM_DEFINED(n, n->size);
 #endif
 
-                r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
-                if (r < 0) {
-                        if (errno == -EALREADY)
-                                return SD_BUS_NAME_ALREADY_OWNER;
-
-                        if (errno == -EEXIST)
-                                return SD_BUS_NAME_EXISTS;
-
-                        return -errno;
-                }
-
-                if (n->flags & KDBUS_NAME_IN_QUEUE)
-                        return SD_BUS_NAME_IN_QUEUE;
-
-                return SD_BUS_NAME_PRIMARY_OWNER;
-        } else {
-                r = sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.DBus",
-                                "/",
-                                "org.freedesktop.DBus",
-                                "RequestName",
-                                NULL,
-                                &reply,
-                                "su",
-                                name,
-                                flags);
-                if (r < 0)
-                        return r;
+        r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
+        if (r < 0)
+                return -errno;
 
-                r = sd_bus_message_read(reply, "u", &ret);
-                if (r < 0)
-                        return r;
+        if (n->flags & KDBUS_NAME_IN_QUEUE)
+                return 0;
 
-                return ret;
-        }
+        return 1;
 }
 
-_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
+static int bus_request_name_dbus1(sd_bus *bus, const char *name, unsigned flags) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         uint32_t ret;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(name, -EINVAL);
-        assert_return(bus->bus_client, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        if (bus->is_kernel) {
-                struct kdbus_cmd_name *n;
-                size_t l;
-
-                l = strlen(name);
-                n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
-                n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
-                memcpy(n->name, name, l+1);
+        assert(bus);
+        assert(name);
 
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-                VALGRIND_MAKE_MEM_DEFINED(n, n->size);
-#endif
-                r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
-                if (r < 0)
-                        return -errno;
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/",
+                        "org.freedesktop.DBus",
+                        "RequestName",
+                        NULL,
+                        &reply,
+                        "su",
+                        name,
+                        flags);
+        if (r < 0)
+                return r;
 
-                return n->flags;
-        } else {
-                r = sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.DBus",
-                                "/",
-                                "org.freedesktop.DBus",
-                                "ReleaseName",
-                                NULL,
-                                &reply,
-                                "s",
-                                name);
-                if (r < 0)
-                        return r;
+        r = sd_bus_message_read(reply, "u", &ret);
+        if (r < 0)
+                return r;
 
-                r = sd_bus_message_read(reply, "u", &ret);
-                if (r < 0)
-                        return r;
-        }
+        if (ret == SD_BUS_NAME_ALREADY_OWNER)
+                return -EALREADY;
+        else if (ret == SD_BUS_NAME_EXISTS)
+                return -EEXIST;
+        else if (ret == SD_BUS_NAME_IN_QUEUE)
+                return 0;
+        else
+                return -EIO;
 
-        return ret;
+        return 1;
 }
 
-_public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
-        char **x = NULL;
-        int r;
-
+_public_ int sd_bus_request_name(sd_bus *bus, const char *name, unsigned flags) {
         assert_return(bus, -EINVAL);
-        assert_return(l, -EINVAL);
+        assert_return(name, -EINVAL);
+        assert_return(bus->bus_client, -EINVAL);
         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
+        assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_DO_NOT_QUEUE)), -EINVAL);
 
-        if (bus->is_kernel) {
-                _cleanup_free_ struct kdbus_cmd_name_list *cmd = NULL;
-                struct kdbus_name_list *name_list;
-                struct kdbus_cmd_name *name;
-
-                cmd = malloc0(sizeof(struct kdbus_cmd_name_list));
-                if (!cmd)
-                        return -ENOMEM;
-
-                cmd->size = sizeof(struct kdbus_cmd_name_list);
-                cmd->flags = KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES;
-
-                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, cmd);
-                if (r < 0)
-                        return -errno;
-
-                name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
-
-                KDBUS_PART_FOREACH(name, name_list, names) {
-                        char *n;
-
-                        if (name->size > sizeof(*name))
-                                n = name->name;
-                        else
-                                asprintf(&n, ":1.%llu", (unsigned long long) name->id);
-
-                        r = strv_extend(&x, n);
-                        if (r < 0)
-                                return -ENOMEM;
-                }
-
-                r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
-                if (r < 0)
-                        return -errno;
-
-                *l = x;
-        } else {
-                r = sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.DBus",
-                                "/",
-                                "org.freedesktop.DBus",
-                                "ListNames",
-                                NULL,
-                                &reply1,
-                                NULL);
-                if (r < 0)
-                        return r;
+        if (bus->is_kernel)
+                return bus_request_name_kernel(bus, name, flags);
+        else
+                return bus_request_name_dbus1(bus, name, flags);
+}
 
-                r = sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.DBus",
-                                "/",
-                                "org.freedesktop.DBus",
-                                "ListActivatableNames",
-                                NULL,
-                                &reply2,
-                                NULL);
-                if (r < 0)
-                        return r;
+static int bus_release_name_kernel(sd_bus *bus, const char *name) {
+        struct kdbus_cmd_name *n;
+        size_t l;
+        int r;
 
-                r = bus_message_read_strv_extend(reply1, &x);
-                if (r < 0) {
-                        strv_free(x);
-                        return r;
-                }
+        assert(bus);
+        assert(name);
 
-                r = bus_message_read_strv_extend(reply2, &x);
-                if (r < 0) {
-                        strv_free(x);
-                        return r;
-                }
+        l = strlen(name);
+        n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
+        n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
+        memcpy(n->name, name, l+1);
 
-                *l = strv_uniq(x);
-        }
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+        VALGRIND_MAKE_MEM_DEFINED(n, n->size);
+#endif
+        r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
+        if (r < 0)
+                return -errno;
 
-        return 0;
+        return n->flags;
 }
 
-static int bus_get_owner_dbus(
-                sd_bus *bus,
-                const char *name,
-                uint64_t mask,
-                sd_bus_creds **creds) {
-
-        _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
-        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
-        const char *unique = NULL;
-        pid_t pid = 0;
+static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        uint32_t ret;
         int r;
 
-        /* Only query the owner if the caller wants to know it or if
-         * the caller just wants to check whether a name exists */
-        if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
-                r = sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.DBus",
-                                "/",
-                                "org.freedesktop.DBus",
-                                "GetNameOwner",
-                                NULL,
-                                &reply_unique,
-                                "s",
-                                name);
-                if (r < 0)
-                        return r;
-
-                r = sd_bus_message_read(reply_unique, "s", &unique);
-                if (r < 0)
-                        return r;
-        }
+        assert(bus);
+        assert(name);
 
-        if (mask != 0) {
-                c = bus_creds_new();
-                if (!c)
-                        return -ENOMEM;
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/",
+                        "org.freedesktop.DBus",
+                        "ReleaseName",
+                        NULL,
+                        &reply,
+                        "s",
+                        name);
+        if (r < 0)
+                return r;
 
-                if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
-                        c->unique_name = strdup(unique);
-                        if (!c->unique_name)
-                                return -ENOMEM;
+        r = sd_bus_message_read(reply, "u", &ret);
+        if (r < 0)
+                return r;
+        if (ret == SD_BUS_NAME_NON_EXISTENT)
+                return -ENOENT;
+        if (ret == SD_BUS_NAME_NOT_OWNER)
+                return -EADDRNOTAVAIL;
+        if (ret == SD_BUS_NAME_RELEASED)
+                return 0;
 
-                        c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
-                }
+        return -EINVAL;
+}
 
-                if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
-                            SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
-                            SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
-                            SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
-                            SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
-                        uint32_t u;
+_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
+        assert_return(bus, -EINVAL);
+        assert_return(name, -EINVAL);
+        assert_return(bus->bus_client, -EINVAL);
+        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
 
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.DBus",
-                                        "/",
-                                        "org.freedesktop.DBus",
-                                        "GetConnectionUnixProcessID",
-                                        NULL,
-                                        &reply,
-                                        "s",
-                                        unique ? unique : name);
-                        if (r < 0)
-                                return r;
+        if (bus->is_kernel)
+                return bus_release_name_kernel(bus, name);
+        else
+                return bus_release_name_dbus1(bus, name);
+}
 
-                        r = sd_bus_message_read(reply, "u", &u);
-                        if (r < 0)
-                                return r;
+static int bus_list_names_kernel(sd_bus *bus, char ***l) {
+        _cleanup_free_ struct kdbus_cmd_name_list *cmd = NULL;
+        struct kdbus_name_list *name_list;
+        struct kdbus_cmd_name *name;
+        char **x = NULL;
+        int r;
 
-                        pid = u;
-                        if (mask & SD_BUS_CREDS_PID) {
-                                c->pid = u;
-                                c->mask |= SD_BUS_CREDS_PID;
-                        }
+        cmd = malloc0(sizeof(struct kdbus_cmd_name_list));
+        if (!cmd)
+                return -ENOMEM;
 
-                        reply = sd_bus_message_unref(reply);
-                }
+        cmd->size = sizeof(struct kdbus_cmd_name_list);
+        cmd->flags = KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES;
 
-                if (mask & SD_BUS_CREDS_UID) {
-                        uint32_t u;
+        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_LIST, cmd);
+        if (r < 0)
+                return -errno;
 
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.DBus",
-                                        "/",
-                                        "org.freedesktop.DBus",
-                                        "GetConnectionUnixUser",
-                                        NULL,
-                                        &reply,
-                                        "s",
-                                        unique ? unique : name);
-                        if (r < 0)
-                                return r;
+        name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
 
-                        r = sd_bus_message_read(reply, "u", &u);
-                        if (r < 0)
-                                return r;
+        KDBUS_PART_FOREACH(name, name_list, names) {
+                char *n;
 
-                        c->uid = u;
-                        c->mask |= SD_BUS_CREDS_UID;
+                if (name->size > sizeof(*name))
+                        n = name->name;
+                else
+                        asprintf(&n, ":1.%llu", (unsigned long long) name->id);
 
-                        reply = sd_bus_message_unref(reply);
-                }
+                r = strv_extend(&x, n);
+                if (r < 0)
+                        return -ENOMEM;
+        }
 
-                if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
-                        const void *p;
-                        size_t sz;
+        r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset);
+        if (r < 0)
+                return -errno;
 
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.DBus",
-                                        "/",
-                                        "org.freedesktop.DBus",
-                                        "GetConnectionSELinuxSecurityContext",
-                                        NULL,
-                                        &reply,
-                                        "s",
-                                        unique ? unique : name);
-                        if (r < 0)
-                                return r;
+        *l = x;
+        return 0;
+}
 
-                        r = sd_bus_message_read_array(reply, 'y', &p, &sz);
-                        if (r < 0)
-                                return r;
+static int bus_list_names_dbus1(sd_bus *bus, char ***l) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
+        char **x = NULL;
+        int r;
 
-                        c->label = strndup(p, sz);
-                        if (!c->label)
-                                return -ENOMEM;
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/",
+                        "org.freedesktop.DBus",
+                        "ListNames",
+                        NULL,
+                        &reply1,
+                        NULL);
+        if (r < 0)
+                return r;
 
-                        c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
-                }
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/",
+                        "org.freedesktop.DBus",
+                        "ListActivatableNames",
+                        NULL,
+                        &reply2,
+                        NULL);
+        if (r < 0)
+                return r;
 
-                r = bus_creds_add_more(c, mask, pid, 0);
-                if (r < 0)
-                        return r;
+        r = bus_message_read_strv_extend(reply1, &x);
+        if (r < 0) {
+                strv_free(x);
+                return r;
         }
 
-        if (creds) {
-                *creds = c;
-                c = NULL;
+        r = bus_message_read_strv_extend(reply2, &x);
+        if (r < 0) {
+                strv_free(x);
+                return r;
         }
 
+        *l = strv_uniq(x);
         return 0;
 }
 
+_public_ int sd_bus_list_names(sd_bus *bus, char ***l) {
+        assert_return(bus, -EINVAL);
+        assert_return(l, -EINVAL);
+        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(!bus_pid_changed(bus), -ECHILD);
+
+        if (bus->is_kernel)
+                return bus_list_names_kernel(bus, l);
+        else
+                return bus_list_names_dbus1(bus, l);
+}
+
 static int bus_get_owner_kdbus(
                 sd_bus *bus,
                 const char *name,
@@ -497,86 +397,236 @@ static int bus_get_owner_kdbus(
                         }
                         break;
 
-                case KDBUS_ITEM_CMDLINE:
-                        if (mask & SD_BUS_CREDS_CMDLINE) {
-                                c->cmdline_size = item->size - KDBUS_PART_HEADER_SIZE;
-                                c->cmdline = memdup(item->data, c->cmdline_size);
-                                if (!c->cmdline) {
-                                        r = -ENOMEM;
-                                        goto fail;
-                                }
+                case KDBUS_ITEM_CMDLINE:
+                        if (mask & SD_BUS_CREDS_CMDLINE) {
+                                c->cmdline_size = item->size - KDBUS_PART_HEADER_SIZE;
+                                c->cmdline = memdup(item->data, c->cmdline_size);
+                                if (!c->cmdline) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                c->mask |= SD_BUS_CREDS_CMDLINE;
+                        }
+                        break;
+
+                case KDBUS_ITEM_CGROUP:
+                        m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
+                             SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
+                             SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
+
+                        if (m) {
+                                c->cgroup = strdup(item->str);
+                                if (!c->cgroup) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                c->mask |= m;
+                        }
+                        break;
+
+                case KDBUS_ITEM_CAPS:
+                        m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
+                             SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
+
+                        if (m) {
+                                c->capability_size = item->size - KDBUS_PART_HEADER_SIZE;
+                                c->capability = memdup(item->data, c->capability_size);
+                                if (!c->capability) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                c->mask |= m;
+                        }
+                        break;
+
+                case KDBUS_ITEM_SECLABEL:
+                        if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
+                                c->label = strdup(item->str);
+                                if (!c->label) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
+                        }
+                        break;
+
+                case KDBUS_ITEM_AUDIT:
+                        m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
+
+                        if (m) {
+                                c->audit_session_id = item->audit.sessionid;
+                                c->audit_login_uid = item->audit.loginuid;
+                                c->mask |= m;
+                        }
+                        break;
+
+                case KDBUS_ITEM_NAMES:
+                        if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
+                                c->well_known_names_size = item->size - KDBUS_PART_HEADER_SIZE;
+                                c->well_known_names = memdup(item->data, c->well_known_names_size);
+                                if (!c->well_known_names) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
+                        }
+                        break;
+                }
+        }
+
+        if (creds) {
+                *creds = c;
+                c = NULL;
+        }
+
+        r = 0;
+
+fail:
+        ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
+        return r;
+}
+
+static int bus_get_owner_dbus1(
+                sd_bus *bus,
+                const char *name,
+                uint64_t mask,
+                sd_bus_creds **creds) {
+
+        _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
+        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
+        const char *unique = NULL;
+        pid_t pid = 0;
+        int r;
+
+        /* Only query the owner if the caller wants to know it or if
+         * the caller just wants to check whether a name exists */
+        if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.DBus",
+                                "/",
+                                "org.freedesktop.DBus",
+                                "GetNameOwner",
+                                NULL,
+                                &reply_unique,
+                                "s",
+                                name);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_read(reply_unique, "s", &unique);
+                if (r < 0)
+                        return r;
+        }
+
+        if (mask != 0) {
+                c = bus_creds_new();
+                if (!c)
+                        return -ENOMEM;
+
+                if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
+                        c->unique_name = strdup(unique);
+                        if (!c->unique_name)
+                                return -ENOMEM;
+
+                        c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
+                }
+
+                if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
+                            SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
+                            SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
+                            SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
+                            SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
+                        uint32_t u;
+
+                        r = sd_bus_call_method(
+                                        bus,
+                                        "org.freedesktop.DBus",
+                                        "/",
+                                        "org.freedesktop.DBus",
+                                        "GetConnectionUnixProcessID",
+                                        NULL,
+                                        &reply,
+                                        "s",
+                                        unique ? unique : name);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_read(reply, "u", &u);
+                        if (r < 0)
+                                return r;
 
-                                c->mask |= SD_BUS_CREDS_CMDLINE;
+                        pid = u;
+                        if (mask & SD_BUS_CREDS_PID) {
+                                c->pid = u;
+                                c->mask |= SD_BUS_CREDS_PID;
                         }
-                        break;
-
-                case KDBUS_ITEM_CGROUP:
-                        m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
-                             SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
-                             SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
 
-                        if (m) {
-                                c->cgroup = strdup(item->str);
-                                if (!c->cgroup) {
-                                        r = -ENOMEM;
-                                        goto fail;
-                                }
+                        reply = sd_bus_message_unref(reply);
+                }
 
-                                c->mask |= m;
-                        }
-                        break;
+                if (mask & SD_BUS_CREDS_UID) {
+                        uint32_t u;
 
-                case KDBUS_ITEM_CAPS:
-                        m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
-                             SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
+                        r = sd_bus_call_method(
+                                        bus,
+                                        "org.freedesktop.DBus",
+                                        "/",
+                                        "org.freedesktop.DBus",
+                                        "GetConnectionUnixUser",
+                                        NULL,
+                                        &reply,
+                                        "s",
+                                        unique ? unique : name);
+                        if (r < 0)
+                                return r;
 
-                        if (m) {
-                                c->capability_size = item->size - KDBUS_PART_HEADER_SIZE;
-                                c->capability = memdup(item->data, c->capability_size);
-                                if (!c->capability) {
-                                        r = -ENOMEM;
-                                        goto fail;
-                                }
+                        r = sd_bus_message_read(reply, "u", &u);
+                        if (r < 0)
+                                return r;
 
-                                c->mask |= m;
-                        }
-                        break;
+                        c->uid = u;
+                        c->mask |= SD_BUS_CREDS_UID;
 
-                case KDBUS_ITEM_SECLABEL:
-                        if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
-                                c->label = strdup(item->str);
-                                if (!c->label) {
-                                        r = -ENOMEM;
-                                        goto fail;
-                                }
+                        reply = sd_bus_message_unref(reply);
+                }
 
-                                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
-                        }
-                        break;
+                if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
+                        const void *p;
+                        size_t sz;
 
-                case KDBUS_ITEM_AUDIT:
-                        m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
+                        r = sd_bus_call_method(
+                                        bus,
+                                        "org.freedesktop.DBus",
+                                        "/",
+                                        "org.freedesktop.DBus",
+                                        "GetConnectionSELinuxSecurityContext",
+                                        NULL,
+                                        &reply,
+                                        "s",
+                                        unique ? unique : name);
+                        if (r < 0)
+                                return r;
 
-                        if (m) {
-                                c->audit_session_id = item->audit.sessionid;
-                                c->audit_login_uid = item->audit.loginuid;
-                                c->mask |= m;
-                        }
-                        break;
+                        r = sd_bus_message_read_array(reply, 'y', &p, &sz);
+                        if (r < 0)
+                                return r;
 
-                case KDBUS_ITEM_NAMES:
-                        if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
-                                c->well_known_names_size = item->size - KDBUS_PART_HEADER_SIZE;
-                                c->well_known_names = memdup(item->data, c->well_known_names_size);
-                                if (!c->well_known_names) {
-                                        r = -ENOMEM;
-                                        goto fail;
-                                }
+                        c->label = strndup(p, sz);
+                        if (!c->label)
+                                return -ENOMEM;
 
-                                c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
-                        }
-                        break;
+                        c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
                 }
+
+                r = bus_creds_add_more(c, mask, pid, 0);
+                if (r < 0)
+                        return r;
         }
 
         if (creds) {
@@ -584,11 +634,7 @@ static int bus_get_owner_kdbus(
                 c = NULL;
         }
 
-        r = 0;
-
-fail:
-        ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
-        return r;
+        return 0;
 }
 
 _public_ int sd_bus_get_owner(
@@ -607,7 +653,7 @@ _public_ int sd_bus_get_owner(
         if (bus->is_kernel)
                 return bus_get_owner_kdbus(bus, name, mask, creds);
         else
-                return bus_get_owner_dbus(bus, name, mask, creds);
+                return bus_get_owner_dbus1(bus, name, mask, creds);
 }
 
 static int add_name_change_match(sd_bus *bus,
@@ -778,231 +824,271 @@ static int add_name_change_match(sd_bus *bus,
         return 0;
 }
 
-int bus_add_match_internal(
+static int bus_add_match_internal_kernel(
                 sd_bus *bus,
                 const char *match,
                 struct bus_match_component *components,
                 unsigned n_components,
                 uint64_t cookie) {
 
+        struct kdbus_cmd_match *m;
+        struct kdbus_item *item;
+        uint64_t bloom[BLOOM_SIZE/8];
+        size_t sz;
+        const char *sender = NULL;
+        size_t sender_length = 0;
+        uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
+        bool using_bloom = false;
+        unsigned i;
+        bool matches_name_change = true;
+        const char *name_change_arg[3] = {};
         int r;
 
         assert(bus);
         assert(match);
 
-        if (bus->is_kernel) {
-                struct kdbus_cmd_match *m;
-                struct kdbus_item *item;
-                uint64_t bloom[BLOOM_SIZE/8];
-                size_t sz;
-                const char *sender = NULL;
-                size_t sender_length = 0;
-                uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
-                bool using_bloom = false;
-                unsigned i;
-                bool matches_name_change = true;
-                const char *name_change_arg[3] = {};
-
-                zero(bloom);
-
-                sz = offsetof(struct kdbus_cmd_match, items);
-
-                for (i = 0; i < n_components; i++) {
-                        struct bus_match_component *c = &components[i];
-
-                        switch (c->type) {
-
-                        case BUS_MATCH_SENDER:
-                                if (!streq(c->value_str, "org.freedesktop.DBus"))
-                                        matches_name_change = false;
-
-                                r = bus_kernel_parse_unique_name(c->value_str, &src_id);
-                                if (r < 0)
-                                        return r;
-
-                                if (r > 0) {
-                                        sender = c->value_str;
-                                        sender_length = strlen(sender);
-                                        sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
-                                }
+        zero(bloom);
 
-                                break;
+        sz = offsetof(struct kdbus_cmd_match, items);
 
-                        case BUS_MATCH_MESSAGE_TYPE:
-                                if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
-                                        matches_name_change = false;
+        for (i = 0; i < n_components; i++) {
+                struct bus_match_component *c = &components[i];
 
-                                bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
-                                using_bloom = true;
-                                break;
+                switch (c->type) {
 
-                        case BUS_MATCH_INTERFACE:
-                                if (!streq(c->value_str, "org.freedesktop.DBus"))
-                                        matches_name_change = false;
+                case BUS_MATCH_SENDER:
+                        if (!streq(c->value_str, "org.freedesktop.DBus"))
+                                matches_name_change = false;
 
-                                bloom_add_pair(bloom, "interface", c->value_str);
-                                using_bloom = true;
-                                break;
+                        r = bus_kernel_parse_unique_name(c->value_str, &src_id);
+                        if (r < 0)
+                                return r;
 
-                        case BUS_MATCH_MEMBER:
-                                if (!streq(c->value_str, "NameOwnerChanged"))
-                                        matches_name_change = false;
+                        if (r > 0) {
+                                sender = c->value_str;
+                                sender_length = strlen(sender);
+                                sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
+                        }
 
-                                bloom_add_pair(bloom, "member", c->value_str);
-                                using_bloom = true;
-                                break;
+                        break;
 
-                        case BUS_MATCH_PATH:
-                                if (!streq(c->value_str, "/org/freedesktop/DBus"))
-                                        matches_name_change = false;
+                case BUS_MATCH_MESSAGE_TYPE:
+                        if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
+                                matches_name_change = false;
 
-                                bloom_add_pair(bloom, "path", c->value_str);
-                                using_bloom = true;
-                                break;
+                        bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
+                        using_bloom = true;
+                        break;
 
-                        case BUS_MATCH_PATH_NAMESPACE:
-                                if (!streq(c->value_str, "/")) {
-                                        bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
-                                        using_bloom = true;
-                                }
-                                break;
+                case BUS_MATCH_INTERFACE:
+                        if (!streq(c->value_str, "org.freedesktop.DBus"))
+                                matches_name_change = false;
 
-                        case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
-                                char buf[sizeof("arg")-1 + 2 + 1];
+                        bloom_add_pair(bloom, "interface", c->value_str);
+                        using_bloom = true;
+                        break;
 
-                                if (c->type - BUS_MATCH_ARG < 3)
-                                        name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
+                case BUS_MATCH_MEMBER:
+                        if (!streq(c->value_str, "NameOwnerChanged"))
+                                matches_name_change = false;
 
-                                snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
-                                bloom_add_pair(bloom, buf, c->value_str);
-                                using_bloom = true;
-                                break;
-                        }
+                        bloom_add_pair(bloom, "member", c->value_str);
+                        using_bloom = true;
+                        break;
 
-                        case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
-                                char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
+                case BUS_MATCH_PATH:
+                        if (!streq(c->value_str, "/org/freedesktop/DBus"))
+                                matches_name_change = false;
 
-                                snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
-                                bloom_add_pair(bloom, buf, c->value_str);
+                        bloom_add_pair(bloom, "path", c->value_str);
+                        using_bloom = true;
+                        break;
+
+                case BUS_MATCH_PATH_NAMESPACE:
+                        if (!streq(c->value_str, "/")) {
+                                bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
                                 using_bloom = true;
-                                break;
                         }
+                        break;
 
-                        case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
-                                char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
+                case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
+                        char buf[sizeof("arg")-1 + 2 + 1];
 
-                                snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
-                                bloom_add_pair(bloom, buf, c->value_str);
-                                using_bloom = true;
-                                break;
-                        }
+                        if (c->type - BUS_MATCH_ARG < 3)
+                                name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
 
-                        case BUS_MATCH_DESTINATION:
-                                /* The bloom filter does not include
-                                   the destination, since it is only
-                                   available for broadcast messages
-                                   which do not carry a destination
-                                   since they are undirected. */
-                                break;
-
-                        case BUS_MATCH_ROOT:
-                        case BUS_MATCH_VALUE:
-                        case BUS_MATCH_LEAF:
-                        case _BUS_MATCH_NODE_TYPE_MAX:
-                        case _BUS_MATCH_NODE_TYPE_INVALID:
-                                assert_not_reached("Invalid match type?");
-                        }
+                        snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
+                        bloom_add_pair(bloom, buf, c->value_str);
+                        using_bloom = true;
+                        break;
                 }
 
-                if (using_bloom)
-                        sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
-
-                m = alloca0(sz);
-                m->size = sz;
-                m->cookie = cookie;
-                m->src_id = src_id;
+                case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
+                        char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
 
-                item = m->items;
+                        snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
+                        bloom_add_pair(bloom, buf, c->value_str);
+                        using_bloom = true;
+                        break;
+                }
 
-                if (using_bloom) {
-                        item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
-                        item->type = KDBUS_MATCH_BLOOM;
-                        memcpy(item->data64, bloom, BLOOM_SIZE);
+                case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
+                        char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
 
-                        item = KDBUS_PART_NEXT(item);
+                        snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
+                        bloom_add_pair(bloom, buf, c->value_str);
+                        using_bloom = true;
+                        break;
                 }
 
-                if (sender) {
-                        item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
-                        item->type = KDBUS_MATCH_SRC_NAME;
-                        memcpy(item->str, sender, sender_length + 1);
+                case BUS_MATCH_DESTINATION:
+                        /* The bloom filter does not include
+                           the destination, since it is only
+                           available for broadcast messages
+                           which do not carry a destination
+                           since they are undirected. */
+                        break;
+
+                case BUS_MATCH_ROOT:
+                case BUS_MATCH_VALUE:
+                case BUS_MATCH_LEAF:
+                case _BUS_MATCH_NODE_TYPE_MAX:
+                case _BUS_MATCH_NODE_TYPE_INVALID:
+                        assert_not_reached("Invalid match type?");
                 }
+        }
+
+        if (using_bloom)
+                sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
+
+        m = alloca0(sz);
+        m->size = sz;
+        m->cookie = cookie;
+        m->src_id = src_id;
 
-                r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
+        item = m->items;
+
+        if (using_bloom) {
+                item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
+                item->type = KDBUS_MATCH_BLOOM;
+                memcpy(item->data64, bloom, BLOOM_SIZE);
+
+                item = KDBUS_PART_NEXT(item);
+        }
+
+        if (sender) {
+                item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
+                item->type = KDBUS_MATCH_SRC_NAME;
+                memcpy(item->str, sender, sender_length + 1);
+        }
+
+        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
+        if (r < 0)
+                return -errno;
+
+        if (matches_name_change) {
+
+                /* If this match could theoretically match
+                 * NameOwnerChanged messages, we need to
+                 * install a second non-bloom filter explitly
+                 * for it */
+
+                r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
                 if (r < 0)
-                        return -errno;
+                        return r;
+        }
+
+        return 0;
+}
 
-                if (matches_name_change) {
+static int bus_add_match_internal_dbus1(
+                sd_bus *bus,
+                const char *match) {
 
-                        /* If this match could theoretically match
-                         * NameOwnerChanged messages, we need to
-                         * install a second non-bloom filter explitly
-                         * for it */
+        assert(bus);
+        assert(match);
 
-                        r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
-                        if (r < 0)
-                                return r;
-                }
+        return sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/",
+                        "org.freedesktop.DBus",
+                        "AddMatch",
+                        NULL,
+                        NULL,
+                        "s",
+                        match);
+}
 
-                return 0;
-        } else
-                return sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.DBus",
-                                "/",
-                                "org.freedesktop.DBus",
-                                "AddMatch",
-                                NULL,
-                                NULL,
-                                "s",
-                                match);
+int bus_add_match_internal(
+                sd_bus *bus,
+                const char *match,
+                struct bus_match_component *components,
+                unsigned n_components,
+                uint64_t cookie) {
+
+        assert(bus);
+        assert(match);
+
+        if (bus->is_kernel)
+                return bus_add_match_internal_kernel(bus, match, components, n_components, cookie);
+        else
+                return bus_add_match_internal_dbus1(bus, match);
 }
 
-int bus_remove_match_internal(
+static int bus_remove_match_internal_kernel(
                 sd_bus *bus,
                 const char *match,
                 uint64_t cookie) {
 
+        struct kdbus_cmd_match m;
         int r;
 
         assert(bus);
         assert(match);
 
-        if (bus->is_kernel) {
-                struct kdbus_cmd_match m;
+        zero(m);
+        m.size = offsetof(struct kdbus_cmd_match, items);
+        m.cookie = cookie;
+
+        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
+        if (r < 0)
+                return -errno;
 
-                zero(m);
-                m.size = offsetof(struct kdbus_cmd_match, items);
-                m.cookie = cookie;
+        return 0;
+}
 
-                r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
-                if (r < 0)
-                        return -errno;
+static int bus_remove_match_internal_dbus1(
+                sd_bus *bus,
+                const char *match) {
 
-                return 0;
+        assert(bus);
+        assert(match);
 
-        } else {
-                return sd_bus_call_method(
-                                bus,
-                                "org.freedesktop.DBus",
-                                "/",
-                                "org.freedesktop.DBus",
-                                "RemoveMatch",
-                                NULL,
-                                NULL,
-                                "s",
-                                match);
-        }
+        return sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/",
+                        "org.freedesktop.DBus",
+                        "RemoveMatch",
+                        NULL,
+                        NULL,
+                        "s",
+                        match);
+}
+
+int bus_remove_match_internal(
+                sd_bus *bus,
+                const char *match,
+                uint64_t cookie) {
+
+        assert(bus);
+        assert(match);
+
+        if (bus->is_kernel)
+                return bus_remove_match_internal_kernel(bus, match, cookie);
+        else
+                return bus_remove_match_internal_dbus1(bus, match);
 }
 
 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
index 7ef4d13..0382232 100644 (file)
@@ -1094,17 +1094,12 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
                 return r;
         }
 
-        r = sd_bus_request_name(bus, "org.freedesktop.locale1", SD_BUS_NAME_DO_NOT_QUEUE);
+        r = sd_bus_request_name(bus, "org.freedesktop.locale1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_DO_NOT_QUEUE);
         if (r < 0) {
                 log_error("Failed to register name: %s", strerror(-r));
                 return r;
         }
 
-        if (r != SD_BUS_NAME_PRIMARY_OWNER) {
-                log_error("Failed to acquire name.");
-                return -EEXIST;
-        }
-
         r = sd_bus_attach_event(bus, event, 0);
         if (r < 0) {
                 log_error("Failed to attach bus to event loop: %s", strerror(-r));
index 47b306b..87d46ee 100644 (file)
@@ -725,17 +725,12 @@ static int manager_connect_bus(Manager *m) {
                 return r;
         }
 
-        r = sd_bus_request_name(m->bus, "org.freedesktop.login1", SD_BUS_NAME_DO_NOT_QUEUE);
+        r = sd_bus_request_name(m->bus, "org.freedesktop.login1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_DO_NOT_QUEUE);
         if (r < 0) {
                 log_error("Failed to register name: %s", strerror(-r));
                 return r;
         }
 
-        if (r != SD_BUS_NAME_PRIMARY_OWNER)  {
-                log_error("Failed to acquire name.");
-                return -EEXIST;
-        }
-
         r = sd_bus_attach_event(m->bus, m->event, 0);
         if (r < 0) {
                 log_error("Failed to attach bus to event loop: %s", strerror(-r));
index 01b2caa..35b33c3 100644 (file)
@@ -217,17 +217,12 @@ static int manager_connect_bus(Manager *m) {
                 return r;
         }
 
-        r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", SD_BUS_NAME_DO_NOT_QUEUE);
+        r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_DO_NOT_QUEUE);
         if (r < 0) {
                 log_error("Failed to register name: %s", strerror(-r));
                 return r;
         }
 
-        if (r != SD_BUS_NAME_PRIMARY_OWNER)  {
-                log_error("Failed to acquire name.");
-                return -EEXIST;
-        }
-
         r = sd_bus_attach_event(m->bus, m->event, 0);
         if (r < 0) {
                 log_error("Failed to attach bus to event loop: %s", strerror(-r));
index 2598d7e..a993e12 100644 (file)
@@ -233,7 +233,7 @@ int sd_bus_message_rewind(sd_bus_message *m, int complete);
 /* Bus management */
 
 int sd_bus_get_unique_name(sd_bus *bus, const char **unique);
-int sd_bus_request_name(sd_bus *bus, const char *name, int flags);
+int sd_bus_request_name(sd_bus *bus, const char *name, unsigned flags);
 int sd_bus_release_name(sd_bus *bus, const char *name);
 int sd_bus_list_names(sd_bus *bus, char ***l); /* free the results */
 int sd_bus_get_owner(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds); /* unref the result! */
index a8261fe..0641f39 100644 (file)
@@ -786,17 +786,12 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
                 return r;
         }
 
-        r = sd_bus_request_name(bus, "org.freedesktop.timedate1", SD_BUS_NAME_DO_NOT_QUEUE);
+        r = sd_bus_request_name(bus, "org.freedesktop.timedate1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_DO_NOT_QUEUE);
         if (r < 0) {
                 log_error("Failed to register name: %s", strerror(-r));
                 return r;
         }
 
-        if (r != SD_BUS_NAME_PRIMARY_OWNER) {
-                log_error("Failed to acquire name.");
-                return -EEXIST;
-        }
-
         r = sd_bus_attach_event(bus, event, 0);
         if (r < 0) {
                 log_error("Failed to attach bus to event loop: %s", strerror(-r));