int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { _cleanup_bus_message_unref_ sd_bus_message *rep = NULL; int r, has_owner = 0; assert(c); assert(name); r = sd_bus_call_method(c, "org.freedesktop.DBus", "/org/freedesktop/dbus", "org.freedesktop.DBus", "NameHasOwner", error, &rep, "s", name); if (r < 0) return r; r = sd_bus_message_read_basic(rep, 'b', &has_owner); if (r < 0) return sd_bus_error_set_errno(error, r); return has_owner; }
static int inhibit(sd_bus *bus, sd_bus_error *error) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; int r; int fd; r = sd_bus_call_method( bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit", error, &reply, "ssss", arg_what, arg_who, arg_why, arg_mode); if (r < 0) return r; r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_UNIX_FD, &fd); if (r < 0) return r; r = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (r < 0) return -errno; return r; }
int bus_message_map_properties_changed(sd_bus *bus, sd_bus_message *m, const struct bus_properties_map *map, void *userdata) { const char *member; int r, invalidated, i; assert(bus); assert(m); assert(map); r = bus_message_map_all_properties(bus, m, map, userdata); if (r < 0) return r; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s"); if (r < 0) return r; invalidated = 0; while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0) for (i = 0; map[i].member; i++) if (streq(map[i].member, member)) { ++invalidated; break; } r = sd_bus_message_exit_container(m); if (r < 0) return r; return invalidated; }
static bool adapter_property_powered_set(void *data, const char *path, sd_bus_message *m) { struct context *ctx = data; enum adapter_state new_state; bool powered, changed; int r; r = sd_bus_message_read_basic(m, SD_BUS_TYPE_BOOLEAN, &powered); SOL_INT_CHECK_GOTO(r, < 0, skip); if (ctx->original_state == ADAPTER_STATE_UNKNOWN) ctx->original_state = powered ? ADAPTER_STATE_ON : ADAPTER_STATE_OFF; new_state = powered ? ADAPTER_STATE_ON : ADAPTER_STATE_OFF; changed = ctx->current_state != new_state; ctx->current_state = new_state; return changed; skip: r = sd_bus_message_skip(m, "b"); SOL_INT_CHECK(r, < 0, false); return false; }
_public_ int sd_bus_get_property_trivial( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, char type, void *ptr) { _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_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) return r; r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type)); if (r < 0) return r; r = sd_bus_message_read_basic(reply, type, ptr); if (r < 0) return r; return 0; }
static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { const char *contents; int r; r = sd_bus_message_peek_type(m, NULL, &contents); if (r < 0) return r; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents); if (r < 0) return r; if (contents[0] == 's' || contents[0] == 'o') { const char *s; char **p = (char **) userdata; r = sd_bus_message_read_basic(m, contents[0], &s); if (r < 0) return r; free(*p); *p = strdup(s); if (!*p) return -ENOMEM; } else { r = sd_bus_message_read_basic(m, contents[0], userdata); if (r < 0) return r; } r = sd_bus_message_skip(m, contents+1); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; return 0; }
static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) { Context *c = userdata; _cleanup_strv_free_ char **l = NULL; char **i; const char *lang = NULL; int interactive; bool modified = false; bool have[_VARIABLE_LC_MAX] = {}; int p; int r; assert(m); assert(c); r = bus_message_read_strv_extend(m, &l); if (r < 0) return r; r = sd_bus_message_read_basic(m, 'b', &interactive); if (r < 0) return r; /* Check whether a variable changed and if it is valid */ STRV_FOREACH(i, l) { bool valid = false; for (p = 0; p < _VARIABLE_LC_MAX; p++) { size_t k; const char *name; name = locale_variable_to_string(p); assert(name); k = strlen(name); if (startswith(*i, name) && (*i)[k] == '=' && locale_is_valid((*i) + k + 1)) { valid = true; have[p] = true; if (p == VARIABLE_LANG) lang = (*i) + k + 1; if (!streq_ptr(*i + k + 1, c->locale[p])) modified = true; break; } } if (!valid) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data."); }
_public_ int sd_bus_get_property_string( sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *error, char **ret) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; const char *s; char *n; int r; 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)) { 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) return r; r = sd_bus_message_enter_container(reply, 'v', "s"); if (r < 0) goto fail; r = sd_bus_message_read_basic(reply, 's', &s); if (r < 0) goto fail; n = strdup(s); if (!n) { r = -ENOMEM; goto fail; } *ret = n; return 0; fail: return sd_bus_error_set_errno(error, r); }
static int inhibit(sd_bus *bus, const char *what) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; const char *who = "Test Tool", *reason = "Just because!", *mode = "block"; int fd; int r; r = sd_bus_call_method(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit", &error, &reply, "ssss", what, who, reason, mode); assert_se(r >= 0); r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_UNIX_FD, &fd); assert_se(r >= 0); assert_se(fd >= 0); return dup(fd); }
int bus_message_map_all_properties(sd_bus *bus, sd_bus_message *m, const struct bus_properties_map *map, void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(m); assert(map); r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return r; while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const struct bus_properties_map *prop; const char *member; const char *contents; void *v; unsigned i; r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member); if (r < 0) return r; for (i = 0, prop = NULL; map[i].member; i++) if (streq(map[i].member, member)) { prop = &map[i]; break; } if (prop) { r = sd_bus_message_peek_type(m, NULL, &contents); if (r < 0) return r; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents); if (r < 0) return r; v = (uint8_t *)userdata + prop->offset; if (map[i].set) r = prop->set(bus, member, m, &error, v); else r = map_basic(bus, member, m, &error, v); if (r < 0) return r; r = sd_bus_message_exit_container(m); if (r < 0) return r; } else { r = sd_bus_message_skip(m, "v"); if (r < 0) return r; } r = sd_bus_message_exit_container(m); if (r < 0) return r; } return sd_bus_message_exit_container(m); }
static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { char type; int r; r = sd_bus_message_peek_type(m, &type, NULL); if (r < 0) return r; switch (type) { case SD_BUS_TYPE_STRING: { const char *s; char *str; char **p = userdata; r = sd_bus_message_read_basic(m, type, &s); if (r < 0) break; if (isempty(s)) break; str = strdup(s); if (!str) { r = -ENOMEM; break; } free(*p); *p = str; break; } case SD_BUS_TYPE_ARRAY: { _cleanup_strv_free_ char **l = NULL; char ***p = userdata; r = bus_message_read_strv_extend(m, &l); if (r < 0) break; strv_free(*p); *p = l; l = NULL; break; } case SD_BUS_TYPE_BOOLEAN: { unsigned b; bool *p = userdata; r = sd_bus_message_read_basic(m, type, &b); if (r < 0) break; *p = b; break; } case SD_BUS_TYPE_UINT32: { uint64_t u; uint32_t *p = userdata; r = sd_bus_message_read_basic(m, type, &u); if (r < 0) break; *p = u; break; } case SD_BUS_TYPE_UINT64: { uint64_t t; uint64_t *p = userdata; r = sd_bus_message_read_basic(m, type, &t); if (r < 0) break; *p = t; break; } default: break; } return r; }
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); assert(path); r = sd_bus_call_method(bus, dest, path, "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", ""); if (r < 0) return r; r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return r; while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const char *name; const char *contents; r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name); if (r < 0) return r; if (!filter || strv_find(filter, name)) { r = sd_bus_message_peek_type(reply, NULL, &contents); if (r < 0) return r; r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents); if (r < 0) return r; r = bus_print_property(name, reply, all); if (r < 0) return r; if (r == 0) { if (all) printf("%s=[unprintable]\n", name); /* skip what we didn't read */ r = sd_bus_message_skip(reply, contents); if (r < 0) return r; } r = sd_bus_message_exit_container(reply); if (r < 0) return r; } else { r = sd_bus_message_skip(reply, "v"); if (r < 0) return r; } r = sd_bus_message_exit_container(reply); if (r < 0) return r; } if (r < 0) return r; r = sd_bus_message_exit_container(reply); if (r < 0) return r; return 0; }
int bus_print_property(const char *name, sd_bus_message *property, bool all) { char type; const char *contents; int r; assert(name); assert(property); r = sd_bus_message_peek_type(property, &type, &contents); if (r < 0) return r; switch (type) { case SD_BUS_TYPE_STRING: { const char *s; r = sd_bus_message_read_basic(property, type, &s); if (r < 0) return r; if (all || !isempty(s)) printf("%s=%s\n", name, s); return 1; } case SD_BUS_TYPE_BOOLEAN: { bool b; r = sd_bus_message_read_basic(property, type, &b); if (r < 0) return r; printf("%s=%s\n", name, yes_no(b)); return 1; } case SD_BUS_TYPE_UINT64: { uint64_t u; r = sd_bus_message_read_basic(property, type, &u); if (r < 0) return r; /* Yes, heuristics! But we can change this check * should it turn out to not be sufficient */ if (endswith(name, "Timestamp")) { char timestamp[FORMAT_TIMESTAMP_MAX], *t; t = format_timestamp(timestamp, sizeof(timestamp), u); if (t || all) printf("%s=%s\n", name, strempty(t)); } else if (strstr(name, "USec")) { char timespan[FORMAT_TIMESPAN_MAX]; printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0)); } else printf("%s=%llu\n", name, (unsigned long long) u); return 1; } case SD_BUS_TYPE_UINT32: { uint32_t u; r = sd_bus_message_read_basic(property, type, &u); if (r < 0) return r; if (strstr(name, "UMask") || strstr(name, "Mode")) printf("%s=%04o\n", name, u); else printf("%s=%u\n", name, (unsigned) u); return 1; } case SD_BUS_TYPE_INT32: { int32_t i; r = sd_bus_message_read_basic(property, type, &i); if (r < 0) return r; printf("%s=%i\n", name, (int) i); return 1; } case SD_BUS_TYPE_DOUBLE: { double d; r = sd_bus_message_read_basic(property, type, &d); if (r < 0) return r; printf("%s=%g\n", name, d); return 1; } case SD_BUS_TYPE_ARRAY: if (streq(contents, "s")) { bool first = true; const char *str; r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents); if (r < 0) return r; while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) { if (first) printf("%s=", name); printf("%s%s", first ? "" : " ", str); first = false; } if (r < 0) return r; if (first && all) printf("%s=", name); if (!first || all) puts(""); r = sd_bus_message_exit_container(property); if (r < 0) return r; return 1; } else if (streq(contents, "y")) { const uint8_t *u; size_t n; r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n); if (r < 0) return r; if (all || n > 0) { unsigned int i; printf("%s=", name); for (i = 0; i < n; i++) printf("%02x", u[i]); puts(""); } return 1; } else if (streq(contents, "u")) { uint32_t *u; size_t n; r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n); if (r < 0) return r; if (all || n > 0) { unsigned int i; printf("%s=", name); for (i = 0; i < n; i++) printf("%08x", u[i]); puts(""); } return 1; } break; } return 0; }
int main(int argc, char *argv[]) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL; int r, boolean; const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature; uint8_t u, v; void *buffer = NULL; size_t sz; char *h; const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array; char *s; _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL; _cleanup_fclose_ FILE *ms = NULL; size_t first_size = 0, second_size = 0, third_size = 0; _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; double dbl; uint64_t u64; r = sd_bus_default_system(&bus); if (r < 0) return EXIT_TEST_SKIP; r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep"); assert_se(r >= 0); r = sd_bus_message_append(m, ""); assert_se(r >= 0); r = sd_bus_message_append(m, "s", "a string"); assert_se(r >= 0); r = sd_bus_message_append(m, "s", NULL); assert_se(r >= 0); r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss"); assert_se(r >= 0); r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after"); assert_se(r >= 0); r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo"); assert_se(r >= 0); r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10); assert_se(r >= 0); r = sd_bus_message_append(m, "()"); assert_se(r >= 0); r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); assert_se(r >= 0); r = sd_bus_message_open_container(m, 'a', "s"); assert_se(r >= 0); r = sd_bus_message_append_basic(m, 's', "foobar"); assert_se(r >= 0); r = sd_bus_message_append_basic(m, 's', "waldo"); assert_se(r >= 0); r = sd_bus_message_close_container(m); assert_se(r >= 0); r = sd_bus_message_append_string_space(m, 5, &s); assert_se(r >= 0); strcpy(s, "hallo"); r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array)); assert_se(r >= 0); r = sd_bus_message_append_array(m, 'u', NULL, 0); assert_se(r >= 0); r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/"); assert_se(r >= 0); r = bus_message_seal(m, 4711, 0); assert_se(r >= 0); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); ms = open_memstream(&first, &first_size); bus_message_dump(m, ms, 0); fflush(ms); assert_se(!ferror(ms)); r = bus_message_get_blob(m, &buffer, &sz); assert_se(r >= 0); h = hexmem(buffer, sz); assert_se(h); log_info("message size = %zu, contents =\n%s", sz, h); free(h); #ifdef HAVE_GLIB { GDBusMessage *g; char *p; #if !defined(GLIB_VERSION_2_36) g_type_init(); #endif g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL); p = g_dbus_message_print(g, 0); log_info("%s", p); g_free(p); g_object_unref(g); } #endif #ifdef HAVE_DBUS { DBusMessage *w; DBusError error; dbus_error_init(&error); w = dbus_message_demarshal(buffer, sz, &error); if (!w) log_error("%s", error.message); else dbus_message_unref(w); dbus_error_free(&error); } #endif m = sd_bus_message_unref(m); r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m); assert_se(r >= 0); bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); fclose(ms); ms = open_memstream(&second, &second_size); bus_message_dump(m, ms, 0); fflush(ms); assert_se(!ferror(ms)); assert_se(first_size == second_size); assert_se(memcmp(first, second, first_size) == 0); assert_se(sd_bus_message_rewind(m, true) >= 0); r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature); assert_se(r > 0); assert_se(streq(x, "a string")); assert_se(streq(x2, "")); assert_se(streq(y, "string #1")); assert_se(streq(z, "string #2")); assert_se(streq(a_signature, "sba(tt)ss")); r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d); assert_se(r > 0); assert_se(streq(x, "foobar")); assert_se(streq(y, "foo")); assert_se(streq(z, "bar")); assert_se(streq(a, "waldo")); assert_se(streq(b, "piep")); assert_se(streq(c, "pap")); assert_se(streq(d, "after")); r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y); assert_se(r > 0); assert_se(u == 3); assert_se(streq(x, "foo")); assert_se(v == 5); assert_se(streq(y, "waldo")); r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u); assert_se(r > 0); assert_se(v == 8); assert_se(u64 == 777); assert_se(u == 7); r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64); assert_se(r > 0); assert_se(v == 9); assert_se(u == 77); assert_se(u64 == 7777); r = sd_bus_message_read(m, "y", &v); assert_se(r > 0); assert_se(v == 10); r = sd_bus_message_read(m, "()"); assert_se(r > 0); r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); assert_se(r > 0); assert_se(boolean); assert_se(streq(x, "aaa")); assert_se(streq(y, "1")); assert_se(streq(a, "bbb")); assert_se(streq(b, "2")); assert_se(streq(c, "ccc")); assert_se(streq(d, "3")); assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0); r = sd_bus_message_read(m, "as", 2, &x, &y); assert_se(r > 0); assert_se(streq(x, "foobar")); assert_se(streq(y, "waldo")); r = sd_bus_message_read_basic(m, 's', &s); assert_se(r > 0); assert_se(streq(s, "hallo")); r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz); assert_se(r > 0); assert_se(sz == sizeof(integer_array)); assert_se(memcmp(integer_array, return_array, sz) == 0); r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz); assert_se(r > 0); assert_se(sz == 0); r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y); assert_se(r > 0); assert_se(streq(x, "foo")); assert_se(u64 == 815ULL); assert_se(fabs(dbl - 47.0) < 0.1); assert_se(streq(y, "/")); r = sd_bus_message_peek_type(m, NULL, NULL); assert_se(r == 0); r = sd_bus_message_new_method_call(bus, ©, "foobar.waldo", "/", "foobar.waldo", "Piep"); assert_se(r >= 0); r = sd_bus_message_rewind(m, true); assert_se(r >= 0); r = sd_bus_message_copy(copy, m, true); assert_se(r >= 0); r = bus_message_seal(copy, 4712, 0); assert_se(r >= 0); fclose(ms); ms = open_memstream(&third, &third_size); bus_message_dump(copy, ms, 0); fflush(ms); assert_se(!ferror(ms)); printf("<%.*s>\n", (int) first_size, first); printf("<%.*s>\n", (int) third_size, third); assert_se(first_size == third_size); assert_se(memcmp(first, third, third_size) == 0); r = sd_bus_message_rewind(m, true); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); r = sd_bus_message_skip(m, "ssasg"); assert_se(r > 0); assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); r = sd_bus_message_skip(m, "sass"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()"); assert_se(r >= 0); assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); r = sd_bus_message_read(m, "b", &boolean); assert_se(r > 0); assert_se(boolean); r = sd_bus_message_enter_container(m, 0, NULL); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &x, &y); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &a, &b); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &c, &d); assert_se(r > 0); r = sd_bus_message_read(m, "(ss)", &x, &y); assert_se(r == 0); r = sd_bus_message_exit_container(m); assert_se(r >= 0); assert_se(streq(x, "aaa")); assert_se(streq(y, "1")); assert_se(streq(a, "bbb")); assert_se(streq(b, "2")); assert_se(streq(c, "ccc")); assert_se(streq(d, "3")); test_bus_label_escape(); test_bus_path_encode(); test_bus_path_encode_unique(); test_bus_path_encode_many(); return 0; }