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