GDBus: Handle autolaunching on UNIX/Freedesktop OSes
[platform/upstream/glib.git] / gio / gdbusmessage.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
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  * Author: David Zeuthen <davidz@redhat.com>
21  */
22
23 /* Uncomment to debug serializer code */
24 /* #define DEBUG_SERIALIZER */
25
26 #include "config.h"
27
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #include "gdbusutils.h"
37 #include "gdbusmessage.h"
38 #include "gdbuserror.h"
39 #include "gioenumtypes.h"
40 #include "ginputstream.h"
41 #include "gdatainputstream.h"
42 #include "gmemoryinputstream.h"
43 #include "goutputstream.h"
44 #include "gdataoutputstream.h"
45 #include "gmemoryoutputstream.h"
46 #include "gseekable.h"
47 #include "gioerror.h"
48 #include "gdbusprivate.h"
49
50 #ifdef G_OS_UNIX
51 #include "gunixfdlist.h"
52 #endif
53
54 #include "glibintl.h"
55 #include "gioalias.h"
56
57 /**
58  * SECTION:gdbusmessage
59  * @short_description: D-Bus Message
60  * @include: gio/gio.h
61  *
62  * A type for representing D-Bus messages that can be sent or received
63  * on a #GDBusConnection.
64  */
65
66 struct _GDBusMessagePrivate
67 {
68   GDBusMessageType type;
69   GDBusMessageFlags flags;
70   guchar major_protocol_version;
71   guint32 serial;
72   GHashTable *headers;
73   GVariant *body;
74 #ifdef G_OS_UNIX
75   GUnixFDList *fd_list;
76 #endif
77 };
78
79 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT);
80
81 static void
82 g_dbus_message_finalize (GObject *object)
83 {
84   GDBusMessage *message = G_DBUS_MESSAGE (object);
85
86   if (message->priv->headers != NULL)
87     g_hash_table_unref (message->priv->headers);
88   if (message->priv->body != NULL)
89     g_variant_unref (message->priv->body);
90 #ifdef G_OS_UNIX
91   if (message->priv->fd_list != NULL)
92     g_object_unref (message->priv->fd_list);
93 #endif
94
95   if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
96     G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
97 }
98
99 static void
100 g_dbus_message_class_init (GDBusMessageClass *klass)
101 {
102   GObjectClass *gobject_class;
103
104   g_type_class_add_private (klass, sizeof (GDBusMessagePrivate));
105
106   gobject_class = G_OBJECT_CLASS (klass);
107
108   gobject_class->finalize     = g_dbus_message_finalize;
109 }
110
111 static void
112 g_dbus_message_init (GDBusMessage *message)
113 {
114   message->priv = G_TYPE_INSTANCE_GET_PRIVATE (message, G_TYPE_DBUS_MESSAGE, GDBusMessagePrivate);
115
116   message->priv->headers = g_hash_table_new_full (g_direct_hash,
117                                                   g_direct_equal,
118                                                   NULL,
119                                                   (GDestroyNotify) g_variant_unref);
120 }
121
122 /**
123  * g_dbus_message_new:
124  *
125  * Creates a new empty #GDBusMessage.
126  *
127  * Returns: A #GDBusMessage. Free with g_object_unref().
128  *
129  * Since: 2.26
130  */
131 GDBusMessage *
132 g_dbus_message_new (void)
133 {
134   return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
135 }
136
137 /**
138  * g_dbus_message_new_method_call:
139  * @name: A valid D-Bus name or %NULL.
140  * @path: A valid object path.
141  * @interface_: A valid D-Bus interface name or %NULL.
142  * @method: A valid method name.
143  *
144  * Creates a new #GDBusMessage for a method call.
145  *
146  * Returns: A #GDBusMessage. Free with g_object_unref().
147  *
148  * Since: 2.26
149  */
150 GDBusMessage *
151 g_dbus_message_new_method_call (const gchar *name,
152                                 const gchar *path,
153                                 const gchar *interface_,
154                                 const gchar *method)
155 {
156   GDBusMessage *message;
157
158   g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
159   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
160   g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
161   g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
162
163   message = g_dbus_message_new ();
164   message->priv->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
165
166   if (name != NULL)
167     g_dbus_message_set_destination (message, name);
168   g_dbus_message_set_path (message, path);
169   g_dbus_message_set_member (message, method);
170   if (interface_ != NULL)
171     g_dbus_message_set_interface (message, interface_);
172
173   return message;
174 }
175
176 /**
177  * g_dbus_message_new_signal:
178  * @path: A valid object path.
179  * @interface_: A valid D-Bus interface name or %NULL.
180  * @signal: A valid signal name.
181  *
182  * Creates a new #GDBusMessage for a signal emission.
183  *
184  * Returns: A #GDBusMessage. Free with g_object_unref().
185  *
186  * Since: 2.26
187  */
188 GDBusMessage *
189 g_dbus_message_new_signal (const gchar  *path,
190                            const gchar  *interface_,
191                            const gchar  *signal)
192 {
193   GDBusMessage *message;
194
195   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
196   g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
197   g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
198
199   message = g_dbus_message_new ();
200   message->priv->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
201   message->priv->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
202
203   g_dbus_message_set_path (message, path);
204   g_dbus_message_set_member (message, signal);
205
206   if (interface_ != NULL)
207     g_dbus_message_set_interface (message, interface_);
208
209   return message;
210 }
211
212
213 /**
214  * g_dbus_message_new_method_reply:
215  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
216  * create a reply message to.
217  *
218  * Creates a new #GDBusMessage that is a reply to @method_call_message.
219  *
220  * Returns: A #GDBusMessage. Free with g_object_unref().
221  *
222  * Since: 2.26
223  */
224 GDBusMessage *
225 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
226 {
227   GDBusMessage *message;
228   const gchar *sender;
229
230   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
231   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
232   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
233
234   message = g_dbus_message_new ();
235   message->priv->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
236   message->priv->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
237
238   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
239   sender = g_dbus_message_get_sender (method_call_message);
240   if (sender != NULL)
241     g_dbus_message_set_destination (message, sender);
242
243   return message;
244 }
245
246 /**
247  * g_dbus_message_new_method_error:
248  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
249  * create a reply message to.
250  * @error_name: A valid D-Bus error name.
251  * @error_message_format: The D-Bus error message in a printf() format.
252  * @...: Arguments for @error_message_format.
253  *
254  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
255  *
256  * Returns: A #GDBusMessage. Free with g_object_unref().
257  *
258  * Since: 2.26
259  */
260 GDBusMessage *
261 g_dbus_message_new_method_error (GDBusMessage             *method_call_message,
262                                  const gchar              *error_name,
263                                  const gchar              *error_message_format,
264                                  ...)
265 {
266   GDBusMessage *ret;
267   va_list var_args;
268
269   va_start (var_args, error_message_format);
270   ret = g_dbus_message_new_method_error_valist (method_call_message,
271                                                 error_name,
272                                                 error_message_format,
273                                                 var_args);
274   va_end (var_args);
275
276   return ret;
277 }
278
279 /**
280  * g_dbus_message_new_method_error_literal:
281  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
282  * create a reply message to.
283  * @error_name: A valid D-Bus error name.
284  * @error_message: The D-Bus error message.
285  *
286  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
287  *
288  * Returns: A #GDBusMessage. Free with g_object_unref().
289  *
290  * Since: 2.26
291  */
292 GDBusMessage *
293 g_dbus_message_new_method_error_literal (GDBusMessage  *method_call_message,
294                                          const gchar   *error_name,
295                                          const gchar   *error_message)
296 {
297   GDBusMessage *message;
298   const gchar *sender;
299
300   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
301   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
302   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
303   g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
304   g_return_val_if_fail (error_message != NULL, NULL);
305
306   message = g_dbus_message_new ();
307   message->priv->type = G_DBUS_MESSAGE_TYPE_ERROR;
308   message->priv->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
309
310   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
311   g_dbus_message_set_error_name (message, error_name);
312   g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
313
314   sender = g_dbus_message_get_sender (method_call_message);
315   if (sender != NULL)
316     g_dbus_message_set_destination (message, sender);
317
318   return message;
319 }
320
321 /**
322  * g_dbus_message_new_method_error_valist:
323  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
324  * create a reply message to.
325  * @error_name: A valid D-Bus error name.
326  * @error_message_format: The D-Bus error message in a printf() format.
327  * @var_args: Arguments for @error_message_format.
328  *
329  * Like g_dbus_message_new_method_error() but intended for language bindings.
330  *
331  * Returns: A #GDBusMessage. Free with g_object_unref().
332  *
333  * Since: 2.26
334  */
335 GDBusMessage *
336 g_dbus_message_new_method_error_valist (GDBusMessage             *method_call_message,
337                                         const gchar              *error_name,
338                                         const gchar              *error_message_format,
339                                         va_list                   var_args)
340 {
341   GDBusMessage *ret;
342   gchar *error_message;
343   error_message = g_strdup_vprintf (error_message_format, var_args);
344   ret = g_dbus_message_new_method_error_literal (method_call_message,
345                                                  error_name,
346                                                  error_message);
347   g_free (error_message);
348   return ret;
349 }
350
351 /* ---------------------------------------------------------------------------------------------------- */
352
353 /* TODO: need GI annotations to specify that any guchar value goes for the type */
354
355 /**
356  * g_dbus_message_get_message_type:
357  * @message: A #GDBusMessage.
358  *
359  * Gets the type of @message.
360  *
361  * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
362  *
363  * Since: 2.26
364  */
365 GDBusMessageType
366 g_dbus_message_get_message_type (GDBusMessage  *message)
367 {
368   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
369   return message->priv->type;
370 }
371
372 /**
373  * g_dbus_message_set_message_type:
374  * @message: A #GDBusMessage.
375  * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
376  *
377  * Sets @message to be of @type.
378  *
379  * Since: 2.26
380  */
381 void
382 g_dbus_message_set_message_type (GDBusMessage      *message,
383                                  GDBusMessageType   type)
384 {
385   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
386   g_return_if_fail (type >=0 && type < 256);
387   message->priv->type = type;
388 }
389
390 /* ---------------------------------------------------------------------------------------------------- */
391
392 /* TODO: need GI annotations to specify that any guchar value goes for flags */
393
394 /**
395  * g_dbus_message_get_flags:
396  * @message: A #GDBusMessage.
397  *
398  * Gets the flags for @message.
399  *
400  * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
401  *
402  * Since: 2.26
403  */
404 GDBusMessageFlags
405 g_dbus_message_get_flags (GDBusMessage  *message)
406 {
407   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
408   return message->priv->flags;
409 }
410
411 /**
412  * g_dbus_message_set_flags:
413  * @message: A #GDBusMessage.
414  * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
415  * enumeration bitwise ORed together).
416  *
417  * Sets the flags to set on @message.
418  *
419  * Since: 2.26
420  */
421 void
422 g_dbus_message_set_flags (GDBusMessage       *message,
423                           GDBusMessageFlags   flags)
424 {
425   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
426   g_return_if_fail (flags >=0 && flags < 256);
427   message->priv->flags = flags;
428 }
429
430 /* ---------------------------------------------------------------------------------------------------- */
431
432 /**
433  * g_dbus_message_get_serial:
434  * @message: A #GDBusMessage.
435  *
436  * Gets the serial for @message.
437  *
438  * Returns: A #guint32.
439  *
440  * Since: 2.26
441  */
442 guint32
443 g_dbus_message_get_serial (GDBusMessage *message)
444 {
445   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
446   return message->priv->serial;
447 }
448
449 /**
450  * g_dbus_message_set_serial:
451  * @message: A #GDBusMessage.
452  * @serial: A #guint32.
453  *
454  * Sets the serial for @message.
455  *
456  * Since: 2.26
457  */
458 void
459 g_dbus_message_set_serial (GDBusMessage  *message,
460                            guint32        serial)
461 {
462   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
463   message->priv->serial = serial;
464 }
465
466 /* ---------------------------------------------------------------------------------------------------- */
467
468 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
469
470 /**
471  * g_dbus_message_get_header:
472  * @message: A #GDBusMessage.
473  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
474  *
475  * Gets a header field on @message.
476  *
477  * Returns: A #GVariant with the value if the header was found, %NULL
478  * otherwise. Do not free, it is owned by @message.
479  *
480  * Since: 2.26
481  */
482 GVariant *
483 g_dbus_message_get_header (GDBusMessage             *message,
484                            GDBusMessageHeaderField   header_field)
485 {
486   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
487   g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
488   return g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
489 }
490
491 /**
492  * g_dbus_message_set_header:
493  * @message: A #GDBusMessage.
494  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
495  * @value: A #GVariant to set the header field or %NULL to clear the header field.
496  *
497  * Sets a header field on @message.
498  *
499  * If @value is floating, @message assumes ownership of @value.
500  *
501  * Since: 2.26
502  */
503 void
504 g_dbus_message_set_header (GDBusMessage             *message,
505                            GDBusMessageHeaderField   header_field,
506                            GVariant                 *value)
507 {
508   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
509   g_return_if_fail (header_field >=0 && header_field < 256);
510   if (value == NULL)
511     {
512       g_hash_table_remove (message->priv->headers, GUINT_TO_POINTER (header_field));
513     }
514   else
515     {
516       g_hash_table_insert (message->priv->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
517     }
518 }
519
520 /**
521  * g_dbus_message_get_header_fields:
522  * @message: A #GDBusMessage.
523  *
524  * Gets an array of all header fields on @message that are set.
525  *
526  * Returns: An array of header fields terminated by
527  * %G_DBUS_MESSAGE_HEADER_FIELD_INVALID.  Each element is a
528  * #guchar. Free with g_free().
529  *
530  * Since: 2.26
531  */
532 guchar *
533 g_dbus_message_get_header_fields (GDBusMessage  *message)
534 {
535   GList *keys;
536   guchar *ret;
537   guint num_keys;
538   GList *l;
539   guint n;
540
541   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
542
543   keys = g_hash_table_get_keys (message->priv->headers);
544   num_keys = g_list_length (keys);
545   ret = g_new (guchar, num_keys + 1);
546   for (l = keys, n = 0; l != NULL; l = l->next, n++)
547     ret[n] = GPOINTER_TO_UINT (l->data);
548   g_assert (n == num_keys);
549   ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
550   g_list_free (keys);
551
552   return ret;
553 }
554
555 /* ---------------------------------------------------------------------------------------------------- */
556
557 /**
558  * g_dbus_message_get_body:
559  * @message: A #GDBusMessage.
560  *
561  * Gets the body of a message.
562  *
563  * Returns: A #GVariant or %NULL if the body is empty. Do not free, it is owned by @message.
564  *
565  * Since: 2.26
566  */
567 GVariant *
568 g_dbus_message_get_body (GDBusMessage  *message)
569 {
570   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
571   return message->priv->body;
572 }
573
574 /**
575  * g_dbus_message_set_body:
576  * @message: A #GDBusMessage.
577  * @body: Either %NULL or a #GVariant that is a tuple.
578  *
579  * Sets the body @message. As a side-effect the
580  * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
581  * type string of @body (or cleared if @body is %NULL).
582  *
583  * If @body is floating, @message assumes ownership of @body.
584  *
585  * Since: 2.26
586  */
587 void
588 g_dbus_message_set_body (GDBusMessage  *message,
589                          GVariant      *body)
590 {
591   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
592   g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
593
594   if (message->priv->body != NULL)
595     g_variant_unref (message->priv->body);
596   if (body == NULL)
597     {
598       message->priv->body = NULL;
599       g_dbus_message_set_signature (message, NULL);
600     }
601   else
602     {
603       const gchar *type_string;
604       gsize type_string_len;
605       gchar *signature;
606
607       message->priv->body = g_variant_ref_sink (body);
608
609       type_string = g_variant_get_type_string (body);
610       type_string_len = strlen (type_string);
611       g_assert (type_string_len >= 2);
612       signature = g_strndup (type_string + 1, type_string_len - 2);
613       g_dbus_message_set_signature (message, signature);
614       g_free (signature);
615     }
616 }
617
618 /* ---------------------------------------------------------------------------------------------------- */
619
620 #ifdef G_OS_UNIX
621 /**
622  * g_dbus_message_get_unix_fd_list:
623  * @message: A #GDBusMessage.
624  *
625  * Gets the UNIX file descriptors associated with @message, if any.
626  *
627  * This method is only available on UNIX.
628  *
629  * Returns: A #GUnixFDList or %NULL if no file descriptors are
630  * associated. Do not free, this object is owned by @message.
631  *
632  * Since: 2.26
633  */
634 GUnixFDList *
635 g_dbus_message_get_unix_fd_list (GDBusMessage  *message)
636 {
637   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
638   return message->priv->fd_list;
639 }
640
641 /**
642  * g_dbus_message_set_unix_fd_list:
643  * @message: A #GDBusMessage.
644  * @fd_list: A #GUnixFDList or %NULL.
645  *
646  * Sets the UNIX file descriptors associated with @message. As a
647  * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
648  * field is set to the number of fds in @fd_list (or cleared if
649  * @fd_list is %NULL).
650  *
651  * This method is only available on UNIX.
652  *
653  * Since: 2.26
654  */
655 void
656 g_dbus_message_set_unix_fd_list (GDBusMessage  *message,
657                                  GUnixFDList   *fd_list)
658 {
659   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
660   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
661   if (message->priv->fd_list != NULL)
662     g_object_unref (message->priv->fd_list);
663   if (fd_list != NULL)
664     {
665       message->priv->fd_list = g_object_ref (fd_list);
666       g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
667     }
668   else
669     {
670       message->priv->fd_list = NULL;
671       g_dbus_message_set_num_unix_fds (message, 0);
672     }
673 }
674 #endif
675
676 /* ---------------------------------------------------------------------------------------------------- */
677
678 static gboolean
679 ensure_input_padding (GMemoryInputStream   *mis,
680                       gsize                 padding_size,
681                       GError              **error)
682 {
683   gsize offset;
684   gsize wanted_offset;
685
686   offset = g_seekable_tell (G_SEEKABLE (mis));
687   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
688
689   if (offset != wanted_offset)
690     {
691       return g_seekable_seek (G_SEEKABLE (mis), wanted_offset, G_SEEK_SET, NULL, error);
692     }
693   else
694     {
695       return TRUE;
696     }
697 }
698
699 static gchar *
700 read_string (GMemoryInputStream    *mis,
701              GDataInputStream      *dis,
702              gsize                  len,
703              GError               **error)
704 {
705   GString *s;
706   gchar buf[256];
707   gsize remaining;
708   guchar nul;
709   GError *local_error;
710
711   s = g_string_new (NULL);
712
713   remaining = len;
714   while (remaining > 0)
715     {
716       gsize to_read;
717       gssize num_read;
718
719       to_read = MIN (remaining, sizeof (buf));
720       num_read = g_input_stream_read (G_INPUT_STREAM (mis),
721                                       buf,
722                                       to_read,
723                                       NULL,
724                                       error);
725       if (num_read < 0)
726         goto fail;
727       if (num_read == 0)
728         {
729           g_set_error (error,
730                        G_IO_ERROR,
731                        G_IO_ERROR_INVALID_ARGUMENT,
732                        _("Wanted to read %" G_GSIZE_FORMAT " bytes but got EOF"),
733                        to_read);
734           goto fail;
735         }
736
737       remaining -= num_read;
738       g_string_append_len (s, buf, num_read);
739     }
740
741   local_error = NULL;
742   nul = g_data_input_stream_read_byte (dis, NULL, &local_error);
743   if (local_error != NULL)
744     {
745       g_propagate_error (error, local_error);
746       goto fail;
747     }
748   if (nul != '\0')
749     {
750       g_set_error (error,
751                    G_IO_ERROR,
752                    G_IO_ERROR_INVALID_ARGUMENT,
753                    _("Expected NUL byte after the string `%s' but found `%c' (%d)"),
754                    s->str, nul, nul);
755       goto fail;
756     }
757
758   return g_string_free (s, FALSE);
759
760  fail:
761   g_string_free (s, TRUE);
762   return NULL;
763 }
764
765 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
766
767 /* returns a non-floating GVariant! */
768 static GVariant *
769 parse_value_from_blob (GMemoryInputStream    *mis,
770                        GDataInputStream      *dis,
771                        const GVariantType    *type,
772                        gboolean               just_align,
773                        guint                  indent,
774                        GError               **error)
775 {
776   GVariant *ret;
777   GError *local_error;
778   gboolean is_leaf;
779
780 #ifdef DEBUG_SERIALIZER
781   if (!just_align)
782     {
783       gchar *s;
784       s = g_variant_type_dup_string (type);
785       g_print ("%*sReading type %s from offset 0x%04x",
786                indent, "",
787                s,
788                (gint) g_seekable_tell (G_SEEKABLE (mis)));
789       g_free (s);
790     }
791 #endif /* DEBUG_SERIALIZER */
792
793   ret = NULL;
794
795   is_leaf = TRUE;
796   local_error = NULL;
797   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
798     {
799       if (!ensure_input_padding (mis, 4, &local_error))
800         goto fail;
801       if (!just_align)
802         {
803           gboolean v;
804           v = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
805           if (local_error != NULL)
806             goto fail;
807           ret = g_variant_new_boolean (v);
808         }
809     }
810   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
811     {
812       if (!just_align)
813         {
814           guchar v;
815           v = g_data_input_stream_read_byte (dis, NULL, &local_error);
816           if (local_error != NULL)
817             goto fail;
818           ret = g_variant_new_byte (v);
819         }
820     }
821   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
822     {
823       if (!ensure_input_padding (mis, 2, &local_error))
824         goto fail;
825       if (!just_align)
826         {
827           gint16 v;
828           v = g_data_input_stream_read_int16 (dis, NULL, &local_error);
829           if (local_error != NULL)
830             goto fail;
831           ret = g_variant_new_int16 (v);
832         }
833     }
834   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
835     {
836       if (!ensure_input_padding (mis, 2, &local_error))
837         goto fail;
838       if (!just_align)
839         {
840           guint16 v;
841           v = g_data_input_stream_read_uint16 (dis, NULL, &local_error);
842           if (local_error != NULL)
843             goto fail;
844           ret = g_variant_new_uint16 (v);
845         }
846     }
847   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
848     {
849       if (!ensure_input_padding (mis, 4, &local_error))
850         goto fail;
851       if (!just_align)
852         {
853           gint32 v;
854           v = g_data_input_stream_read_int32 (dis, NULL, &local_error);
855           if (local_error != NULL)
856             goto fail;
857           ret = g_variant_new_int32 (v);
858         }
859     }
860   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
861     {
862       if (!ensure_input_padding (mis, 4, &local_error))
863         goto fail;
864       if (!just_align)
865         {
866           guint32 v;
867           v = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
868           if (local_error != NULL)
869             goto fail;
870           ret = g_variant_new_uint32 (v);
871         }
872     }
873   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
874     {
875       if (!ensure_input_padding (mis, 8, &local_error))
876         goto fail;
877       if (!just_align)
878         {
879           gint64 v;
880           v = g_data_input_stream_read_int64 (dis, NULL, &local_error);
881           if (local_error != NULL)
882             goto fail;
883           ret = g_variant_new_int64 (v);
884         }
885     }
886   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
887     {
888       if (!ensure_input_padding (mis, 8, &local_error))
889         goto fail;
890       if (!just_align)
891         {
892           guint64 v;
893           v = g_data_input_stream_read_uint64 (dis, NULL, &local_error);
894           if (local_error != NULL)
895             goto fail;
896           ret = g_variant_new_uint64 (v);
897         }
898     }
899   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
900     {
901       if (!ensure_input_padding (mis, 8, &local_error))
902         goto fail;
903       if (!just_align)
904         {
905           guint64 v;
906           gdouble *encoded;
907           v = g_data_input_stream_read_uint64 (dis, NULL, &local_error);
908           if (local_error != NULL)
909             goto fail;
910           /* TODO: hmm */
911           encoded = (gdouble *) &v;
912           ret = g_variant_new_double (*encoded);
913         }
914     }
915   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
916     {
917       if (!ensure_input_padding (mis, 4, &local_error))
918         goto fail;
919       if (!just_align)
920         {
921           guint32 len;
922           gchar *v;
923           len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
924           if (local_error != NULL)
925             goto fail;
926           v = read_string (mis, dis, (gsize) len, &local_error);
927           if (v == NULL)
928             goto fail;
929           ret = g_variant_new_string (v);
930           g_free (v);
931         }
932     }
933   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
934     {
935       if (!ensure_input_padding (mis, 4, &local_error))
936         goto fail;
937       if (!just_align)
938         {
939           guint32 len;
940           gchar *v;
941           len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
942           if (local_error != NULL)
943             goto fail;
944           v = read_string (mis, dis, (gsize) len, &local_error);
945           if (v == NULL)
946             goto fail;
947           if (!g_variant_is_object_path (v))
948             {
949               g_set_error (&local_error,
950                            G_IO_ERROR,
951                            G_IO_ERROR_INVALID_ARGUMENT,
952                            _("Parsed value `%s' is not a valid D-Bus object path"),
953                            v);
954               g_free (v);
955               goto fail;
956             }
957           ret = g_variant_new_object_path (v);
958           g_free (v);
959         }
960     }
961   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
962     {
963       if (!just_align)
964         {
965           guchar len;
966           gchar *v;
967           len = g_data_input_stream_read_byte (dis, NULL, &local_error);
968           if (local_error != NULL)
969             goto fail;
970           v = read_string (mis, dis, (gsize) len, &local_error);
971           if (v == NULL)
972             goto fail;
973           if (!g_variant_is_signature (v))
974             {
975               g_set_error (&local_error,
976                            G_IO_ERROR,
977                            G_IO_ERROR_INVALID_ARGUMENT,
978                            _("Parsed value `%s' is not a valid D-Bus signature"),
979                        v);
980               g_free (v);
981               goto fail;
982             }
983           ret = g_variant_new_signature (v);
984           g_free (v);
985         }
986     }
987   else if (g_variant_type_is_array (type))
988     {
989       guint32 array_len;
990       goffset offset;
991       goffset target;
992       const GVariantType *element_type;
993       GVariantBuilder builder;
994
995       if (!ensure_input_padding (mis, 4, &local_error))
996         goto fail;
997
998       if (just_align)
999         {
1000           array_len = 0;
1001         }
1002       else
1003         {
1004           array_len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
1005           if (local_error != NULL)
1006             goto fail;
1007
1008           is_leaf = FALSE;
1009 #ifdef DEBUG_SERIALIZER
1010           g_print (": array spans 0x%04x bytes\n", array_len);
1011 #endif /* DEBUG_SERIALIZER */
1012
1013           if (array_len > (2<<26))
1014             {
1015               g_set_error (&local_error,
1016                            G_IO_ERROR,
1017                            G_IO_ERROR_INVALID_ARGUMENT,
1018                            _("Encountered array of length %" G_GUINT32_FORMAT " bytes. Maximum length is 2<<26 bytes."),
1019                            array_len);
1020               goto fail;
1021             }
1022         }
1023
1024       g_variant_builder_init (&builder, type);
1025       element_type = g_variant_type_element (type);
1026
1027       if (array_len == 0)
1028         {
1029           GVariant *item;
1030           item = parse_value_from_blob (mis,
1031                                         dis,
1032                                         element_type,
1033                                         TRUE,
1034                                         indent + 2,
1035                                         &local_error);
1036           g_assert (item == NULL);
1037         }
1038       else
1039         {
1040           /* TODO: optimize array of primitive types */
1041           offset = g_seekable_tell (G_SEEKABLE (mis));
1042           target = offset + array_len;
1043           while (offset < target)
1044             {
1045               GVariant *item;
1046               item = parse_value_from_blob (mis,
1047                                             dis,
1048                                             element_type,
1049                                             FALSE,
1050                                             indent + 2,
1051                                             &local_error);
1052               if (item == NULL)
1053                 {
1054                   g_variant_builder_clear (&builder);
1055                   goto fail;
1056                 }
1057               g_variant_builder_add_value (&builder, item);
1058               g_variant_unref (item);
1059               offset = g_seekable_tell (G_SEEKABLE (mis));
1060             }
1061         }
1062
1063       if (!just_align)
1064         {
1065           ret = g_variant_builder_end (&builder);
1066         }
1067       else
1068         {
1069           g_variant_builder_clear (&builder);
1070         }
1071     }
1072   else if (g_variant_type_is_dict_entry (type))
1073     {
1074       const GVariantType *key_type;
1075       const GVariantType *value_type;
1076       GVariant *key;
1077       GVariant *value;
1078
1079       if (!ensure_input_padding (mis, 8, &local_error))
1080         goto fail;
1081
1082       is_leaf = FALSE;
1083 #ifdef DEBUG_SERIALIZER
1084       g_print ("\n");
1085 #endif /* DEBUG_SERIALIZER */
1086
1087       if (!just_align)
1088         {
1089           key_type = g_variant_type_key (type);
1090           key = parse_value_from_blob (mis,
1091                                        dis,
1092                                        key_type,
1093                                        FALSE,
1094                                        indent + 2,
1095                                        &local_error);
1096           if (key == NULL)
1097             goto fail;
1098           value_type = g_variant_type_value (type);
1099           value = parse_value_from_blob (mis,
1100                                          dis,
1101                                          value_type,
1102                                          FALSE,
1103                                          indent + 2,
1104                                          &local_error);
1105           if (value == NULL)
1106             {
1107               g_variant_unref (key);
1108               goto fail;
1109             }
1110           ret = g_variant_new_dict_entry (key, value);
1111           g_variant_unref (key);
1112           g_variant_unref (value);
1113         }
1114     }
1115   else if (g_variant_type_is_tuple (type))
1116     {
1117       if (!ensure_input_padding (mis, 8, &local_error))
1118         goto fail;
1119
1120       is_leaf = FALSE;
1121 #ifdef DEBUG_SERIALIZER
1122       g_print ("\n");
1123 #endif /* DEBUG_SERIALIZER */
1124
1125       if (!just_align)
1126         {
1127           const GVariantType *element_type;
1128           GVariantBuilder builder;
1129
1130           g_variant_builder_init (&builder, type);
1131           element_type = g_variant_type_first (type);
1132           while (element_type != NULL)
1133             {
1134               GVariant *item;
1135               item = parse_value_from_blob (mis,
1136                                             dis,
1137                                             element_type,
1138                                             FALSE,
1139                                             indent + 2,
1140                                             &local_error);
1141               if (item == NULL)
1142                 {
1143                   g_variant_builder_clear (&builder);
1144                   goto fail;
1145                 }
1146               g_variant_builder_add_value (&builder, item);
1147               g_variant_unref (item);
1148
1149               element_type = g_variant_type_next (element_type);
1150             }
1151           ret = g_variant_builder_end (&builder);
1152         }
1153     }
1154   else if (g_variant_type_is_variant (type))
1155     {
1156       is_leaf = FALSE;
1157 #ifdef DEBUG_SERIALIZER
1158       g_print ("\n");
1159 #endif /* DEBUG_SERIALIZER */
1160
1161       if (!just_align)
1162         {
1163           guchar siglen;
1164           gchar *sig;
1165           GVariantType *variant_type;
1166           GVariant *value;
1167
1168           siglen = g_data_input_stream_read_byte (dis, NULL, &local_error);
1169           if (local_error != NULL)
1170             goto fail;
1171           sig = read_string (mis, dis, (gsize) siglen, &local_error);
1172           if (sig == NULL)
1173             goto fail;
1174           if (!g_variant_is_signature (sig))
1175             {
1176               g_set_error (&local_error,
1177                            G_IO_ERROR,
1178                            G_IO_ERROR_INVALID_ARGUMENT,
1179                            _("Parsed value `%s' for variant is not a valid D-Bus signature"),
1180                            sig);
1181               g_free (sig);
1182               goto fail;
1183             }
1184           variant_type = g_variant_type_new (sig);
1185           g_free (sig);
1186           value = parse_value_from_blob (mis,
1187                                          dis,
1188                                          variant_type,
1189                                          FALSE,
1190                                          indent + 2,
1191                                          &local_error);
1192           g_variant_type_free (variant_type);
1193           if (value == NULL)
1194             goto fail;
1195           ret = g_variant_new_variant (value);
1196           g_variant_unref (value);
1197         }
1198     }
1199   else
1200     {
1201       gchar *s;
1202       s = g_variant_type_dup_string (type);
1203       g_set_error (&local_error,
1204                    G_IO_ERROR,
1205                    G_IO_ERROR_INVALID_ARGUMENT,
1206                    _("Error deserializing GVariant with type-string `%s' from the D-Bus wire format"),
1207                    s);
1208       g_free (s);
1209       goto fail;
1210     }
1211
1212   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1213
1214 #ifdef DEBUG_SERIALIZER
1215   if (ret != NULL)
1216     {
1217       if (is_leaf)
1218         {
1219           gchar *s;
1220           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1221             {
1222               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1223             }
1224           else
1225             {
1226               s = g_variant_print (ret, FALSE);
1227             }
1228           g_print (": %s\n", s);
1229           g_free (s);
1230         }
1231     }
1232 #endif /* DEBUG_SERIALIZER */
1233
1234   /* sink the reference */
1235   if (ret != NULL)
1236     {
1237       g_assert (g_variant_is_floating (ret));
1238       g_variant_ref_sink (ret);
1239     }
1240   return ret;
1241
1242  fail:
1243 #ifdef DEBUG_SERIALIZER
1244   g_print ("\n"
1245            "%*sFAILURE: %s (%s, %d)\n",
1246            indent, "",
1247            local_error->message,
1248            g_quark_to_string (local_error->domain),
1249            local_error->code);
1250 #endif /* DEBUG_SERIALIZER */
1251   g_propagate_error (error, local_error);
1252   return NULL;
1253 }
1254
1255 /* ---------------------------------------------------------------------------------------------------- */
1256
1257 /* message_header must be at least 16 bytes */
1258
1259 /**
1260  * g_dbus_message_bytes_needed:
1261  * @blob: A blob represent a binary D-Bus message.
1262  * @blob_len: The length of @blob (must be at least 16).
1263  * @error: Return location for error or %NULL.
1264  *
1265  * Utility function to calculate how many bytes are needed to
1266  * completely deserialize the D-Bus message stored at @blob.
1267  *
1268  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1269  * @blob contains invalid data or not enough data is available to
1270  * determine the size).
1271  *
1272  * Since: 2.26
1273  */
1274 gssize
1275 g_dbus_message_bytes_needed (guchar                *blob,
1276                              gsize                  blob_len,
1277                              GError               **error)
1278 {
1279   gssize ret;
1280
1281   ret = -1;
1282
1283   g_return_val_if_fail (blob != NULL, -1);
1284   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1285   g_return_val_if_fail (blob_len >= 16, -1);
1286
1287   if (blob[0] == 'l')
1288     {
1289       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1290       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1291       /* round up so it's a multiple of 8 */
1292       ret = 8 * ((ret + 7)/8);
1293       /* finally add the body size */
1294       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1295     }
1296   else if (blob[0] == 'B')
1297     {
1298       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1299       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1300       /* round up so it's a multiple of 8 */
1301       ret = 8 * ((ret + 7)/8);
1302       /* finally add the body size */
1303       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1304     }
1305   else
1306     {
1307       g_set_error (error,
1308                    G_IO_ERROR,
1309                    G_IO_ERROR_INVALID_ARGUMENT,
1310                    "Unable to determine message blob length - given blob is malformed");
1311     }
1312
1313   if (ret > (2<<27))
1314     {
1315       g_set_error (error,
1316                    G_IO_ERROR,
1317                    G_IO_ERROR_INVALID_ARGUMENT,
1318                    "Blob indicates that message exceeds maximum message length (128MiB)");
1319       ret = -1;
1320     }
1321
1322   return ret;
1323 }
1324
1325 /* ---------------------------------------------------------------------------------------------------- */
1326
1327 /**
1328  * g_dbus_message_new_from_blob:
1329  * @blob: A blob represent a binary D-Bus message.
1330  * @blob_len: The length of @blob.
1331  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1332  * @error: Return location for error or %NULL.
1333  *
1334  * Creates a new #GDBusMessage from the data stored at @blob.
1335  *
1336  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
1337  * g_object_unref().
1338  *
1339  * Since: 2.26
1340  */
1341 GDBusMessage *
1342 g_dbus_message_new_from_blob (guchar                *blob,
1343                               gsize                  blob_len,
1344                               GDBusCapabilityFlags   capabilities,
1345                               GError               **error)
1346 {
1347   gboolean ret;
1348   GMemoryInputStream *mis;
1349   GDataInputStream *dis;
1350   GDBusMessage *message;
1351   guchar endianness;
1352   guchar major_protocol_version;
1353   GDataStreamByteOrder byte_order;
1354   guint32 message_body_len;
1355   GVariant *headers;
1356   GVariant *item;
1357   GVariantIter iter;
1358   GVariant *signature;
1359
1360   /* TODO: check against @capabilities */
1361
1362   ret = FALSE;
1363
1364   g_return_val_if_fail (blob != NULL, NULL);
1365   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1366   g_return_val_if_fail (blob_len >= 12, NULL);
1367
1368   message = g_dbus_message_new ();
1369
1370   mis = G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (blob, blob_len, NULL));
1371   dis = g_data_input_stream_new (G_INPUT_STREAM (mis));
1372
1373   endianness = g_data_input_stream_read_byte (dis, NULL, NULL);
1374   switch (endianness)
1375     {
1376     case 'l':
1377       byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1378       break;
1379     case 'B':
1380       byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
1381       break;
1382     default:
1383       g_set_error (error,
1384                    G_IO_ERROR,
1385                    G_IO_ERROR_INVALID_ARGUMENT,
1386                    _("Invalid endianness value. Expected 'l' or 'B' but found '%c' (%d)"),
1387                    endianness, endianness);
1388       goto out;
1389     }
1390   g_data_input_stream_set_byte_order (dis, byte_order);
1391
1392   message->priv->type = g_data_input_stream_read_byte (dis, NULL, NULL);
1393   message->priv->flags = g_data_input_stream_read_byte (dis, NULL, NULL);
1394   major_protocol_version = g_data_input_stream_read_byte (dis, NULL, NULL);
1395   if (major_protocol_version != 1)
1396     {
1397       g_set_error (error,
1398                    G_IO_ERROR,
1399                    G_IO_ERROR_INVALID_ARGUMENT,
1400                    _("Invalid major protocol version. Expected 1 but found %d"),
1401                    major_protocol_version);
1402       goto out;
1403     }
1404   message_body_len = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1405   message->priv->serial = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1406
1407 #ifdef DEBUG_SERIALIZER
1408   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1409   {
1410     gchar *s;
1411     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
1412     g_print ("%s\n", s);
1413     g_free (s);
1414   }
1415 #endif /* DEBUG_SERIALIZER */
1416
1417 #ifdef DEBUG_SERIALIZER
1418   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1419 #endif /* DEBUG_SERIALIZER */
1420   headers = parse_value_from_blob (mis,
1421                                    dis,
1422                                    G_VARIANT_TYPE ("a{yv}"),
1423                                    FALSE,
1424                                    2,
1425                                    error);
1426   if (headers == NULL)
1427     goto out;
1428   g_variant_iter_init (&iter, headers);
1429   while ((item = g_variant_iter_next_value (&iter)) != NULL)
1430     {
1431       guchar header_field;
1432       GVariant *value;
1433       g_variant_get (item,
1434                      "{yv}",
1435                      &header_field,
1436                      &value);
1437       g_dbus_message_set_header (message, header_field, value);
1438       g_variant_unref (value);
1439       g_variant_unref (item);
1440     }
1441   g_variant_unref (headers);
1442
1443   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
1444   if (signature != NULL)
1445     {
1446       const gchar *signature_str;
1447       gsize signature_str_len;
1448
1449       signature_str = g_variant_get_string (signature, &signature_str_len);
1450
1451       /* signature but no body */
1452       if (message_body_len == 0 && signature_str_len > 0)
1453         {
1454           g_set_error (error,
1455                        G_IO_ERROR,
1456                        G_IO_ERROR_INVALID_ARGUMENT,
1457                        _("Signature header with signature `%s' found but message body is empty"),
1458                        signature_str);
1459           goto out;
1460         }
1461       else if (signature_str_len > 0)
1462         {
1463           GVariantType *variant_type;
1464           gchar *tupled_signature_str;
1465
1466           if (!g_variant_is_signature (signature_str))
1467             {
1468               g_set_error (error,
1469                            G_IO_ERROR,
1470                            G_IO_ERROR_INVALID_ARGUMENT,
1471                            _("Parsed value `%s' is not a valid D-Bus signature (for body)"),
1472                            signature_str);
1473               goto out;
1474             }
1475           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
1476           variant_type = g_variant_type_new (tupled_signature_str);
1477           g_free (tupled_signature_str);
1478 #ifdef DEBUG_SERIALIZER
1479           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1480 #endif /* DEBUG_SERIALIZER */
1481           message->priv->body = parse_value_from_blob (mis,
1482                                                        dis,
1483                                                        variant_type,
1484                                                        FALSE,
1485                                                        2,
1486                                                        error);
1487           g_variant_type_free (variant_type);
1488           if (message->priv->body == NULL)
1489             goto out;
1490         }
1491     }
1492   else
1493     {
1494       /* no signature, this is only OK if the body is empty */
1495       if (message_body_len != 0)
1496         {
1497           g_set_error (error,
1498                        G_IO_ERROR,
1499                        G_IO_ERROR_INVALID_ARGUMENT,
1500                        _("No signature header in message but the message body is %" G_GUINT32_FORMAT " bytes"),
1501                        message_body_len);
1502           goto out;
1503         }
1504     }
1505
1506
1507   ret = TRUE;
1508
1509  out:
1510   g_object_unref (dis);
1511   g_object_unref (mis);
1512
1513   if (ret)
1514     {
1515       return message;
1516     }
1517   else
1518     {
1519       if (message != NULL)
1520         g_object_unref (message);
1521       return NULL;
1522     }
1523 }
1524
1525 /* ---------------------------------------------------------------------------------------------------- */
1526
1527 static gsize
1528 ensure_output_padding (GMemoryOutputStream  *mos,
1529                        GDataOutputStream    *dos,
1530                        gsize                 padding_size)
1531 {
1532   gsize offset;
1533   gsize wanted_offset;
1534   gsize padding_needed;
1535   guint n;
1536
1537   offset = g_memory_output_stream_get_data_size (mos);
1538   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1539   padding_needed = wanted_offset - offset;
1540
1541   for (n = 0; n < padding_needed; n++)
1542     g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1543
1544   return padding_needed;
1545 }
1546
1547 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
1548 static gboolean
1549 append_value_to_blob (GVariant             *value,
1550                       const GVariantType   *type,
1551                       GMemoryOutputStream  *mos,
1552                       GDataOutputStream    *dos,
1553                       gsize                *out_padding_added,
1554                       GError              **error)
1555 {
1556   gsize padding_added;
1557
1558   padding_added = 0;
1559
1560   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1561     {
1562       padding_added = ensure_output_padding (mos, dos, 4);
1563       if (value != NULL)
1564         {
1565           gboolean v = g_variant_get_boolean (value);
1566           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1567         }
1568     }
1569   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1570     {
1571       if (value != NULL)
1572         {
1573           guint8 v = g_variant_get_byte (value);
1574           g_data_output_stream_put_byte (dos, v, NULL, NULL);
1575         }
1576     }
1577   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
1578     {
1579       padding_added = ensure_output_padding (mos, dos, 2);
1580       if (value != NULL)
1581         {
1582           gint16 v = g_variant_get_int16 (value);
1583           g_data_output_stream_put_int16 (dos, v, NULL, NULL);
1584         }
1585     }
1586   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
1587     {
1588       padding_added = ensure_output_padding (mos, dos, 2);
1589       if (value != NULL)
1590         {
1591           guint16 v = g_variant_get_uint16 (value);
1592           g_data_output_stream_put_uint16 (dos, v, NULL, NULL);
1593         }
1594     }
1595   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
1596     {
1597       padding_added = ensure_output_padding (mos, dos, 4);
1598       if (value != NULL)
1599         {
1600           gint32 v = g_variant_get_int32 (value);
1601           g_data_output_stream_put_int32 (dos, v, NULL, NULL);
1602         }
1603     }
1604   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
1605     {
1606       padding_added = ensure_output_padding (mos, dos, 4);
1607       if (value != NULL)
1608         {
1609           guint32 v = g_variant_get_uint32 (value);
1610           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1611         }
1612     }
1613   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
1614     {
1615       padding_added = ensure_output_padding (mos, dos, 8);
1616       if (value != NULL)
1617         {
1618           gint64 v = g_variant_get_int64 (value);
1619           g_data_output_stream_put_int64 (dos, v, NULL, NULL);
1620         }
1621     }
1622   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
1623     {
1624       padding_added = ensure_output_padding (mos, dos, 8);
1625       if (value != NULL)
1626         {
1627           guint64 v = g_variant_get_uint64 (value);
1628           g_data_output_stream_put_uint64 (dos, v, NULL, NULL);
1629         }
1630     }
1631   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1632     {
1633       padding_added = ensure_output_padding (mos, dos, 8);
1634       if (value != NULL)
1635         {
1636           guint64 *encoded;
1637           gdouble v = g_variant_get_double (value);
1638           /* TODO: hmm */
1639           encoded = (guint64 *) &v;
1640           g_data_output_stream_put_uint64 (dos, *encoded, NULL, NULL);
1641         }
1642     }
1643   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1644     {
1645       padding_added = ensure_output_padding (mos, dos, 4);
1646       if (value != NULL)
1647         {
1648           gsize len;
1649           const gchar *v = g_variant_get_string (value, &len);
1650           g_data_output_stream_put_uint32 (dos, len, NULL, NULL);
1651           g_data_output_stream_put_string (dos, v, NULL, NULL);
1652           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1653         }
1654     }
1655   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1656     {
1657       padding_added = ensure_output_padding (mos, dos, 4);
1658       if (value != NULL)
1659         {
1660           /* TODO: validate object path */
1661           gsize len;
1662           const gchar *v = g_variant_get_string (value, &len);
1663           g_data_output_stream_put_uint32 (dos, len, NULL, NULL);
1664           g_data_output_stream_put_string (dos, v, NULL, NULL);
1665           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1666         }
1667     }
1668   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1669     {
1670       if (value != NULL)
1671         {
1672           /* TODO: validate signature (including max len being 255) */
1673           gsize len;
1674           const gchar *v = g_variant_get_string (value, &len);
1675           g_data_output_stream_put_byte (dos, len, NULL, NULL);
1676           g_data_output_stream_put_string (dos, v, NULL, NULL);
1677           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1678         }
1679     }
1680   else if (g_variant_type_is_array (type))
1681     {
1682       GVariant *item;
1683       GVariantIter iter;
1684       goffset array_len_offset;
1685       goffset array_payload_begin_offset;
1686       goffset cur_offset;
1687       gsize array_len;
1688
1689       padding_added = ensure_output_padding (mos, dos, 4);
1690       if (value != NULL)
1691         {
1692           /* array length - will be filled in later */
1693           array_len_offset = g_memory_output_stream_get_data_size (mos);
1694           g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
1695
1696           /* From the D-Bus spec:
1697            *
1698            *   "A UINT32 giving the length of the array data in bytes,
1699            *    followed by alignment padding to the alignment boundary of
1700            *    the array element type, followed by each array element. The
1701            *    array length is from the end of the alignment padding to
1702            *    the end of the last element, i.e. it does not include the
1703            *    padding after the length, or any padding after the last
1704            *    element."
1705            *
1706            * Thus, we need to count how much padding the first element
1707            * contributes and subtract that from the array length.
1708            */
1709           array_payload_begin_offset = g_memory_output_stream_get_data_size (mos);
1710
1711           if (g_variant_n_children (value) == 0)
1712             {
1713               gsize padding_added_for_item;
1714               if (!append_value_to_blob (NULL,
1715                                          g_variant_type_element (type),
1716                                          mos,
1717                                          dos,
1718                                          &padding_added_for_item,
1719                                          error))
1720                 goto fail;
1721               array_payload_begin_offset += padding_added_for_item;
1722             }
1723           else
1724             {
1725               guint n;
1726               n = 0;
1727               g_variant_iter_init (&iter, value);
1728               while ((item = g_variant_iter_next_value (&iter)) != NULL)
1729                 {
1730                   gsize padding_added_for_item;
1731                   if (!append_value_to_blob (item,
1732                                              g_variant_get_type (item),
1733                                              mos,
1734                                              dos,
1735                                              &padding_added_for_item,
1736                                              error))
1737                     {
1738                       g_variant_unref (item);
1739                       goto fail;
1740                     }
1741                   g_variant_unref (item);
1742                   if (n == 0)
1743                     {
1744                       array_payload_begin_offset += padding_added_for_item;
1745                     }
1746                   n++;
1747                 }
1748             }
1749
1750           cur_offset = g_memory_output_stream_get_data_size (mos);
1751
1752           array_len = cur_offset - array_payload_begin_offset;
1753
1754           if (!g_seekable_seek (G_SEEKABLE (mos), array_len_offset, G_SEEK_SET, NULL, error))
1755             goto fail;
1756
1757           g_data_output_stream_put_uint32 (dos, array_len, NULL, NULL);
1758
1759           if (!g_seekable_seek (G_SEEKABLE (mos), cur_offset, G_SEEK_SET, NULL, error))
1760             goto fail;
1761         }
1762     }
1763   else if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
1764     {
1765       padding_added = ensure_output_padding (mos, dos, 8);
1766       if (value != NULL)
1767         {
1768           GVariant *item;
1769           GVariantIter iter;
1770           g_variant_iter_init (&iter, value);
1771           while ((item = g_variant_iter_next_value (&iter)) != NULL)
1772             {
1773               if (!append_value_to_blob (item,
1774                                          g_variant_get_type (item),
1775                                          mos,
1776                                          dos,
1777                                          NULL,
1778                                          error))
1779                 {
1780                   g_variant_unref (item);
1781                   goto fail;
1782                 }
1783               g_variant_unref (item);
1784             }
1785         }
1786     }
1787   else if (g_variant_type_is_variant (type))
1788     {
1789       if (value != NULL)
1790         {
1791           GVariant *child;
1792           const gchar *signature;
1793           child = g_variant_get_child_value (value, 0);
1794           signature = g_variant_get_type_string (child);
1795           /* TODO: validate signature (including max len being 255) */
1796           g_data_output_stream_put_byte (dos, strlen (signature), NULL, NULL);
1797           g_data_output_stream_put_string (dos, signature, NULL, NULL);
1798           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1799           if (!append_value_to_blob (child,
1800                                      g_variant_get_type (child),
1801                                      mos,
1802                                      dos,
1803                                      NULL,
1804                                      error))
1805             {
1806               g_variant_unref (child);
1807               goto fail;
1808             }
1809           g_variant_unref (child);
1810         }
1811     }
1812   else
1813     {
1814       g_set_error (error,
1815                    G_IO_ERROR,
1816                    G_IO_ERROR_INVALID_ARGUMENT,
1817                    _("Error serializing GVariant with type-string `%s' to the D-Bus wire format"),
1818                    g_variant_get_type_string (value));
1819       goto fail;
1820     }
1821
1822   if (out_padding_added != NULL)
1823     *out_padding_added = padding_added;
1824
1825   return TRUE;
1826
1827  fail:
1828   return FALSE;
1829 }
1830
1831 static gboolean
1832 append_body_to_blob (GVariant             *value,
1833                      GMemoryOutputStream  *mos,
1834                      GDataOutputStream    *dos,
1835                      GError              **error)
1836 {
1837   gboolean ret;
1838   GVariant *item;
1839   GVariantIter iter;
1840
1841   ret = FALSE;
1842
1843   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
1844     {
1845       g_set_error (error,
1846                    G_IO_ERROR,
1847                    G_IO_ERROR_INVALID_ARGUMENT,
1848                    "Expected a tuple for the body of the GDBusMessage.");
1849       goto fail;
1850     }
1851
1852   g_variant_iter_init (&iter, value);
1853   while ((item = g_variant_iter_next_value (&iter)) != NULL)
1854     {
1855       if (!append_value_to_blob (item,
1856                                  g_variant_get_type (item),
1857                                  mos,
1858                                  dos,
1859                                  NULL,
1860                                  error))
1861         {
1862           g_variant_unref (item);
1863           goto fail;
1864         }
1865       g_variant_unref (item);
1866     }
1867   return TRUE;
1868
1869  fail:
1870   return FALSE;
1871 }
1872
1873 /* ---------------------------------------------------------------------------------------------------- */
1874
1875 /**
1876  * g_dbus_message_to_blob:
1877  * @message: A #GDBusMessage.
1878  * @out_size: Return location for size of generated blob.
1879  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1880  * @error: Return location for error.
1881  *
1882  * Serializes @message to a blob.
1883  *
1884  * Returns: A pointer to a valid binary D-Bus message of @out_size bytes
1885  * generated by @message or %NULL if @error is set. Free with g_free().
1886  *
1887  * Since: 2.26
1888  */
1889 guchar *
1890 g_dbus_message_to_blob (GDBusMessage          *message,
1891                         gsize                 *out_size,
1892                         GDBusCapabilityFlags   capabilities,
1893                         GError               **error)
1894 {
1895   GMemoryOutputStream *mos;
1896   GDataOutputStream *dos;
1897   guchar *ret;
1898   gsize size;
1899   GDataStreamByteOrder byte_order;
1900   goffset body_len_offset;
1901   goffset body_start_offset;
1902   gsize body_size;
1903   GVariant *header_fields;
1904   GVariantBuilder builder;
1905   GHashTableIter hash_iter;
1906   gpointer key;
1907   GVariant *header_value;
1908   GVariant *signature;
1909   const gchar *signature_str;
1910   gint num_fds_in_message;
1911   gint num_fds_according_to_header;
1912
1913   /* TODO: check against @capabilities */
1914
1915   ret = NULL;
1916
1917   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1918   g_return_val_if_fail (out_size != NULL, NULL);
1919   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1920
1921   mos = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
1922   dos = g_data_output_stream_new (G_OUTPUT_STREAM (mos));
1923
1924   /* TODO: detect endianess... */
1925   byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1926   g_data_output_stream_set_byte_order (dos, byte_order);
1927
1928   /* Core header */
1929   g_data_output_stream_put_byte (dos, byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN ? 'l' : 'B', NULL, NULL);
1930   g_data_output_stream_put_byte (dos, message->priv->type, NULL, NULL);
1931   g_data_output_stream_put_byte (dos, message->priv->flags, NULL, NULL);
1932   g_data_output_stream_put_byte (dos, 1, NULL, NULL); /* major protocol version */
1933   body_len_offset = g_memory_output_stream_get_data_size (mos);
1934   /* body length - will be filled in later */
1935   g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
1936   g_data_output_stream_put_uint32 (dos, message->priv->serial, NULL, NULL);
1937
1938   num_fds_in_message = 0;
1939 #ifdef G_OS_UNIX
1940   if (message->priv->fd_list != NULL)
1941     num_fds_in_message = g_unix_fd_list_get_length (message->priv->fd_list);
1942 #endif
1943   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
1944   /* TODO: check we have all the right header fields and that they are the correct value etc etc */
1945   if (num_fds_in_message != num_fds_according_to_header)
1946     {
1947       g_set_error (error,
1948                    G_IO_ERROR,
1949                    G_IO_ERROR_INVALID_ARGUMENT,
1950                    _("Message has %d fds but the header field indicates %d fds"),
1951                    num_fds_in_message,
1952                    num_fds_according_to_header);
1953       goto out;
1954     }
1955
1956   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
1957   g_hash_table_iter_init (&hash_iter, message->priv->headers);
1958   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
1959     {
1960       g_variant_builder_add (&builder,
1961                              "{yv}",
1962                              (guchar) GPOINTER_TO_UINT (key),
1963                              header_value);
1964     }
1965   header_fields = g_variant_builder_end (&builder);
1966
1967   if (!append_value_to_blob (header_fields,
1968                              g_variant_get_type (header_fields),
1969                              mos, dos,
1970                              NULL,
1971                              error))
1972     {
1973       g_variant_unref (header_fields);
1974       goto out;
1975     }
1976   g_variant_unref (header_fields);
1977
1978   /* header size must be a multiple of 8 */
1979   ensure_output_padding (mos, dos, 8);
1980
1981   body_start_offset = g_memory_output_stream_get_data_size (mos);
1982
1983   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
1984   signature_str = NULL;
1985   if (signature != NULL)
1986       signature_str = g_variant_get_string (signature, NULL);
1987   if (message->priv->body != NULL)
1988     {
1989       gchar *tupled_signature_str;
1990       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
1991       if (signature == NULL)
1992         {
1993           g_set_error (error,
1994                        G_IO_ERROR,
1995                        G_IO_ERROR_INVALID_ARGUMENT,
1996                        _("Message body has signature `%s' but there is no signature header"),
1997                        signature_str);
1998           g_free (tupled_signature_str);
1999           goto out;
2000         }
2001       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->priv->body)) != 0)
2002         {
2003           g_set_error (error,
2004                        G_IO_ERROR,
2005                        G_IO_ERROR_INVALID_ARGUMENT,
2006                        _("Message body has type signature `%s' but signature in the header field is `%s'"),
2007                        tupled_signature_str, g_variant_get_type_string (message->priv->body));
2008           g_free (tupled_signature_str);
2009           goto out;
2010         }
2011       g_free (tupled_signature_str);
2012       if (!append_body_to_blob (message->priv->body, mos, dos, error))
2013         goto out;
2014     }
2015   else
2016     {
2017       if (signature != NULL)
2018         {
2019           g_set_error (error,
2020                        G_IO_ERROR,
2021                        G_IO_ERROR_INVALID_ARGUMENT,
2022                        _("Message body is empty but signature in the header field is `(%s)'"),
2023                        signature_str);
2024           goto out;
2025         }
2026     }
2027
2028   /* OK, we're done writing the message - set the body length */
2029   size = g_memory_output_stream_get_data_size (mos);
2030   body_size = size - body_start_offset;
2031
2032   if (!g_seekable_seek (G_SEEKABLE (mos), body_len_offset, G_SEEK_SET, NULL, error))
2033     goto out;
2034
2035   g_data_output_stream_put_uint32 (dos, body_size, NULL, NULL);
2036
2037   *out_size = size;
2038   ret = g_memdup (g_memory_output_stream_get_data (mos), size);
2039
2040  out:
2041   g_object_unref (dos);
2042   g_object_unref (mos);
2043
2044   return ret;
2045 }
2046
2047 /* ---------------------------------------------------------------------------------------------------- */
2048
2049 static guint32
2050 get_uint32_header (GDBusMessage            *message,
2051                    GDBusMessageHeaderField  header_field)
2052 {
2053   GVariant *value;
2054   guint32 ret;
2055
2056   ret = 0;
2057   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2058   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2059     ret = g_variant_get_uint32 (value);
2060
2061   return ret;
2062 }
2063
2064 static const gchar *
2065 get_string_header (GDBusMessage            *message,
2066                    GDBusMessageHeaderField  header_field)
2067 {
2068   GVariant *value;
2069   const gchar *ret;
2070
2071   ret = NULL;
2072   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2073   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2074     ret = g_variant_get_string (value, NULL);
2075
2076   return ret;
2077 }
2078
2079 static const gchar *
2080 get_object_path_header (GDBusMessage            *message,
2081                         GDBusMessageHeaderField  header_field)
2082 {
2083   GVariant *value;
2084   const gchar *ret;
2085
2086   ret = NULL;
2087   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2088   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2089     ret = g_variant_get_string (value, NULL);
2090
2091   return ret;
2092 }
2093
2094 static const gchar *
2095 get_signature_header (GDBusMessage            *message,
2096                       GDBusMessageHeaderField  header_field)
2097 {
2098   GVariant *value;
2099   const gchar *ret;
2100
2101   ret = NULL;
2102   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2103   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2104     ret = g_variant_get_string (value, NULL);
2105
2106   return ret;
2107 }
2108
2109 /* ---------------------------------------------------------------------------------------------------- */
2110
2111 static void
2112 set_uint32_header (GDBusMessage             *message,
2113                    GDBusMessageHeaderField   header_field,
2114                    guint32                   value)
2115 {
2116   g_dbus_message_set_header (message,
2117                              header_field,
2118                              g_variant_new_uint32 (value));
2119 }
2120
2121 static void
2122 set_string_header (GDBusMessage             *message,
2123                    GDBusMessageHeaderField   header_field,
2124                    const gchar              *value)
2125 {
2126   g_dbus_message_set_header (message,
2127                              header_field,
2128                              value == NULL ? NULL : g_variant_new_string (value));
2129 }
2130
2131 static void
2132 set_object_path_header (GDBusMessage             *message,
2133                         GDBusMessageHeaderField   header_field,
2134                         const gchar              *value)
2135 {
2136   g_dbus_message_set_header (message,
2137                              header_field,
2138                              value == NULL ? NULL : g_variant_new_object_path (value));
2139 }
2140
2141 static void
2142 set_signature_header (GDBusMessage             *message,
2143                       GDBusMessageHeaderField   header_field,
2144                       const gchar              *value)
2145 {
2146   g_dbus_message_set_header (message,
2147                              header_field,
2148                              value == NULL ? NULL : g_variant_new_signature (value));
2149 }
2150
2151 /* ---------------------------------------------------------------------------------------------------- */
2152
2153 /**
2154  * g_dbus_message_get_reply_serial:
2155  * @message: A #GDBusMessage.
2156  *
2157  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2158  *
2159  * Returns: The value.
2160  *
2161  * Since: 2.26
2162  */
2163 guint32
2164 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2165 {
2166   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2167   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2168 }
2169
2170 /**
2171  * g_dbus_message_set_reply_serial:
2172  * @message: A #GDBusMessage.
2173  * @value: The value to set.
2174  *
2175  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2176  *
2177  * Since: 2.26
2178  */
2179 void
2180 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2181                                  guint32        value)
2182 {
2183   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2184   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2185 }
2186
2187 /* ---------------------------------------------------------------------------------------------------- */
2188
2189 /**
2190  * g_dbus_message_get_interface:
2191  * @message: A #GDBusMessage.
2192  *
2193  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2194  *
2195  * Returns: The value.
2196  *
2197  * Since: 2.26
2198  */
2199 const gchar *
2200 g_dbus_message_get_interface (GDBusMessage  *message)
2201 {
2202   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2203   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2204 }
2205
2206 /**
2207  * g_dbus_message_set_interface:
2208  * @message: A #GDBusMessage.
2209  * @value: The value to set.
2210  *
2211  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2212  *
2213  * Since: 2.26
2214  */
2215 void
2216 g_dbus_message_set_interface (GDBusMessage  *message,
2217                               const gchar   *value)
2218 {
2219   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2220   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2221   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2222 }
2223
2224 /* ---------------------------------------------------------------------------------------------------- */
2225
2226 /**
2227  * g_dbus_message_get_member:
2228  * @message: A #GDBusMessage.
2229  *
2230  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2231  *
2232  * Returns: The value.
2233  *
2234  * Since: 2.26
2235  */
2236 const gchar *
2237 g_dbus_message_get_member (GDBusMessage  *message)
2238 {
2239   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2240   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2241 }
2242
2243 /**
2244  * g_dbus_message_set_member:
2245  * @message: A #GDBusMessage.
2246  * @value: The value to set.
2247  *
2248  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2249  *
2250  * Since: 2.26
2251  */
2252 void
2253 g_dbus_message_set_member (GDBusMessage  *message,
2254                            const gchar   *value)
2255 {
2256   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2257   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2258   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2259 }
2260
2261 /* ---------------------------------------------------------------------------------------------------- */
2262
2263 /**
2264  * g_dbus_message_get_path:
2265  * @message: A #GDBusMessage.
2266  *
2267  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2268  *
2269  * Returns: The value.
2270  *
2271  * Since: 2.26
2272  */
2273 const gchar *
2274 g_dbus_message_get_path (GDBusMessage  *message)
2275 {
2276   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2277   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2278 }
2279
2280 /**
2281  * g_dbus_message_set_path:
2282  * @message: A #GDBusMessage.
2283  * @value: The value to set.
2284  *
2285  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2286  *
2287  * Since: 2.26
2288  */
2289 void
2290 g_dbus_message_set_path (GDBusMessage  *message,
2291                          const gchar   *value)
2292 {
2293   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2294   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2295   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2296 }
2297
2298 /* ---------------------------------------------------------------------------------------------------- */
2299
2300 /**
2301  * g_dbus_message_get_sender:
2302  * @message: A #GDBusMessage.
2303  *
2304  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2305  *
2306  * Returns: The value.
2307  *
2308  * Since: 2.26
2309  */
2310 const gchar *
2311 g_dbus_message_get_sender (GDBusMessage *message)
2312 {
2313   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2314   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
2315 }
2316
2317 /**
2318  * g_dbus_message_set_sender:
2319  * @message: A #GDBusMessage.
2320  * @value: The value to set.
2321  *
2322  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2323  *
2324  * Since: 2.26
2325  */
2326 void
2327 g_dbus_message_set_sender (GDBusMessage  *message,
2328                            const gchar   *value)
2329 {
2330   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2331   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2332   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
2333 }
2334
2335 /* ---------------------------------------------------------------------------------------------------- */
2336
2337 /**
2338  * g_dbus_message_get_destination:
2339  * @message: A #GDBusMessage.
2340  *
2341  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2342  *
2343  * Returns: The value.
2344  *
2345  * Since: 2.26
2346  */
2347 const gchar *
2348 g_dbus_message_get_destination (GDBusMessage  *message)
2349 {
2350   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2351   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
2352 }
2353
2354 /**
2355  * g_dbus_message_set_destination:
2356  * @message: A #GDBusMessage.
2357  * @value: The value to set.
2358  *
2359  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2360  *
2361  * Since: 2.26
2362  */
2363 void
2364 g_dbus_message_set_destination (GDBusMessage  *message,
2365                                 const gchar   *value)
2366 {
2367   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2368   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2369   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
2370 }
2371
2372 /* ---------------------------------------------------------------------------------------------------- */
2373
2374 /**
2375  * g_dbus_message_get_error_name:
2376  * @message: A #GDBusMessage.
2377  *
2378  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2379  *
2380  * Returns: The value.
2381  *
2382  * Since: 2.26
2383  */
2384 const gchar *
2385 g_dbus_message_get_error_name (GDBusMessage  *message)
2386 {
2387   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2388   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
2389 }
2390
2391 /**
2392  * g_dbus_message_set_error_name:
2393  * @message: A #GDBusMessage.
2394  * @value: The value to set.
2395  *
2396  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2397  *
2398  * Since: 2.26
2399  */
2400 void
2401 g_dbus_message_set_error_name (GDBusMessage  *message,
2402                                const gchar   *value)
2403 {
2404   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2405   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2406   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
2407 }
2408
2409 /* ---------------------------------------------------------------------------------------------------- */
2410
2411 /**
2412  * g_dbus_message_get_signature:
2413  * @message: A #GDBusMessage.
2414  *
2415  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2416  *
2417  * Returns: The value.
2418  *
2419  * Since: 2.26
2420  */
2421 const gchar *
2422 g_dbus_message_get_signature (GDBusMessage  *message)
2423 {
2424   const gchar *ret;
2425   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2426   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2427   if (ret == NULL)
2428     ret = "";
2429   return ret;
2430 }
2431
2432 /**
2433  * g_dbus_message_set_signature:
2434  * @message: A #GDBusMessage.
2435  * @value: The value to set.
2436  *
2437  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2438  *
2439  * Since: 2.26
2440  */
2441 void
2442 g_dbus_message_set_signature (GDBusMessage  *message,
2443                               const gchar   *value)
2444 {
2445   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2446   g_return_if_fail (value == NULL || g_variant_is_signature (value));
2447   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
2448 }
2449
2450 /* ---------------------------------------------------------------------------------------------------- */
2451
2452 /**
2453  * g_dbus_message_get_arg0:
2454  * @message: A #GDBusMessage.
2455  *
2456  * Convenience to get the first item in the body of @message.
2457  *
2458  * Returns: The string item or %NULL if the first item in the body of
2459  * @message is not a string.
2460  *
2461  * Since: 2.26
2462  */
2463 const gchar *
2464 g_dbus_message_get_arg0 (GDBusMessage  *message)
2465 {
2466   const gchar *ret;
2467
2468   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2469
2470   ret = NULL;
2471
2472   if (message->priv->body != NULL && g_variant_is_of_type (message->priv->body, G_VARIANT_TYPE_TUPLE))
2473     {
2474       GVariant *item;
2475       item = g_variant_get_child_value (message->priv->body, 0);
2476       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
2477         ret = g_variant_get_string (item, NULL);
2478       g_variant_unref (item);
2479     }
2480
2481   return ret;
2482 }
2483
2484 /* ---------------------------------------------------------------------------------------------------- */
2485
2486 /**
2487  * g_dbus_message_get_num_unix_fds:
2488  * @message: A #GDBusMessage.
2489  *
2490  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2491  *
2492  * Returns: The value.
2493  *
2494  * Since: 2.26
2495  */
2496 guint32
2497 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
2498 {
2499   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2500   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
2501 }
2502
2503 /**
2504  * g_dbus_message_set_num_unix_fds:
2505  * @message: A #GDBusMessage.
2506  * @value: The value to set.
2507  *
2508  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2509  *
2510  * Since: 2.26
2511  */
2512 void
2513 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
2514                                  guint32        value)
2515 {
2516   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2517   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
2518 }
2519
2520 /* ---------------------------------------------------------------------------------------------------- */
2521
2522 /**
2523  * g_dbus_message_to_gerror:
2524  * @message: A #GDBusMessage.
2525  * @error: The #GError to set.
2526  *
2527  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
2528  * nothing and returns %FALSE.
2529  *
2530  * Otherwise this method encodes the error in @message as a #GError
2531  * using g_dbus_error_set_dbus_error() using the information in the
2532  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
2533  * well as the first string item in @message's body.
2534  *
2535  * Returns: %TRUE if @error was set, %FALSE otherwise.
2536  *
2537  * Since: 2.26
2538  */
2539 gboolean
2540 g_dbus_message_to_gerror (GDBusMessage   *message,
2541                           GError        **error)
2542 {
2543   gboolean ret;
2544   const gchar *error_name;
2545
2546   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
2547
2548   ret = FALSE;
2549   if (message->priv->type != G_DBUS_MESSAGE_TYPE_ERROR)
2550     goto out;
2551
2552   error_name = g_dbus_message_get_error_name (message);
2553   if (error_name != NULL)
2554     {
2555       GVariant *body;
2556
2557       body = g_dbus_message_get_body (message);
2558
2559       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
2560         {
2561           const gchar *error_message;
2562           g_variant_get (body, "(&s)", &error_message);
2563           g_dbus_error_set_dbus_error (error,
2564                                        error_name,
2565                                        error_message,
2566                                        NULL);
2567         }
2568       else
2569         {
2570           /* these two situations are valid, yet pretty rare */
2571           if (body != NULL)
2572             {
2573               g_dbus_error_set_dbus_error (error,
2574                                            error_name,
2575                                            "",
2576                                            _("Error return with body of type `%s'"),
2577                                            g_variant_get_type_string (body));
2578             }
2579           else
2580             {
2581               g_dbus_error_set_dbus_error (error,
2582                                            error_name,
2583                                            "",
2584                                            _("Error return with empty body"));
2585             }
2586         }
2587     }
2588   else
2589     {
2590       /* TOOD: this shouldn't happen - should check this at message serialization
2591        * time and disconnect the peer.
2592        */
2593       g_set_error (error,
2594                    G_IO_ERROR,
2595                    G_IO_ERROR_FAILED,
2596                    "Error return without error-name header!");
2597     }
2598
2599   ret = TRUE;
2600
2601  out:
2602   return ret;
2603 }
2604
2605 /* ---------------------------------------------------------------------------------------------------- */
2606
2607 static gchar *
2608 flags_to_string (GType flags_type, guint value)
2609 {
2610   GString *s;
2611   GFlagsClass *klass;
2612   guint n;
2613
2614   klass = g_type_class_ref (flags_type);
2615   s = g_string_new (NULL);
2616   for (n = 0; n < 32; n++)
2617     {
2618       if ((value & (1<<n)) != 0)
2619         {
2620           GFlagsValue *flags_value;
2621           flags_value = g_flags_get_first_value (klass, (1<<n));
2622           if (s->len > 0)
2623             g_string_append_c (s, ',');
2624           if (flags_value != NULL)
2625             g_string_append (s, flags_value->value_nick);
2626           else
2627             g_string_append_printf (s, "unknown (bit %d)", n);
2628         }
2629     }
2630   if (s->len == 0)
2631     g_string_append (s, "none");
2632   g_type_class_unref (klass);
2633   return g_string_free (s, FALSE);
2634 }
2635
2636 static gint
2637 _sort_keys_func (gconstpointer a,
2638                  gconstpointer b)
2639 {
2640   gint ia;
2641   gint ib;
2642
2643   ia = GPOINTER_TO_INT (a);
2644   ib = GPOINTER_TO_INT (b);
2645
2646   return ia - ib;
2647 }
2648
2649 /**
2650  * g_dbus_message_print:
2651  * @message: A #GDBusMessage.
2652  * @indent: Indentation level.
2653  *
2654  * Produces a human-readable multi-line description of @message.
2655  *
2656  * The contents of the description has no ABI guarantees, the contents
2657  * and formatting is subject to change at any time. Typical output
2658  * looks something like this:
2659  * <programlisting>
2660  * Type:    method-call
2661  * Flags:   none
2662  * Version: 0
2663  * Serial:  4
2664  * Headers:
2665  *   path -> objectpath '/org/gtk/GDBus/TestObject'
2666  *   interface -> 'org.gtk.GDBus.TestInterface'
2667  *   member -> 'GimmeStdout'
2668  *   destination -> ':1.146'
2669  * Body: ()
2670  * UNIX File Descriptors:
2671  *   (none)
2672  * </programlisting>
2673  * or
2674  * <programlisting>
2675  * Type:    method-return
2676  * Flags:   no-reply-expected
2677  * Version: 0
2678  * Serial:  477
2679  * Headers:
2680  *   reply-serial -> uint32 4
2681  *   destination -> ':1.159'
2682  *   sender -> ':1.146'
2683  *   num-unix-fds -> uint32 1
2684  * Body: ()
2685  * UNIX File Descriptors:
2686  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
2687  * </programlisting>
2688  *
2689  * Returns: A string that should be freed with g_free().
2690  *
2691  * Since: 2.26
2692  */
2693 gchar *
2694 g_dbus_message_print (GDBusMessage *message,
2695                       guint         indent)
2696 {
2697   GString *str;
2698   gchar *s;
2699   GList *keys;
2700   GList *l;
2701
2702   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2703
2704   str = g_string_new (NULL);
2705
2706   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->priv->type);
2707   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
2708   g_free (s);
2709   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->priv->flags);
2710   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
2711   g_free (s);
2712   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->priv->major_protocol_version);
2713   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->priv->serial);
2714
2715   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
2716   keys = g_hash_table_get_keys (message->priv->headers);
2717   keys = g_list_sort (keys, _sort_keys_func);
2718   if (keys != NULL)
2719     {
2720       for (l = keys; l != NULL; l = l->next)
2721         {
2722           gint key = GPOINTER_TO_INT (l->data);
2723           GVariant *value;
2724           gchar *value_str;
2725
2726           value = g_hash_table_lookup (message->priv->headers, l->data);
2727           g_assert (value != NULL);
2728
2729           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
2730           value_str = g_variant_print (value, TRUE);
2731           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
2732           g_free (s);
2733           g_free (value_str);
2734         }
2735     }
2736   else
2737     {
2738       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2739     }
2740   g_string_append_printf (str, "%*sBody: ", indent, "");
2741   if (message->priv->body != NULL)
2742     {
2743       g_variant_print_string (message->priv->body,
2744                               str,
2745                               TRUE);
2746     }
2747   else
2748     {
2749       g_string_append (str, "()");
2750     }
2751   g_string_append (str, "\n");
2752 #ifdef G_OS_UNIX
2753   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
2754   if (message->priv->fd_list != NULL)
2755     {
2756       gint num_fds;
2757       const gint *fds;
2758       gint n;
2759
2760       fds = g_unix_fd_list_peek_fds (message->priv->fd_list, &num_fds);
2761       if (num_fds > 0)
2762         {
2763           for (n = 0; n < num_fds; n++)
2764             {
2765               GString *fs;
2766               struct stat statbuf;
2767               fs = g_string_new (NULL);
2768               if (fstat (fds[n], &statbuf) == 0)
2769                 {
2770                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
2771                                           major (statbuf.st_dev), minor (statbuf.st_dev));
2772                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
2773                                           statbuf.st_mode);
2774                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2775                                           (guint64) statbuf.st_ino);
2776                   g_string_append_printf (fs, "%s" "uid=%d", fs->len > 0 ? "," : "",
2777                                           statbuf.st_uid);
2778                   g_string_append_printf (fs, "%s" "gid=%d", fs->len > 0 ? "," : "",
2779                                           statbuf.st_gid);
2780                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
2781                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
2782                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2783                                           (guint64) statbuf.st_size);
2784                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2785                                           (guint64) statbuf.st_atime);
2786                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2787                                           (guint64) statbuf.st_mtime);
2788                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2789                                           (guint64) statbuf.st_ctime);
2790                 }
2791               else
2792                 {
2793                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
2794                 }
2795               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
2796               g_string_free (fs, TRUE);
2797             }
2798         }
2799       else
2800         {
2801           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
2802         }
2803     }
2804   else
2805     {
2806       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2807     }
2808 #endif
2809
2810   return g_string_free (str, FALSE);
2811 }
2812
2813
2814 #define __G_DBUS_MESSAGE_C__
2815 #include "gioaliasdef.c"