Import Upstream version 2.72.4
This commit is contained in:
commit
4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions
735
gio/gunixconnection.c
Normal file
735
gio/gunixconnection.c
Normal file
|
|
@ -0,0 +1,735 @@
|
|||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright © 2009 Codethink Limited
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* See the included COPYING file for more information.
|
||||
*
|
||||
* Authors: Ryan Lortie <desrt@desrt.ca>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gunixconnection.h"
|
||||
#include "gnetworking.h"
|
||||
#include "gsocket.h"
|
||||
#include "gsocketcontrolmessage.h"
|
||||
#include "gunixcredentialsmessage.h"
|
||||
#include "gunixfdmessage.h"
|
||||
#include "glibintl.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:gunixconnection
|
||||
* @title: GUnixConnection
|
||||
* @short_description: A UNIX domain GSocketConnection
|
||||
* @include: gio/gunixconnection.h
|
||||
* @see_also: #GSocketConnection.
|
||||
*
|
||||
* This is the subclass of #GSocketConnection that is created
|
||||
* for UNIX domain sockets.
|
||||
*
|
||||
* It contains functions to do some of the UNIX socket specific
|
||||
* functionality like passing file descriptors.
|
||||
*
|
||||
* Since GLib 2.72, #GUnixConnection is available on all platforms. It requires
|
||||
* underlying system support (such as Windows 10 with `AF_UNIX`) at run time.
|
||||
*
|
||||
* Before GLib 2.72, `<gio/gunixconnection.h>` belonged to the UNIX-specific GIO
|
||||
* interfaces, thus you had to use the `gio-unix-2.0.pc` pkg-config file when
|
||||
* using it. This is no longer necessary since GLib 2.72.
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
|
||||
/**
|
||||
* GUnixConnection:
|
||||
*
|
||||
* #GUnixConnection is an opaque data structure and can only be accessed
|
||||
* using the following functions.
|
||||
**/
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GUnixConnection, g_unix_connection,
|
||||
G_TYPE_SOCKET_CONNECTION,
|
||||
g_socket_connection_factory_register_type (g_define_type_id,
|
||||
G_SOCKET_FAMILY_UNIX,
|
||||
G_SOCKET_TYPE_STREAM,
|
||||
G_SOCKET_PROTOCOL_DEFAULT);
|
||||
);
|
||||
|
||||
/**
|
||||
* g_unix_connection_send_fd:
|
||||
* @connection: a #GUnixConnection
|
||||
* @fd: a file descriptor
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @error: (nullable): #GError for error reporting, or %NULL to ignore.
|
||||
*
|
||||
* Passes a file descriptor to the receiving side of the
|
||||
* connection. The receiving end has to call g_unix_connection_receive_fd()
|
||||
* to accept the file descriptor.
|
||||
*
|
||||
* As well as sending the fd this also writes a single byte to the
|
||||
* stream, as this is required for fd passing to work on some
|
||||
* implementations.
|
||||
*
|
||||
* Returns: a %TRUE on success, %NULL on error.
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
gboolean
|
||||
g_unix_connection_send_fd (GUnixConnection *connection,
|
||||
gint fd,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef G_OS_UNIX
|
||||
GSocketControlMessage *scm;
|
||||
GSocket *socket;
|
||||
|
||||
g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
|
||||
g_return_val_if_fail (fd >= 0, FALSE);
|
||||
|
||||
scm = g_unix_fd_message_new ();
|
||||
|
||||
if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (scm), fd, error))
|
||||
{
|
||||
g_object_unref (scm);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_get (connection, "socket", &socket, NULL);
|
||||
if (g_socket_send_message (socket, NULL, NULL, 0, &scm, 1, 0, cancellable, error) != 1)
|
||||
/* XXX could it 'fail' with zero? */
|
||||
{
|
||||
g_object_unref (socket);
|
||||
g_object_unref (scm);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_unref (socket);
|
||||
g_object_unref (scm);
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Sending FD is not supported"));
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_connection_receive_fd:
|
||||
* @connection: a #GUnixConnection
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
|
||||
* @error: (nullable): #GError for error reporting, or %NULL to ignore
|
||||
*
|
||||
* Receives a file descriptor from the sending end of the connection.
|
||||
* The sending end has to call g_unix_connection_send_fd() for this
|
||||
* to work.
|
||||
*
|
||||
* As well as reading the fd this also reads a single byte from the
|
||||
* stream, as this is required for fd passing to work on some
|
||||
* implementations.
|
||||
*
|
||||
* Returns: a file descriptor on success, -1 on error.
|
||||
*
|
||||
* Since: 2.22
|
||||
**/
|
||||
gint
|
||||
g_unix_connection_receive_fd (GUnixConnection *connection,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef G_OS_UNIX
|
||||
GSocketControlMessage **scms;
|
||||
gint *fds, nfd, fd, nscm;
|
||||
GUnixFDMessage *fdmsg;
|
||||
GSocket *socket;
|
||||
|
||||
g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), -1);
|
||||
|
||||
g_object_get (connection, "socket", &socket, NULL);
|
||||
if (g_socket_receive_message (socket, NULL, NULL, 0,
|
||||
&scms, &nscm, NULL, cancellable, error) != 1)
|
||||
/* XXX it _could_ 'fail' with zero. */
|
||||
{
|
||||
g_object_unref (socket);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_object_unref (socket);
|
||||
|
||||
if (nscm != 1)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
ngettext("Expecting 1 control message, got %d",
|
||||
"Expecting 1 control message, got %d",
|
||||
nscm),
|
||||
nscm);
|
||||
|
||||
for (i = 0; i < nscm; i++)
|
||||
g_object_unref (scms[i]);
|
||||
|
||||
g_free (scms);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!G_IS_UNIX_FD_MESSAGE (scms[0]))
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Unexpected type of ancillary data"));
|
||||
g_object_unref (scms[0]);
|
||||
g_free (scms);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
fdmsg = G_UNIX_FD_MESSAGE (scms[0]);
|
||||
g_free (scms);
|
||||
|
||||
fds = g_unix_fd_message_steal_fds (fdmsg, &nfd);
|
||||
g_object_unref (fdmsg);
|
||||
|
||||
if (nfd != 1)
|
||||
{
|
||||
gint i;
|
||||
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
ngettext("Expecting one fd, but got %d\n",
|
||||
"Expecting one fd, but got %d\n",
|
||||
nfd),
|
||||
nfd);
|
||||
|
||||
for (i = 0; i < nfd; i++)
|
||||
close (fds[i]);
|
||||
|
||||
g_free (fds);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = *fds;
|
||||
g_free (fds);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Received invalid fd"));
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
#else
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Receiving FD is not supported"));
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
g_unix_connection_init (GUnixConnection *connection)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
g_unix_connection_class_init (GUnixConnectionClass *class)
|
||||
{
|
||||
}
|
||||
|
||||
/* TODO: Other stuff we might want to add are:
|
||||
void g_unix_connection_send_fd_async (GUnixConnection *connection,
|
||||
gint fd,
|
||||
gboolean close,
|
||||
gint io_priority,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean g_unix_connection_send_fd_finish (GUnixConnection *connection,
|
||||
GError **error);
|
||||
|
||||
gboolean g_unix_connection_send_fds (GUnixConnection *connection,
|
||||
gint *fds,
|
||||
gint nfds,
|
||||
GError **error);
|
||||
void g_unix_connection_send_fds_async (GUnixConnection *connection,
|
||||
gint *fds,
|
||||
gint nfds,
|
||||
gint io_priority,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean g_unix_connection_send_fds_finish (GUnixConnection *connection,
|
||||
GError **error);
|
||||
|
||||
void g_unix_connection_receive_fd_async (GUnixConnection *connection,
|
||||
gint io_priority,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gint g_unix_connection_receive_fd_finish (GUnixConnection *connection,
|
||||
GError **error);
|
||||
|
||||
|
||||
gboolean g_unix_connection_send_fake_credentials (GUnixConnection *connection,
|
||||
guint64 pid,
|
||||
guint64 uid,
|
||||
guint64 gid,
|
||||
GError **error);
|
||||
void g_unix_connection_send_fake_credentials_async (GUnixConnection *connection,
|
||||
guint64 pid,
|
||||
guint64 uid,
|
||||
guint64 gid,
|
||||
gint io_priority,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean g_unix_connection_send_fake_credentials_finish (GUnixConnection *connection,
|
||||
GError **error);
|
||||
|
||||
gboolean g_unix_connection_create_pair (GUnixConnection **one,
|
||||
GUnixConnection **two,
|
||||
GError **error);
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* g_unix_connection_send_credentials:
|
||||
* @connection: A #GUnixConnection.
|
||||
* @cancellable: (nullable): A #GCancellable or %NULL.
|
||||
* @error: Return location for error or %NULL.
|
||||
*
|
||||
* Passes the credentials of the current user the receiving side
|
||||
* of the connection. The receiving end has to call
|
||||
* g_unix_connection_receive_credentials() (or similar) to accept the
|
||||
* credentials.
|
||||
*
|
||||
* As well as sending the credentials this also writes a single NUL
|
||||
* byte to the stream, as this is required for credentials passing to
|
||||
* work on some implementations.
|
||||
*
|
||||
* This method can be expected to be available on the following platforms:
|
||||
*
|
||||
* - Linux since GLib 2.26
|
||||
* - FreeBSD since GLib 2.26
|
||||
* - GNU/kFreeBSD since GLib 2.36
|
||||
* - Solaris, Illumos and OpenSolaris since GLib 2.40
|
||||
* - GNU/Hurd since GLib 2.40
|
||||
*
|
||||
* Other ways to exchange credentials with a foreign peer includes the
|
||||
* #GUnixCredentialsMessage type and g_socket_get_credentials() function.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE if @error is set.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
gboolean
|
||||
g_unix_connection_send_credentials (GUnixConnection *connection,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GCredentials *credentials;
|
||||
GSocketControlMessage *scm;
|
||||
GSocket *socket;
|
||||
gboolean ret;
|
||||
GOutputVector vector;
|
||||
guchar nul_byte[1] = {'\0'};
|
||||
gint num_messages;
|
||||
|
||||
g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
credentials = g_credentials_new ();
|
||||
|
||||
vector.buffer = &nul_byte;
|
||||
vector.size = 1;
|
||||
|
||||
if (g_unix_credentials_message_is_supported ())
|
||||
{
|
||||
scm = g_unix_credentials_message_new_with_credentials (credentials);
|
||||
num_messages = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
scm = NULL;
|
||||
num_messages = 0;
|
||||
}
|
||||
|
||||
g_object_get (connection, "socket", &socket, NULL);
|
||||
if (g_socket_send_message (socket,
|
||||
NULL, /* address */
|
||||
&vector,
|
||||
1,
|
||||
&scm,
|
||||
num_messages,
|
||||
G_SOCKET_MSG_NONE,
|
||||
cancellable,
|
||||
error) != 1)
|
||||
{
|
||||
g_prefix_error (error, _("Error sending credentials: "));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
g_object_unref (socket);
|
||||
if (scm != NULL)
|
||||
g_object_unref (scm);
|
||||
g_object_unref (credentials);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
send_credentials_async_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (g_unix_connection_send_credentials (G_UNIX_CONNECTION (source_object),
|
||||
cancellable,
|
||||
&error))
|
||||
g_task_return_boolean (task, TRUE);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_connection_send_credentials_async:
|
||||
* @connection: A #GUnixConnection.
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
*
|
||||
* Asynchronously send credentials.
|
||||
*
|
||||
* For more details, see g_unix_connection_send_credentials() which is
|
||||
* the synchronous version of this call.
|
||||
*
|
||||
* When the operation is finished, @callback will be called. You can then call
|
||||
* g_unix_connection_send_credentials_finish() to get the result of the operation.
|
||||
*
|
||||
* Since: 2.32
|
||||
**/
|
||||
void
|
||||
g_unix_connection_send_credentials_async (GUnixConnection *connection,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (connection, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, g_unix_connection_send_credentials_async);
|
||||
g_task_run_in_thread (task, send_credentials_async_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_connection_send_credentials_finish:
|
||||
* @connection: A #GUnixConnection.
|
||||
* @result: a #GAsyncResult.
|
||||
* @error: a #GError, or %NULL
|
||||
*
|
||||
* Finishes an asynchronous send credentials operation started with
|
||||
* g_unix_connection_send_credentials_async().
|
||||
*
|
||||
* Returns: %TRUE if the operation was successful, otherwise %FALSE.
|
||||
*
|
||||
* Since: 2.32
|
||||
**/
|
||||
gboolean
|
||||
g_unix_connection_send_credentials_finish (GUnixConnection *connection,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, connection), FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_connection_receive_credentials:
|
||||
* @connection: A #GUnixConnection.
|
||||
* @cancellable: (nullable): A #GCancellable or %NULL.
|
||||
* @error: Return location for error or %NULL.
|
||||
*
|
||||
* Receives credentials from the sending end of the connection. The
|
||||
* sending end has to call g_unix_connection_send_credentials() (or
|
||||
* similar) for this to work.
|
||||
*
|
||||
* As well as reading the credentials this also reads (and discards) a
|
||||
* single byte from the stream, as this is required for credentials
|
||||
* passing to work on some implementations.
|
||||
*
|
||||
* This method can be expected to be available on the following platforms:
|
||||
*
|
||||
* - Linux since GLib 2.26
|
||||
* - FreeBSD since GLib 2.26
|
||||
* - GNU/kFreeBSD since GLib 2.36
|
||||
* - Solaris, Illumos and OpenSolaris since GLib 2.40
|
||||
* - GNU/Hurd since GLib 2.40
|
||||
*
|
||||
* Other ways to exchange credentials with a foreign peer includes the
|
||||
* #GUnixCredentialsMessage type and g_socket_get_credentials() function.
|
||||
*
|
||||
* Returns: (transfer full): Received credentials on success (free with
|
||||
* g_object_unref()), %NULL if @error is set.
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
GCredentials *
|
||||
g_unix_connection_receive_credentials (GUnixConnection *connection,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GCredentials *ret;
|
||||
GSocketControlMessage **scms;
|
||||
gint nscm;
|
||||
GSocket *socket;
|
||||
gint n;
|
||||
gssize num_bytes_read;
|
||||
#ifdef __linux__
|
||||
gboolean turn_off_so_passcreds;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
ret = NULL;
|
||||
scms = NULL;
|
||||
|
||||
g_object_get (connection, "socket", &socket, NULL);
|
||||
|
||||
/* On Linux, we need to turn on SO_PASSCRED if it isn't enabled
|
||||
* already. We also need to turn it off when we're done. See
|
||||
* #617483 for more discussion.
|
||||
*/
|
||||
#ifdef __linux__
|
||||
{
|
||||
gint opt_val;
|
||||
|
||||
turn_off_so_passcreds = FALSE;
|
||||
opt_val = 0;
|
||||
if (!g_socket_get_option (socket,
|
||||
SOL_SOCKET,
|
||||
SO_PASSCRED,
|
||||
&opt_val,
|
||||
NULL))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errsv),
|
||||
_("Error checking if SO_PASSCRED is enabled for socket: %s"),
|
||||
g_strerror (errsv));
|
||||
goto out;
|
||||
}
|
||||
if (opt_val == 0)
|
||||
{
|
||||
if (!g_socket_set_option (socket,
|
||||
SOL_SOCKET,
|
||||
SO_PASSCRED,
|
||||
TRUE,
|
||||
NULL))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errsv),
|
||||
_("Error enabling SO_PASSCRED: %s"),
|
||||
g_strerror (errsv));
|
||||
goto out;
|
||||
}
|
||||
turn_off_so_passcreds = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
g_type_ensure (G_TYPE_UNIX_CREDENTIALS_MESSAGE);
|
||||
num_bytes_read = g_socket_receive_message (socket,
|
||||
NULL, /* GSocketAddress **address */
|
||||
NULL,
|
||||
0,
|
||||
&scms,
|
||||
&nscm,
|
||||
NULL,
|
||||
cancellable,
|
||||
error);
|
||||
if (num_bytes_read != 1)
|
||||
{
|
||||
/* Handle situation where g_socket_receive_message() returns
|
||||
* 0 bytes and not setting @error
|
||||
*/
|
||||
if (num_bytes_read == 0 && error != NULL && *error == NULL)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
_("Expecting to read a single byte for receiving credentials but read zero bytes"));
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_unix_credentials_message_is_supported () &&
|
||||
/* Fall back on get_credentials if the other side didn't send the credentials */
|
||||
nscm > 0)
|
||||
{
|
||||
if (nscm != 1)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
ngettext("Expecting 1 control message, got %d",
|
||||
"Expecting 1 control message, got %d",
|
||||
nscm),
|
||||
nscm);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!G_IS_UNIX_CREDENTIALS_MESSAGE (scms[0]))
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
_("Unexpected type of ancillary data"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = g_unix_credentials_message_get_credentials (G_UNIX_CREDENTIALS_MESSAGE (scms[0]));
|
||||
g_object_ref (ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nscm != 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
_("Not expecting control message, but got %d"),
|
||||
nscm);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = g_socket_get_credentials (socket, error);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
#ifdef __linux__
|
||||
if (turn_off_so_passcreds)
|
||||
{
|
||||
if (!g_socket_set_option (socket,
|
||||
SOL_SOCKET,
|
||||
SO_PASSCRED,
|
||||
FALSE,
|
||||
NULL))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errsv),
|
||||
_("Error while disabling SO_PASSCRED: %s"),
|
||||
g_strerror (errsv));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scms != NULL)
|
||||
{
|
||||
for (n = 0; n < nscm; n++)
|
||||
g_object_unref (scms[n]);
|
||||
g_free (scms);
|
||||
}
|
||||
g_object_unref (socket);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
receive_credentials_async_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GCredentials *creds;
|
||||
GError *error = NULL;
|
||||
|
||||
creds = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (source_object),
|
||||
cancellable,
|
||||
&error);
|
||||
if (creds)
|
||||
g_task_return_pointer (task, creds, g_object_unref);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_connection_receive_credentials_async:
|
||||
* @connection: A #GUnixConnection.
|
||||
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
|
||||
* @user_data: (closure): the data to pass to callback function
|
||||
*
|
||||
* Asynchronously receive credentials.
|
||||
*
|
||||
* For more details, see g_unix_connection_receive_credentials() which is
|
||||
* the synchronous version of this call.
|
||||
*
|
||||
* When the operation is finished, @callback will be called. You can then call
|
||||
* g_unix_connection_receive_credentials_finish() to get the result of the operation.
|
||||
*
|
||||
* Since: 2.32
|
||||
**/
|
||||
void
|
||||
g_unix_connection_receive_credentials_async (GUnixConnection *connection,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (connection, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, g_unix_connection_receive_credentials_async);
|
||||
g_task_run_in_thread (task, receive_credentials_async_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_connection_receive_credentials_finish:
|
||||
* @connection: A #GUnixConnection.
|
||||
* @result: a #GAsyncResult.
|
||||
* @error: a #GError, or %NULL
|
||||
*
|
||||
* Finishes an asynchronous receive credentials operation started with
|
||||
* g_unix_connection_receive_credentials_async().
|
||||
*
|
||||
* Returns: (transfer full): a #GCredentials, or %NULL on error.
|
||||
* Free the returned object with g_object_unref().
|
||||
*
|
||||
* Since: 2.32
|
||||
**/
|
||||
GCredentials *
|
||||
g_unix_connection_receive_credentials_finish (GUnixConnection *connection,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, connection), NULL);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue