+ len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
+
+ if (path) {
+ p = new(char, len);
+ if (!p)
+ return -ENOMEM;
+ } else
+ p = newa(char, len);
+
+ sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
+
+ fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ if (fd < 0) {
+ if (path)
+ free(p);
+
+ return -errno;
+ }
+
+ if (path)
+ *path = p;
+
+ return fd;
+}
+
+int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **ep_path) {
+ _cleanup_free_ char *path = NULL;
+ struct kdbus_cmd_make *make;
+ struct kdbus_item *n;
+ const char *name;
+ int fd;
+
+ fd = bus_kernel_open_bus_fd(bus_name, &path);
+ if (fd < 0)
+ return fd;
+
+ make = alloca0_align(ALIGN8(offsetof(struct kdbus_cmd_make, items)) +
+ ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + strlen(ep_name) + 1),
+ 8);
+ make->size = ALIGN8(offsetof(struct kdbus_cmd_make, items));
+ make->flags = KDBUS_MAKE_ACCESS_WORLD;
+
+ n = make->items;
+ sprintf(n->str, UID_FMT "-%s", getuid(), ep_name);
+ n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
+ n->type = KDBUS_ITEM_MAKE_NAME;
+ make->size += ALIGN8(n->size);
+ name = n->str;
+
+ if (ioctl(fd, KDBUS_CMD_ENDPOINT_MAKE, make) < 0) {
+ safe_close(fd);
+ return -errno;
+ }
+
+ if (ep_path) {
+ char *p;
+
+ p = strjoin(dirname(path), "/", name, NULL);
+ if (!p) {
+ safe_close(fd);
+ return -ENOMEM;
+ }
+
+ *ep_path = p;
+ }
+
+ return fd;
+}
+
+int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) {
+
+ struct kdbus_cmd_update *update;
+ struct kdbus_item *n;
+ BusEndpointPolicy *po;
+ Iterator i;
+ size_t size;
+ int r;
+
+ size = ALIGN8(offsetof(struct kdbus_cmd_update, items));
+
+ HASHMAP_FOREACH(po, ep->policy_hash, i) {
+ size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1);
+ size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));