mirror of
https://github.com/systemd/systemd
synced 2024-10-15 04:24:19 +00:00
Merge pull request #23531 from yuwata/sd-bus-drop-version-2
sd-bus: drop version 2 format support
This commit is contained in:
commit
9db25d01ef
1
TODO
1
TODO
|
@ -1356,7 +1356,6 @@ Features:
|
|||
- longer term: priority inheritance
|
||||
- dbus spec updates:
|
||||
- NameLost/NameAcquired obsolete
|
||||
- GVariant
|
||||
- path escaping
|
||||
- update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now
|
||||
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
---
|
||||
title: GVariant D-Bus Message Serialization
|
||||
category: Interfaces
|
||||
layout: default
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
---
|
||||
|
||||
# GVariant D-Bus Message Serialization
|
||||
|
||||
We stay as close to the original dbus1 framing as possible, but make
|
||||
certain changes to adapt for GVariant. dbus1 has the following
|
||||
framing:
|
||||
|
||||
1. A fixed header of "yyyyuu"
|
||||
2. Additional header fields of "a(yv)"
|
||||
3. Padding with NUL bytes to pad up to next 8byte boundary
|
||||
4. The body
|
||||
|
||||
Note that the body is not padded at the end, the complete message
|
||||
hence might have a non-aligned size. Reading multiple messages at once
|
||||
will hence result in possibly unaligned messages in memory.
|
||||
|
||||
The header consists of the following:
|
||||
|
||||
y Endianness, 'l' or 'B'
|
||||
y Message Type
|
||||
y Flags
|
||||
y Protocol version, '1'
|
||||
u Length of the body, i.e. the length of part 4 above
|
||||
u 32bit Serial number
|
||||
|
||||
= 12 bytes
|
||||
|
||||
This header is then followed by the fields array, whose first value is
|
||||
a 32bit array size.
|
||||
|
||||
When using GVariant we keep the basic structure in place, only
|
||||
slightly alter the header, and define protocol version '2'. The new
|
||||
header:
|
||||
|
||||
y Endianness, 'l' or 'B'
|
||||
y Message Type
|
||||
y Flags
|
||||
y Protocol version, '2'
|
||||
u Reserved, must be 0
|
||||
t 64bit Cookie
|
||||
|
||||
= 16 bytes
|
||||
|
||||
This is then followed by the GVariant fields array ("a{tv}"), and
|
||||
finally the actual body as variant (v). Putting this altogether a
|
||||
packet on dbus2 hence qualifies as a fully compliant GVariant
|
||||
structure of (yyyyuta{tv}v).
|
||||
|
||||
For details on gvariant, see:
|
||||
|
||||
https://people.gnome.org/~desrt/gvariant-serialisation.pdf
|
||||
|
||||
Regarding the framing of dbus2, also see:
|
||||
|
||||
https://wiki.gnome.org/Projects/GLib/GDBus/Version2
|
||||
|
||||
The first four bytes of the header are defined the same way for dbus1
|
||||
and dbus2. The first bytes contain the endianness field and the
|
||||
protocol version, so that the remainder of the message can be safely
|
||||
made sense of just by looking at the first 32bit.
|
||||
|
||||
Note that the length of the body is no longer included in the header
|
||||
on dbus2! In fact, the message size must be known in advance, from the
|
||||
underlying transport in order to parse dbus2 messages, while it is
|
||||
directly included in dbus1 message headers. This change of semantics
|
||||
is an effect of GVariant's basic design.
|
||||
|
||||
The serial number has been renamed cookie and has been extended from
|
||||
32bit to 64bit. It is recommended to avoid the higher 32bit of the
|
||||
cookie field though, to simplify compatibility with dbus1 peers. Note
|
||||
that not only the cookie/serial field in the fixed header, but also
|
||||
the reply_cookie/reply_serial additional header field has been
|
||||
increased from 32bit to 64bit, too!
|
||||
|
||||
The header field identifiers have been extended from 8bit to
|
||||
64bit. This has been done to simplify things, and has no effect
|
||||
on the serialization size, as due to alignment for each 8bit
|
||||
header field identifier 56 bits of padding had to be added.
|
||||
|
||||
Note that the header size changed, due to these changes. However,
|
||||
consider that on dbus1 the beginning of the fields array contains the
|
||||
32bit array size (since that is how arrays are encoded on dbus1),
|
||||
thus, if one considers that size part of the header, instead of the
|
||||
array, the size of the header on dbus1 and dbus2 stays identical, at
|
||||
16 bytes.
|
||||
|
||||
0 4 8 12 16
|
||||
Common: | E | T | F | V | ...
|
||||
|
||||
dbus1: | (as above) | Body Length | Serial | Fields Length | Fields array ...
|
||||
|
||||
gvariant: | (as above) | Reserved | Cookie | Fields array ...
|
||||
|
||||
And that's already it.
|
||||
|
||||
Note: To simplify parsing, valid dbus2 messages must include the entire
|
||||
fixed header and additional header fields in a single non-memfd
|
||||
message part. Also, the signature string of the body variant all the
|
||||
way to the end of the message must be in a single non-memfd part
|
||||
too. The parts for this extended header and footer can be the same
|
||||
one, and can also continue any amount of additional body bytes.
|
||||
|
||||
Note: The GVariant "MAYBE" type is not supported, so that messages can
|
||||
be fully converted forth and back between dbus1 and gvariant
|
||||
representations.
|
|
@ -3928,7 +3928,6 @@ install_data('LICENSE.GPL2',
|
|||
'docs/TRANSIENT-SETTINGS.md',
|
||||
'docs/TRANSLATORS.md',
|
||||
'docs/UIDS-GIDS.md',
|
||||
'docs/GVARIANT-SERIALIZATION.md',
|
||||
install_dir : docdir)
|
||||
|
||||
install_subdir('LICENSES',
|
||||
|
|
|
@ -110,25 +110,6 @@
|
|||
#error "neither int nor long are four bytes long?!?"
|
||||
#endif
|
||||
|
||||
/* Rounds up */
|
||||
|
||||
#define ALIGN4(l) (((l) + 3) & ~3)
|
||||
#define ALIGN8(l) (((l) + 7) & ~7)
|
||||
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
#define ALIGN(l) ALIGN8(l)
|
||||
#elif __SIZEOF_POINTER__ == 4
|
||||
#define ALIGN(l) ALIGN4(l)
|
||||
#else
|
||||
#error "Wut? Pointers are neither 4 nor 8 bytes long?"
|
||||
#endif
|
||||
|
||||
#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) (p)))
|
||||
#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) (p)))
|
||||
#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p)))
|
||||
|
||||
#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) (p), (ali)))
|
||||
|
||||
/* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */
|
||||
static inline unsigned long ALIGN_POWER2(unsigned long u) {
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ static inline void static_destruct(void) {
|
|||
if (!__start_SYSTEMD_STATIC_DESTRUCT)
|
||||
return;
|
||||
|
||||
d = ALIGN_TO_PTR(__start_SYSTEMD_STATIC_DESTRUCT, sizeof(void*));
|
||||
d = ALIGN_PTR(__start_SYSTEMD_STATIC_DESTRUCT);
|
||||
while (d < __stop_SYSTEMD_STATIC_DESTRUCT) {
|
||||
d->destroy(d->data);
|
||||
d = ALIGN_TO_PTR(d + 1, sizeof(void*));
|
||||
d = ALIGN_PTR(d + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,12 +96,12 @@ static EFI_STATUS pack_cpio_one(
|
|||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
/* Align the whole header to 4 byte size */
|
||||
l = ALIGN_TO(l, 4);
|
||||
l = ALIGN4(l);
|
||||
if (l == UINTN_MAX) /* overflow check */
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
/* Align the contents to 4 byte size */
|
||||
q = ALIGN_TO(contents_size, 4);
|
||||
q = ALIGN4(contents_size);
|
||||
if (q == UINTN_MAX) /* overflow check */
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
|
@ -188,7 +188,7 @@ static EFI_STATUS pack_cpio_dir(
|
|||
l += path_size;
|
||||
|
||||
/* Align the whole header to 4 byte size */
|
||||
l = ALIGN_TO(l, 4);
|
||||
l = ALIGN4(l);
|
||||
if (l == UINTN_MAX) /* overflow check */
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ static EFI_STATUS combine_initrd(
|
|||
|
||||
/* Combines four initrds into one, by simple concatenation in memory */
|
||||
|
||||
n = ALIGN_TO(initrd_size, 4); /* main initrd might not be padded yet */
|
||||
n = ALIGN4(initrd_size); /* main initrd might not be padded yet */
|
||||
if (credential_initrd) {
|
||||
if (n > UINTN_MAX - credential_initrd_size)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
|
@ -71,7 +71,7 @@ static EFI_STATUS combine_initrd(
|
|||
memcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
|
||||
p += initrd_size;
|
||||
|
||||
pad = ALIGN_TO(initrd_size, 4) - initrd_size;
|
||||
pad = ALIGN4(initrd_size) - initrd_size;
|
||||
if (pad > 0) {
|
||||
memset(p, 0, pad);
|
||||
p += pad;
|
||||
|
|
|
@ -320,6 +320,14 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
|
|||
return ((l + ali - 1) & ~(ali - 1));
|
||||
}
|
||||
|
||||
#define ALIGN4(l) ALIGN_TO(l, 4)
|
||||
#define ALIGN8(l) ALIGN_TO(l, 8)
|
||||
#ifndef SD_BOOT
|
||||
/* libefi also provides ALIGN, and we do not use them in sd-boot explicitly. */
|
||||
#define ALIGN(l) ALIGN_TO(l, sizeof(void*))
|
||||
#define ALIGN_PTR(p) ((void*) ALIGN((uintptr_t) (p)))
|
||||
#endif
|
||||
|
||||
/* Same as ALIGN_TO but callable in constant contexts. */
|
||||
#define CONST_ALIGN_TO(l, ali) \
|
||||
__builtin_choose_expr( \
|
||||
|
|
|
@ -95,8 +95,6 @@ libsystemd_sources = files(
|
|||
'sd-bus/bus-dump.h',
|
||||
'sd-bus/bus-error.c',
|
||||
'sd-bus/bus-error.h',
|
||||
'sd-bus/bus-gvariant.c',
|
||||
'sd-bus/bus-gvariant.h',
|
||||
'sd-bus/bus-internal.c',
|
||||
'sd-bus/bus-internal.h',
|
||||
'sd-bus/bus-introspect.c',
|
||||
|
@ -262,12 +260,6 @@ tests += [
|
|||
[files('sd-bus/test-bus-vtable.c',
|
||||
'sd-bus/test-vtable-data.h')],
|
||||
|
||||
[files('sd-bus/test-bus-gvariant.c'),
|
||||
[],
|
||||
[libglib,
|
||||
libgobject,
|
||||
libgio]],
|
||||
|
||||
[files('sd-bus/test-bus-creds.c')],
|
||||
|
||||
[files('sd-bus/test-bus-match.c')],
|
||||
|
|
|
@ -79,7 +79,7 @@ _public_ int sd_bus_message_dump(sd_bus_message *m, FILE *f, uint64_t flags) {
|
|||
|
||||
/* Display synthetic message serial number in a more readable
|
||||
* format than UINT32_MAX */
|
||||
if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL)
|
||||
if (BUS_MESSAGE_COOKIE(m) == UINT32_MAX)
|
||||
fprintf(f, " Cookie=-1");
|
||||
else
|
||||
fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m));
|
||||
|
|
|
@ -92,7 +92,7 @@ static int bus_error_name_to_errno(const char *name) {
|
|||
}
|
||||
}
|
||||
|
||||
m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*));
|
||||
m = ALIGN_PTR(__start_SYSTEMD_BUS_ERROR_MAP);
|
||||
while (m < __stop_SYSTEMD_BUS_ERROR_MAP) {
|
||||
/* For magic ELF error maps, the end marker might
|
||||
* appear in the middle of things, since multiple maps
|
||||
|
@ -101,7 +101,7 @@ static int bus_error_name_to_errno(const char *name) {
|
|||
* boundary, which is the selected alignment for the
|
||||
* arrays. */
|
||||
if (m->code == BUS_ERROR_MAP_END_MARKER) {
|
||||
m = ALIGN_TO_PTR(m + 1, sizeof(void*));
|
||||
m = ALIGN_PTR(m + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,299 +0,0 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "bus-gvariant.h"
|
||||
#include "bus-signature.h"
|
||||
#include "bus-type.h"
|
||||
|
||||
int bus_gvariant_get_size(const char *signature) {
|
||||
const char *p;
|
||||
int sum = 0, r;
|
||||
|
||||
/* For fixed size structs. Fails for variable size structs. */
|
||||
|
||||
p = signature;
|
||||
while (*p != 0) {
|
||||
size_t n;
|
||||
|
||||
r = signature_element_length(p, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else {
|
||||
char t[n+1];
|
||||
|
||||
memcpy(t, p, n);
|
||||
t[n] = 0;
|
||||
|
||||
r = bus_gvariant_get_alignment(t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sum = ALIGN_TO(sum, r);
|
||||
}
|
||||
|
||||
switch (*p) {
|
||||
|
||||
case SD_BUS_TYPE_BOOLEAN:
|
||||
case SD_BUS_TYPE_BYTE:
|
||||
sum += 1;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_INT16:
|
||||
case SD_BUS_TYPE_UINT16:
|
||||
sum += 2;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_INT32:
|
||||
case SD_BUS_TYPE_UINT32:
|
||||
case SD_BUS_TYPE_UNIX_FD:
|
||||
sum += 4;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_INT64:
|
||||
case SD_BUS_TYPE_UINT64:
|
||||
case SD_BUS_TYPE_DOUBLE:
|
||||
sum += 8;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_STRUCT_BEGIN:
|
||||
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
|
||||
if (n == 2) {
|
||||
/* unary type () has fixed size of 1 */
|
||||
r = 1;
|
||||
} else {
|
||||
char t[n-1];
|
||||
|
||||
memcpy(t, p + 1, n - 2);
|
||||
t[n - 2] = 0;
|
||||
|
||||
r = bus_gvariant_get_size(t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
sum += r;
|
||||
break;
|
||||
}
|
||||
|
||||
case SD_BUS_TYPE_STRING:
|
||||
case SD_BUS_TYPE_OBJECT_PATH:
|
||||
case SD_BUS_TYPE_SIGNATURE:
|
||||
case SD_BUS_TYPE_ARRAY:
|
||||
case SD_BUS_TYPE_VARIANT:
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
p += n;
|
||||
}
|
||||
|
||||
r = bus_gvariant_get_alignment(signature);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return ALIGN_TO(sum, r);
|
||||
}
|
||||
|
||||
int bus_gvariant_get_alignment(const char *signature) {
|
||||
size_t alignment = 1;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
p = signature;
|
||||
while (*p != 0 && alignment < 8) {
|
||||
size_t n;
|
||||
int a;
|
||||
|
||||
r = signature_element_length(p, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (*p) {
|
||||
|
||||
case SD_BUS_TYPE_BYTE:
|
||||
case SD_BUS_TYPE_BOOLEAN:
|
||||
case SD_BUS_TYPE_STRING:
|
||||
case SD_BUS_TYPE_OBJECT_PATH:
|
||||
case SD_BUS_TYPE_SIGNATURE:
|
||||
a = 1;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_INT16:
|
||||
case SD_BUS_TYPE_UINT16:
|
||||
a = 2;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_INT32:
|
||||
case SD_BUS_TYPE_UINT32:
|
||||
case SD_BUS_TYPE_UNIX_FD:
|
||||
a = 4;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_INT64:
|
||||
case SD_BUS_TYPE_UINT64:
|
||||
case SD_BUS_TYPE_DOUBLE:
|
||||
case SD_BUS_TYPE_VARIANT:
|
||||
a = 8;
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_ARRAY: {
|
||||
char t[n];
|
||||
|
||||
memcpy(t, p + 1, n - 1);
|
||||
t[n - 1] = 0;
|
||||
|
||||
a = bus_gvariant_get_alignment(t);
|
||||
break;
|
||||
}
|
||||
|
||||
case SD_BUS_TYPE_STRUCT_BEGIN:
|
||||
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
|
||||
char t[n-1];
|
||||
|
||||
memcpy(t, p + 1, n - 2);
|
||||
t[n - 2] = 0;
|
||||
|
||||
a = bus_gvariant_get_alignment(t);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (a < 0)
|
||||
return a;
|
||||
|
||||
assert(a > 0 && a <= 8);
|
||||
if ((size_t) a > alignment)
|
||||
alignment = (size_t) a;
|
||||
|
||||
p += n;
|
||||
}
|
||||
|
||||
return alignment;
|
||||
}
|
||||
|
||||
int bus_gvariant_is_fixed_size(const char *signature) {
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(signature);
|
||||
|
||||
p = signature;
|
||||
while (*p != 0) {
|
||||
size_t n;
|
||||
|
||||
r = signature_element_length(p, &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (*p) {
|
||||
|
||||
case SD_BUS_TYPE_STRING:
|
||||
case SD_BUS_TYPE_OBJECT_PATH:
|
||||
case SD_BUS_TYPE_SIGNATURE:
|
||||
case SD_BUS_TYPE_ARRAY:
|
||||
case SD_BUS_TYPE_VARIANT:
|
||||
return 0;
|
||||
|
||||
case SD_BUS_TYPE_BYTE:
|
||||
case SD_BUS_TYPE_BOOLEAN:
|
||||
case SD_BUS_TYPE_INT16:
|
||||
case SD_BUS_TYPE_UINT16:
|
||||
case SD_BUS_TYPE_INT32:
|
||||
case SD_BUS_TYPE_UINT32:
|
||||
case SD_BUS_TYPE_UNIX_FD:
|
||||
case SD_BUS_TYPE_INT64:
|
||||
case SD_BUS_TYPE_UINT64:
|
||||
case SD_BUS_TYPE_DOUBLE:
|
||||
break;
|
||||
|
||||
case SD_BUS_TYPE_STRUCT_BEGIN:
|
||||
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
|
||||
char t[n-1];
|
||||
|
||||
memcpy(t, p + 1, n - 2);
|
||||
t[n - 2] = 0;
|
||||
|
||||
r = bus_gvariant_is_fixed_size(t);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
p += n;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
|
||||
if (sz + extra <= 0xFF)
|
||||
return 1;
|
||||
else if (sz + extra*2 <= 0xFFFF)
|
||||
return 2;
|
||||
else if (sz + extra*4 <= 0xFFFFFFFF)
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
}
|
||||
|
||||
size_t bus_gvariant_read_word_le(void *p, size_t sz) {
|
||||
union {
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
} x;
|
||||
|
||||
assert(p);
|
||||
|
||||
if (sz == 1)
|
||||
return *(uint8_t*) p;
|
||||
|
||||
memcpy(&x, p, sz);
|
||||
|
||||
if (sz == 2)
|
||||
return le16toh(x.u16);
|
||||
else if (sz == 4)
|
||||
return le32toh(x.u32);
|
||||
else if (sz == 8)
|
||||
return le64toh(x.u64);
|
||||
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
|
||||
union {
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
} x;
|
||||
|
||||
assert(p);
|
||||
assert(sz == 8 || (value < (1ULL << (sz*8))));
|
||||
|
||||
if (sz == 1) {
|
||||
*(uint8_t*) p = value;
|
||||
return;
|
||||
} else if (sz == 2)
|
||||
x.u16 = htole16((uint16_t) value);
|
||||
else if (sz == 4)
|
||||
x.u32 = htole32((uint32_t) value);
|
||||
else if (sz == 8)
|
||||
x.u64 = htole64((uint64_t) value);
|
||||
else
|
||||
assert_not_reached();
|
||||
|
||||
memcpy(p, &x, sz);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
int bus_gvariant_get_size(const char *signature) _pure_;
|
||||
int bus_gvariant_get_alignment(const char *signature) _pure_;
|
||||
int bus_gvariant_is_fixed_size(const char *signature) _pure_;
|
||||
|
||||
size_t bus_gvariant_determine_word_size(size_t sz, size_t extra);
|
||||
void bus_gvariant_write_word_le(void *p, size_t sz, size_t value);
|
||||
size_t bus_gvariant_read_word_le(void *p, size_t sz);
|
File diff suppressed because it is too large
Load diff
|
@ -14,21 +14,16 @@
|
|||
|
||||
struct bus_container {
|
||||
char enclosing;
|
||||
bool need_offsets:1;
|
||||
|
||||
/* Indexes into the signature string */
|
||||
/* Indexes into the signature string */
|
||||
unsigned index, saved_index;
|
||||
char *signature;
|
||||
|
||||
size_t before, begin, end;
|
||||
|
||||
/* dbus1: pointer to the array size value, if this is a value */
|
||||
/* pointer to the array size value, if this is a value */
|
||||
uint32_t *array_size;
|
||||
|
||||
/* gvariant: list of offsets to end of children if this is struct/dict entry/array */
|
||||
size_t *offsets, n_offsets, offset_index;
|
||||
size_t item_size;
|
||||
|
||||
char *peeked_signature;
|
||||
};
|
||||
|
||||
|
@ -86,13 +81,8 @@ struct sd_bus_message {
|
|||
bool poisoned:1;
|
||||
bool sensitive:1;
|
||||
|
||||
/* The first and last bytes of the message */
|
||||
/* The first bytes of the message */
|
||||
struct bus_header *header;
|
||||
void *footer;
|
||||
|
||||
/* How many bytes are accessible in the above pointers */
|
||||
size_t header_accessible;
|
||||
size_t footer_accessible;
|
||||
|
||||
size_t fields_size;
|
||||
size_t body_size;
|
||||
|
@ -148,10 +138,7 @@ static inline uint64_t BUS_MESSAGE_BSWAP64(sd_bus_message *m, uint64_t u) {
|
|||
}
|
||||
|
||||
static inline uint64_t BUS_MESSAGE_COOKIE(sd_bus_message *m) {
|
||||
if (m->header->version == 2)
|
||||
return BUS_MESSAGE_BSWAP64(m, m->header->dbus2.cookie);
|
||||
|
||||
return BUS_MESSAGE_BSWAP32(m, m->header->dbus1.serial);
|
||||
return BUS_MESSAGE_BSWAP32(m, m->header->serial);
|
||||
}
|
||||
|
||||
static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) {
|
||||
|
@ -171,26 +158,9 @@ static inline void* BUS_MESSAGE_FIELDS(sd_bus_message *m) {
|
|||
return (uint8_t*) m->header + sizeof(struct bus_header);
|
||||
}
|
||||
|
||||
static inline bool BUS_MESSAGE_IS_GVARIANT(sd_bus_message *m) {
|
||||
return m->header->version == 2;
|
||||
}
|
||||
|
||||
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz);
|
||||
int bus_message_read_strv_extend(sd_bus_message *m, char ***l);
|
||||
|
||||
int bus_message_from_header(
|
||||
sd_bus *bus,
|
||||
void *header,
|
||||
size_t header_accessible,
|
||||
void *footer,
|
||||
size_t footer_accessible,
|
||||
size_t message_size,
|
||||
int *fds,
|
||||
size_t n_fds,
|
||||
const char *label,
|
||||
size_t extra,
|
||||
sd_bus_message **ret);
|
||||
|
||||
int bus_message_from_malloc(
|
||||
sd_bus *bus,
|
||||
void *buffer,
|
||||
|
@ -203,18 +173,12 @@ int bus_message_from_malloc(
|
|||
int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str);
|
||||
int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv);
|
||||
|
||||
int bus_message_parse_fields(sd_bus_message *m);
|
||||
|
||||
struct bus_body_part *message_append_part(sd_bus_message *m);
|
||||
|
||||
#define MESSAGE_FOREACH_PART(part, i, m) \
|
||||
for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts; (i)++, (part) = (part)->next)
|
||||
|
||||
int bus_body_part_map(struct bus_body_part *part);
|
||||
void bus_body_part_unmap(struct bus_body_part *part);
|
||||
|
||||
int bus_message_to_errno(sd_bus_message *m);
|
||||
|
||||
int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m);
|
||||
|
||||
int bus_message_remarshal(sd_bus *bus, sd_bus_message **m);
|
||||
|
|
|
@ -8,32 +8,15 @@
|
|||
/* Packet header */
|
||||
|
||||
struct _packed_ bus_header {
|
||||
/* The first four fields are identical for dbus1, and dbus2 */
|
||||
uint8_t endian;
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
uint8_t version;
|
||||
|
||||
union _packed_ {
|
||||
/* dbus1: Used for SOCK_STREAM connections */
|
||||
struct _packed_ {
|
||||
uint32_t body_size;
|
||||
|
||||
/* Note that what the bus spec calls "serial" we'll call
|
||||
"cookie" instead, because we don't want to imply that the
|
||||
cookie was in any way monotonically increasing. */
|
||||
uint32_t serial;
|
||||
uint32_t fields_size;
|
||||
} dbus1;
|
||||
|
||||
/* dbus2: Used for kdbus connections */
|
||||
struct _packed_ {
|
||||
uint32_t _reserved;
|
||||
uint64_t cookie;
|
||||
} dbus2;
|
||||
|
||||
/* Note that both header versions have the same size! */
|
||||
};
|
||||
uint32_t body_size;
|
||||
/* Note that what the bus spec calls "serial" we'll call "cookie" instead, because we don't
|
||||
* want to imply that the cookie was in any way monotonically increasing. */
|
||||
uint32_t serial;
|
||||
uint32_t fields_size;
|
||||
};
|
||||
|
||||
/* Endianness */
|
||||
|
|
|
@ -1124,7 +1124,7 @@ static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
|
|||
} else
|
||||
return -EBADMSG;
|
||||
|
||||
sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
|
||||
sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN8(b) + (uint64_t) a;
|
||||
if (sum >= BUS_MESSAGE_SIZE_MAX)
|
||||
return -ENOBUFS;
|
||||
|
||||
|
|
|
@ -1966,10 +1966,8 @@ int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
|
|||
* hence let's fill something in for synthetic messages. Since
|
||||
* synthetic messages might have a fake sender and we don't
|
||||
* want to interfere with the real sender's serial numbers we
|
||||
* pick a fixed, artificial one. We use UINT32_MAX rather
|
||||
* than UINT64_MAX since dbus1 only had 32bit identifiers,
|
||||
* even though kdbus can do 64bit. */
|
||||
return sd_bus_message_seal(m, 0xFFFFFFFFULL, 0);
|
||||
* pick a fixed, artificial one. */
|
||||
return sd_bus_message_seal(m, UINT32_MAX, 0);
|
||||
}
|
||||
|
||||
static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
|
||||
|
|
|
@ -131,11 +131,11 @@ static int dump_mapping_table(void) {
|
|||
const sd_bus_error_map *m;
|
||||
|
||||
printf("----- errno mappings ------\n");
|
||||
m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*));
|
||||
m = ALIGN_PTR(__start_SYSTEMD_BUS_ERROR_MAP);
|
||||
while (m < __stop_SYSTEMD_BUS_ERROR_MAP) {
|
||||
|
||||
if (m->code == BUS_ERROR_MAP_END_MARKER) {
|
||||
m = ALIGN_TO_PTR(m + 1, sizeof(void*));
|
||||
m = ALIGN_PTR(m + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,206 +0,0 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#if HAVE_GLIB
|
||||
#include <glib.h>
|
||||
#endif
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-dump.h"
|
||||
#include "bus-gvariant.h"
|
||||
#include "bus-internal.h"
|
||||
#include "bus-message.h"
|
||||
#include "macro.h"
|
||||
#include "tests.h"
|
||||
#include "util.h"
|
||||
|
||||
TEST(bus_gvariant_is_fixed_size) {
|
||||
assert_se(bus_gvariant_is_fixed_size("") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("()") == -EINVAL);
|
||||
assert_se(bus_gvariant_is_fixed_size("y") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("u") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("b") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("n") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("q") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("i") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("t") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("d") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("s") == 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("o") == 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("g") == 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("h") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("ay") == 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("v") == 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("(u)") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("(uuuuy)") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("(uusuuy)") == 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("a{ss}") == 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiii)))") > 0);
|
||||
assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiivi)))") == 0);
|
||||
}
|
||||
|
||||
TEST(bus_gvariant_get_size) {
|
||||
assert_se(bus_gvariant_get_size("") == 0);
|
||||
assert_se(bus_gvariant_get_size("()") == -EINVAL);
|
||||
assert_se(bus_gvariant_get_size("y") == 1);
|
||||
assert_se(bus_gvariant_get_size("u") == 4);
|
||||
assert_se(bus_gvariant_get_size("b") == 1);
|
||||
assert_se(bus_gvariant_get_size("n") == 2);
|
||||
assert_se(bus_gvariant_get_size("q") == 2);
|
||||
assert_se(bus_gvariant_get_size("i") == 4);
|
||||
assert_se(bus_gvariant_get_size("t") == 8);
|
||||
assert_se(bus_gvariant_get_size("d") == 8);
|
||||
assert_se(bus_gvariant_get_size("s") < 0);
|
||||
assert_se(bus_gvariant_get_size("o") < 0);
|
||||
assert_se(bus_gvariant_get_size("g") < 0);
|
||||
assert_se(bus_gvariant_get_size("h") == 4);
|
||||
assert_se(bus_gvariant_get_size("ay") < 0);
|
||||
assert_se(bus_gvariant_get_size("v") < 0);
|
||||
assert_se(bus_gvariant_get_size("(u)") == 4);
|
||||
assert_se(bus_gvariant_get_size("(uuuuy)") == 20);
|
||||
assert_se(bus_gvariant_get_size("(uusuuy)") < 0);
|
||||
assert_se(bus_gvariant_get_size("a{ss}") < 0);
|
||||
assert_se(bus_gvariant_get_size("((u)yyy(b(iiii)))") == 28);
|
||||
assert_se(bus_gvariant_get_size("((u)yyy(b(iiivi)))") < 0);
|
||||
assert_se(bus_gvariant_get_size("((b)(t))") == 16);
|
||||
assert_se(bus_gvariant_get_size("((b)(b)(t))") == 16);
|
||||
assert_se(bus_gvariant_get_size("(bt)") == 16);
|
||||
assert_se(bus_gvariant_get_size("((t)(b))") == 16);
|
||||
assert_se(bus_gvariant_get_size("(tb)") == 16);
|
||||
assert_se(bus_gvariant_get_size("((b)(b))") == 2);
|
||||
assert_se(bus_gvariant_get_size("((t)(t))") == 16);
|
||||
}
|
||||
|
||||
TEST(bus_gvariant_get_alignment) {
|
||||
assert_se(bus_gvariant_get_alignment("") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("()") == -EINVAL);
|
||||
assert_se(bus_gvariant_get_alignment("y") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("b") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("u") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("s") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("o") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("g") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("v") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("h") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("i") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("t") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("x") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("q") == 2);
|
||||
assert_se(bus_gvariant_get_alignment("n") == 2);
|
||||
assert_se(bus_gvariant_get_alignment("d") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("ay") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("as") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("au") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("an") == 2);
|
||||
assert_se(bus_gvariant_get_alignment("ans") == 2);
|
||||
assert_se(bus_gvariant_get_alignment("ant") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("(ss)") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("(ssu)") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("a(ssu)") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("(u)") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("(uuuuy)") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("(uusuuy)") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("a{ss}") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiii)))") == 4);
|
||||
assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiivi)))") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("((b)(t))") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("((b)(b)(t))") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("(bt)") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("((t)(b))") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("(tb)") == 8);
|
||||
assert_se(bus_gvariant_get_alignment("((b)(b))") == 1);
|
||||
assert_se(bus_gvariant_get_alignment("((t)(t))") == 8);
|
||||
}
|
||||
|
||||
TEST_RET(marshal) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *n = NULL;
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_free_ void *blob = NULL;
|
||||
size_t sz;
|
||||
int r;
|
||||
|
||||
r = sd_bus_open_user(&bus);
|
||||
if (r < 0)
|
||||
r = sd_bus_open_system(&bus);
|
||||
if (r < 0)
|
||||
return log_tests_skipped_errno(r, "Failed to connect to bus");
|
||||
|
||||
bus->message_version = 2; /* dirty hack to enable gvariant */
|
||||
|
||||
r = sd_bus_message_new_method_call(bus, &m, "a.service.name",
|
||||
"/an/object/path/which/is/really/really/long/so/that/we/hit/the/eight/bit/boundary/by/quite/some/margin/to/test/this/stuff/that/it/really/works",
|
||||
"an.interface.name", "AMethodName");
|
||||
assert_se(r >= 0);
|
||||
|
||||
assert_cc(sizeof(struct bus_header) == 16);
|
||||
|
||||
assert_se(sd_bus_message_append(m,
|
||||
"a(usv)", 3,
|
||||
4711, "first-string-parameter", "(st)", "X", (uint64_t) 1111,
|
||||
4712, "second-string-parameter", "(a(si))", 2, "Y", 5, "Z", 6,
|
||||
4713, "third-string-parameter", "(uu)", 1, 2) >= 0);
|
||||
|
||||
assert_se(sd_bus_message_seal(m, 4711, 0) >= 0);
|
||||
|
||||
#if HAVE_GLIB
|
||||
{
|
||||
GVariant *v;
|
||||
char *t;
|
||||
|
||||
#if !defined(GLIB_VERSION_2_36)
|
||||
g_type_init();
|
||||
#endif
|
||||
|
||||
v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv})"), m->header, sizeof(struct bus_header) + m->fields_size, false, NULL, NULL);
|
||||
assert_se(g_variant_is_normal_form(v));
|
||||
t = g_variant_print(v, TRUE);
|
||||
printf("%s\n", t);
|
||||
g_free(t);
|
||||
g_variant_unref(v);
|
||||
|
||||
v = g_variant_new_from_data(G_VARIANT_TYPE("(a(usv))"), m->body.data, m->user_body_size, false, NULL, NULL);
|
||||
assert_se(g_variant_is_normal_form(v));
|
||||
t = g_variant_print(v, TRUE);
|
||||
printf("%s\n", t);
|
||||
g_free(t);
|
||||
g_variant_unref(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
assert_se(sd_bus_message_dump(m, NULL, SD_BUS_MESSAGE_DUMP_WITH_HEADER) >= 0);
|
||||
|
||||
assert_se(bus_message_get_blob(m, &blob, &sz) >= 0);
|
||||
|
||||
#if HAVE_GLIB
|
||||
{
|
||||
GVariant *v;
|
||||
char *t;
|
||||
|
||||
v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv}v)"), blob, sz, false, NULL, NULL);
|
||||
assert_se(g_variant_is_normal_form(v));
|
||||
t = g_variant_print(v, TRUE);
|
||||
printf("%s\n", t);
|
||||
g_free(t);
|
||||
g_variant_unref(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
assert_se(bus_message_from_malloc(bus, blob, sz, NULL, 0, NULL, &n) >= 0);
|
||||
blob = NULL;
|
||||
|
||||
assert_se(sd_bus_message_dump(n, NULL, SD_BUS_MESSAGE_DUMP_WITH_HEADER) >= 0);
|
||||
|
||||
m = sd_bus_message_unref(m);
|
||||
|
||||
assert_se(sd_bus_message_new_method_call(bus, &m, "a.x", "/a/x", "a.x", "Ax") >= 0);
|
||||
|
||||
assert_se(sd_bus_message_append(m, "as", 0) >= 0);
|
||||
|
||||
assert_se(sd_bus_message_seal(m, 4712, 0) >= 0);
|
||||
assert_se(sd_bus_message_dump(m, NULL, SD_BUS_MESSAGE_DUMP_WITH_HEADER) >= 0);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
|
@ -88,7 +88,7 @@ static inline int run_test_table(void) {
|
|||
if (!__start_SYSTEMD_TEST_TABLE)
|
||||
return r;
|
||||
|
||||
const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*));
|
||||
const TestFunc *t = ALIGN_PTR(__start_SYSTEMD_TEST_TABLE);
|
||||
while (t < __stop_SYSTEMD_TEST_TABLE) {
|
||||
|
||||
if (t->sd_booted && sd_booted() <= 0) {
|
||||
|
@ -106,7 +106,7 @@ static inline int run_test_table(void) {
|
|||
t->f.void_func();
|
||||
}
|
||||
|
||||
t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*));
|
||||
t = ALIGN_PTR(t + 1);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
|
Loading…
Reference in a new issue