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