#include <stdio.h>
#include <errno.h>
#include <limits.h>
+#include <stdlib.h>
#endif
static DBusConnection *
else
#endif
{
-
if (!bus_registry_list_services (registry, &services, &len))
{
dbus_message_unref (reply);
if (! _dbus_list_append (&base_names, dbus_service_name))
goto oom;
}
+#ifdef ENABLE_KDBUS_TRANSPORT
+ else if (!bus_context_is_kdbus(bus_transaction_get_context (transaction)) && (service == NULL))
+#else
else if (service == NULL)
+#endif
{
dbus_set_error (error,
DBUS_ERROR_NAME_HAS_NO_OWNER,
}
else
{
- if (!bus_service_list_queued_owners (service,
- &base_names,
- error))
- goto failed;
+#ifdef ENABLE_KDBUS_TRANSPORT
+ if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
+ {
+ if(!kdbus_list_queued (connection, &base_names, text ,error))
+ goto failed;
+ }
+ else
+#endif
+ {
+ if (!bus_service_list_queued_owners (service,
+ &base_names,
+ error))
+ goto failed;
+ }
}
_dbus_assert (base_names != NULL);
dbus_message_unref (reply);
+ if(bus_context_is_kdbus(bus_transaction_get_context (transaction)))
+ {
+ link = _dbus_list_get_first_link (&base_names);
+ while (link != NULL)
+ {
+ DBusList *next = _dbus_list_get_next_link (&base_names, link);
+
+ if(link->data != NULL)
+ free(link->data);
+
+ _dbus_list_free_link (link);
+ link = next;
+ }
+ }
+
return TRUE;
oom:
_DBUS_ASSERT_ERROR_IS_SET (error);
if (reply)
dbus_message_unref (reply);
-
if (base_names)
_dbus_list_clear (&base_names);
-
return FALSE;
}
}
/*
+ * Asks kdbus for list of connections being in the queue to own
+ * given well-known name. The list includes the owner of the name on the
+ * first position.
+ */
+dbus_bool_t kdbus_list_queued (DBusConnection *connection, DBusList **return_list,
+ const char *name, DBusError *error)
+{
+ int fd;
+ struct kdbus_cmd_names* pCmd;
+ __u64 cmd_size;
+ dbus_bool_t ret_val = FALSE;
+ int name_length;
+
+ _dbus_assert (*return_list == NULL);
+
+ name_length = strlen(name) + 1;
+ cmd_size = sizeof(struct kdbus_cmd_names) + sizeof(struct kdbus_cmd_name) + name_length;
+ pCmd = malloc(cmd_size);
+ if(pCmd == NULL)
+ goto out;
+ pCmd->size = cmd_size;
+ pCmd->names[0].id = 0;
+ pCmd->names[0].size = sizeof(struct kdbus_cmd_name) + name_length;
+ memcpy(pCmd->names[0].name, name, name_length);
+ _dbus_verbose ("Asking for queued owners of %s\n", pCmd->names[0].name);
+
+ _dbus_transport_get_socket_fd(dbus_connection_get_transport(connection), &fd);
+
+ again:
+ cmd_size = 0;
+ if(ioctl(fd, KDBUS_CMD_NAME_LIST_QUEUED, pCmd))
+ {
+ if(errno == EINTR)
+ goto again;
+ if(errno == ENOBUFS) //buffer to small to put all names into it
+ cmd_size = pCmd->size; //here kernel tells how much memory it needs
+ else if(errno == ENOENT)
+ {
+ dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
+ "Could not get owners of name '%s': no such name", name);
+ free(pCmd);
+ return FALSE;
+ }
+ else
+ {
+ _dbus_verbose("kdbus error asking for queued owners list: err %d (%m)\n",errno);
+ goto out;
+ }
+ }
+ if(cmd_size) //kernel needs more memory
+ {
+ pCmd = realloc(pCmd, cmd_size); //prepare memory
+ if(pCmd == NULL)
+ return FALSE;
+ goto again; //and try again
+ }
+ else
+ {
+ struct kdbus_cmd_name* pCmd_name;
+
+ for (pCmd_name = pCmd->names; (uint8_t *)(pCmd_name) < (uint8_t *)(pCmd) + pCmd->size; pCmd_name = KDBUS_PART_NEXT(pCmd_name))
+ {
+ char *uname = NULL;
+
+ _dbus_verbose ("Got queued owner id: %llu\n", (unsigned long long)pCmd_name->id);
+ uname = malloc(snprintf(uname, 0, ":1.%llu0", (unsigned long long)pCmd_name->id));
+ if(uname == NULL)
+ goto out;
+ sprintf(uname, ":1.%llu", (unsigned long long int)pCmd_name->id);
+ if (!_dbus_list_append (return_list, uname))
+ goto out;
+ }
+ }
+
+ ret_val = TRUE;
+
+ out:
+ if(pCmd)
+ free(pCmd);
+ if(ret_val == FALSE)
+ {
+ DBusList *link;
+
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to list queued owners of \"%s\": %s",
+ name, _dbus_strerror (errno));
+
+ link = _dbus_list_get_first_link (return_list);
+ while (link != NULL)
+ {
+ DBusList *next = _dbus_list_get_next_link (return_list, link);
+
+ if(link->data != NULL)
+ free(link->data);
+
+ _dbus_list_free_link (link);
+ link = next;
+ }
+ }
+
+ return ret_val;
+}
+
+/*
* Register match rule in kdbus on behalf of sender of the message
*/
dbus_bool_t kdbus_add_match_rule (DBusConnection* connection, DBusMessage* message, const char* text, DBusError* error)
dbus_uint32_t kdbus_request_name(DBusConnection* connection, const DBusString *service_name, dbus_uint32_t flags, __u64 sender_id);
dbus_uint32_t kdbus_release_name(DBusConnection* connection, const DBusString *service_name, __u64 sender_id);
dbus_bool_t kdbus_list_services (DBusConnection* connection, char ***listp, int *array_len);
+dbus_bool_t kdbus_list_queued (DBusConnection *connection, DBusList **return_list, const char *name, DBusError *error);
dbus_bool_t kdbus_add_match_rule (DBusConnection* connection, DBusMessage* message, const char* text, DBusError* error);
dbus_bool_t kdbus_remove_match (DBusConnection* connection, DBusMessage* message, DBusError* error);
KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOC_MAGIC, 0x51, struct kdbus_cmd_name),
KDBUS_CMD_NAME_LIST = _IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_names),
KDBUS_CMD_NAME_QUERY = _IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),
+ KDBUS_CMD_NAME_LIST_QUEUED = _IOWR(KDBUS_IOC_MAGIC, 0x54, struct kdbus_cmd_names),
KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOC_MAGIC, 0x60, struct kdbus_cmd_match),
KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOC_MAGIC, 0x61, struct kdbus_cmd_match),