chiark / gitweb /
Prep v225: Applying various fixes and changes to src/libelogind/sd-bus that got lost...
authorSven Eden <yamakuzure@gmx.net>
Wed, 4 Jan 2017 05:40:46 +0000 (06:40 +0100)
committerSven Eden <yamakuzure@gmx.net>
Tue, 14 Mar 2017 09:18:46 +0000 (10:18 +0100)
12 files changed:
src/libelogind/sd-bus/bus-control.c
src/libelogind/sd-bus/bus-convenience.c
src/libelogind/sd-bus/bus-internal.h
src/libelogind/sd-bus/bus-introspect.c
src/libelogind/sd-bus/bus-kernel.c
src/libelogind/sd-bus/bus-match.c
src/libelogind/sd-bus/bus-match.h
src/libelogind/sd-bus/bus-message.c
src/libelogind/sd-bus/bus-message.h
src/libelogind/sd-bus/bus-objects.c
src/libelogind/sd-bus/bus-socket.c
src/libelogind/sd-bus/sd-bus.c

index feed51cd94e61a473048d48c6f302ad2387e64f6..356772ca5f75506227b64a720376f05f95b3f99e 100644 (file)
@@ -1129,7 +1129,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If the old name is unset or empty, then
                  * this can match against added names */
-                if (!old_owner || old_owner[0] == 0) {
+                if (isempty(old_owner)) {
                         item->type = KDBUS_ITEM_NAME_ADD;
 
                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1139,7 +1139,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If the new name is unset or empty, then
                  * this can match against removed names */
-                if (!new_owner || new_owner[0] == 0) {
+                if (isempty(new_owner)) {
                         item->type = KDBUS_ITEM_NAME_REMOVE;
 
                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
@@ -1183,7 +1183,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If the old name is unset or empty, then this can
                  * match against added ids */
-                if (!old_owner || old_owner[0] == 0) {
+                if (isempty(old_owner)) {
                         item->type = KDBUS_ITEM_ID_ADD;
                         if (!isempty(new_owner))
                                 item->id_change.id = new_owner_id;
@@ -1195,7 +1195,7 @@ static int add_name_change_match(sd_bus *bus,
 
                 /* If thew new name is unset or empty, then this can
                  * match against removed ids */
-                if (!new_owner || new_owner[0] == 0) {
+                if (isempty(new_owner)) {
                         item->type = KDBUS_ITEM_ID_REMOVE;
                         if (!isempty(old_owner))
                                 item->id_change.id = old_owner_id;
@@ -1309,7 +1309,16 @@ int bus_add_match_internal_kernel(
                         break;
                 }
 
-                case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
+                case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
+                        char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
+
+                        xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
+                        bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
+                        using_bloom = true;
+                        break;
+                }
+
+                case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
                         /*
                          * XXX: DBus spec defines arg[0..63]path= matching to be
                          * a two-way glob. That is, if either string is a prefix
@@ -1323,7 +1332,6 @@ int bus_add_match_internal_kernel(
                          * to properly support multiple-matches here.
                          */
                         break;
-                }
 
                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
@@ -1334,7 +1342,7 @@ int bus_add_match_internal_kernel(
                         break;
                 }
 
-                case BUS_MATCH_DESTINATION: {
+                case BUS_MATCH_DESTINATION:
                         /*
                          * Kernel only supports matching on destination IDs, but
                          * not on destination names. So just skip the
@@ -1352,7 +1360,6 @@ int bus_add_match_internal_kernel(
                                 matches_name_change = false;
 
                         break;
-                }
 
                 case BUS_MATCH_ROOT:
                 case BUS_MATCH_VALUE:
index 59c7c86aee42b11ecb981d5a87256e1230f161a7..b72049ef074bfa0edced3fbe34c3db52eb2560e1 100644 (file)
@@ -111,15 +111,17 @@ _public_ int sd_bus_call_method(
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus_assert_return(bus, -EINVAL, error);
+        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
 
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
+        if (!BUS_IS_OPEN(bus->state)) {
+                r = -ENOTCONN;
+                goto fail;
+        }
 
         r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
         if (r < 0)
-                return r;
+                goto fail;
 
         if (!isempty(types)) {
                 va_list ap;
@@ -128,10 +130,13 @@ _public_ int sd_bus_call_method(
                 r = bus_message_append_ap(m, types, ap);
                 va_end(ap);
                 if (r < 0)
-                        return r;
+                        goto fail;
         }
 
         return sd_bus_call(bus, m, 0, error, reply);
+
+fail:
+        return sd_bus_error_set_errno(error, r);
 }
 
 _public_ int sd_bus_reply_method_return(
@@ -296,15 +301,17 @@ _public_ int sd_bus_get_property(
         sd_bus_message *rep = NULL;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
-        assert_return(member_name_is_valid(member), -EINVAL);
-        assert_return(reply, -EINVAL);
-        assert_return(signature_is_single(type, false), -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus_assert_return(bus, -EINVAL, error);
+        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+        bus_assert_return(reply, -EINVAL, error);
+        bus_assert_return(signature_is_single(type, false), -EINVAL, error);
+        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
 
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
+        if (!BUS_IS_OPEN(bus->state)) {
+                r = -ENOTCONN;
+                goto fail;
+        }
 
         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
         if (r < 0)
@@ -313,11 +320,14 @@ _public_ int sd_bus_get_property(
         r = sd_bus_message_enter_container(rep, 'v', type);
         if (r < 0) {
                 sd_bus_message_unref(rep);
-                return r;
+                goto fail;
         }
 
         *reply = rep;
         return 0;
+
+fail:
+        return sd_bus_error_set_errno(error, r);
 }
 
 /// UNNEEDED by elogind
@@ -334,15 +344,17 @@ _public_ int sd_bus_get_property_trivial(
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
-        assert_return(member_name_is_valid(member), -EINVAL);
-        assert_return(bus_type_is_trivial(type), -EINVAL);
-        assert_return(ptr, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus_assert_return(bus, -EINVAL, error);
+        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+        bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
+        bus_assert_return(ptr, -EINVAL, error);
+        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
 
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
+        if (!BUS_IS_OPEN(bus->state)) {
+                r = -ENOTCONN;
+                goto fail;
+        }
 
         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
         if (r < 0)
@@ -350,13 +362,16 @@ _public_ int sd_bus_get_property_trivial(
 
         r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
         if (r < 0)
-                return r;
+                goto fail;
 
         r = sd_bus_message_read_basic(reply, type, ptr);
         if (r < 0)
-                return r;
+                goto fail;
 
         return 0;
+
+fail:
+        return sd_bus_error_set_errno(error, r);
 }
 #endif // 0
 
@@ -374,14 +389,16 @@ _public_ int sd_bus_get_property_string(
         char *n;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
-        assert_return(member_name_is_valid(member), -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus_assert_return(bus, -EINVAL, error);
+        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+        bus_assert_return(ret, -EINVAL, error);
+        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
 
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
+        if (!BUS_IS_OPEN(bus->state)) {
+                r = -ENOTCONN;
+                goto fail;
+        }
 
         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
         if (r < 0)
@@ -389,18 +406,23 @@ _public_ int sd_bus_get_property_string(
 
         r = sd_bus_message_enter_container(reply, 'v', "s");
         if (r < 0)
-                return r;
+                goto fail;
 
         r = sd_bus_message_read_basic(reply, 's', &s);
         if (r < 0)
-                return r;
+                goto fail;
 
         n = strdup(s);
-        if (!n)
-                return -ENOMEM;
+        if (!n) {
+                r = -ENOMEM;
+                goto fail;
+        }
 
         *ret = n;
         return 0;
+
+fail:
+        return sd_bus_error_set_errno(error, r);
 }
 
 /// UNNEEDED by elogind
@@ -417,14 +439,16 @@ _public_ int sd_bus_get_property_strv(
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
-        assert_return(member_name_is_valid(member), -EINVAL);
-        assert_return(ret, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus_assert_return(bus, -EINVAL, error);
+        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+        bus_assert_return(ret, -EINVAL, error);
+        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
 
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
+        if (!BUS_IS_OPEN(bus->state)) {
+                r = -ENOTCONN;
+                goto fail;
+        }
 
         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
         if (r < 0)
@@ -432,13 +456,16 @@ _public_ int sd_bus_get_property_strv(
 
         r = sd_bus_message_enter_container(reply, 'v', NULL);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = sd_bus_message_read_strv(reply, ret);
         if (r < 0)
-                return r;
+                goto fail;
 
         return 0;
+
+fail:
+        return sd_bus_error_set_errno(error, r);
 }
 
 _public_ int sd_bus_set_property(
@@ -454,38 +481,43 @@ _public_ int sd_bus_set_property(
         va_list ap;
         int r;
 
-        assert_return(bus, -EINVAL);
-        assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
-        assert_return(member_name_is_valid(member), -EINVAL);
-        assert_return(signature_is_single(type, false), -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus_assert_return(bus, -EINVAL, error);
+        bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
+        bus_assert_return(member_name_is_valid(member), -EINVAL, error);
+        bus_assert_return(signature_is_single(type, false), -EINVAL, error);
+        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
 
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
+        if (!BUS_IS_OPEN(bus->state)) {
+                r = -ENOTCONN;
+                goto fail;
+        }
 
         r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
         if (r < 0)
-                return r;
+                goto fail;
 
         r = sd_bus_message_append(m, "ss", strempty(interface), member);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = sd_bus_message_open_container(m, 'v', type);
         if (r < 0)
-                return r;
+                goto fail;
 
         va_start(ap, type);
         r = bus_message_append_ap(m, type, ap);
         va_end(ap);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = sd_bus_message_close_container(m);
         if (r < 0)
-                return r;
+                goto fail;
 
         return sd_bus_call(bus, m, 0, error, NULL);
+
+fail:
+        return sd_bus_error_set_errno(error, r);
 }
 #endif // 0
 
index 05dae42b2795045db4e9f897591c7f30dd170e67..efee735b9c6592605a87439679ab46bf1ebdbeec 100644 (file)
@@ -393,3 +393,9 @@ int bus_set_address_system_machine(sd_bus *b, const char *machine);
 int bus_get_root_path(sd_bus *bus);
 
 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
+
+#define bus_assert_return(expr, r, error)                               \
+        do {                                                            \
+                if (!assert_log(expr))                                  \
+                        return sd_bus_error_set_errno(error, r);        \
+        } while (false)
index e2f4550c7ec942e6879df7c664068b73885244a3..24aa21dfd3a4c2550820ec36679ed3b22fdc876f 100644 (file)
@@ -81,6 +81,9 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) {
                 fputs("   <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n", i->f);
 
         if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) {
+                if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
+                        fputs("   <annotation name=\"org.freedesktop.systemd1.Explicit\" value=\"true\"/>\n", i->f);
+
                 if (flags & SD_BUS_VTABLE_PROPERTY_CONST)
                         fputs("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i->f);
                 else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)
@@ -179,10 +182,10 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b
         assert(reply);
 
         fputs("</node>\n", i->f);
-        fflush(i->f);
 
-        if (ferror(i->f))
-                return -ENOMEM;
+        r = fflush_and_check(i->f);
+        if (r < 0)
+                return r;
 
         r = sd_bus_message_new_method_return(m, &q);
         if (r < 0)
@@ -204,8 +207,6 @@ void introspect_free(struct introspect *i) {
         if (i->f)
                 fclose(i->f);
 
-        if (i->introspection)
                 free(i->introspection);
-
         zero(*i);
 }
index e5d8a2cc57951ae22a01ccee7466b5e341a1a38c..25fc4ba80e9e72b9854ff95a62545ff5d7cb0d63 100644 (file)
@@ -168,6 +168,27 @@ static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i,
         bloom_add_prefixes(data, size, n_hash, buf, t, '/');
 }
 
+static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
+        char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
+        char *e;
+
+        assert(data);
+        assert(size > 0);
+        assert(i < 64);
+        assert(t);
+
+        e = stpcpy(buf, "arg");
+        if (i < 10)
+                *(e++) = '0' + (char) i;
+        else {
+                *(e++) = '0' + (char) (i / 10);
+                *(e++) = '0' + (char) (i % 10);
+        }
+
+        strcpy(e, "-has");
+        bloom_add_pair(data, size, n_hash, buf, t);
+}
+
 static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
         void *data;
         unsigned i;
@@ -212,7 +233,9 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter
                                 return r;
 
                         add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
-                } if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
+                }
+
+                if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
 
                         /* As well as array of simple strings of any kinds */
                         r = sd_bus_message_enter_container(m, type, contents);
@@ -220,7 +243,7 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter
                                 return r;
 
                         while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
-                                add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
+                                add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
                         if (r < 0)
                                 return r;
 
index 53c231331d4500e7e0add28bbee28a2639063463..8ef30f55e74e16d43e19b0a06ca22e966b935167 100644 (file)
  */
 
 static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) {
-        return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_NAMESPACE_LAST;
+        return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_HAS_LAST;
 }
 
 static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) {
         return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) ||
-                (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST);
+                (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST) ||
+                (t >= BUS_MATCH_ARG_HAS && t <= BUS_MATCH_ARG_HAS_LAST);
 }
 
 static void bus_match_node_free(struct bus_match_node *node) {
@@ -179,12 +180,16 @@ static bool value_node_test(
         case BUS_MATCH_INTERFACE:
         case BUS_MATCH_MEMBER:
         case BUS_MATCH_PATH:
-        case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: {
-                char **i;
+        case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
 
                 if (value_str)
                         return streq_ptr(node->value.str, value_str);
 
+                return false;
+
+        case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: {
+                char **i;
+
                 STRV_FOREACH(i, value_strv)
                         if (streq_ptr(node->value.str, *i))
                                 return true;
@@ -192,33 +197,20 @@ static bool value_node_test(
                 return false;
         }
 
-        case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: {
-                char **i;
-
+        case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
                 if (value_str)
                         return namespace_simple_pattern(node->value.str, value_str);
 
-                STRV_FOREACH(i, value_strv)
-                        if (namespace_simple_pattern(node->value.str, *i))
-                                return true;
                 return false;
-        }
 
         case BUS_MATCH_PATH_NAMESPACE:
                 return path_simple_pattern(node->value.str, value_str);
 
-        case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: {
-                char **i;
-
+        case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
                 if (value_str)
                         return path_complex_pattern(node->value.str, value_str);
 
-                STRV_FOREACH(i, value_strv)
-                        if (path_complex_pattern(node->value.str, *i))
-                                return true;
-
                 return false;
-        }
 
         default:
                 assert_not_reached("Invalid node type");
@@ -249,6 +241,7 @@ static bool value_node_same(
         case BUS_MATCH_MEMBER:
         case BUS_MATCH_PATH:
         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
+        case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
         case BUS_MATCH_PATH_NAMESPACE:
         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
@@ -372,15 +365,19 @@ int bus_match_run(
                 break;
 
         case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
-                (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str, &test_strv);
+                (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str);
                 break;
 
         case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
-                (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str, &test_strv);
+                (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str);
                 break;
 
         case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
-                (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str, &test_strv);
+                (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str);
+                break;
+
+        case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
+                (void) bus_message_get_arg_strv(m, node->type - BUS_MATCH_ARG_HAS, &test_strv);
                 break;
 
         default:
@@ -743,6 +740,32 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
                 return t;
         }
 
+        if (n == 7 && startswith(k, "arg") && startswith(k + 4, "has")) {
+                int j;
+
+                j = undecchar(k[3]);
+                if (j < 0)
+                        return -EINVAL;
+
+                return BUS_MATCH_ARG_HAS + j;
+        }
+
+        if (n == 8 && startswith(k, "arg") && startswith(k + 5, "has")) {
+                enum bus_match_node_type t;
+                int a, b;
+
+                a = undecchar(k[3]);
+                b = undecchar(k[4]);
+                if (a <= 0 || b < 0)
+                        return -EINVAL;
+
+                t = BUS_MATCH_ARG_HAS + a * 10 + b;
+                if (t > BUS_MATCH_ARG_HAS_LAST)
+                        return -EINVAL;
+
+                return t;
+        }
+
         return -EINVAL;
 }
 
@@ -861,8 +884,7 @@ int bus_match_parse(
                         if (r < 0)
                                 goto fail;
 
-                        free(value);
-                        value = NULL;
+                        value = mfree(value);
                 } else
                         u = 0;
 
@@ -944,8 +966,8 @@ char *bus_match_to_string(struct bus_match_component *components, unsigned n_com
                 fputc('\'', f);
         }
 
-        fflush(f);
-        if (ferror(f))
+        r = fflush_and_check(f);
+        if (r < 0)
                 return NULL;
 
         return buffer;
@@ -1114,6 +1136,10 @@ const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[]
                 snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE);
                 return buf;
 
+        case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
+                snprintf(buf, l, "arg%ihas", t - BUS_MATCH_ARG_HAS);
+                return buf;
+
         default:
                 return NULL;
         }
index cefb87e08e5060661c4b136a6e72c55dc9e97809..8b72a4f7c1642820936064a8d99c26c88fa08527 100644 (file)
@@ -44,6 +44,8 @@ enum bus_match_node_type {
         BUS_MATCH_ARG_PATH_LAST = BUS_MATCH_ARG_PATH + 63,
         BUS_MATCH_ARG_NAMESPACE,
         BUS_MATCH_ARG_NAMESPACE_LAST = BUS_MATCH_ARG_NAMESPACE + 63,
+        BUS_MATCH_ARG_HAS,
+        BUS_MATCH_ARG_HAS_LAST = BUS_MATCH_ARG_HAS + 63,
         _BUS_MATCH_NODE_TYPE_MAX,
         _BUS_MATCH_NODE_TYPE_INVALID = -1
 };
index 85882c1811d24ef7d8cb517e0600ba063158784a..dad6db8af2285f249d75ce015cab694b20b8a185 100644 (file)
@@ -2706,7 +2706,7 @@ _public_ int sd_bus_message_append_array_memfd(
         int r;
 
         assert_return(m, -EINVAL);
-        assert_return(memfd >= 0, -EINVAL);
+        assert_return(memfd >= 0, -EBADF);
         assert_return(bus_type_is_trivial(type), -EINVAL);
         assert_return(size > 0, -EINVAL);
         assert_return(!m->sealed, -EPERM);
@@ -2782,7 +2782,7 @@ _public_ int sd_bus_message_append_string_memfd(
         int r;
 
         assert_return(m, -EINVAL);
-        assert_return(memfd >= 0, -EINVAL);
+        assert_return(memfd >= 0, -EBADF);
         assert_return(size > 0, -EINVAL);
         assert_return(!m->sealed, -EPERM);
         assert_return(!m->poisoned, -ESTALE);
@@ -5642,21 +5642,23 @@ _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
         return 1;
 }
 
-int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) {
-        const char *contents;
+static int bus_message_get_arg_skip(
+                sd_bus_message *m,
+                unsigned i,
+                char *_type,
+                const char **_contents) {
+
         unsigned j;
-        char type;
         int r;
 
-        assert(m);
-        assert(str);
-        assert(strv);
-
         r = sd_bus_message_rewind(m, true);
         if (r < 0)
                 return r;
 
         for (j = 0;; j++) {
+                const char *contents;
+                char type;
+
                 r = sd_bus_message_peek_type(m, &type, &contents);
                 if (r < 0)
                         return r;
@@ -5668,31 +5670,56 @@ int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char **
                     !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
                         return -ENXIO;
 
-                if (j >= i)
-                        break;
+                if (j >= i) {
+                        if (_contents)
+                                *_contents = contents;
+                        if (_type)
+                                *_type = type;
+                        return 0;
+                }
 
                 r = sd_bus_message_skip(m, NULL);
                 if (r < 0)
                         return r;
         }
 
-        if (type == SD_BUS_TYPE_ARRAY) {
+}
+
+int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
+        char type;
+        int r;
+
+        assert(m);
+        assert(str);
 
-                r = sd_bus_message_read_strv(m, strv);
+        r = bus_message_get_arg_skip(m, i, &type, NULL);
                 if (r < 0)
                         return r;
 
-                *str = NULL;
+        if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
+                return -ENXIO;
 
-        } else {
-                r = sd_bus_message_read_basic(m, type, str);
+        return sd_bus_message_read_basic(m, type, str);
+}
+
+int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
+        const char *contents;
+        char type;
+        int r;
+
+        assert(m);
+        assert(strv);
+
+        r = bus_message_get_arg_skip(m, i, &type, &contents);
                 if (r < 0)
                         return r;
 
-                *strv = NULL;
-        }
+        if (type != SD_BUS_TYPE_ARRAY)
+                return -ENXIO;
+        if (!STR_IN_SET(contents, "s", "o", "g"))
+                return -ENXIO;
 
-        return 0;
+        return sd_bus_message_read_strv(m, strv);
 }
 
 _public_ int sd_bus_message_get_errno(sd_bus_message *m) {
index 2f338ff6fc6a8cf2112877b3f642a7ea4e661e0d..9b004464116272029dec5da7de373447664b06ec 100644 (file)
@@ -218,7 +218,8 @@ int bus_message_from_malloc(
                 const char *label,
                 sd_bus_message **ret);
 
-int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv);
+int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str);
+int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv);
 
 int bus_message_append_ap(sd_bus_message *m, const char *types, va_list ap);
 
index a3d9e552d1abe01e9d315309c27f296b7e8bc86a..fa5c8ab227a6aaad04c02f0744d72bacaf09e8ab 100644 (file)
@@ -750,6 +750,9 @@ static int vtable_append_all_properties(
                 if (v->flags & SD_BUS_VTABLE_HIDDEN)
                         continue;
 
+                if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
+                        continue;
+
                 r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
                 if (r < 0)
                         return r;
@@ -1176,10 +1179,6 @@ static int process_get_managed_objects(
         if (bus->nodes_modified)
                 return 0;
 
-        r = set_put_strdup(s, m->path);
-        if (r < 0)
-                return r;
-
         r = sd_bus_message_new_method_return(m, &reply);
         if (r < 0)
                 return r;
@@ -1745,8 +1744,9 @@ static int add_object_vtable_internal(
                         if (!member_name_is_valid(v->x.property.member) ||
                             !signature_is_single(v->x.property.signature, false) ||
                             !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) ||
-                            v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY ||
+                            (v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ||
                             (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 ||
+                            ((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) ||
                             (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) {
                                 r = -EINVAL;
                                 goto fail;
index 322d57ddbba43437348b713b36a72454d3081591..735a775cb4bd77e97703d957c23918fa7ca21a9c 100644 (file)
@@ -264,6 +264,8 @@ static bool line_begins(const char *s, size_t m, const char *word) {
 
 static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
         _cleanup_free_ char *token = NULL;
+        size_t len;
+        int r;
 
         if (!b->anonymous_auth)
                 return 0;
@@ -276,11 +278,12 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
 
         if (l % 2 != 0)
                 return 0;
-        token = unhexmem(p, l);
-        if (!token)
-                return -ENOMEM;
 
-        if (memchr(token, 0, l/2))
+        r = unhexmem(p, l, (void **) &token, &len);
+        if (r < 0)
+                return 0;
+
+        if (memchr(token, 0, len))
                 return 0;
 
         return !!utf8_is_valid(token);
@@ -288,6 +291,7 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
 
 static int verify_external_token(sd_bus *b, const char *p, size_t l) {
         _cleanup_free_ char *token = NULL;
+        size_t len;
         uid_t u;
         int r;
 
@@ -307,11 +311,11 @@ static int verify_external_token(sd_bus *b, const char *p, size_t l) {
         if (l % 2 != 0)
                 return 0;
 
-        token = unhexmem(p, l);
-        if (!token)
-                return -ENOMEM;
+        r = unhexmem(p, l, (void**) &token, &len);
+        if (r < 0)
+                return 0;
 
-        if (memchr(token, 0, l/2))
+        if (memchr(token, 0, len))
                 return 0;
 
         r = parse_uid(token, &u);
index d2a96f87b0fdc43a0d63c96245f57a68a2874724..957d4374585b00c3131e307ae0078c6ca154ba8e 100644 (file)
@@ -33,6 +33,7 @@
 #include "missing.h"
 #include "def.h"
 #include "cgroup-util.h"
+#include "hostname-util.h"
 #include "bus-label.h"
 
 #include "sd-bus.h"
@@ -214,8 +215,8 @@ _public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
 _public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
         assert_return(bus, -EINVAL);
         assert_return(bus->state == BUS_UNSET, -EPERM);
-        assert_return(input_fd >= 0, -EINVAL);
-        assert_return(output_fd >= 0, -EINVAL);
+        assert_return(input_fd >= 0, -EBADF);
+        assert_return(output_fd >= 0, -EBADF);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         bus->input_fd = input_fd;
@@ -899,10 +900,9 @@ static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid
         } else
                 b->nspid = 0;
 
-        free(b->kernel);
-        b->kernel = strdup("/sys/fs/kdbus/0-system/bus");
-        if (!b->kernel)
-                return -ENOMEM;
+        r = free_and_strdup(&b->kernel, "/sys/fs/kdbus/0-system/bus");
+        if (r < 0)
+                return r;
 
         return 0;
 }
@@ -1011,6 +1011,8 @@ static int bus_parse_next_address(sd_bus *b) {
 }
 
 static int bus_start_address(sd_bus *b) {
+        bool container_kdbus_available = false;
+        bool kdbus_available = false;
         int r;
 
         assert(b);
@@ -1020,17 +1022,31 @@ static int bus_start_address(sd_bus *b) {
 
                 bus_close_fds(b);
 
+                /*
+                 * Usually, if you provide multiple different bus-addresses, we
+                 * try all of them in order. We use the first one that
+                 * succeeds. However, if you mix kernel and unix addresses, we
+                 * never try unix-addresses if a previous kernel address was
+                 * tried and kdbus was available. This is required to prevent
+                 * clients to fallback to the bus-proxy if kdbus is available
+                 * but failed (eg., too many connections).
+                 */
+
                 if (b->exec_path)
                         r = bus_socket_exec(b);
 #if 0
-               else if ((b->nspid > 0 || b->machine) && b->kernel)
+                else if ((b->nspid > 0 || b->machine) && b->kernel) {
                         r = bus_container_connect_kernel(b);
-                else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
+                        if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
+                                container_kdbus_available = true;
+                } else if (!container_kdbus_available && (b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
                         r = bus_container_connect_socket(b);
 #endif // 0
-                else if (b->kernel)
+                else if (b->kernel) {
                         r = bus_kernel_connect(b);
-                else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
+                        if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
+                                kdbus_available = true;
+                } else if (!kdbus_available && b->sockaddr.sa.sa_family != AF_UNSPEC)
                         r = bus_socket_connect(b);
                 else
                         skipped = true;
@@ -1143,6 +1159,9 @@ _public_ int sd_bus_open(sd_bus **ret) {
 
         e = secure_getenv("DBUS_STARTER_ADDRESS");
         if (!e) {
+                if (cg_pid_get_owner_uid(0, NULL) >= 0)
+                        return sd_bus_open_user(ret);
+                else
                 return sd_bus_open_system(ret);
         }
 
@@ -1963,37 +1982,39 @@ _public_ int sd_bus_call(
         unsigned i;
         int r;
 
-        assert_return(m, -EINVAL);
-        assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
-        assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
-        assert_return(!bus_error_is_dirty(error), -EINVAL);
+        bus_assert_return(m, -EINVAL, error);
+        bus_assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL, error);
+        bus_assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL, error);
+        bus_assert_return(!bus_error_is_dirty(error), -EINVAL, error);
 
         if (!bus)
                 bus = m->bus;
 
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-        assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
+        bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
+        bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error);
 
-        if (!BUS_IS_OPEN(bus->state))
-                return -ENOTCONN;
+        if (!BUS_IS_OPEN(bus->state)) {
+                r = -ENOTCONN;
+                goto fail;
+        }
 
         r = bus_ensure_running(bus);
         if (r < 0)
-                return r;
+                goto fail;
 
         i = bus->rqueue_size;
 
         r = bus_seal_message(bus, m, usec);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = bus_remarshal_message(bus, &m);
         if (r < 0)
-                return r;
+                goto fail;
 
         r = bus_send_internal(bus, m, &cookie, true);
         if (r < 0)
-                return r;
+                goto fail;
 
         timeout = calc_elapse(m->timeout);
 
@@ -2024,14 +2045,17 @@ _public_ int sd_bus_call(
                                         }
 
                                         r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
+                                        sd_bus_message_unref(incoming);
+                                        return r;
 
-                                } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
+                                } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
                                         r = sd_bus_error_copy(error, &incoming->error);
-                                else
-                                        r = -EIO;
-
                                 sd_bus_message_unref(incoming);
                                 return r;
+                                } else {
+                                        r = -EIO;
+                                        goto fail;
+                                }
 
                         } else if (BUS_MESSAGE_COOKIE(incoming) == cookie &&
                                    bus->unique_name &&
@@ -2047,7 +2071,8 @@ _public_ int sd_bus_call(
                                  * immediately. */
 
                                 sd_bus_message_unref(incoming);
-                                return -ELOOP;
+                                r = -ELOOP;
+                                goto fail;
                         }
 
                         /* Try to read more, right-away */
@@ -2058,10 +2083,10 @@ _public_ int sd_bus_call(
                 if (r < 0) {
                         if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
                                 bus_enter_closing(bus);
-                                return -ECONNRESET;
+                                r = -ECONNRESET;
                         }
 
-                        return r;
+                        goto fail;
                 }
                 if (r > 0)
                         continue;
@@ -2070,8 +2095,10 @@ _public_ int sd_bus_call(
                         usec_t n;
 
                         n = now(CLOCK_MONOTONIC);
-                        if (n >= timeout)
-                                return -ETIMEDOUT;
+                        if (n >= timeout) {
+                                r = -ETIMEDOUT;
+                                goto fail;
+                        }
 
                         left = timeout - n;
                 } else
@@ -2079,20 +2106,25 @@ _public_ int sd_bus_call(
 
                 r = bus_poll(bus, true, left);
                 if (r < 0)
-                        return r;
-                if (r == 0)
-                        return -ETIMEDOUT;
+                        goto fail;
+                if (r == 0) {
+                        r = -ETIMEDOUT;
+                        goto fail;
+                }
 
                 r = dispatch_wqueue(bus);
                 if (r < 0) {
                         if (r == -ENOTCONN || r == -ECONNRESET || r == -EPIPE || r == -ESHUTDOWN) {
                                 bus_enter_closing(bus);
-                                return -ECONNRESET;
+                                r = -ECONNRESET;
                         }
 
-                        return r;
+                        goto fail;
                 }
         }
+
+fail:
+        return sd_bus_error_set_errno(error, r);
 }
 
 _public_ int sd_bus_get_fd(sd_bus *bus) {
@@ -3371,6 +3403,9 @@ _public_ int sd_bus_default(sd_bus **ret) {
         /* Finally, if nothing is set use the cached connection for
          * the right scope */
 
+        if (cg_pid_get_owner_uid(0, NULL) >= 0)
+                return sd_bus_default_user(ret);
+        else
         return sd_bus_default_system(ret);
 }