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