Merge remote branch 'gvdb/master'
[platform/upstream/glib.git] / gio / gunixconnection.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright © 2009 Codethink Limited
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; either version 2 of the licence or (at
8  * your option) any later version.
9  *
10  * See the included COPYING file for more information.
11  *
12  * Authors: Ryan Lortie <desrt@desrt.ca>
13  */
14
15 #include "config.h"
16 #include "gunixconnection.h"
17 #include "glibintl.h"
18
19 /**
20  * SECTION: gunixconnection
21  * @title: GUnixConnection
22  * @short_description: a Unix domain #GSocketConnection
23  * @see_also: #GSocketConnection.
24  *
25  * This is the subclass of #GSocketConnection that is created
26  * for UNIX domain sockets.
27  *
28  * It contains functions to do some of the unix socket specific
29  * functionallity like passing file descriptors.
30  *
31  * Since: 2.22
32  */
33
34 #include <gio/gsocketcontrolmessage.h>
35 #include <gio/gunixfdmessage.h>
36 #include <gio/gsocket.h>
37 #include <unistd.h>
38
39 #include "gioalias.h"
40
41 G_DEFINE_TYPE_WITH_CODE (GUnixConnection, g_unix_connection,
42                          G_TYPE_SOCKET_CONNECTION,
43   g_socket_connection_factory_register_type (g_define_type_id,
44                                              G_SOCKET_FAMILY_UNIX,
45                                              G_SOCKET_TYPE_STREAM,
46                                              G_SOCKET_PROTOCOL_DEFAULT);
47                          );
48
49 /**
50  * g_unix_connection_send_fd:
51  * @connection: a #GUnixConnection
52  * @fd: a file descriptor
53  * @cancellable: optional #GCancellable object, %NULL to ignore.
54  * @error: #GError for error reporting, or %NULL to ignore.
55  *
56  * Passes a file descriptor to the recieving side of the
57  * connection. The recieving end has to call g_unix_connection_receive_fd()
58  * to accept the file descriptor.
59  *
60  * As well as sending the fd this also writes a single byte to the
61  * stream, as this is required for fd passing to work on some
62  * implementations.
63  *
64  * Returns: a %TRUE on success, %NULL on error.
65  *
66  * Since: 2.22
67  */
68 gboolean
69 g_unix_connection_send_fd (GUnixConnection  *connection,
70                            gint              fd,
71                            GCancellable     *cancellable,
72                            GError          **error)
73 {
74   GSocketControlMessage *scm;
75   GSocket *socket;
76
77   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), FALSE);
78   g_return_val_if_fail (fd >= 0, FALSE);
79
80   scm = g_unix_fd_message_new ();
81
82   if (!g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (scm), fd, error))
83     {
84       g_object_unref (scm);
85       return FALSE;
86     }
87
88   g_object_get (connection, "socket", &socket, NULL);
89   if (g_socket_send_message (socket, NULL, NULL, 0, &scm, 1, 0, cancellable, error) != 1)
90     /* XXX could it 'fail' with zero? */
91     {
92       g_object_unref (socket);
93       g_object_unref (scm);
94
95       return FALSE;
96     }
97
98   g_object_unref (socket);
99   g_object_unref (scm);
100
101   return TRUE;
102 }
103
104 /**
105  * g_unix_connection_receive_fd:
106  * @connection: a #GUnixConnection
107  * @cancellable: optional #GCancellable object, %NULL to ignore
108  * @error: #GError for error reporting, or %NULL to ignore
109  *
110  * Receives a file descriptor from the sending end of the connection.
111  * The sending end has to call g_unix_connection_send_fd() for this
112  * to work.
113  *
114  * As well as reading the fd this also reads a single byte from the
115  * stream, as this is required for fd passing to work on some
116  * implementations.
117  *
118  * Returns: a file descriptor on success, -1 on error.
119  *
120  * Since: 2.22
121  */
122 gint
123 g_unix_connection_receive_fd (GUnixConnection  *connection,
124                               GCancellable     *cancellable,
125                               GError          **error)
126 {
127   GSocketControlMessage **scms;
128   gint *fds, nfd, fd, nscm;
129   GUnixFDMessage *fdmsg;
130   GSocket *socket;
131
132   g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), -1);
133
134   g_object_get (connection, "socket", &socket, NULL);
135   if (g_socket_receive_message (socket, NULL, NULL, 0,
136                                 &scms, &nscm, NULL, cancellable, error) != 1)
137     /* XXX it _could_ 'fail' with zero. */
138     {
139       g_object_unref (socket);
140
141       return -1;
142     }
143
144   g_object_unref (socket);
145
146   if (nscm != 1)
147     {
148       gint i;
149
150       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
151                    _("Expecting 1 control message, got %d"), nscm);
152
153       for (i = 0; i < nscm; i++)
154         g_object_unref (scms[i]);
155
156       g_free (scms);
157
158       return -1;
159     }
160
161   if (!G_IS_UNIX_FD_MESSAGE (scms[0]))
162     {
163       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
164                            _("Unexpected type of ancillary data"));
165       g_object_unref (scms[0]);
166       g_free (scms);
167
168       return -1;
169     }
170
171   fdmsg = G_UNIX_FD_MESSAGE (scms[0]);
172   g_free (scms);
173
174   fds = g_unix_fd_message_steal_fds (fdmsg, &nfd);
175   g_object_unref (fdmsg);
176
177   if (nfd != 1)
178     {
179       gint i;
180
181       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
182                    _("Expecting one fd, but got %d\n"), nfd);
183
184       for (i = 0; i < nfd; i++)
185         close (fds[i]);
186
187       g_free (fds);
188
189       return -1;
190     }
191
192   fd = *fds;
193   g_free (fds);
194
195   if (fd < 0)
196     {
197       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
198                            _("Received invalid fd"));
199       fd = -1;
200     }
201
202   return fd;
203 }
204
205 static void
206 g_unix_connection_init (GUnixConnection *connection)
207 {
208 }
209
210 static void
211 g_unix_connection_class_init (GUnixConnectionClass *class)
212 {
213 }
214
215 /* TODO: Other stuff we might want to add are:
216 void                    g_unix_connection_send_fd_async                 (GUnixConnection      *connection,
217                                                                          gint                  fd,
218                                                                          gboolean              close,
219                                                                          gint                  io_priority,
220                                                                          GAsyncReadyCallback   callback,
221                                                                          gpointer              user_data);
222 gboolean                g_unix_connection_send_fd_finish                (GUnixConnection      *connection,
223                                                                          GError              **error);
224
225 gboolean                g_unix_connection_send_fds                      (GUnixConnection      *connection,
226                                                                          gint                 *fds,
227                                                                          gint                  nfds,
228                                                                          GError              **error);
229 void                    g_unix_connection_send_fds_async                (GUnixConnection      *connection,
230                                                                          gint                 *fds,
231                                                                          gint                  nfds,
232                                                                          gint                  io_priority,
233                                                                          GAsyncReadyCallback   callback,
234                                                                          gpointer              user_data);
235 gboolean                g_unix_connection_send_fds_finish               (GUnixConnection      *connection,
236                                                                          GError              **error);
237
238 void                    g_unix_connection_receive_fd_async              (GUnixConnection      *connection,
239                                                                          gint                  io_priority,
240                                                                          GAsyncReadyCallback   callback,
241                                                                          gpointer              user_data);
242 gint                    g_unix_connection_receive_fd_finish             (GUnixConnection      *connection,
243                                                                          GError              **error);
244
245
246 gboolean                g_unix_connection_send_credentials              (GUnixConnection      *connection,
247                                                                          GError              **error);
248 void                    g_unix_connection_send_credentials_async        (GUnixConnection      *connection,
249                                                                          gint                  io_priority,
250                                                                          GAsyncReadyCallback   callback,
251                                                                          gpointer              user_data);
252 gboolean                g_unix_connection_send_credentials_finish       (GUnixConnection      *connection,
253                                                                          GError              **error);
254
255 gboolean                g_unix_connection_send_fake_credentials         (GUnixConnection      *connection,
256                                                                          guint64               pid,
257                                                                          guint64               uid,
258                                                                          guint64               gid,
259                                                                          GError              **error);
260 void                    g_unix_connection_send_fake_credentials_async   (GUnixConnection      *connection,
261                                                                          guint64               pid,
262                                                                          guint64               uid,
263                                                                          guint64               gid,
264                                                                          gint                  io_priority,
265                                                                          GAsyncReadyCallback   callback,
266                                                                          gpointer              user_data);
267 gboolean                g_unix_connection_send_fake_credentials_finish  (GUnixConnection      *connection,
268                                                                          GError              **error);
269
270 gboolean                g_unix_connection_receive_credentials           (GUnixConnection      *connection,
271                                                                          guint64              *pid,
272                                                                          guint64              *uid,
273                                                                          guint64              *gid,
274                                                                          GError              **error);
275 void                    g_unix_connection_receive_credentials_async     (GUnixConnection      *connection,
276                                                                          gint                  io_priority,
277                                                                          GAsyncReadyCallback   callback,
278                                                                          gpointer              user_data);
279 gboolean                g_unix_connection_receive_credentials_finish    (GUnixConnection      *connection,
280                                                                          guint64              *pid,
281                                                                          guint64              *uid,
282                                                                          guint64              *gid,
283                                                                          GError              **error);
284
285 gboolean                g_unix_connection_create_pair                   (GUnixConnection     **one,
286                                                                          GUnixConnection     **two,
287                                                                          GError              **error);
288 */
289
290 #define __G_UNIX_CONNECTION_C__
291 #include "gioaliasdef.c"