* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Author: David Zeuthen <davidz@redhat.com>
*/
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef HAVE_SYS_MKDEV_H
+
+#if MAJOR_IN_MKDEV
#include <sys/mkdev.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#elif MAJOR_IN_SYSMACROS
+#include <sys/sysmacros.h>
#endif
#include "gdbusutils.h"
GDataStreamByteOrder byte_order;
};
+static gboolean
+g_memory_buffer_is_byteswapped (GMemoryBuffer *mbuf)
+{
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
+#else
+ return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
+#endif
+}
+
static guchar
-g_memory_buffer_read_byte (GMemoryBuffer *mbuf,
- GError **error)
+g_memory_buffer_read_byte (GMemoryBuffer *mbuf)
{
if (mbuf->pos >= mbuf->valid_len)
return 0;
}
static gint16
-g_memory_buffer_read_int16 (GMemoryBuffer *mbuf,
- GError **error)
+g_memory_buffer_read_int16 (GMemoryBuffer *mbuf)
{
gint16 v;
memcpy (&v, mbuf->data + mbuf->pos, 2);
mbuf->pos += 2;
- switch (mbuf->byte_order)
- {
- case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
- v = GINT16_FROM_BE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
- v = GINT16_FROM_LE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
- default:
- break;
- }
+
+ if (g_memory_buffer_is_byteswapped (mbuf))
+ v = GUINT16_SWAP_LE_BE (v);
+
return v;
}
static guint16
-g_memory_buffer_read_uint16 (GMemoryBuffer *mbuf,
- GError **error)
+g_memory_buffer_read_uint16 (GMemoryBuffer *mbuf)
{
guint16 v;
memcpy (&v, mbuf->data + mbuf->pos, 2);
mbuf->pos += 2;
- switch (mbuf->byte_order)
- {
- case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
- v = GINT16_FROM_BE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
- v = GINT16_FROM_LE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
- default:
- break;
- }
+
+ if (g_memory_buffer_is_byteswapped (mbuf))
+ v = GUINT16_SWAP_LE_BE (v);
+
return v;
}
static gint32
-g_memory_buffer_read_int32 (GMemoryBuffer *mbuf,
- GError **error)
+g_memory_buffer_read_int32 (GMemoryBuffer *mbuf)
{
gint32 v;
memcpy (&v, mbuf->data + mbuf->pos, 4);
mbuf->pos += 4;
- switch (mbuf->byte_order)
- {
- case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
- v = GINT32_FROM_BE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
- v = GINT32_FROM_LE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
- default:
- break;
- }
+
+ if (g_memory_buffer_is_byteswapped (mbuf))
+ v = GUINT32_SWAP_LE_BE (v);
+
return v;
}
static guint32
-g_memory_buffer_read_uint32 (GMemoryBuffer *mbuf,
- GError **error)
+g_memory_buffer_read_uint32 (GMemoryBuffer *mbuf)
{
guint32 v;
memcpy (&v, mbuf->data + mbuf->pos, 4);
mbuf->pos += 4;
- switch (mbuf->byte_order)
- {
- case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
- v = GUINT32_FROM_BE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
- v = GUINT32_FROM_LE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
- default:
- break;
- }
+
+ if (g_memory_buffer_is_byteswapped (mbuf))
+ v = GUINT32_SWAP_LE_BE (v);
+
return v;
}
static gint64
-g_memory_buffer_read_int64 (GMemoryBuffer *mbuf,
- GError **error)
+g_memory_buffer_read_int64 (GMemoryBuffer *mbuf)
{
gint64 v;
memcpy (&v, mbuf->data + mbuf->pos, 8);
mbuf->pos += 8;
- switch (mbuf->byte_order)
- {
- case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
- v = GINT64_FROM_BE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
- v = GINT64_FROM_LE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
- default:
- break;
- }
+
+ if (g_memory_buffer_is_byteswapped (mbuf))
+ v = GUINT64_SWAP_LE_BE (v);
+
return v;
}
static guint64
-g_memory_buffer_read_uint64 (GMemoryBuffer *mbuf,
- GError **error)
+g_memory_buffer_read_uint64 (GMemoryBuffer *mbuf)
{
guint64 v;
memcpy (&v, mbuf->data + mbuf->pos, 8);
mbuf->pos += 8;
- switch (mbuf->byte_order)
- {
- case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
- v = GUINT64_FROM_BE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
- v = GUINT64_FROM_LE (v);
- break;
- case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
- default:
- break;
- }
- return v;
+
+ if (g_memory_buffer_is_byteswapped (mbuf))
+ v = GUINT64_SWAP_LE_BE (v);
+
+ return v;
}
#define MIN_ARRAY_SIZE 128
}
static void
-array_resize (GMemoryBuffer *mbuf,
- gsize size)
+array_resize (GMemoryBuffer *mbuf,
+ gsize size)
{
gpointer data;
gsize len;
static gboolean
g_memory_buffer_write (GMemoryBuffer *mbuf,
- const void *buffer,
- gsize count)
+ const void *buffer,
+ gsize count)
{
guint8 *dest;
gsize new_size;
*
* Since: 2.26
*/
+G_GNUC_PRINTF(3, 0)
GDBusMessage *
g_dbus_message_new_method_error_valist (GDBusMessage *method_call_message,
const gchar *error_name,
*
* Gets the body of a message.
*
- * Returns: A #GVariant or %NULL if the body is empty. Do not free, it is owned by @message.
+ * Returns: (transfer none): A #GVariant or %NULL if the body is
+ * empty. Do not free, it is owned by @message.
*
* Since: 2.26
*/
/* ---------------------------------------------------------------------------------------------------- */
+static guint
+get_type_fixed_size (const GVariantType *type)
+{
+ /* NB: we do not treat 'b' as fixed-size here because GVariant and
+ * D-Bus disagree about the size.
+ */
+ switch (*g_variant_type_peek_string (type))
+ {
+ case 'y':
+ return 1;
+ case 'n': case 'q':
+ return 2;
+ case 'i': case 'u': case 'h':
+ return 4;
+ case 'x': case 't': case 'd':
+ return 8;
+ default:
+ return 0;
+ }
+}
+
static gboolean
validate_headers (GDBusMessage *message,
GError **error)
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
-ensure_input_padding (GMemoryBuffer *buf,
- gsize padding_size,
- GError **error)
+ensure_input_padding (GMemoryBuffer *buf,
+ gsize padding_size)
{
gsize offset;
gsize wanted_offset;
}
static const gchar *
-read_string (GMemoryBuffer *mbuf,
- gsize len,
- GError **error)
+read_string (GMemoryBuffer *mbuf,
+ gsize len,
+ GError **error)
{
gchar *str;
const gchar *end_valid;
- if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
+ if G_UNLIKELY (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
{
mbuf->pos = mbuf->valid_len;
/* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
g_dngettext (GETTEXT_PACKAGE,
- "Wanted to read %lu bytes but only got %lu",
"Wanted to read %lu byte but only got %lu",
+ "Wanted to read %lu bytes but only got %lu",
(gulong)len),
(gulong)len,
- (gulong)mbuf->valid_len - mbuf->pos);
- mbuf->pos = mbuf->valid_len;
+ (gulong)(mbuf->valid_len - mbuf->pos));
return NULL;
}
- if (mbuf->data[mbuf->pos + len] != '\0')
+ if G_UNLIKELY (mbuf->data[mbuf->pos + len] != '\0')
{
str = g_strndup (mbuf->data + mbuf->pos, len);
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Expected NUL byte after the string `%s' but found byte %d"),
+ _("Expected NUL byte after the string '%s' but found byte %d"),
str, mbuf->data[mbuf->pos + len]);
g_free (str);
mbuf->pos += len + 1;
str = mbuf->data + mbuf->pos;
mbuf->pos += len + 1;
- if (!g_utf8_validate (str, -1, &end_valid))
+ if G_UNLIKELY (!g_utf8_validate (str, -1, &end_valid))
{
gint offset;
gchar *valid_str;
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
_("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
- "The valid UTF-8 string up until that point was `%s'"),
+ "The valid UTF-8 string up until that point was '%s'"),
offset,
(gint) len,
valid_str);
return str;
}
+static gconstpointer
+read_bytes (GMemoryBuffer *mbuf,
+ gsize len,
+ GError **error)
+{
+ gconstpointer result;
+
+ if G_UNLIKELY (mbuf->pos + len > mbuf->valid_len || mbuf->pos + len < mbuf->pos)
+ {
+ mbuf->pos = mbuf->valid_len;
+ /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ g_dngettext (GETTEXT_PACKAGE,
+ "Wanted to read %lu byte but only got %lu",
+ "Wanted to read %lu bytes but only got %lu",
+ (gulong)len),
+ (gulong)len,
+ (gulong)(mbuf->valid_len - mbuf->pos));
+ return NULL;
+ }
+
+ result = mbuf->data + mbuf->pos;
+ mbuf->pos += len;
+
+ return result;
+}
+
/* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
/* returns a non-floating GVariant! */
static GVariant *
-parse_value_from_blob (GMemoryBuffer *buf,
- const GVariantType *type,
- gboolean just_align,
- guint indent,
- GError **error)
+parse_value_from_blob (GMemoryBuffer *buf,
+ const GVariantType *type,
+ gboolean just_align,
+ guint indent,
+ GError **error)
{
GVariant *ret;
GError *local_error;
switch (type_string[0])
{
case 'b': /* G_VARIANT_TYPE_BOOLEAN */
- if (!ensure_input_padding (buf, 4, &local_error))
- goto fail;
+ ensure_input_padding (buf, 4);
if (!just_align)
{
gboolean v;
- v = g_memory_buffer_read_uint32 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_uint32 (buf);
ret = g_variant_new_boolean (v);
}
break;
if (!just_align)
{
guchar v;
- v = g_memory_buffer_read_byte (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_byte (buf);
ret = g_variant_new_byte (v);
}
break;
case 'n': /* G_VARIANT_TYPE_INT16 */
- if (!ensure_input_padding (buf, 2, &local_error))
- goto fail;
+ ensure_input_padding (buf, 2);
if (!just_align)
{
gint16 v;
- v = g_memory_buffer_read_int16 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_int16 (buf);
ret = g_variant_new_int16 (v);
}
break;
case 'q': /* G_VARIANT_TYPE_UINT16 */
- if (!ensure_input_padding (buf, 2, &local_error))
- goto fail;
+ ensure_input_padding (buf, 2);
if (!just_align)
{
guint16 v;
- v = g_memory_buffer_read_uint16 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_uint16 (buf);
ret = g_variant_new_uint16 (v);
}
break;
case 'i': /* G_VARIANT_TYPE_INT32 */
- if (!ensure_input_padding (buf, 4, &local_error))
- goto fail;
+ ensure_input_padding (buf, 4);
if (!just_align)
{
gint32 v;
- v = g_memory_buffer_read_int32 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_int32 (buf);
ret = g_variant_new_int32 (v);
}
break;
case 'u': /* G_VARIANT_TYPE_UINT32 */
- if (!ensure_input_padding (buf, 4, &local_error))
- goto fail;
+ ensure_input_padding (buf, 4);
if (!just_align)
{
guint32 v;
- v = g_memory_buffer_read_uint32 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_uint32 (buf);
ret = g_variant_new_uint32 (v);
}
break;
case 'x': /* G_VARIANT_TYPE_INT64 */
- if (!ensure_input_padding (buf, 8, &local_error))
- goto fail;
+ ensure_input_padding (buf, 8);
if (!just_align)
{
gint64 v;
- v = g_memory_buffer_read_int64 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_int64 (buf);
ret = g_variant_new_int64 (v);
}
break;
case 't': /* G_VARIANT_TYPE_UINT64 */
- if (!ensure_input_padding (buf, 8, &local_error))
- goto fail;
+ ensure_input_padding (buf, 8);
if (!just_align)
{
guint64 v;
- v = g_memory_buffer_read_uint64 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_uint64 (buf);
ret = g_variant_new_uint64 (v);
}
break;
case 'd': /* G_VARIANT_TYPE_DOUBLE */
- if (!ensure_input_padding (buf, 8, &local_error))
- goto fail;
+ ensure_input_padding (buf, 8);
if (!just_align)
{
union {
gdouble v_double;
} u;
G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
- u.v_uint64 = g_memory_buffer_read_uint64 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ u.v_uint64 = g_memory_buffer_read_uint64 (buf);
ret = g_variant_new_double (u.v_double);
}
break;
case 's': /* G_VARIANT_TYPE_STRING */
- if (!ensure_input_padding (buf, 4, &local_error))
- goto fail;
+ ensure_input_padding (buf, 4);
if (!just_align)
{
guint32 len;
const gchar *v;
- len = g_memory_buffer_read_uint32 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ len = g_memory_buffer_read_uint32 (buf);
v = read_string (buf, (gsize) len, &local_error);
if (v == NULL)
goto fail;
break;
case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
- if (!ensure_input_padding (buf, 4, &local_error))
- goto fail;
+ ensure_input_padding (buf, 4);
if (!just_align)
{
guint32 len;
const gchar *v;
- len = g_memory_buffer_read_uint32 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ len = g_memory_buffer_read_uint32 (buf);
v = read_string (buf, (gsize) len, &local_error);
if (v == NULL)
goto fail;
g_set_error (&local_error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Parsed value `%s' is not a valid D-Bus object path"),
+ _("Parsed value '%s' is not a valid D-Bus object path"),
v);
goto fail;
}
{
guchar len;
const gchar *v;
- len = g_memory_buffer_read_byte (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ len = g_memory_buffer_read_byte (buf);
v = read_string (buf, (gsize) len, &local_error);
if (v == NULL)
goto fail;
g_set_error (&local_error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Parsed value `%s' is not a valid D-Bus signature"),
+ _("Parsed value '%s' is not a valid D-Bus signature"),
v);
goto fail;
}
break;
case 'h': /* G_VARIANT_TYPE_HANDLE */
- if (!ensure_input_padding (buf, 4, &local_error))
- goto fail;
+ ensure_input_padding (buf, 4);
if (!just_align)
{
gint32 v;
- v = g_memory_buffer_read_int32 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ v = g_memory_buffer_read_int32 (buf);
ret = g_variant_new_handle (v);
}
break;
case 'a': /* G_VARIANT_TYPE_ARRAY */
- if (!ensure_input_padding (buf, 4, &local_error))
- goto fail;
+ ensure_input_padding (buf, 4);
/* If we are only aligning for this array type, it is the child type of
* another array, which is empty. So, we do not need to add padding for
if (!just_align)
{
guint32 array_len;
- goffset offset;
- goffset target;
const GVariantType *element_type;
- GVariantBuilder builder;
+ guint fixed_size;
- array_len = g_memory_buffer_read_uint32 (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ array_len = g_memory_buffer_read_uint32 (buf);
is_leaf = FALSE;
#ifdef DEBUG_SERIALIZER
goto fail;
}
- g_variant_builder_init (&builder, type);
element_type = g_variant_type_element (type);
+ fixed_size = get_type_fixed_size (element_type);
- if (array_len == 0)
+ /* Fast-path the cases like 'ay', etc. */
+ if (fixed_size != 0)
{
- GVariant *item;
- item = parse_value_from_blob (buf,
- element_type,
- TRUE,
- indent + 2,
- NULL);
- g_assert (item == NULL);
+ gconstpointer array_data;
+
+ if (array_len % fixed_size != 0)
+ {
+ g_set_error (&local_error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Encountered array of type 'a%c', expected to have a length a multiple "
+ "of %u bytes, but found to be %u bytes in length"),
+ g_variant_type_peek_string (element_type)[0], fixed_size, array_len);
+ goto fail;
+ }
+
+ ensure_input_padding (buf, fixed_size);
+ array_data = read_bytes (buf, array_len, &local_error);
+ if (array_data == NULL)
+ goto fail;
+
+ ret = g_variant_new_fixed_array (element_type, array_data, array_len / fixed_size, fixed_size);
+
+ if (g_memory_buffer_is_byteswapped (buf))
+ {
+ GVariant *tmp = g_variant_ref_sink (ret);
+ ret = g_variant_byteswap (tmp);
+ g_variant_unref (tmp);
+ }
}
else
{
- /* TODO: optimize array of primitive types */
- offset = buf->pos;
- target = offset + array_len;
- while (offset < target)
+ GVariantBuilder builder;
+ goffset offset;
+ goffset target;
+
+ g_variant_builder_init (&builder, type);
+
+ if (array_len == 0)
{
GVariant *item;
item = parse_value_from_blob (buf,
element_type,
- FALSE,
+ TRUE,
indent + 2,
- &local_error);
- if (item == NULL)
+ NULL);
+ g_assert (item == NULL);
+ }
+ else
+ {
+ offset = buf->pos;
+ target = offset + array_len;
+ while (offset < target)
{
- g_variant_builder_clear (&builder);
- goto fail;
+ GVariant *item;
+ item = parse_value_from_blob (buf,
+ element_type,
+ FALSE,
+ indent + 2,
+ &local_error);
+ if (item == NULL)
+ {
+ g_variant_builder_clear (&builder);
+ goto fail;
+ }
+ g_variant_builder_add_value (&builder, item);
+ g_variant_unref (item);
+ offset = buf->pos;
}
- g_variant_builder_add_value (&builder, item);
- g_variant_unref (item);
- offset = buf->pos;
}
- }
- ret = g_variant_builder_end (&builder);
+ ret = g_variant_builder_end (&builder);
+ }
}
break;
GVariant *key;
GVariant *value;
- if (!ensure_input_padding (buf, 8, &local_error))
- goto fail;
+ ensure_input_padding (buf, 8);
is_leaf = FALSE;
#ifdef DEBUG_SERIALIZER
}
else if (g_variant_type_is_tuple (type))
{
- if (!ensure_input_padding (buf, 8, &local_error))
- goto fail;
+ ensure_input_padding (buf, 8);
is_leaf = FALSE;
#ifdef DEBUG_SERIALIZER
GVariantType *variant_type;
GVariant *value;
- siglen = g_memory_buffer_read_byte (buf, &local_error);
- if (local_error != NULL)
- goto fail;
+ siglen = g_memory_buffer_read_byte (buf);
sig = read_string (buf, (gsize) siglen, &local_error);
if (sig == NULL)
goto fail;
g_set_error (&local_error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Parsed value `%s' for variant is not a valid D-Bus signature"),
+ _("Parsed value '%s' for variant is not a valid D-Bus signature"),
sig);
goto fail;
}
g_set_error (&local_error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Error deserializing GVariant with type string `%s' from the D-Bus wire format"),
+ _("Error deserializing GVariant with type string '%s' from the D-Bus wire format"),
s);
g_free (s);
goto fail;
is_leaf = is_leaf; /* To avoid -Wunused-but-set-variable */
#endif /* DEBUG_SERIALIZER */
- /* sink the reference */
+ /* sink the reference, if floating */
if (ret != NULL)
- {
- g_assert (g_variant_is_floating (ret));
- g_variant_ref_sink (ret);
- }
+ g_variant_take_ref (ret);
return ret;
fail:
* Since: 2.26
*/
gssize
-g_dbus_message_bytes_needed (guchar *blob,
- gsize blob_len,
- GError **error)
+g_dbus_message_bytes_needed (guchar *blob,
+ gsize blob_len,
+ GError **error)
{
gssize ret;
mbuf.data = (gchar *)blob;
mbuf.len = mbuf.valid_len = blob_len;
- endianness = g_memory_buffer_read_byte (&mbuf, NULL);
+ endianness = g_memory_buffer_read_byte (&mbuf);
switch (endianness)
{
case 'l':
goto out;
}
- message->type = g_memory_buffer_read_byte (&mbuf, NULL);
- message->flags = g_memory_buffer_read_byte (&mbuf, NULL);
- major_protocol_version = g_memory_buffer_read_byte (&mbuf, NULL);
+ message->type = g_memory_buffer_read_byte (&mbuf);
+ message->flags = g_memory_buffer_read_byte (&mbuf);
+ major_protocol_version = g_memory_buffer_read_byte (&mbuf);
if (major_protocol_version != 1)
{
g_set_error (error,
major_protocol_version);
goto out;
}
- message_body_len = g_memory_buffer_read_uint32 (&mbuf, NULL);
- message->serial = g_memory_buffer_read_uint32 (&mbuf, NULL);
+ message_body_len = g_memory_buffer_read_uint32 (&mbuf);
+ message->serial = g_memory_buffer_read_uint32 (&mbuf);
#ifdef DEBUG_SERIALIZER
g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Signature header with signature `%s' found but message body is empty"),
+ _("Signature header with signature '%s' found but message body is empty"),
signature_str);
goto out;
}
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Parsed value `%s' is not a valid D-Bus signature (for body)"),
+ _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
signature_str);
goto out;
}
static gsize
ensure_output_padding (GMemoryBuffer *mbuf,
- gsize padding_size)
+ gsize padding_size)
{
gsize offset;
gsize wanted_offset;
/* note that value can be NULL for e.g. empty arrays - type is never NULL */
static gboolean
-append_value_to_blob (GVariant *value,
- const GVariantType *type,
- GMemoryBuffer *mbuf,
- gsize *out_padding_added,
- GError **error)
+append_value_to_blob (GVariant *value,
+ const GVariantType *type,
+ GMemoryBuffer *mbuf,
+ gsize *out_padding_added,
+ GError **error)
{
gsize padding_added;
const gchar *type_string;
case 'a': /* G_VARIANT_TYPE_ARRAY */
{
+ const GVariantType *element_type;
GVariant *item;
GVariantIter iter;
goffset array_len_offset;
goffset array_payload_begin_offset;
goffset cur_offset;
gsize array_len;
+ guint fixed_size;
padding_added = ensure_output_padding (mbuf, 4);
if (value != NULL)
*/
array_payload_begin_offset = mbuf->valid_len;
+ element_type = g_variant_type_element (type);
+ fixed_size = get_type_fixed_size (element_type);
+
if (g_variant_n_children (value) == 0)
{
gsize padding_added_for_item;
if (!append_value_to_blob (NULL,
- g_variant_type_element (type),
+ element_type,
mbuf,
&padding_added_for_item,
error))
goto fail;
array_payload_begin_offset += padding_added_for_item;
}
+ else if (fixed_size != 0)
+ {
+ GVariant *use_value;
+
+ if (g_memory_buffer_is_byteswapped (mbuf))
+ use_value = g_variant_byteswap (value);
+ else
+ use_value = g_variant_ref (value);
+
+ ensure_output_padding (mbuf, fixed_size);
+ array_len = g_variant_get_size (use_value);
+ g_memory_buffer_write (mbuf, g_variant_get_data (use_value), array_len);
+ g_variant_unref (use_value);
+ }
else
{
guint n;
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Error serializing GVariant with type string `%s' to the D-Bus wire format"),
+ _("Error serializing GVariant with type string '%s' to the D-Bus wire format"),
g_variant_get_type_string (value));
goto fail;
}
}
static gboolean
-append_body_to_blob (GVariant *value,
+append_body_to_blob (GVariant *value,
GMemoryBuffer *mbuf,
- GError **error)
+ GError **error)
{
GVariant *item;
GVariantIter iter;
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Message body has signature `%s' but there is no signature header"),
+ _("Message body has signature '%s' but there is no signature header"),
signature_str);
g_free (tupled_signature_str);
goto out;
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Message body has type signature `%s' but signature in the header field is `%s'"),
+ _("Message body has type signature '%s' but signature in the header field is '%s'"),
tupled_signature_str, g_variant_get_type_string (message->body));
g_free (tupled_signature_str);
goto out;
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
- _("Message body is empty but signature in the header field is `(%s)'"),
+ _("Message body is empty but signature in the header field is '(%s)'"),
signature_str);
goto out;
}
g_dbus_error_set_dbus_error (error,
error_name,
"",
- _("Error return with body of type `%s'"),
+ _("Error return with body of type '%s'"),
g_variant_get_type_string (body));
}
else
* The contents of the description has no ABI guarantees, the contents
* and formatting is subject to change at any time. Typical output
* looks something like this:
- * <programlisting>
- * Type: method-call
- * Flags: none
- * Version: 0
- * Serial: 4
- * Headers:
+ * |[
+ * Type: method-call
+ * Flags: none
+ * Version: 0
+ * Serial: 4
+ * Headers:
* path -> objectpath '/org/gtk/GDBus/TestObject'
* interface -> 'org.gtk.GDBus.TestInterface'
* member -> 'GimmeStdout'
* destination -> ':1.146'
- * Body: ()
+ * Body: ()
* UNIX File Descriptors:
* (none)
- * </programlisting>
+ * ]|
* or
- * <programlisting>
- * Type: method-return
- * Flags: no-reply-expected
- * Version: 0
- * Serial: 477
- * Headers:
+ * |[
+ * Type: method-return
+ * Flags: no-reply-expected
+ * Version: 0
+ * Serial: 477
+ * Headers:
* reply-serial -> uint32 4
* destination -> ':1.159'
* sender -> ':1.146'
* num-unix-fds -> uint32 1
- * Body: ()
- * UNIX File Descriptors:
+ * Body: ()
+ * UNIX File Descriptors:
* fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
- * </programlisting>
+ * ]|
*
* Returns: A string that should be freed with g_free().
*
statbuf.st_mode);
g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
(guint64) statbuf.st_ino);
- g_string_append_printf (fs, "%s" "uid=%d", fs->len > 0 ? "," : "",
- statbuf.st_uid);
- g_string_append_printf (fs, "%s" "gid=%d", fs->len > 0 ? "," : "",
- statbuf.st_gid);
+ g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
+ (guint) statbuf.st_uid);
+ g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
+ (guint) statbuf.st_gid);
g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
major (statbuf.st_rdev), minor (statbuf.st_rdev));
g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",