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