- ioctl(kdbus->priv->fd, KDBUS_CMD_FREE, &cmd->offset);
- return TRUE;
-
-}
-
-
-/**
- * g_kdbus_NameHasOwner_handler:
- * Returns: TRUE on success.
- */
-static gboolean
-g_kdbus_NameHasOwner_handler (GDBusWorker *worker,
- GKdbus *kdbus,
- GDBusMessage *dbus_msg)
-{
- GDBusMessage *reply;
- GVariant *result = NULL;
- const gchar *name;
-
- /* read and validate message */
- GVariant *body = g_dbus_message_get_body (dbus_msg);
-
- if (!g_kdbus_check_signature (worker, dbus_msg, "NameHasOwner", body, G_VARIANT_TYPE("(s)")))
- return TRUE;
-
- g_variant_get (body, "(&s)", &name);
-
- if (!g_kdbus_check_name (worker, dbus_msg, name))
- return TRUE;
-
- /* check whether name has owner */
- if (!g_kdbus_NameHasOwner (kdbus, name))
- result = g_variant_new ("(b)", FALSE);
- else
- result = g_variant_new ("(b)", TRUE);
-
- /* generate local reply */
- reply = g_kdbus_generate_local_reply (dbus_msg,
- G_DBUS_MESSAGE_TYPE_METHOD_RETURN,
- G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
- g_dbus_message_get_serial (dbus_msg),
- result,
- NULL);
- _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
- return TRUE;
-}
-
-
-/**
- * g_kdbus_GetId_handler:
- * Returns: TRUE on success.
- */
-static gboolean
-g_kdbus_GetId_handler (GDBusWorker *worker,
- GKdbus *kdbus,
- GDBusMessage *dbus_msg)
-{
- GDBusMessage *reply;
- GString *result = g_string_new (NULL);
- gint i;
-
- for (i=0; i<16; i++)
- g_string_append_printf (result, "%02x", kdbus->priv->bus_id[i]);
-
- /* generate local reply */
- reply = g_kdbus_generate_local_reply (dbus_msg,
- G_DBUS_MESSAGE_TYPE_METHOD_RETURN,
- G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
- g_dbus_message_get_serial (dbus_msg),
- g_variant_new ("(s)", result->str),
- NULL);
- _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
-
- g_string_free (result,TRUE);
- return TRUE;
-}
-
-
-/**
- * g_kdbus_StartServiceByName_handler:
- * Returns: TRUE on success.
- *
- */
-static gboolean
-g_kdbus_StartServiceByName_handler (GDBusWorker *worker,
- GKdbus *kdbus,
- GDBusMessage *dbus_msg)
-{
- GDBusMessage *reply;
- GVariant *body;
- const gchar *name;
- guint64 flags;
-
- body = g_dbus_message_get_body (dbus_msg);
-
- if (!g_kdbus_check_signature (worker, dbus_msg, "StartServiceByName", body, G_VARIANT_TYPE("(su)")))
- return TRUE;
-
- g_variant_get (body, "(&su)", &name, &flags);
-
- if (!g_kdbus_check_name (worker, dbus_msg, name))
- return TRUE;
-
- if (g_kdbus_NameHasOwner (kdbus, name))
- {
- reply = g_kdbus_generate_local_reply (dbus_msg,
- G_DBUS_MESSAGE_TYPE_METHOD_RETURN,
- G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED,
- g_dbus_message_get_serial (dbus_msg),
- g_variant_new ("(u)", G_BUS_START_REPLY_ALREADY_RUNNING),
- NULL);
- _g_dbus_worker_queue_or_deliver_received_message (worker, reply);
- return TRUE;
- }
-
- /* TODO */
- g_error ("[KDBUS] StartServiceByName method is not implemented yet");
-
- return TRUE;
-}
-
-
-/**
- * g_kdbus_AddMatch_handler:
- * Returns: TRUE on success.
- *
- */
-static gboolean
-g_kdbus_AddMatch_handler (GDBusWorker *worker,
- GKdbus *kdbus,
- GDBusMessage *dbus_msg)
-{
- GVariant *body;
- const gchar *rule;
-
- body = g_dbus_message_get_body (dbus_msg);
-
- if (!g_kdbus_check_signature (worker, dbus_msg, "AddMatch", body, G_VARIANT_TYPE("(s)")))
- return TRUE;
-
- g_variant_get (body, "(&s)", &rule);
-
- /* TODO */
- g_error ("[KDBUS] AddMatch method is not implemented yet");
-
- return TRUE;
-}
-
-
-/**
- * g_kdbus_RemoveMatch_handler:
- * Returns: TRUE on success.
- *
- */
-static gboolean
-g_kdbus_RemoveMatch_handler (GDBusWorker *worker,
- GKdbus *kdbus,
- GDBusMessage *dbus_msg)
-{
- GVariant *body;
- const gchar *rule;
-
- body = g_dbus_message_get_body (dbus_msg);
-
- if (!g_kdbus_check_signature (worker, dbus_msg, "RemoveMatch", body, G_VARIANT_TYPE("(s)")))
- return TRUE;
-
- g_variant_get (body, "(&s)", &rule);
-
- /* TODO */
- g_error ("[KDBUS] RemoveMatch method is not implemented yet");
-
- return TRUE;
-}
-
-
-/**
- * g_kdbus_UnsupportedMethod_handler:
- * Returns: TRUE on success.
- */
-static gboolean
-g_kdbus_UnsupportedMethod_handler (GDBusWorker *worker,
- GKdbus *kdbus,
- GDBusMessage *dbus_msg,
- const gchar *method_name)
-{
- GString *error_name = g_string_new (NULL);
- g_string_printf (error_name, "Method \"%s\" is not supported", method_name);
- g_kdbus_generate_local_error (worker,
- dbus_msg,
- g_variant_new ("(s)",error_name->str),
- G_DBUS_ERROR_UNKNOWN_METHOD);
- g_string_free (error_name,TRUE);
- return TRUE;
-}
-
-
-/**
- * g_kdbus_bus_driver:
- *
- */
-static gboolean
-g_kdbus_bus_driver (GDBusWorker *worker,
- GKdbus *kdbus,
- GDBusMessage *dbus_msg)
-{
- gboolean ret = FALSE;
-
- /* Hello */
- if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "Hello") == 0)
- {
- g_kdbus_take_fd (kdbus);
- ret = g_kdbus_Hello_reply (worker, kdbus, dbus_msg);
- }
-
- /* RequestName and ReleaseName */
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "RequestName") == 0)
- ret = g_kdbus_RequestName_handler (worker, kdbus, dbus_msg);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "ReleaseName") == 0)
- ret = g_kdbus_ReleaseName_handler (worker, kdbus, dbus_msg);
-
- /* All List* Methods */
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "ListNames") == 0)
- ret = g_kdbus_ListNames_handler (worker, kdbus, dbus_msg, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "ListActivatableNames") == 0)
- ret = g_kdbus_ListNames_handler (worker, kdbus, dbus_msg, KDBUS_NAME_LIST_ACTIVATORS);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "ListQueuedOwners") == 0)
- ret = g_kdbus_ListQueuedOwners_handler (worker, kdbus, dbus_msg);
-
- /* All Get* Methods */
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "GetNameOwner") == 0)
- ret = g_kdbus_GetOwner_handler (worker, kdbus, dbus_msg, G_BUS_CREDS_UNIQUE_NAME);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "GetConnectionUnixProcessID") == 0)
- ret = g_kdbus_GetOwner_handler (worker, kdbus, dbus_msg, G_BUS_CREDS_PID);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "GetConnectionUnixUser") == 0)
- ret = g_kdbus_GetOwner_handler (worker, kdbus, dbus_msg, G_BUS_CREDS_UID);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "GetConnectionSELinuxSecurityContext") == 0)
- ret = g_kdbus_GetOwner_handler (worker, kdbus, dbus_msg, G_BUS_CREDS_SELINUX_CONTEXT);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "GetId") == 0)
- ret = g_kdbus_GetId_handler (worker, kdbus, dbus_msg);
-
- /* NameHasOwner nad StartServiceByName methods */
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "NameHasOwner") == 0)
- ret = g_kdbus_NameHasOwner_handler (worker, kdbus, dbus_msg);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "StartServiceByName") == 0)
- ret = g_kdbus_StartServiceByName_handler (worker, kdbus, dbus_msg);
-
- /* AddMatch and RemoveMatch */
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "AddMatch") == 0)
- ret = g_kdbus_AddMatch_handler (worker, kdbus, dbus_msg);
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "RemoveMatch") == 0)
- ret = g_kdbus_RemoveMatch_handler (worker, kdbus, dbus_msg);
-
- /* Unsupported Methods */
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "ReloadConfig") == 0)
- ret = g_kdbus_UnsupportedMethod_handler (worker, kdbus, dbus_msg, "ReloadConfig");
- else if (g_strcmp0(g_dbus_message_get_member(dbus_msg), "UpdateActivationEnvironment") == 0)
- ret = g_kdbus_UnsupportedMethod_handler (worker, kdbus, dbus_msg, "UpdateActivationEnvironment");
-
- else
- {
- GString *error_name;
-
- error_name = g_string_new (NULL);
- g_string_printf (error_name, "org.freedesktop.DBus does not understand message %s", g_dbus_message_get_member(dbus_msg));
-
- g_kdbus_generate_local_error (worker,
- dbus_msg,
- g_variant_new ("(s)",error_name->str),
- G_DBUS_ERROR_UNKNOWN_METHOD);
- g_string_free (error_name,TRUE);
- }
-
- return ret;
-}
-
-
-/**
- * g_kdbus_alloc_memfd:
- *
- */
-static gboolean
-g_kdbus_alloc_memfd (GKdbus *kdbus)
-{
- struct kdbus_cmd_memfd_make *memfd;
- struct kdbus_item *item;
- gssize size;
- gchar *name = "gdbus-memfd";
-
- size = ALIGN8(G_STRUCT_OFFSET(struct kdbus_cmd_memfd_make, items)) +
- ALIGN8(G_STRUCT_OFFSET(struct kdbus_item, str)) +
- strlen(name) + 1;
-
- memfd = g_alloca0 (size);
- memfd->size = size;
-
- item = memfd->items;
- item->size = ALIGN8(offsetof(struct kdbus_item, str)) + strlen(name) + 1;
- item->type = KDBUS_ITEM_MEMFD_NAME;
- memcpy(item->str, name, strlen(name) + 1);
-
- if (ioctl(kdbus->priv->fd, KDBUS_CMD_MEMFD_NEW, memfd) < 0)
- return FALSE;
-
- kdbus->priv->memfd = memfd->fd;
-
- return TRUE;
-}
-
-
-/**
- * _g_kdbus_release_msg:
- * Release memory occupied by kdbus_msg.
- * Use after DBUS message is extracted.
- */
-void
-_g_kdbus_release_kmsg (GKdbus *kdbus)
-{
- struct kdbus_item *item = NULL;
- GSList *iterator = NULL;
- guint64 offset;
-
- offset = (guint8 *)kdbus->priv->kmsg - (guint8 *)kdbus->priv->kdbus_buffer;
- ioctl(kdbus->priv->fd, KDBUS_CMD_FREE, &offset);
-
- for (iterator = kdbus->priv->kdbus_msg_items; iterator; iterator = iterator->next)
- g_free ((msg_part*)iterator->data);
-
- g_slist_free (kdbus->priv->kdbus_msg_items);
- kdbus->priv->kdbus_msg_items = NULL;
-
- KDBUS_ITEM_FOREACH (item, kdbus->priv->kmsg, items)
- {
- if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD)
- close(item->memfd.fd);
- else if (item->type == KDBUS_ITEM_FDS)
- {
- gint i;
- gint num_fds = (item->size - G_STRUCT_OFFSET(struct kdbus_item, fds)) / sizeof(int);
-
- for (i = 0; i < num_fds; i++)
- close(item->fds[i]);
- }
- }
-}
-
-
-/**
- * g_kdbus_append_payload_vec:
- *
- */
-static void
-g_kdbus_append_payload_vec (struct kdbus_item **item,
- const void *data_ptr,
- gssize size)
-{
- *item = ALIGN8_PTR(*item);
- (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, vec) + sizeof(struct kdbus_vec);
- (*item)->type = KDBUS_ITEM_PAYLOAD_VEC;
- (*item)->vec.address = (guint64)((guintptr)data_ptr);
- (*item)->vec.size = size;
- *item = KDBUS_ITEM_NEXT(*item);
-}
-
-
-/**
- * g_kdbus_append_payload_memfd:
- *
- */
-static void
-g_kdbus_append_payload_memfd (struct kdbus_item **item,
- int fd,
- gssize size)
-{
- *item = ALIGN8_PTR(*item);
- (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
- (*item)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
- (*item)->memfd.fd = fd;
- (*item)->memfd.size = size;
- *item = KDBUS_ITEM_NEXT(*item);
-}
-
-
-/**
- * g_kdbus_append_payload_destiantion:
- *
- */
-static void
-g_kdbus_append_destination (struct kdbus_item **item,
- const gchar *destination,
- gsize size)
-{
- *item = ALIGN8_PTR(*item);
- (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, str) + size + 1;
- (*item)->type = KDBUS_ITEM_DST_NAME;
- memcpy ((*item)->str, destination, size+1);
- *item = KDBUS_ITEM_NEXT(*item);
-}
-
-
-/**
- * g_kdbus_append_payload_bloom:
- *
- */
-static struct kdbus_bloom_filter *
-g_kdbus_append_bloom (struct kdbus_item **item,
- gsize size)
-{
- struct kdbus_item *bloom_item;
-
- bloom_item = ALIGN8_PTR(*item);
- bloom_item->size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
- G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
- size;
-
- bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
-
- *item = KDBUS_ITEM_NEXT(bloom_item);
- return &bloom_item->bloom_filter;
-}
-
-
-/**
- * g_kdbus_append_fds:
- *
- */
-static void
-g_kdbus_append_fds (struct kdbus_item **item,
- GUnixFDList *fd_list)
-{
- *item = ALIGN8_PTR(*item);
- (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, fds) + sizeof(int) * g_unix_fd_list_get_length(fd_list);
- (*item)->type = KDBUS_ITEM_FDS;
- memcpy ((*item)->fds, g_unix_fd_list_peek_fds(fd_list, NULL), sizeof(int) * g_unix_fd_list_get_length(fd_list));
-
- *item = KDBUS_ITEM_NEXT(*item);
-}
-
-
-/**
- * _g_kdbus_attach_fds_to_msg:
- *
- */
-void
-_g_kdbus_attach_fds_to_msg (GKdbus *kdbus,
- GUnixFDList **fd_list)
-{
- if ((kdbus->priv->fds != NULL) && (kdbus->priv->num_fds > 0))
- {
- gint n;
-
- if (*fd_list == NULL)
- *fd_list = g_unix_fd_list_new();
-
- for (n = 0; n < kdbus->priv->num_fds; n++)
- {
- g_unix_fd_list_append (*fd_list, kdbus->priv->fds[n], NULL);
- (void) g_close (kdbus->priv->fds[n], NULL);
- }
-
- g_free (kdbus->priv->fds);
- kdbus->priv->fds = NULL;
- kdbus->priv->num_fds = 0;
- }
-}
-
-
-/**
- * g_kdbus_bloom_add_data:
- * Based on bus-bloom.c from systemd
- * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
- */
-static void
-g_kdbus_bloom_add_data (GKdbus *kdbus,
- guint64 bloom_data [],
- const void *data,
- gsize n)
-{
- guint8 hash[8];
- guint64 bit_num;
- guint bytes_num = 0;
- guint cnt_1, cnt_2;
-
- guint c = 0;
- guint64 p = 0;
-
- bit_num = kdbus->priv->bloom_size * 8;
-
- if (bit_num > 1)
- bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8;
-
- for (cnt_1 = 0; cnt_1 < (kdbus->priv->bloom_n_hash); cnt_1++)
- {
- for (cnt_2 = 0; cnt_2 < bytes_num; cnt_2++)
- {
- if (c <= 0)
- {
- g_siphash24(hash, data, n, hash_keys[cnt_1++]);
- c += 8;
- }
-
- p = (p << 8ULL) | (guint64) hash[8 - c];
- c--;
- }
-
- p &= bit_num - 1;
- bloom_data[p >> 6] |= 1ULL << (p & 63);
- }