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