Documentation and coding style fixups
[platform/upstream/glib.git] / gio / gunixsocketaddress.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2008 Christian Kellner, Samuel Cormier-Iijima
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Authors: Christian Kellner <gicmo@gnome.org>
21  *          Samuel Cormier-Iijima <sciyoshi@gmail.com>
22  */
23
24 #include <config.h>
25 #include <glib.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29
30 #include "gunixsocketaddress.h"
31 #include "glibintl.h"
32 #include "gnetworkingprivate.h"
33
34 #include "gioalias.h"
35
36 /**
37  * SECTION:gunixsocketaddress
38  * @short_description: Unix #GSocketAddress
39  *
40  * Support for UNIX-domain (aka local) sockets.
41  */
42
43 /**
44  * GUnixSocketAddress:
45  *
46  * A UNIX-domain (local) socket address, corresponding to a
47  * <type>struct sockaddr_un</type>.
48  */
49 G_DEFINE_TYPE (GUnixSocketAddress, g_unix_socket_address, G_TYPE_SOCKET_ADDRESS);
50
51 enum
52 {
53   PROP_0,
54   PROP_PATH,
55   PROP_PATH_AS_ARRAY,
56   PROP_ABSTRACT,
57 };
58
59 #define UNIX_PATH_MAX sizeof (((struct sockaddr_un *) 0)->sun_path)
60
61 struct _GUnixSocketAddressPrivate
62 {
63   char path[UNIX_PATH_MAX]; /* Not including the initial zero in abstract case, so
64                                we can guarantee zero termination of abstract
65                                pathnames in the get_path() API */
66   gsize path_len; /* Not including any terminating zeros */
67   gboolean abstract;
68 };
69
70 static void
71 g_unix_socket_address_set_property (GObject      *object,
72                                     guint         prop_id,
73                                     const GValue *value,
74                                     GParamSpec   *pspec)
75 {
76   GUnixSocketAddress *address = G_UNIX_SOCKET_ADDRESS (object);
77   const char *str;
78   GByteArray *array;
79   gsize len;
80
81   switch (prop_id)
82     {
83     case PROP_PATH:
84       str = g_value_get_string (value);
85       if (str)
86         {
87           g_strlcpy (address->priv->path, str,
88                      sizeof (address->priv->path));
89           address->priv->path_len = strlen (address->priv->path);
90         }
91       break;
92
93     case PROP_PATH_AS_ARRAY:
94       array = g_value_get_boxed (value);
95
96       if (array)
97         {
98           /* Clip to fit in UNIX_PATH_MAX with zero termination or first byte */
99           len = MIN (array->len, UNIX_PATH_MAX-1);
100
101           /* Remove any trailing zeros from path_len */
102           while (len > 0 && array->data[len-1] == 0)
103             len--;
104
105           memcpy (address->priv->path, array->data, len);
106           address->priv->path[len] = 0; /* Ensure null-terminated */
107           address->priv->path_len = len;
108         }
109       break;
110
111     case PROP_ABSTRACT:
112       address->priv->abstract = g_value_get_boolean (value);
113       break;
114
115     default:
116       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117     }
118 }
119
120 static void
121 g_unix_socket_address_get_property (GObject    *object,
122                                     guint       prop_id,
123                                     GValue     *value,
124                                     GParamSpec *pspec)
125 {
126   GUnixSocketAddress *address = G_UNIX_SOCKET_ADDRESS (object);
127   GByteArray *array;
128
129   switch (prop_id)
130     {
131       case PROP_PATH:
132         g_value_set_string (value, address->priv->path);
133         break;
134
135       case PROP_PATH_AS_ARRAY:
136         array = g_byte_array_sized_new (address->priv->path_len);
137         g_byte_array_append (array, (guint8 *)address->priv->path, address->priv->path_len);
138         g_value_take_boxed (value, array);
139         break;
140
141       case PROP_ABSTRACT:
142         g_value_set_boolean (value, address->priv->abstract);
143         break;
144
145       default:
146         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
147     }
148 }
149
150 static GSocketFamily
151 g_unix_socket_address_get_family (GSocketAddress *address)
152 {
153   g_assert (PF_UNIX == G_SOCKET_FAMILY_UNIX);
154
155   return G_SOCKET_FAMILY_UNIX;
156 }
157
158 static gssize
159 g_unix_socket_address_get_native_size (GSocketAddress *address)
160 {
161   return sizeof (struct sockaddr_un);
162 }
163
164 static gboolean
165 g_unix_socket_address_to_native (GSocketAddress *address,
166                                  gpointer        dest,
167                                  gsize           destlen,
168                                  GError        **error)
169 {
170   GUnixSocketAddress *addr = G_UNIX_SOCKET_ADDRESS (address);
171   struct sockaddr_un *sock;
172
173   if (destlen < sizeof (*sock))
174     {
175       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
176                            _("Not enough space for socket address"));
177       return FALSE;
178     }
179
180   if (addr->priv->abstract &&
181       !g_unix_socket_address_abstract_names_supported ())
182     {
183       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
184                            _("Abstract unix domain socket addresses not supported on this system"));
185       return FALSE;
186     }
187
188   sock = (struct sockaddr_un *) dest;
189   sock->sun_family = AF_UNIX;
190   memset (sock->sun_path, 0, sizeof (sock->sun_path));
191   if (addr->priv->abstract)
192     {
193       sock->sun_path[0] = 0;
194       memcpy (sock->sun_path+1, addr->priv->path, addr->priv->path_len);
195     }
196   else
197     strcpy (sock->sun_path, addr->priv->path);
198
199   return TRUE;
200 }
201
202 static void
203 g_unix_socket_address_class_init (GUnixSocketAddressClass *klass)
204 {
205   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
206   GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass);
207
208   g_type_class_add_private (klass, sizeof (GUnixSocketAddressPrivate));
209
210   gobject_class->set_property = g_unix_socket_address_set_property;
211   gobject_class->get_property = g_unix_socket_address_get_property;
212
213   gsocketaddress_class->get_family = g_unix_socket_address_get_family;
214   gsocketaddress_class->to_native = g_unix_socket_address_to_native;
215   gsocketaddress_class->get_native_size = g_unix_socket_address_get_native_size;
216
217   g_object_class_install_property (gobject_class,
218                                    PROP_PATH,
219                                    g_param_spec_string ("path",
220                                                         P_("Path"),
221                                                         P_("UNIX socket path"),
222                                                         NULL,
223                                                         G_PARAM_READWRITE |
224                                                         G_PARAM_CONSTRUCT_ONLY |
225                                                         G_PARAM_STATIC_STRINGS));
226   g_object_class_install_property (gobject_class, PROP_PATH_AS_ARRAY,
227                                    g_param_spec_boxed ("path-as-array",
228                                                        P_("Path array"),
229                                                        P_("UNIX socket path, as byte array"),
230                                                        G_TYPE_BYTE_ARRAY,
231                                                        G_PARAM_READWRITE |
232                                                        G_PARAM_CONSTRUCT_ONLY |
233                                                        G_PARAM_STATIC_STRINGS));
234   g_object_class_install_property (gobject_class, PROP_ABSTRACT,
235                                    g_param_spec_boolean ("abstract",
236                                                          P_("Abstract"),
237                                                          P_("Whether or not this is an abstract address"),
238                                                          FALSE,
239                                                          G_PARAM_READWRITE |
240                                                          G_PARAM_CONSTRUCT_ONLY |
241                                                          G_PARAM_STATIC_STRINGS));
242 }
243
244 static void
245 g_unix_socket_address_init (GUnixSocketAddress *address)
246 {
247   address->priv = G_TYPE_INSTANCE_GET_PRIVATE (address,
248                                                G_TYPE_UNIX_SOCKET_ADDRESS,
249                                                GUnixSocketAddressPrivate);
250
251   memset (address->priv->path, 0, sizeof (address->priv->path));
252   address->priv->path_len = -1;
253 }
254
255 /**
256  * g_unix_socket_address_new:
257  * @path: the socket path
258  *
259  * Creates a new #GUnixSocketAddress for @path.
260  *
261  * To create abstract socket addresses, on systems that support that,
262  * use g_unix_socket_address_new_abstract().
263  *
264  * Returns: a new #GUnixSocketAddress
265  *
266  * Since: 2.22
267  */
268 GSocketAddress *
269 g_unix_socket_address_new (const gchar *path)
270 {
271   return g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
272                        "path", path,
273                        "abstract", FALSE,
274                        NULL);
275 }
276
277 /**
278  * g_unix_socket_address_new_abstract:
279  * @path: the abstract name
280  * @path_len: the length of @path, or -1
281  *
282  * Creates a new abstract #GUnixSocketAddress for @path.
283  *
284  * Unix domain sockets are generally visible in the filesystem. However, some
285  * systems support abstract socket name which are not visible in the
286  * filesystem and not affected by the filesystem permissions, visibility, etc.
287  *
288  * Note that not all systems (really only Linux) support abstract
289  * socket names, so if you use them on other systems function calls may
290  * return %G_IO_ERROR_NOT_SUPPORTED errors. You can use
291  * g_unix_socket_address_abstract_names_supported() to see if abstract
292  * names are supported.
293  *
294  * If @path_len is -1 then @path is assumed to be a zero terminated
295  * string (although in general abstract names need not be zero terminated
296  * and can have embedded nuls). All bytes after @path_len up to the max size
297  * of an abstract unix domain name is filled with zero bytes.
298  *
299  * Returns: a new #GUnixSocketAddress
300  *
301  * Since: 2.22
302  */
303 GSocketAddress *
304 g_unix_socket_address_new_abstract (const gchar *path,
305                                     int path_len)
306 {
307   GSocketAddress *address;
308   GByteArray *array;
309
310   if (path_len == -1)
311     path_len = strlen (path);
312
313   array = g_byte_array_sized_new (path_len);
314
315   g_byte_array_append (array, (guint8 *)path, path_len);
316
317   address = g_object_new (G_TYPE_UNIX_SOCKET_ADDRESS,
318                           "path-as-array", array,
319                           "abstract", TRUE,
320                           NULL);
321
322   g_byte_array_unref (array);
323
324   return address;
325 }
326
327 /**
328  * g_unix_socket_address_get_path:
329  * @address: a #GInetSocketAddress
330  *
331  * Gets @address's path, or for abstract sockets the "name".
332  *
333  * Guaranteed to be zero-terminated, but an abstract socket
334  * may contain embedded zeros, and thus you should use
335  * g_unix_socket_address_get_path_len() to get the true length
336  * of this string.
337  *
338  * Returns: the path for @address
339  *
340  * Since: 2.22
341  */
342 const char *
343 g_unix_socket_address_get_path (GUnixSocketAddress *address)
344 {
345   return address->priv->path;
346 }
347
348 /**
349  * g_unix_socket_address_get_path_len:
350  * @address: a #GInetSocketAddress
351  *
352  * Gets the length of @address's path.
353  *
354  * For details, see g_unix_socket_address_get_path().
355  *
356  * Returns: the length of the path
357  *
358  * Since: 2.22
359  */
360 gsize
361 g_unix_socket_address_get_path_len (GUnixSocketAddress *address)
362 {
363   return address->priv->path_len;
364 }
365
366 /**
367  * g_unix_socket_address_get_is_abstract:
368  * @address: a #GInetSocketAddress
369  *
370  * Gets @address's path.
371  *
372  * Returns: %TRUE if the address is abstract, %FALSE otherwise
373  *
374  * Since: 2.22
375  */
376 gboolean
377 g_unix_socket_address_get_is_abstract (GUnixSocketAddress *address)
378 {
379   return address->priv->abstract;
380 }
381
382 /**
383  * g_unix_socket_address_abstract_names_supported:
384  *
385  * Checks if abstract unix domain socket names are supported.
386  *
387  * Returns: %TRUE if supported, %FALSE otherwise
388  *
389  * Since: 2.22
390  */
391 gboolean
392 g_unix_socket_address_abstract_names_supported (void)
393 {
394 #ifdef __linux__
395   return TRUE;
396 #else
397   return FALSE;
398 #endif
399 }
400
401 #define __G_UNIX_SOCKET_ADDRESS_C__
402 #include "gioaliasdef.c"