Fix some errors in translated strings
[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_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
730           g_set_error (error,
731                        G_IO_ERROR,
732                        G_IO_ERROR_INVALID_ARGUMENT,
733                        _("Wanted to read %lu bytes but got EOF"),
734                        to_read);
735           goto fail;
736         }
737
738       remaining -= num_read;
739       g_string_append_len (s, buf, num_read);
740     }
741
742   local_error = NULL;
743   nul = g_data_input_stream_read_byte (dis, NULL, &local_error);
744   if (local_error != NULL)
745     {
746       g_propagate_error (error, local_error);
747       goto fail;
748     }
749   if (nul != '\0')
750     {
751       g_set_error (error,
752                    G_IO_ERROR,
753                    G_IO_ERROR_INVALID_ARGUMENT,
754                    _("Expected NUL byte after the string `%s' but found `%c' (%d)"),
755                    s->str, nul, nul);
756       goto fail;
757     }
758
759   return g_string_free (s, FALSE);
760
761  fail:
762   g_string_free (s, TRUE);
763   return NULL;
764 }
765
766 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
767
768 /* returns a non-floating GVariant! */
769 static GVariant *
770 parse_value_from_blob (GMemoryInputStream    *mis,
771                        GDataInputStream      *dis,
772                        const GVariantType    *type,
773                        gboolean               just_align,
774                        guint                  indent,
775                        GError               **error)
776 {
777   GVariant *ret;
778   GError *local_error;
779   gboolean is_leaf;
780
781 #ifdef DEBUG_SERIALIZER
782   if (!just_align)
783     {
784       gchar *s;
785       s = g_variant_type_dup_string (type);
786       g_print ("%*sReading type %s from offset 0x%04x",
787                indent, "",
788                s,
789                (gint) g_seekable_tell (G_SEEKABLE (mis)));
790       g_free (s);
791     }
792 #endif /* DEBUG_SERIALIZER */
793
794   ret = NULL;
795
796   is_leaf = TRUE;
797   local_error = NULL;
798   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
799     {
800       if (!ensure_input_padding (mis, 4, &local_error))
801         goto fail;
802       if (!just_align)
803         {
804           gboolean v;
805           v = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
806           if (local_error != NULL)
807             goto fail;
808           ret = g_variant_new_boolean (v);
809         }
810     }
811   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
812     {
813       if (!just_align)
814         {
815           guchar v;
816           v = g_data_input_stream_read_byte (dis, NULL, &local_error);
817           if (local_error != NULL)
818             goto fail;
819           ret = g_variant_new_byte (v);
820         }
821     }
822   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
823     {
824       if (!ensure_input_padding (mis, 2, &local_error))
825         goto fail;
826       if (!just_align)
827         {
828           gint16 v;
829           v = g_data_input_stream_read_int16 (dis, NULL, &local_error);
830           if (local_error != NULL)
831             goto fail;
832           ret = g_variant_new_int16 (v);
833         }
834     }
835   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
836     {
837       if (!ensure_input_padding (mis, 2, &local_error))
838         goto fail;
839       if (!just_align)
840         {
841           guint16 v;
842           v = g_data_input_stream_read_uint16 (dis, NULL, &local_error);
843           if (local_error != NULL)
844             goto fail;
845           ret = g_variant_new_uint16 (v);
846         }
847     }
848   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
849     {
850       if (!ensure_input_padding (mis, 4, &local_error))
851         goto fail;
852       if (!just_align)
853         {
854           gint32 v;
855           v = g_data_input_stream_read_int32 (dis, NULL, &local_error);
856           if (local_error != NULL)
857             goto fail;
858           ret = g_variant_new_int32 (v);
859         }
860     }
861   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
862     {
863       if (!ensure_input_padding (mis, 4, &local_error))
864         goto fail;
865       if (!just_align)
866         {
867           guint32 v;
868           v = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
869           if (local_error != NULL)
870             goto fail;
871           ret = g_variant_new_uint32 (v);
872         }
873     }
874   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
875     {
876       if (!ensure_input_padding (mis, 8, &local_error))
877         goto fail;
878       if (!just_align)
879         {
880           gint64 v;
881           v = g_data_input_stream_read_int64 (dis, NULL, &local_error);
882           if (local_error != NULL)
883             goto fail;
884           ret = g_variant_new_int64 (v);
885         }
886     }
887   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
888     {
889       if (!ensure_input_padding (mis, 8, &local_error))
890         goto fail;
891       if (!just_align)
892         {
893           guint64 v;
894           v = g_data_input_stream_read_uint64 (dis, NULL, &local_error);
895           if (local_error != NULL)
896             goto fail;
897           ret = g_variant_new_uint64 (v);
898         }
899     }
900   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
901     {
902       if (!ensure_input_padding (mis, 8, &local_error))
903         goto fail;
904       if (!just_align)
905         {
906           guint64 v;
907           gdouble *encoded;
908           v = g_data_input_stream_read_uint64 (dis, NULL, &local_error);
909           if (local_error != NULL)
910             goto fail;
911           /* TODO: hmm */
912           encoded = (gdouble *) &v;
913           ret = g_variant_new_double (*encoded);
914         }
915     }
916   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
917     {
918       if (!ensure_input_padding (mis, 4, &local_error))
919         goto fail;
920       if (!just_align)
921         {
922           guint32 len;
923           gchar *v;
924           len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
925           if (local_error != NULL)
926             goto fail;
927           v = read_string (mis, dis, (gsize) len, &local_error);
928           if (v == NULL)
929             goto fail;
930           ret = g_variant_new_string (v);
931           g_free (v);
932         }
933     }
934   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
935     {
936       if (!ensure_input_padding (mis, 4, &local_error))
937         goto fail;
938       if (!just_align)
939         {
940           guint32 len;
941           gchar *v;
942           len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
943           if (local_error != NULL)
944             goto fail;
945           v = read_string (mis, dis, (gsize) len, &local_error);
946           if (v == NULL)
947             goto fail;
948           if (!g_variant_is_object_path (v))
949             {
950               g_set_error (&local_error,
951                            G_IO_ERROR,
952                            G_IO_ERROR_INVALID_ARGUMENT,
953                            _("Parsed value `%s' is not a valid D-Bus object path"),
954                            v);
955               g_free (v);
956               goto fail;
957             }
958           ret = g_variant_new_object_path (v);
959           g_free (v);
960         }
961     }
962   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
963     {
964       if (!just_align)
965         {
966           guchar len;
967           gchar *v;
968           len = g_data_input_stream_read_byte (dis, NULL, &local_error);
969           if (local_error != NULL)
970             goto fail;
971           v = read_string (mis, dis, (gsize) len, &local_error);
972           if (v == NULL)
973             goto fail;
974           if (!g_variant_is_signature (v))
975             {
976               g_set_error (&local_error,
977                            G_IO_ERROR,
978                            G_IO_ERROR_INVALID_ARGUMENT,
979                            _("Parsed value `%s' is not a valid D-Bus signature"),
980                        v);
981               g_free (v);
982               goto fail;
983             }
984           ret = g_variant_new_signature (v);
985           g_free (v);
986         }
987     }
988   else if (g_variant_type_is_array (type))
989     {
990       guint32 array_len;
991       goffset offset;
992       goffset target;
993       const GVariantType *element_type;
994       GVariantBuilder builder;
995
996       if (!ensure_input_padding (mis, 4, &local_error))
997         goto fail;
998
999       if (just_align)
1000         {
1001           array_len = 0;
1002         }
1003       else
1004         {
1005           array_len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
1006           if (local_error != NULL)
1007             goto fail;
1008
1009           is_leaf = FALSE;
1010 #ifdef DEBUG_SERIALIZER
1011           g_print (": array spans 0x%04x bytes\n", array_len);
1012 #endif /* DEBUG_SERIALIZER */
1013
1014           if (array_len > (2<<26))
1015             {
1016               /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1017               g_set_error (&local_error,
1018                            G_IO_ERROR,
1019                            G_IO_ERROR_INVALID_ARGUMENT,
1020                            _("Encountered array of length %u bytes. Maximum length is 2<<26 bytes."),
1021                            array_len);
1022               goto fail;
1023             }
1024         }
1025
1026       g_variant_builder_init (&builder, type);
1027       element_type = g_variant_type_element (type);
1028
1029       if (array_len == 0)
1030         {
1031           GVariant *item;
1032           item = parse_value_from_blob (mis,
1033                                         dis,
1034                                         element_type,
1035                                         TRUE,
1036                                         indent + 2,
1037                                         &local_error);
1038           g_assert (item == NULL);
1039         }
1040       else
1041         {
1042           /* TODO: optimize array of primitive types */
1043           offset = g_seekable_tell (G_SEEKABLE (mis));
1044           target = offset + array_len;
1045           while (offset < target)
1046             {
1047               GVariant *item;
1048               item = parse_value_from_blob (mis,
1049                                             dis,
1050                                             element_type,
1051                                             FALSE,
1052                                             indent + 2,
1053                                             &local_error);
1054               if (item == NULL)
1055                 {
1056                   g_variant_builder_clear (&builder);
1057                   goto fail;
1058                 }
1059               g_variant_builder_add_value (&builder, item);
1060               g_variant_unref (item);
1061               offset = g_seekable_tell (G_SEEKABLE (mis));
1062             }
1063         }
1064
1065       if (!just_align)
1066         {
1067           ret = g_variant_builder_end (&builder);
1068         }
1069       else
1070         {
1071           g_variant_builder_clear (&builder);
1072         }
1073     }
1074   else if (g_variant_type_is_dict_entry (type))
1075     {
1076       const GVariantType *key_type;
1077       const GVariantType *value_type;
1078       GVariant *key;
1079       GVariant *value;
1080
1081       if (!ensure_input_padding (mis, 8, &local_error))
1082         goto fail;
1083
1084       is_leaf = FALSE;
1085 #ifdef DEBUG_SERIALIZER
1086       g_print ("\n");
1087 #endif /* DEBUG_SERIALIZER */
1088
1089       if (!just_align)
1090         {
1091           key_type = g_variant_type_key (type);
1092           key = parse_value_from_blob (mis,
1093                                        dis,
1094                                        key_type,
1095                                        FALSE,
1096                                        indent + 2,
1097                                        &local_error);
1098           if (key == NULL)
1099             goto fail;
1100           value_type = g_variant_type_value (type);
1101           value = parse_value_from_blob (mis,
1102                                          dis,
1103                                          value_type,
1104                                          FALSE,
1105                                          indent + 2,
1106                                          &local_error);
1107           if (value == NULL)
1108             {
1109               g_variant_unref (key);
1110               goto fail;
1111             }
1112           ret = g_variant_new_dict_entry (key, value);
1113           g_variant_unref (key);
1114           g_variant_unref (value);
1115         }
1116     }
1117   else if (g_variant_type_is_tuple (type))
1118     {
1119       if (!ensure_input_padding (mis, 8, &local_error))
1120         goto fail;
1121
1122       is_leaf = FALSE;
1123 #ifdef DEBUG_SERIALIZER
1124       g_print ("\n");
1125 #endif /* DEBUG_SERIALIZER */
1126
1127       if (!just_align)
1128         {
1129           const GVariantType *element_type;
1130           GVariantBuilder builder;
1131
1132           g_variant_builder_init (&builder, type);
1133           element_type = g_variant_type_first (type);
1134           while (element_type != NULL)
1135             {
1136               GVariant *item;
1137               item = parse_value_from_blob (mis,
1138                                             dis,
1139                                             element_type,
1140                                             FALSE,
1141                                             indent + 2,
1142                                             &local_error);
1143               if (item == NULL)
1144                 {
1145                   g_variant_builder_clear (&builder);
1146                   goto fail;
1147                 }
1148               g_variant_builder_add_value (&builder, item);
1149               g_variant_unref (item);
1150
1151               element_type = g_variant_type_next (element_type);
1152             }
1153           ret = g_variant_builder_end (&builder);
1154         }
1155     }
1156   else if (g_variant_type_is_variant (type))
1157     {
1158       is_leaf = FALSE;
1159 #ifdef DEBUG_SERIALIZER
1160       g_print ("\n");
1161 #endif /* DEBUG_SERIALIZER */
1162
1163       if (!just_align)
1164         {
1165           guchar siglen;
1166           gchar *sig;
1167           GVariantType *variant_type;
1168           GVariant *value;
1169
1170           siglen = g_data_input_stream_read_byte (dis, NULL, &local_error);
1171           if (local_error != NULL)
1172             goto fail;
1173           sig = read_string (mis, dis, (gsize) siglen, &local_error);
1174           if (sig == NULL)
1175             goto fail;
1176           if (!g_variant_is_signature (sig))
1177             {
1178               g_set_error (&local_error,
1179                            G_IO_ERROR,
1180                            G_IO_ERROR_INVALID_ARGUMENT,
1181                            _("Parsed value `%s' for variant is not a valid D-Bus signature"),
1182                            sig);
1183               g_free (sig);
1184               goto fail;
1185             }
1186           variant_type = g_variant_type_new (sig);
1187           g_free (sig);
1188           value = parse_value_from_blob (mis,
1189                                          dis,
1190                                          variant_type,
1191                                          FALSE,
1192                                          indent + 2,
1193                                          &local_error);
1194           g_variant_type_free (variant_type);
1195           if (value == NULL)
1196             goto fail;
1197           ret = g_variant_new_variant (value);
1198           g_variant_unref (value);
1199         }
1200     }
1201   else
1202     {
1203       gchar *s;
1204       s = g_variant_type_dup_string (type);
1205       g_set_error (&local_error,
1206                    G_IO_ERROR,
1207                    G_IO_ERROR_INVALID_ARGUMENT,
1208                    _("Error deserializing GVariant with type-string `%s' from the D-Bus wire format"),
1209                    s);
1210       g_free (s);
1211       goto fail;
1212     }
1213
1214   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1215
1216 #ifdef DEBUG_SERIALIZER
1217   if (ret != NULL)
1218     {
1219       if (is_leaf)
1220         {
1221           gchar *s;
1222           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1223             {
1224               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1225             }
1226           else
1227             {
1228               s = g_variant_print (ret, FALSE);
1229             }
1230           g_print (": %s\n", s);
1231           g_free (s);
1232         }
1233     }
1234 #endif /* DEBUG_SERIALIZER */
1235
1236   /* sink the reference */
1237   if (ret != NULL)
1238     {
1239       g_assert (g_variant_is_floating (ret));
1240       g_variant_ref_sink (ret);
1241     }
1242   return ret;
1243
1244  fail:
1245 #ifdef DEBUG_SERIALIZER
1246   g_print ("\n"
1247            "%*sFAILURE: %s (%s, %d)\n",
1248            indent, "",
1249            local_error->message,
1250            g_quark_to_string (local_error->domain),
1251            local_error->code);
1252 #endif /* DEBUG_SERIALIZER */
1253   g_propagate_error (error, local_error);
1254   return NULL;
1255 }
1256
1257 /* ---------------------------------------------------------------------------------------------------- */
1258
1259 /* message_header must be at least 16 bytes */
1260
1261 /**
1262  * g_dbus_message_bytes_needed:
1263  * @blob: A blob represent a binary D-Bus message.
1264  * @blob_len: The length of @blob (must be at least 16).
1265  * @error: Return location for error or %NULL.
1266  *
1267  * Utility function to calculate how many bytes are needed to
1268  * completely deserialize the D-Bus message stored at @blob.
1269  *
1270  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1271  * @blob contains invalid data or not enough data is available to
1272  * determine the size).
1273  *
1274  * Since: 2.26
1275  */
1276 gssize
1277 g_dbus_message_bytes_needed (guchar                *blob,
1278                              gsize                  blob_len,
1279                              GError               **error)
1280 {
1281   gssize ret;
1282
1283   ret = -1;
1284
1285   g_return_val_if_fail (blob != NULL, -1);
1286   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1287   g_return_val_if_fail (blob_len >= 16, -1);
1288
1289   if (blob[0] == 'l')
1290     {
1291       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1292       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1293       /* round up so it's a multiple of 8 */
1294       ret = 8 * ((ret + 7)/8);
1295       /* finally add the body size */
1296       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1297     }
1298   else if (blob[0] == 'B')
1299     {
1300       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1301       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1302       /* round up so it's a multiple of 8 */
1303       ret = 8 * ((ret + 7)/8);
1304       /* finally add the body size */
1305       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1306     }
1307   else
1308     {
1309       g_set_error (error,
1310                    G_IO_ERROR,
1311                    G_IO_ERROR_INVALID_ARGUMENT,
1312                    "Unable to determine message blob length - given blob is malformed");
1313     }
1314
1315   if (ret > (2<<27))
1316     {
1317       g_set_error (error,
1318                    G_IO_ERROR,
1319                    G_IO_ERROR_INVALID_ARGUMENT,
1320                    "Blob indicates that message exceeds maximum message length (128MiB)");
1321       ret = -1;
1322     }
1323
1324   return ret;
1325 }
1326
1327 /* ---------------------------------------------------------------------------------------------------- */
1328
1329 /**
1330  * g_dbus_message_new_from_blob:
1331  * @blob: A blob represent a binary D-Bus message.
1332  * @blob_len: The length of @blob.
1333  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1334  * @error: Return location for error or %NULL.
1335  *
1336  * Creates a new #GDBusMessage from the data stored at @blob.
1337  *
1338  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
1339  * g_object_unref().
1340  *
1341  * Since: 2.26
1342  */
1343 GDBusMessage *
1344 g_dbus_message_new_from_blob (guchar                *blob,
1345                               gsize                  blob_len,
1346                               GDBusCapabilityFlags   capabilities,
1347                               GError               **error)
1348 {
1349   gboolean ret;
1350   GMemoryInputStream *mis;
1351   GDataInputStream *dis;
1352   GDBusMessage *message;
1353   guchar endianness;
1354   guchar major_protocol_version;
1355   GDataStreamByteOrder byte_order;
1356   guint32 message_body_len;
1357   GVariant *headers;
1358   GVariant *item;
1359   GVariantIter iter;
1360   GVariant *signature;
1361
1362   /* TODO: check against @capabilities */
1363
1364   ret = FALSE;
1365
1366   g_return_val_if_fail (blob != NULL, NULL);
1367   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1368   g_return_val_if_fail (blob_len >= 12, NULL);
1369
1370   message = g_dbus_message_new ();
1371
1372   mis = G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (blob, blob_len, NULL));
1373   dis = g_data_input_stream_new (G_INPUT_STREAM (mis));
1374
1375   endianness = g_data_input_stream_read_byte (dis, NULL, NULL);
1376   switch (endianness)
1377     {
1378     case 'l':
1379       byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1380       break;
1381     case 'B':
1382       byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
1383       break;
1384     default:
1385       g_set_error (error,
1386                    G_IO_ERROR,
1387                    G_IO_ERROR_INVALID_ARGUMENT,
1388                    _("Invalid endianness value. Expected 'l' or 'B' but found '%c' (%d)"),
1389                    endianness, endianness);
1390       goto out;
1391     }
1392   g_data_input_stream_set_byte_order (dis, byte_order);
1393
1394   message->priv->type = g_data_input_stream_read_byte (dis, NULL, NULL);
1395   message->priv->flags = g_data_input_stream_read_byte (dis, NULL, NULL);
1396   major_protocol_version = g_data_input_stream_read_byte (dis, NULL, NULL);
1397   if (major_protocol_version != 1)
1398     {
1399       g_set_error (error,
1400                    G_IO_ERROR,
1401                    G_IO_ERROR_INVALID_ARGUMENT,
1402                    _("Invalid major protocol version. Expected 1 but found %d"),
1403                    major_protocol_version);
1404       goto out;
1405     }
1406   message_body_len = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1407   message->priv->serial = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1408
1409 #ifdef DEBUG_SERIALIZER
1410   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1411   {
1412     gchar *s;
1413     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
1414     g_print ("%s\n", s);
1415     g_free (s);
1416   }
1417 #endif /* DEBUG_SERIALIZER */
1418
1419 #ifdef DEBUG_SERIALIZER
1420   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1421 #endif /* DEBUG_SERIALIZER */
1422   headers = parse_value_from_blob (mis,
1423                                    dis,
1424                                    G_VARIANT_TYPE ("a{yv}"),
1425                                    FALSE,
1426                                    2,
1427                                    error);
1428   if (headers == NULL)
1429     goto out;
1430   g_variant_iter_init (&iter, headers);
1431   while ((item = g_variant_iter_next_value (&iter)) != NULL)
1432     {
1433       guchar header_field;
1434       GVariant *value;
1435       g_variant_get (item,
1436                      "{yv}",
1437                      &header_field,
1438                      &value);
1439       g_dbus_message_set_header (message, header_field, value);
1440       g_variant_unref (value);
1441       g_variant_unref (item);
1442     }
1443   g_variant_unref (headers);
1444
1445   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
1446   if (signature != NULL)
1447     {
1448       const gchar *signature_str;
1449       gsize signature_str_len;
1450
1451       signature_str = g_variant_get_string (signature, &signature_str_len);
1452
1453       /* signature but no body */
1454       if (message_body_len == 0 && signature_str_len > 0)
1455         {
1456           g_set_error (error,
1457                        G_IO_ERROR,
1458                        G_IO_ERROR_INVALID_ARGUMENT,
1459                        _("Signature header with signature `%s' found but message body is empty"),
1460                        signature_str);
1461           goto out;
1462         }
1463       else if (signature_str_len > 0)
1464         {
1465           GVariantType *variant_type;
1466           gchar *tupled_signature_str;
1467
1468           if (!g_variant_is_signature (signature_str))
1469             {
1470               g_set_error (error,
1471                            G_IO_ERROR,
1472                            G_IO_ERROR_INVALID_ARGUMENT,
1473                            _("Parsed value `%s' is not a valid D-Bus signature (for body)"),
1474                            signature_str);
1475               goto out;
1476             }
1477           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
1478           variant_type = g_variant_type_new (tupled_signature_str);
1479           g_free (tupled_signature_str);
1480 #ifdef DEBUG_SERIALIZER
1481           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1482 #endif /* DEBUG_SERIALIZER */
1483           message->priv->body = parse_value_from_blob (mis,
1484                                                        dis,
1485                                                        variant_type,
1486                                                        FALSE,
1487                                                        2,
1488                                                        error);
1489           g_variant_type_free (variant_type);
1490           if (message->priv->body == NULL)
1491             goto out;
1492         }
1493     }
1494   else
1495     {
1496       /* no signature, this is only OK if the body is empty */
1497       if (message_body_len != 0)
1498         {
1499           /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
1500           g_set_error (error,
1501                        G_IO_ERROR,
1502                        G_IO_ERROR_INVALID_ARGUMENT,
1503                        _("No signature header in message but the message body is %u bytes"),
1504                        message_body_len);
1505           goto out;
1506         }
1507     }
1508
1509
1510   ret = TRUE;
1511
1512  out:
1513   g_object_unref (dis);
1514   g_object_unref (mis);
1515
1516   if (ret)
1517     {
1518       return message;
1519     }
1520   else
1521     {
1522       if (message != NULL)
1523         g_object_unref (message);
1524       return NULL;
1525     }
1526 }
1527
1528 /* ---------------------------------------------------------------------------------------------------- */
1529
1530 static gsize
1531 ensure_output_padding (GMemoryOutputStream  *mos,
1532                        GDataOutputStream    *dos,
1533                        gsize                 padding_size)
1534 {
1535   gsize offset;
1536   gsize wanted_offset;
1537   gsize padding_needed;
1538   guint n;
1539
1540   offset = g_memory_output_stream_get_data_size (mos);
1541   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1542   padding_needed = wanted_offset - offset;
1543
1544   for (n = 0; n < padding_needed; n++)
1545     g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1546
1547   return padding_needed;
1548 }
1549
1550 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
1551 static gboolean
1552 append_value_to_blob (GVariant             *value,
1553                       const GVariantType   *type,
1554                       GMemoryOutputStream  *mos,
1555                       GDataOutputStream    *dos,
1556                       gsize                *out_padding_added,
1557                       GError              **error)
1558 {
1559   gsize padding_added;
1560
1561   padding_added = 0;
1562
1563   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1564     {
1565       padding_added = ensure_output_padding (mos, dos, 4);
1566       if (value != NULL)
1567         {
1568           gboolean v = g_variant_get_boolean (value);
1569           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1570         }
1571     }
1572   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1573     {
1574       if (value != NULL)
1575         {
1576           guint8 v = g_variant_get_byte (value);
1577           g_data_output_stream_put_byte (dos, v, NULL, NULL);
1578         }
1579     }
1580   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
1581     {
1582       padding_added = ensure_output_padding (mos, dos, 2);
1583       if (value != NULL)
1584         {
1585           gint16 v = g_variant_get_int16 (value);
1586           g_data_output_stream_put_int16 (dos, v, NULL, NULL);
1587         }
1588     }
1589   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
1590     {
1591       padding_added = ensure_output_padding (mos, dos, 2);
1592       if (value != NULL)
1593         {
1594           guint16 v = g_variant_get_uint16 (value);
1595           g_data_output_stream_put_uint16 (dos, v, NULL, NULL);
1596         }
1597     }
1598   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
1599     {
1600       padding_added = ensure_output_padding (mos, dos, 4);
1601       if (value != NULL)
1602         {
1603           gint32 v = g_variant_get_int32 (value);
1604           g_data_output_stream_put_int32 (dos, v, NULL, NULL);
1605         }
1606     }
1607   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
1608     {
1609       padding_added = ensure_output_padding (mos, dos, 4);
1610       if (value != NULL)
1611         {
1612           guint32 v = g_variant_get_uint32 (value);
1613           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1614         }
1615     }
1616   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
1617     {
1618       padding_added = ensure_output_padding (mos, dos, 8);
1619       if (value != NULL)
1620         {
1621           gint64 v = g_variant_get_int64 (value);
1622           g_data_output_stream_put_int64 (dos, v, NULL, NULL);
1623         }
1624     }
1625   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
1626     {
1627       padding_added = ensure_output_padding (mos, dos, 8);
1628       if (value != NULL)
1629         {
1630           guint64 v = g_variant_get_uint64 (value);
1631           g_data_output_stream_put_uint64 (dos, v, NULL, NULL);
1632         }
1633     }
1634   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1635     {
1636       padding_added = ensure_output_padding (mos, dos, 8);
1637       if (value != NULL)
1638         {
1639           guint64 *encoded;
1640           gdouble v = g_variant_get_double (value);
1641           /* TODO: hmm */
1642           encoded = (guint64 *) &v;
1643           g_data_output_stream_put_uint64 (dos, *encoded, NULL, NULL);
1644         }
1645     }
1646   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1647     {
1648       padding_added = ensure_output_padding (mos, dos, 4);
1649       if (value != NULL)
1650         {
1651           gsize len;
1652           const gchar *v = g_variant_get_string (value, &len);
1653           g_data_output_stream_put_uint32 (dos, len, NULL, NULL);
1654           g_data_output_stream_put_string (dos, v, NULL, NULL);
1655           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1656         }
1657     }
1658   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1659     {
1660       padding_added = ensure_output_padding (mos, dos, 4);
1661       if (value != NULL)
1662         {
1663           /* TODO: validate object path */
1664           gsize len;
1665           const gchar *v = g_variant_get_string (value, &len);
1666           g_data_output_stream_put_uint32 (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_equal (type, G_VARIANT_TYPE_SIGNATURE))
1672     {
1673       if (value != NULL)
1674         {
1675           /* TODO: validate signature (including max len being 255) */
1676           gsize len;
1677           const gchar *v = g_variant_get_string (value, &len);
1678           g_data_output_stream_put_byte (dos, len, NULL, NULL);
1679           g_data_output_stream_put_string (dos, v, NULL, NULL);
1680           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1681         }
1682     }
1683   else if (g_variant_type_is_array (type))
1684     {
1685       GVariant *item;
1686       GVariantIter iter;
1687       goffset array_len_offset;
1688       goffset array_payload_begin_offset;
1689       goffset cur_offset;
1690       gsize array_len;
1691
1692       padding_added = ensure_output_padding (mos, dos, 4);
1693       if (value != NULL)
1694         {
1695           /* array length - will be filled in later */
1696           array_len_offset = g_memory_output_stream_get_data_size (mos);
1697           g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
1698
1699           /* From the D-Bus spec:
1700            *
1701            *   "A UINT32 giving the length of the array data in bytes,
1702            *    followed by alignment padding to the alignment boundary of
1703            *    the array element type, followed by each array element. The
1704            *    array length is from the end of the alignment padding to
1705            *    the end of the last element, i.e. it does not include the
1706            *    padding after the length, or any padding after the last
1707            *    element."
1708            *
1709            * Thus, we need to count how much padding the first element
1710            * contributes and subtract that from the array length.
1711            */
1712           array_payload_begin_offset = g_memory_output_stream_get_data_size (mos);
1713
1714           if (g_variant_n_children (value) == 0)
1715             {
1716               gsize padding_added_for_item;
1717               if (!append_value_to_blob (NULL,
1718                                          g_variant_type_element (type),
1719                                          mos,
1720                                          dos,
1721                                          &padding_added_for_item,
1722                                          error))
1723                 goto fail;
1724               array_payload_begin_offset += padding_added_for_item;
1725             }
1726           else
1727             {
1728               guint n;
1729               n = 0;
1730               g_variant_iter_init (&iter, value);
1731               while ((item = g_variant_iter_next_value (&iter)) != NULL)
1732                 {
1733                   gsize padding_added_for_item;
1734                   if (!append_value_to_blob (item,
1735                                              g_variant_get_type (item),
1736                                              mos,
1737                                              dos,
1738                                              &padding_added_for_item,
1739                                              error))
1740                     {
1741                       g_variant_unref (item);
1742                       goto fail;
1743                     }
1744                   g_variant_unref (item);
1745                   if (n == 0)
1746                     {
1747                       array_payload_begin_offset += padding_added_for_item;
1748                     }
1749                   n++;
1750                 }
1751             }
1752
1753           cur_offset = g_memory_output_stream_get_data_size (mos);
1754
1755           array_len = cur_offset - array_payload_begin_offset;
1756
1757           if (!g_seekable_seek (G_SEEKABLE (mos), array_len_offset, G_SEEK_SET, NULL, error))
1758             goto fail;
1759
1760           g_data_output_stream_put_uint32 (dos, array_len, NULL, NULL);
1761
1762           if (!g_seekable_seek (G_SEEKABLE (mos), cur_offset, G_SEEK_SET, NULL, error))
1763             goto fail;
1764         }
1765     }
1766   else if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
1767     {
1768       padding_added = ensure_output_padding (mos, dos, 8);
1769       if (value != NULL)
1770         {
1771           GVariant *item;
1772           GVariantIter iter;
1773           g_variant_iter_init (&iter, value);
1774           while ((item = g_variant_iter_next_value (&iter)) != NULL)
1775             {
1776               if (!append_value_to_blob (item,
1777                                          g_variant_get_type (item),
1778                                          mos,
1779                                          dos,
1780                                          NULL,
1781                                          error))
1782                 {
1783                   g_variant_unref (item);
1784                   goto fail;
1785                 }
1786               g_variant_unref (item);
1787             }
1788         }
1789     }
1790   else if (g_variant_type_is_variant (type))
1791     {
1792       if (value != NULL)
1793         {
1794           GVariant *child;
1795           const gchar *signature;
1796           child = g_variant_get_child_value (value, 0);
1797           signature = g_variant_get_type_string (child);
1798           /* TODO: validate signature (including max len being 255) */
1799           g_data_output_stream_put_byte (dos, strlen (signature), NULL, NULL);
1800           g_data_output_stream_put_string (dos, signature, NULL, NULL);
1801           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1802           if (!append_value_to_blob (child,
1803                                      g_variant_get_type (child),
1804                                      mos,
1805                                      dos,
1806                                      NULL,
1807                                      error))
1808             {
1809               g_variant_unref (child);
1810               goto fail;
1811             }
1812           g_variant_unref (child);
1813         }
1814     }
1815   else
1816     {
1817       g_set_error (error,
1818                    G_IO_ERROR,
1819                    G_IO_ERROR_INVALID_ARGUMENT,
1820                    _("Error serializing GVariant with type-string `%s' to the D-Bus wire format"),
1821                    g_variant_get_type_string (value));
1822       goto fail;
1823     }
1824
1825   if (out_padding_added != NULL)
1826     *out_padding_added = padding_added;
1827
1828   return TRUE;
1829
1830  fail:
1831   return FALSE;
1832 }
1833
1834 static gboolean
1835 append_body_to_blob (GVariant             *value,
1836                      GMemoryOutputStream  *mos,
1837                      GDataOutputStream    *dos,
1838                      GError              **error)
1839 {
1840   gboolean ret;
1841   GVariant *item;
1842   GVariantIter iter;
1843
1844   ret = FALSE;
1845
1846   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
1847     {
1848       g_set_error (error,
1849                    G_IO_ERROR,
1850                    G_IO_ERROR_INVALID_ARGUMENT,
1851                    "Expected a tuple for the body of the GDBusMessage.");
1852       goto fail;
1853     }
1854
1855   g_variant_iter_init (&iter, value);
1856   while ((item = g_variant_iter_next_value (&iter)) != NULL)
1857     {
1858       if (!append_value_to_blob (item,
1859                                  g_variant_get_type (item),
1860                                  mos,
1861                                  dos,
1862                                  NULL,
1863                                  error))
1864         {
1865           g_variant_unref (item);
1866           goto fail;
1867         }
1868       g_variant_unref (item);
1869     }
1870   return TRUE;
1871
1872  fail:
1873   return FALSE;
1874 }
1875
1876 /* ---------------------------------------------------------------------------------------------------- */
1877
1878 /**
1879  * g_dbus_message_to_blob:
1880  * @message: A #GDBusMessage.
1881  * @out_size: Return location for size of generated blob.
1882  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1883  * @error: Return location for error.
1884  *
1885  * Serializes @message to a blob.
1886  *
1887  * Returns: A pointer to a valid binary D-Bus message of @out_size bytes
1888  * generated by @message or %NULL if @error is set. Free with g_free().
1889  *
1890  * Since: 2.26
1891  */
1892 guchar *
1893 g_dbus_message_to_blob (GDBusMessage          *message,
1894                         gsize                 *out_size,
1895                         GDBusCapabilityFlags   capabilities,
1896                         GError               **error)
1897 {
1898   GMemoryOutputStream *mos;
1899   GDataOutputStream *dos;
1900   guchar *ret;
1901   gsize size;
1902   GDataStreamByteOrder byte_order;
1903   goffset body_len_offset;
1904   goffset body_start_offset;
1905   gsize body_size;
1906   GVariant *header_fields;
1907   GVariantBuilder builder;
1908   GHashTableIter hash_iter;
1909   gpointer key;
1910   GVariant *header_value;
1911   GVariant *signature;
1912   const gchar *signature_str;
1913   gint num_fds_in_message;
1914   gint num_fds_according_to_header;
1915
1916   /* TODO: check against @capabilities */
1917
1918   ret = NULL;
1919
1920   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1921   g_return_val_if_fail (out_size != NULL, NULL);
1922   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1923
1924   mos = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
1925   dos = g_data_output_stream_new (G_OUTPUT_STREAM (mos));
1926
1927   /* TODO: detect endianess... */
1928   byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1929   g_data_output_stream_set_byte_order (dos, byte_order);
1930
1931   /* Core header */
1932   g_data_output_stream_put_byte (dos, byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN ? 'l' : 'B', NULL, NULL);
1933   g_data_output_stream_put_byte (dos, message->priv->type, NULL, NULL);
1934   g_data_output_stream_put_byte (dos, message->priv->flags, NULL, NULL);
1935   g_data_output_stream_put_byte (dos, 1, NULL, NULL); /* major protocol version */
1936   body_len_offset = g_memory_output_stream_get_data_size (mos);
1937   /* body length - will be filled in later */
1938   g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
1939   g_data_output_stream_put_uint32 (dos, message->priv->serial, NULL, NULL);
1940
1941   num_fds_in_message = 0;
1942 #ifdef G_OS_UNIX
1943   if (message->priv->fd_list != NULL)
1944     num_fds_in_message = g_unix_fd_list_get_length (message->priv->fd_list);
1945 #endif
1946   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
1947   /* TODO: check we have all the right header fields and that they are the correct value etc etc */
1948   if (num_fds_in_message != num_fds_according_to_header)
1949     {
1950       g_set_error (error,
1951                    G_IO_ERROR,
1952                    G_IO_ERROR_INVALID_ARGUMENT,
1953                    _("Message has %d fds but the header field indicates %d fds"),
1954                    num_fds_in_message,
1955                    num_fds_according_to_header);
1956       goto out;
1957     }
1958
1959   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
1960   g_hash_table_iter_init (&hash_iter, message->priv->headers);
1961   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
1962     {
1963       g_variant_builder_add (&builder,
1964                              "{yv}",
1965                              (guchar) GPOINTER_TO_UINT (key),
1966                              header_value);
1967     }
1968   header_fields = g_variant_builder_end (&builder);
1969
1970   if (!append_value_to_blob (header_fields,
1971                              g_variant_get_type (header_fields),
1972                              mos, dos,
1973                              NULL,
1974                              error))
1975     {
1976       g_variant_unref (header_fields);
1977       goto out;
1978     }
1979   g_variant_unref (header_fields);
1980
1981   /* header size must be a multiple of 8 */
1982   ensure_output_padding (mos, dos, 8);
1983
1984   body_start_offset = g_memory_output_stream_get_data_size (mos);
1985
1986   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
1987   signature_str = NULL;
1988   if (signature != NULL)
1989       signature_str = g_variant_get_string (signature, NULL);
1990   if (message->priv->body != NULL)
1991     {
1992       gchar *tupled_signature_str;
1993       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
1994       if (signature == NULL)
1995         {
1996           g_set_error (error,
1997                        G_IO_ERROR,
1998                        G_IO_ERROR_INVALID_ARGUMENT,
1999                        _("Message body has signature `%s' but there is no signature header"),
2000                        signature_str);
2001           g_free (tupled_signature_str);
2002           goto out;
2003         }
2004       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->priv->body)) != 0)
2005         {
2006           g_set_error (error,
2007                        G_IO_ERROR,
2008                        G_IO_ERROR_INVALID_ARGUMENT,
2009                        _("Message body has type signature `%s' but signature in the header field is `%s'"),
2010                        tupled_signature_str, g_variant_get_type_string (message->priv->body));
2011           g_free (tupled_signature_str);
2012           goto out;
2013         }
2014       g_free (tupled_signature_str);
2015       if (!append_body_to_blob (message->priv->body, mos, dos, error))
2016         goto out;
2017     }
2018   else
2019     {
2020       if (signature != NULL)
2021         {
2022           g_set_error (error,
2023                        G_IO_ERROR,
2024                        G_IO_ERROR_INVALID_ARGUMENT,
2025                        _("Message body is empty but signature in the header field is `(%s)'"),
2026                        signature_str);
2027           goto out;
2028         }
2029     }
2030
2031   /* OK, we're done writing the message - set the body length */
2032   size = g_memory_output_stream_get_data_size (mos);
2033   body_size = size - body_start_offset;
2034
2035   if (!g_seekable_seek (G_SEEKABLE (mos), body_len_offset, G_SEEK_SET, NULL, error))
2036     goto out;
2037
2038   g_data_output_stream_put_uint32 (dos, body_size, NULL, NULL);
2039
2040   *out_size = size;
2041   ret = g_memdup (g_memory_output_stream_get_data (mos), size);
2042
2043  out:
2044   g_object_unref (dos);
2045   g_object_unref (mos);
2046
2047   return ret;
2048 }
2049
2050 /* ---------------------------------------------------------------------------------------------------- */
2051
2052 static guint32
2053 get_uint32_header (GDBusMessage            *message,
2054                    GDBusMessageHeaderField  header_field)
2055 {
2056   GVariant *value;
2057   guint32 ret;
2058
2059   ret = 0;
2060   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2061   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2062     ret = g_variant_get_uint32 (value);
2063
2064   return ret;
2065 }
2066
2067 static const gchar *
2068 get_string_header (GDBusMessage            *message,
2069                    GDBusMessageHeaderField  header_field)
2070 {
2071   GVariant *value;
2072   const gchar *ret;
2073
2074   ret = NULL;
2075   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2076   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2077     ret = g_variant_get_string (value, NULL);
2078
2079   return ret;
2080 }
2081
2082 static const gchar *
2083 get_object_path_header (GDBusMessage            *message,
2084                         GDBusMessageHeaderField  header_field)
2085 {
2086   GVariant *value;
2087   const gchar *ret;
2088
2089   ret = NULL;
2090   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2091   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2092     ret = g_variant_get_string (value, NULL);
2093
2094   return ret;
2095 }
2096
2097 static const gchar *
2098 get_signature_header (GDBusMessage            *message,
2099                       GDBusMessageHeaderField  header_field)
2100 {
2101   GVariant *value;
2102   const gchar *ret;
2103
2104   ret = NULL;
2105   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
2106   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2107     ret = g_variant_get_string (value, NULL);
2108
2109   return ret;
2110 }
2111
2112 /* ---------------------------------------------------------------------------------------------------- */
2113
2114 static void
2115 set_uint32_header (GDBusMessage             *message,
2116                    GDBusMessageHeaderField   header_field,
2117                    guint32                   value)
2118 {
2119   g_dbus_message_set_header (message,
2120                              header_field,
2121                              g_variant_new_uint32 (value));
2122 }
2123
2124 static void
2125 set_string_header (GDBusMessage             *message,
2126                    GDBusMessageHeaderField   header_field,
2127                    const gchar              *value)
2128 {
2129   g_dbus_message_set_header (message,
2130                              header_field,
2131                              value == NULL ? NULL : g_variant_new_string (value));
2132 }
2133
2134 static void
2135 set_object_path_header (GDBusMessage             *message,
2136                         GDBusMessageHeaderField   header_field,
2137                         const gchar              *value)
2138 {
2139   g_dbus_message_set_header (message,
2140                              header_field,
2141                              value == NULL ? NULL : g_variant_new_object_path (value));
2142 }
2143
2144 static void
2145 set_signature_header (GDBusMessage             *message,
2146                       GDBusMessageHeaderField   header_field,
2147                       const gchar              *value)
2148 {
2149   g_dbus_message_set_header (message,
2150                              header_field,
2151                              value == NULL ? NULL : g_variant_new_signature (value));
2152 }
2153
2154 /* ---------------------------------------------------------------------------------------------------- */
2155
2156 /**
2157  * g_dbus_message_get_reply_serial:
2158  * @message: A #GDBusMessage.
2159  *
2160  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2161  *
2162  * Returns: The value.
2163  *
2164  * Since: 2.26
2165  */
2166 guint32
2167 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2168 {
2169   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2170   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2171 }
2172
2173 /**
2174  * g_dbus_message_set_reply_serial:
2175  * @message: A #GDBusMessage.
2176  * @value: The value to set.
2177  *
2178  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2179  *
2180  * Since: 2.26
2181  */
2182 void
2183 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2184                                  guint32        value)
2185 {
2186   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2187   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2188 }
2189
2190 /* ---------------------------------------------------------------------------------------------------- */
2191
2192 /**
2193  * g_dbus_message_get_interface:
2194  * @message: A #GDBusMessage.
2195  *
2196  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2197  *
2198  * Returns: The value.
2199  *
2200  * Since: 2.26
2201  */
2202 const gchar *
2203 g_dbus_message_get_interface (GDBusMessage  *message)
2204 {
2205   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2206   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2207 }
2208
2209 /**
2210  * g_dbus_message_set_interface:
2211  * @message: A #GDBusMessage.
2212  * @value: The value to set.
2213  *
2214  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2215  *
2216  * Since: 2.26
2217  */
2218 void
2219 g_dbus_message_set_interface (GDBusMessage  *message,
2220                               const gchar   *value)
2221 {
2222   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2223   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2224   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2225 }
2226
2227 /* ---------------------------------------------------------------------------------------------------- */
2228
2229 /**
2230  * g_dbus_message_get_member:
2231  * @message: A #GDBusMessage.
2232  *
2233  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2234  *
2235  * Returns: The value.
2236  *
2237  * Since: 2.26
2238  */
2239 const gchar *
2240 g_dbus_message_get_member (GDBusMessage  *message)
2241 {
2242   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2243   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2244 }
2245
2246 /**
2247  * g_dbus_message_set_member:
2248  * @message: A #GDBusMessage.
2249  * @value: The value to set.
2250  *
2251  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2252  *
2253  * Since: 2.26
2254  */
2255 void
2256 g_dbus_message_set_member (GDBusMessage  *message,
2257                            const gchar   *value)
2258 {
2259   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2260   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2261   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2262 }
2263
2264 /* ---------------------------------------------------------------------------------------------------- */
2265
2266 /**
2267  * g_dbus_message_get_path:
2268  * @message: A #GDBusMessage.
2269  *
2270  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2271  *
2272  * Returns: The value.
2273  *
2274  * Since: 2.26
2275  */
2276 const gchar *
2277 g_dbus_message_get_path (GDBusMessage  *message)
2278 {
2279   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2280   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2281 }
2282
2283 /**
2284  * g_dbus_message_set_path:
2285  * @message: A #GDBusMessage.
2286  * @value: The value to set.
2287  *
2288  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2289  *
2290  * Since: 2.26
2291  */
2292 void
2293 g_dbus_message_set_path (GDBusMessage  *message,
2294                          const gchar   *value)
2295 {
2296   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2297   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2298   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2299 }
2300
2301 /* ---------------------------------------------------------------------------------------------------- */
2302
2303 /**
2304  * g_dbus_message_get_sender:
2305  * @message: A #GDBusMessage.
2306  *
2307  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2308  *
2309  * Returns: The value.
2310  *
2311  * Since: 2.26
2312  */
2313 const gchar *
2314 g_dbus_message_get_sender (GDBusMessage *message)
2315 {
2316   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2317   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
2318 }
2319
2320 /**
2321  * g_dbus_message_set_sender:
2322  * @message: A #GDBusMessage.
2323  * @value: The value to set.
2324  *
2325  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2326  *
2327  * Since: 2.26
2328  */
2329 void
2330 g_dbus_message_set_sender (GDBusMessage  *message,
2331                            const gchar   *value)
2332 {
2333   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2334   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2335   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
2336 }
2337
2338 /* ---------------------------------------------------------------------------------------------------- */
2339
2340 /**
2341  * g_dbus_message_get_destination:
2342  * @message: A #GDBusMessage.
2343  *
2344  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2345  *
2346  * Returns: The value.
2347  *
2348  * Since: 2.26
2349  */
2350 const gchar *
2351 g_dbus_message_get_destination (GDBusMessage  *message)
2352 {
2353   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2354   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
2355 }
2356
2357 /**
2358  * g_dbus_message_set_destination:
2359  * @message: A #GDBusMessage.
2360  * @value: The value to set.
2361  *
2362  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2363  *
2364  * Since: 2.26
2365  */
2366 void
2367 g_dbus_message_set_destination (GDBusMessage  *message,
2368                                 const gchar   *value)
2369 {
2370   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2371   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2372   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
2373 }
2374
2375 /* ---------------------------------------------------------------------------------------------------- */
2376
2377 /**
2378  * g_dbus_message_get_error_name:
2379  * @message: A #GDBusMessage.
2380  *
2381  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2382  *
2383  * Returns: The value.
2384  *
2385  * Since: 2.26
2386  */
2387 const gchar *
2388 g_dbus_message_get_error_name (GDBusMessage  *message)
2389 {
2390   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2391   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
2392 }
2393
2394 /**
2395  * g_dbus_message_set_error_name:
2396  * @message: A #GDBusMessage.
2397  * @value: The value to set.
2398  *
2399  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2400  *
2401  * Since: 2.26
2402  */
2403 void
2404 g_dbus_message_set_error_name (GDBusMessage  *message,
2405                                const gchar   *value)
2406 {
2407   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2408   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2409   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
2410 }
2411
2412 /* ---------------------------------------------------------------------------------------------------- */
2413
2414 /**
2415  * g_dbus_message_get_signature:
2416  * @message: A #GDBusMessage.
2417  *
2418  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2419  *
2420  * Returns: The value.
2421  *
2422  * Since: 2.26
2423  */
2424 const gchar *
2425 g_dbus_message_get_signature (GDBusMessage  *message)
2426 {
2427   const gchar *ret;
2428   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2429   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2430   if (ret == NULL)
2431     ret = "";
2432   return ret;
2433 }
2434
2435 /**
2436  * g_dbus_message_set_signature:
2437  * @message: A #GDBusMessage.
2438  * @value: The value to set.
2439  *
2440  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2441  *
2442  * Since: 2.26
2443  */
2444 void
2445 g_dbus_message_set_signature (GDBusMessage  *message,
2446                               const gchar   *value)
2447 {
2448   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2449   g_return_if_fail (value == NULL || g_variant_is_signature (value));
2450   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
2451 }
2452
2453 /* ---------------------------------------------------------------------------------------------------- */
2454
2455 /**
2456  * g_dbus_message_get_arg0:
2457  * @message: A #GDBusMessage.
2458  *
2459  * Convenience to get the first item in the body of @message.
2460  *
2461  * Returns: The string item or %NULL if the first item in the body of
2462  * @message is not a string.
2463  *
2464  * Since: 2.26
2465  */
2466 const gchar *
2467 g_dbus_message_get_arg0 (GDBusMessage  *message)
2468 {
2469   const gchar *ret;
2470
2471   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2472
2473   ret = NULL;
2474
2475   if (message->priv->body != NULL && g_variant_is_of_type (message->priv->body, G_VARIANT_TYPE_TUPLE))
2476     {
2477       GVariant *item;
2478       item = g_variant_get_child_value (message->priv->body, 0);
2479       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
2480         ret = g_variant_get_string (item, NULL);
2481       g_variant_unref (item);
2482     }
2483
2484   return ret;
2485 }
2486
2487 /* ---------------------------------------------------------------------------------------------------- */
2488
2489 /**
2490  * g_dbus_message_get_num_unix_fds:
2491  * @message: A #GDBusMessage.
2492  *
2493  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2494  *
2495  * Returns: The value.
2496  *
2497  * Since: 2.26
2498  */
2499 guint32
2500 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
2501 {
2502   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2503   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
2504 }
2505
2506 /**
2507  * g_dbus_message_set_num_unix_fds:
2508  * @message: A #GDBusMessage.
2509  * @value: The value to set.
2510  *
2511  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2512  *
2513  * Since: 2.26
2514  */
2515 void
2516 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
2517                                  guint32        value)
2518 {
2519   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2520   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
2521 }
2522
2523 /* ---------------------------------------------------------------------------------------------------- */
2524
2525 /**
2526  * g_dbus_message_to_gerror:
2527  * @message: A #GDBusMessage.
2528  * @error: The #GError to set.
2529  *
2530  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
2531  * nothing and returns %FALSE.
2532  *
2533  * Otherwise this method encodes the error in @message as a #GError
2534  * using g_dbus_error_set_dbus_error() using the information in the
2535  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
2536  * well as the first string item in @message's body.
2537  *
2538  * Returns: %TRUE if @error was set, %FALSE otherwise.
2539  *
2540  * Since: 2.26
2541  */
2542 gboolean
2543 g_dbus_message_to_gerror (GDBusMessage   *message,
2544                           GError        **error)
2545 {
2546   gboolean ret;
2547   const gchar *error_name;
2548
2549   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
2550
2551   ret = FALSE;
2552   if (message->priv->type != G_DBUS_MESSAGE_TYPE_ERROR)
2553     goto out;
2554
2555   error_name = g_dbus_message_get_error_name (message);
2556   if (error_name != NULL)
2557     {
2558       GVariant *body;
2559
2560       body = g_dbus_message_get_body (message);
2561
2562       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
2563         {
2564           const gchar *error_message;
2565           g_variant_get (body, "(&s)", &error_message);
2566           g_dbus_error_set_dbus_error (error,
2567                                        error_name,
2568                                        error_message,
2569                                        NULL);
2570         }
2571       else
2572         {
2573           /* these two situations are valid, yet pretty rare */
2574           if (body != NULL)
2575             {
2576               g_dbus_error_set_dbus_error (error,
2577                                            error_name,
2578                                            "",
2579                                            _("Error return with body of type `%s'"),
2580                                            g_variant_get_type_string (body));
2581             }
2582           else
2583             {
2584               g_dbus_error_set_dbus_error (error,
2585                                            error_name,
2586                                            "",
2587                                            _("Error return with empty body"));
2588             }
2589         }
2590     }
2591   else
2592     {
2593       /* TOOD: this shouldn't happen - should check this at message serialization
2594        * time and disconnect the peer.
2595        */
2596       g_set_error (error,
2597                    G_IO_ERROR,
2598                    G_IO_ERROR_FAILED,
2599                    "Error return without error-name header!");
2600     }
2601
2602   ret = TRUE;
2603
2604  out:
2605   return ret;
2606 }
2607
2608 /* ---------------------------------------------------------------------------------------------------- */
2609
2610 static gchar *
2611 flags_to_string (GType flags_type, guint value)
2612 {
2613   GString *s;
2614   GFlagsClass *klass;
2615   guint n;
2616
2617   klass = g_type_class_ref (flags_type);
2618   s = g_string_new (NULL);
2619   for (n = 0; n < 32; n++)
2620     {
2621       if ((value & (1<<n)) != 0)
2622         {
2623           GFlagsValue *flags_value;
2624           flags_value = g_flags_get_first_value (klass, (1<<n));
2625           if (s->len > 0)
2626             g_string_append_c (s, ',');
2627           if (flags_value != NULL)
2628             g_string_append (s, flags_value->value_nick);
2629           else
2630             g_string_append_printf (s, "unknown (bit %d)", n);
2631         }
2632     }
2633   if (s->len == 0)
2634     g_string_append (s, "none");
2635   g_type_class_unref (klass);
2636   return g_string_free (s, FALSE);
2637 }
2638
2639 static gint
2640 _sort_keys_func (gconstpointer a,
2641                  gconstpointer b)
2642 {
2643   gint ia;
2644   gint ib;
2645
2646   ia = GPOINTER_TO_INT (a);
2647   ib = GPOINTER_TO_INT (b);
2648
2649   return ia - ib;
2650 }
2651
2652 /**
2653  * g_dbus_message_print:
2654  * @message: A #GDBusMessage.
2655  * @indent: Indentation level.
2656  *
2657  * Produces a human-readable multi-line description of @message.
2658  *
2659  * The contents of the description has no ABI guarantees, the contents
2660  * and formatting is subject to change at any time. Typical output
2661  * looks something like this:
2662  * <programlisting>
2663  * Type:    method-call
2664  * Flags:   none
2665  * Version: 0
2666  * Serial:  4
2667  * Headers:
2668  *   path -> objectpath '/org/gtk/GDBus/TestObject'
2669  *   interface -> 'org.gtk.GDBus.TestInterface'
2670  *   member -> 'GimmeStdout'
2671  *   destination -> ':1.146'
2672  * Body: ()
2673  * UNIX File Descriptors:
2674  *   (none)
2675  * </programlisting>
2676  * or
2677  * <programlisting>
2678  * Type:    method-return
2679  * Flags:   no-reply-expected
2680  * Version: 0
2681  * Serial:  477
2682  * Headers:
2683  *   reply-serial -> uint32 4
2684  *   destination -> ':1.159'
2685  *   sender -> ':1.146'
2686  *   num-unix-fds -> uint32 1
2687  * Body: ()
2688  * UNIX File Descriptors:
2689  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
2690  * </programlisting>
2691  *
2692  * Returns: A string that should be freed with g_free().
2693  *
2694  * Since: 2.26
2695  */
2696 gchar *
2697 g_dbus_message_print (GDBusMessage *message,
2698                       guint         indent)
2699 {
2700   GString *str;
2701   gchar *s;
2702   GList *keys;
2703   GList *l;
2704
2705   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2706
2707   str = g_string_new (NULL);
2708
2709   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->priv->type);
2710   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
2711   g_free (s);
2712   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->priv->flags);
2713   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
2714   g_free (s);
2715   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->priv->major_protocol_version);
2716   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->priv->serial);
2717
2718   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
2719   keys = g_hash_table_get_keys (message->priv->headers);
2720   keys = g_list_sort (keys, _sort_keys_func);
2721   if (keys != NULL)
2722     {
2723       for (l = keys; l != NULL; l = l->next)
2724         {
2725           gint key = GPOINTER_TO_INT (l->data);
2726           GVariant *value;
2727           gchar *value_str;
2728
2729           value = g_hash_table_lookup (message->priv->headers, l->data);
2730           g_assert (value != NULL);
2731
2732           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
2733           value_str = g_variant_print (value, TRUE);
2734           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
2735           g_free (s);
2736           g_free (value_str);
2737         }
2738     }
2739   else
2740     {
2741       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2742     }
2743   g_string_append_printf (str, "%*sBody: ", indent, "");
2744   if (message->priv->body != NULL)
2745     {
2746       g_variant_print_string (message->priv->body,
2747                               str,
2748                               TRUE);
2749     }
2750   else
2751     {
2752       g_string_append (str, "()");
2753     }
2754   g_string_append (str, "\n");
2755 #ifdef G_OS_UNIX
2756   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
2757   if (message->priv->fd_list != NULL)
2758     {
2759       gint num_fds;
2760       const gint *fds;
2761       gint n;
2762
2763       fds = g_unix_fd_list_peek_fds (message->priv->fd_list, &num_fds);
2764       if (num_fds > 0)
2765         {
2766           for (n = 0; n < num_fds; n++)
2767             {
2768               GString *fs;
2769               struct stat statbuf;
2770               fs = g_string_new (NULL);
2771               if (fstat (fds[n], &statbuf) == 0)
2772                 {
2773                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
2774                                           major (statbuf.st_dev), minor (statbuf.st_dev));
2775                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
2776                                           statbuf.st_mode);
2777                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2778                                           (guint64) statbuf.st_ino);
2779                   g_string_append_printf (fs, "%s" "uid=%d", fs->len > 0 ? "," : "",
2780                                           statbuf.st_uid);
2781                   g_string_append_printf (fs, "%s" "gid=%d", fs->len > 0 ? "," : "",
2782                                           statbuf.st_gid);
2783                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
2784                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
2785                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2786                                           (guint64) statbuf.st_size);
2787                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2788                                           (guint64) statbuf.st_atime);
2789                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2790                                           (guint64) statbuf.st_mtime);
2791                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2792                                           (guint64) statbuf.st_ctime);
2793                 }
2794               else
2795                 {
2796                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
2797                 }
2798               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
2799               g_string_free (fs, TRUE);
2800             }
2801         }
2802       else
2803         {
2804           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
2805         }
2806     }
2807   else
2808     {
2809       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2810     }
2811 #endif
2812
2813   return g_string_free (str, FALSE);
2814 }
2815
2816
2817 #define __G_DBUS_MESSAGE_C__
2818 #include "gioaliasdef.c"