summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2017-05-20 17:35:06 -0400
committerLuke Shumaker <lukeshu@lukeshu.com>2017-05-20 17:35:06 -0400
commitf2f1f2472c5efc541bd53f51289ad58a86fa2d41 (patch)
tree42807ddc64ab0672744c716d9f952e5673762b9d /src/libsystemd/sd-bus
parent3eed542bbc10978aa0b68a39dd3619edf7a7d90b (diff)
./tools/notsd-move
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r--src/libsystemd/sd-bus/DIFFERENCES25
-rw-r--r--src/libsystemd/sd-bus/GVARIANT-SERIALIZATION110
l---------src/libsystemd/sd-bus/Makefile1
-rw-r--r--src/libsystemd/sd-bus/PORTING-DBUS1535
-rw-r--r--src/libsystemd/sd-bus/bus-bloom.c156
-rw-r--r--src/libsystemd/sd-bus/bus-bloom.h43
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.c112
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.h89
-rw-r--r--src/libsystemd/sd-bus/bus-container.c277
-rw-r--r--src/libsystemd/sd-bus/bus-container.h25
-rw-r--r--src/libsystemd/sd-bus/bus-control.c1588
-rw-r--r--src/libsystemd/sd-bus/bus-control.h32
-rw-r--r--src/libsystemd/sd-bus/bus-convenience.c626
-rw-r--r--src/libsystemd/sd-bus/bus-creds.c1349
-rw-r--r--src/libsystemd/sd-bus/bus-creds.h90
-rw-r--r--src/libsystemd/sd-bus/bus-dump.c602
-rw-r--r--src/libsystemd/sd-bus/bus-dump.h37
-rw-r--r--src/libsystemd/sd-bus/bus-error.c606
-rw-r--r--src/libsystemd/sd-bus/bus-error.h64
-rw-r--r--src/libsystemd/sd-bus/bus-gvariant.c311
-rw-r--r--src/libsystemd/sd-bus/bus-gvariant.h30
-rw-r--r--src/libsystemd/sd-bus/bus-internal.c374
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h403
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.c212
-rw-r--r--src/libsystemd/sd-bus/bus-introspect.h40
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c1782
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.h93
-rw-r--r--src/libsystemd/sd-bus/bus-match.c1221
-rw-r--r--src/libsystemd/sd-bus/bus-match.h100
-rw-r--r--src/libsystemd/sd-bus/bus-message.c5939
-rw-r--r--src/libsystemd/sd-bus/bus-message.h244
-rw-r--r--src/libsystemd/sd-bus/bus-objects.c2806
-rw-r--r--src/libsystemd/sd-bus/bus-objects.h25
-rw-r--r--src/libsystemd/sd-bus/bus-protocol.h180
-rw-r--r--src/libsystemd/sd-bus/bus-signature.c158
-rw-r--r--src/libsystemd/sd-bus/bus-signature.h28
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c284
-rw-r--r--src/libsystemd/sd-bus/bus-slot.h28
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c1064
-rw-r--r--src/libsystemd/sd-bus/bus-socket.h37
-rw-r--r--src/libsystemd/sd-bus/bus-track.c525
-rw-r--r--src/libsystemd/sd-bus/bus-track.h23
-rw-r--r--src/libsystemd/sd-bus/bus-type.c176
-rw-r--r--src/libsystemd/sd-bus/bus-type.h37
-rw-r--r--src/libsystemd/sd-bus/busctl-introspect.c790
-rw-r--r--src/libsystemd/sd-bus/busctl-introspect.h32
-rw-r--r--src/libsystemd/sd-bus/busctl.c2086
-rw-r--r--src/libsystemd/sd-bus/kdbus.h980
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c3853
-rw-r--r--src/libsystemd/sd-bus/test-bus-benchmark.c371
-rw-r--r--src/libsystemd/sd-bus/test-bus-chat.c560
-rw-r--r--src/libsystemd/sd-bus/test-bus-cleanup.c95
-rw-r--r--src/libsystemd/sd-bus/test-bus-creds.c55
-rw-r--r--src/libsystemd/sd-bus/test-bus-error.c232
-rw-r--r--src/libsystemd/sd-bus/test-bus-gvariant.c224
-rw-r--r--src/libsystemd/sd-bus/test-bus-introspect.c63
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel-bloom.c141
-rw-r--r--src/libsystemd/sd-bus/test-bus-kernel.c190
-rw-r--r--src/libsystemd/sd-bus/test-bus-marshal.c432
-rw-r--r--src/libsystemd/sd-bus/test-bus-match.c159
-rw-r--r--src/libsystemd/sd-bus/test-bus-objects.c555
-rw-r--r--src/libsystemd/sd-bus/test-bus-server.c216
-rw-r--r--src/libsystemd/sd-bus/test-bus-signature.c164
-rw-r--r--src/libsystemd/sd-bus/test-bus-track.c113
-rw-r--r--src/libsystemd/sd-bus/test-bus-zero-copy.c210
65 files changed, 0 insertions, 34008 deletions
diff --git a/src/libsystemd/sd-bus/DIFFERENCES b/src/libsystemd/sd-bus/DIFFERENCES
deleted file mode 100644
index db269675a7..0000000000
--- a/src/libsystemd/sd-bus/DIFFERENCES
+++ /dev/null
@@ -1,25 +0,0 @@
-Known differences between dbus1 and kdbus:
-
-- NameAcquired/NameLost is gone entirely on kdbus backends if
- libsystemd is used. It is still added in by systemd-bus-proxyd
- for old dbus1 clients, and it is available if libsystemd is used
- against the classic dbus1 daemon. If you want to write compatible
- code with libsystem-bus you need to explicitly subscribe to
- NameOwnerChanged signals and just ignore NameAcquired/NameLost
-
-- Applications have to deal with spurious signals they didn't expect,
- due to the probabilistic bloom filters. They need to handle this
- anyway, given that any client can send anything to arbitrary clients
- anyway, even in dbus1, so not much changes.
-
-- clients of the system bus when kdbus is used must roll their own
- security. Only legacy dbus1 clients get the old XML policy enforced,
- which is implemented by systemd-bus-proxyd.
-
-- Serial numbers of synthesized messages are always (uint32_t) -1.
-
-- NameOwnerChanged is a synthetic message, generated locally and not
- by the driver. On dbus1 only the Disconnected message was
- synthesized like this.
-
-- There's no standard per-session bus anymore. Only a per-user bus.
diff --git a/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION b/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
deleted file mode 100644
index 6aeb11364a..0000000000
--- a/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION
+++ /dev/null
@@ -1,110 +0,0 @@
-How we use GVariant for serializing D-Bus messages
---------------------------------------------------
-
-We stay 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 endianess 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 (as kdbus otherwise uses
-exclusively 64bit types, unless there is a strong reason not to), 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 kdbus/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: on kdbus only native endian messages marshalled in gvariant may
- be sent. If a client receives a message in non-native endianness
- or in dbus1 marshalling it shall ignore the message.
-
-Note: The GVariant "MAYBE" type is not supported, so that messages can
- be fully converted forth and back between dbus1 and gvariant
- representations.
diff --git a/src/libsystemd/sd-bus/Makefile b/src/libsystemd/sd-bus/Makefile
deleted file mode 120000
index 94aaae2c4d..0000000000
--- a/src/libsystemd/sd-bus/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../../Makefile \ No newline at end of file
diff --git a/src/libsystemd/sd-bus/PORTING-DBUS1 b/src/libsystemd/sd-bus/PORTING-DBUS1
deleted file mode 100644
index 2dedb28bcf..0000000000
--- a/src/libsystemd/sd-bus/PORTING-DBUS1
+++ /dev/null
@@ -1,535 +0,0 @@
-A few hints on supporting kdbus as backend in your favorite D-Bus library.
-
-~~~
-
-Before you read this, have a look at the DIFFERENCES and
-GVARIANT_SERIALIZATION texts you find in the same directory where you
-found this.
-
-We invite you to port your favorite D-Bus protocol implementation
-over to kdbus. However, there are a couple of complexities
-involved. On kdbus we only speak GVariant marshaling, kdbus clients
-ignore traffic in dbus1 marshaling. Thus, you need to add a second,
-GVariant compatible marshaler to your library first.
-
-After you have done that: here's the basic principle how kdbus works:
-
-You connect to a bus by opening its bus node in /sys/fs/kdbus/. All
-buses have a device node there, it starts with a numeric UID of the
-owner of the bus, followed by a dash and a string identifying the
-bus. The system bus is thus called /sys/fs/kdbus/0-system, and for user
-buses the device node is /sys/fs/kdbus/1000-user (if 1000 is your user
-id).
-
-(Before we proceed, please always keep a copy of libsystemd next
-to you, ultimately that's where the details are, this document simply
-is a rough overview to help you grok things.)
-
-CONNECTING
-
-To connect to a bus, simply open() its device node and issue the
-KDBUS_CMD_HELLO call. That's it. Now you are connected. Do not send
-Hello messages or so (as you would on dbus1), that does not exist for
-kdbus.
-
-The structure you pass to the ioctl will contain a couple of
-parameters that you need to know, to operate on the bus.
-
-There are two flags fields, one indicating features of the kdbus
-kernel side ("conn_flags"), the other one ("bus_flags") indicating
-features of the bus owner (i.e. systemd). Both flags fields are 64bit
-in width.
-
-When calling into the ioctl, you need to place your own supported
-feature bits into these fields. This tells the kernel about the
-features you support. When the ioctl returns, it will contain the
-features the kernel supports.
-
-If any of the higher 32bit are set on the two flags fields and your
-client does not know what they mean, it must disconnect. The upper
-32bit are used to indicate "incompatible" feature additions on the bus
-system, the lower 32bit indicate "compatible" feature additions. A
-client that does not support a "compatible" feature addition can go on
-communicating with the bus, however a client that does not support an
-"incompatible" feature must not proceed with the connection. When a
-client encountes such an "incompatible" feature it should immediately
-try the next bus address configured in the bus address string.
-
-The hello structure also contains another flags field "attach_flags"
-which indicates metadata that is optionally attached to all incoming
-messages. You probably want to set KDBUS_ATTACH_NAMES unconditionally
-in it. This has the effect that all well-known names of a sender are
-attached to all incoming messages. You need this information to
-implement matches that match on a message sender name correctly. Of
-course, you should only request the attachment of as little metadata
-fields as you need.
-
-The kernel will return in the "id" field your unique id. This is a
-simple numeric value. For compatibility with classic dbus1 simply
-format this as string and prefix ":1.".
-
-The kernel will also return the bloom filter size and bloom filter
-hash function number used for the signal broadcast bloom filter (see
-below).
-
-The kernel will also return the bus ID of the bus in a 128bit field.
-
-The pool size field specifies the size of the memory mapped buffer.
-After the calling the hello ioctl, you should memory map the kdbus
-fd. In this memory mapped region, the kernel will place all your incoming
-messages.
-
-SENDING MESSAGES
-
-Use the MSG_SEND ioctl to send a message to another peer. The ioctl
-takes a structure that contains a variety of fields:
-
-The flags field corresponds closely to the old dbus1 message header
-flags field, though the DONT_EXPECT_REPLY field got inverted into
-EXPECT_REPLY.
-
-The dst_id/src_id field contains the unique id of the destination and
-the sender. The sender field is overridden by the kernel usually, hence
-you shouldn't fill it in. The destination field can also take the
-special value KDBUS_DST_ID_BROADCAST for broadcast messages. For
-messages intended to a well-known name set the field to
-KDBUS_DST_ID_NAME, and attach the name in a special "items" entry to
-the message (see below).
-
-The payload field indicates the payload. For all dbus traffic it
-should carry the value 0x4442757344427573ULL. (Which encodes
-'DBusDBus').
-
-The cookie field corresponds with the "serial" field of classic
-dbus1. We simply renamed it here (and extended it to 64bit) since we
-didn't want to imply the monotonicity of the assignment the way the
-word "serial" indicates it.
-
-When sending a message that expects a reply, you need to set the
-EXPECT_REPLY flag in the message flag field. In this case you should
-also fill out the "timeout_ns" value which indicates the timeout in
-nsec for this call. If the peer does not respond in this time you will
-get a notification of a timeout. Note that this is also used for
-security purposes: a single reply messages is only allowed through the
-bus as long as the timeout has not ended. With this timeout value you
-hence "open a time window" in which the peer might respond to your
-request and the policy allows the response to go through.
-
-When sending a message that is a reply, you need to fill in the
-cookie_reply field, which is similar to the reply_serial field of
-dbus1. Note that a message cannot have EXPECT_REPLY and a reply_serial
-at the same time!
-
-This pretty much explains the ioctl header. The actual payload of the
-data is now referenced in additional items that are attached to this
-ioctl header structure at the end. When sending a message, you attach
-items of the type PAYLOAD_VEC, PAYLOAD_MEMFD, FDS, BLOOM_FILTER,
-DST_NAME to it:
-
- KDBUS_ITEM_PAYLOAD_VEC: contains a pointer + length pair for
- referencing arbitrary user memory. This is how you reference most
- of your data. It's a lot like the good old iovec structure of glibc.
-
- KDBUS_ITEM_PAYLOAD_MEMFD: for large data blocks it is preferable
- to send prepared "memfds" (see below) over. This item contains an
- fd for a memfd plus a size.
-
- KDBUS_ITEM_FDS: for sending over fds attach an item of this type with
- an array of fds.
-
- KDBUS_ITEM_BLOOM_FILTER: the calculated bloom filter of this message,
- only for undirected (broadcast) message.
-
- KDBUS_ITEM_DST_NAME: for messages that are directed to a well-known
- name (instead of a unique name), this item contains the well-known
- name field.
-
-A single message may consists of no, one or more payload items of type
-PAYLOAD_VEC or PAYLOAD_MEMFD. D-Bus protocol implementations should
-treat them as a single block that just happens to be split up into
-multiple items. Some restrictions apply however:
-
- The message header in its entirety must be contained in a single
- PAYLOAD_VEC item.
-
- You may only split your message up right in front of each GVariant
- contained in the payload, as well is immediately before framing of a
- Gvariant, as well after as any padding bytes if there are any. The
- padding bytes must be wholly contained in the preceding
- PAYLOAD_VEC/PAYLOAD_MEMFD item. You may not split up basic types
- nor arrays of fixed types. The latter is necessary to allow APIs
- to return direct pointers to linear arrays of numeric
- values. Examples: The basic types "u", "s", "t" have to be in the
- same payload item. The array of fixed types "ay", "ai" have to be
- fully in contained in the same payload item. For an array "as" or
- "a(si)" the only restriction however is to keep each string
- individually in an uninterrupted item, to keep the framing of each
- element and the array in a single uninterrupted item, however the
- various strings might end up in different items.
-
-Note again, that splitting up messages into separate items is up to the
-implementation. Also note that the kdbus kernel side might merge
-separate items if it deems this to be useful. However, the order in
-which items are contained in the message is left untouched.
-
-PAYLOAD_MEMFD items allow zero-copy data transfer (see below regarding
-the memfd concept). Note however that the overhead of mapping these
-makes them relatively expensive, and only worth the trouble for memory
-blocks > 512K (this value appears to be quite universal across
-architectures, as we tested). Thus we recommend sending PAYLOAD_VEC
-items over for small messages and restore to PAYLOAD_MEMFD items for
-messages > 512K. Since while building up the message you might not
-know yet whether it will grow beyond this boundary a good approach is
-to simply build the message unconditionally in a memfd
-object. However, when the message is sealed to be sent away check for
-the size limit. If the size of the message is < 512K, then simply send
-the data as PAYLOAD_VEC and reuse the memfd. If it is >= 512K, seal
-the memfd and send it as PAYLOAD_MEMFD, and allocate a new memfd for
-the next message.
-
-RECEIVING MESSAGES
-
-Use the MSG_RECV ioctl to read a message from kdbus. This will return
-an offset into the pool memory map, relative to its beginning.
-
-The received message structure more or less follows the structure of
-the message originally sent. However, certain changes have been
-made. In the header the src_id field will be filled in.
-
-The payload items might have gotten merged and PAYLOAD_VEC items are
-not used. Instead, you will only find PAYLOAD_OFF and PAYLOAD_MEMFD
-items. The former contain an offset and size into your memory mapped
-pool where you find the payload.
-
-If during the HELLO ioctl you asked for getting metadata attached to
-your message, you will find additional KDBUS_ITEM_CREDS,
-KDBUS_ITEM_PID_COMM, KDBUS_ITEM_TID_COMM, KDBUS_ITEM_TIMESTAMP,
-KDBUS_ITEM_EXE, KDBUS_ITEM_CMDLINE, KDBUS_ITEM_CGROUP,
-KDBUS_ITEM_CAPS, KDBUS_ITEM_SECLABEL, KDBUS_ITEM_AUDIT items that
-contain this metadata. This metadata will be gathered from the sender
-at the point in time it sends the message. This information is
-uncached, and since it is appended by the kernel, trustable. The
-KDBUS_ITEM_SECLABEL item usually contains the SELinux security label,
-if it is used.
-
-After processing the message you need to call the KDBUS_CMD_FREE
-ioctl, which releases the message from the pool, and allows the kernel
-to store another message there. Note that the memory used by the pool
-is ordinary anonymous, swappable memory that is backed by tmpfs. Hence
-there is no need to copy the message out of it quickly, instead you
-can just leave it there as long as you need it and release it via the
-FREE ioctl only after that's done.
-
-BLOOM FILTERS
-
-The kernel does not understand dbus marshaling, it will not look into
-the message payload. To allow clients to subscribe to specific subsets
-of the broadcast matches we employ bloom filters.
-
-When broadcasting messages, a bloom filter needs to be attached to the
-message in a KDBUS_ITEM_BLOOM item (and only for broadcasting
-messages!). If you don't know what bloom filters are, read up now on
-Wikipedia. In short: they are a very efficient way how to
-probabilistically check whether a certain word is contained in a
-vocabulary. It knows no false negatives, but it does know false
-positives.
-
-The parameters for the bloom filters that need to be included in
-broadcast message is communicated to userspace as part of the hello
-response structure (see above). By default it has the parameters m=512
-(bits in the filter), k=8 (nr of hash functions). Note however, that
-this is subject to change in later versions, and userspace
-implementations must be capable of handling m values between at least
-m=8 and m=2^32, and k values between at least k=1 and k=32. The
-underlying hash function is SipHash-2-4. It is used with a number of
-constant (yet originally randomly generated) 128bit hash keys, more
-specifically:
-
- b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15,
- aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b,
- 63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8,
- 23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5,
- 56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10,
- 31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29,
- 7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d,
- f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35
-
-When calculating the first bit index into the bloom filter, the
-SipHash-2-4 hash value is calculated for the input data and the first
-16 bytes of the array above as hash key. Of the resulting 8 bytes of
-output, as many full bytes are taken for the bit index as necessary,
-starting from the output's first byte. For the second bit index the
-same hash value is used, continuing with the next unused output byte,
-and so on. Each time the bytes returned by the hash function are
-depleted it is recalculated with the next 16 byte hash key from the
-array above and the same input data.
-
-For each message to send across the bus we populate the bloom filter
-with all possible matchable strings. If a client then wants to
-subscribe to messages of this type, it simply tells the kernel to test
-its own calculated bit mask against the bloom filter of each message.
-
-More specifically, the following strings are added to the bloom filter
-of each message that is broadcasted:
-
- The string "interface:" suffixed by the interface name
-
- The string "member:" suffixed by the member name
-
- The string "path:" suffixed by the path name
-
- The string "path-slash-prefix:" suffixed with the path name, and
- also all prefixes of the path name (cut off at "/"), also prefixed
- with "path-slash-prefix".
-
- The string "message-type:" suffixed with the strings "signal",
- "method_call", "error" or "method_return" for the respective message
- type of the message.
-
- If the first argument of the message is a string, "arg0:" suffixed
- with the first argument.
-
- If the first argument of the message is a string, "arg0-dot-prefix"
- suffixed with the first argument, and also all prefixes of the
- argument (cut off at "."), also prefixed with "arg0-dot-prefix".
-
- If the first argument of the message is a string,
- "arg0-slash-prefix" suffixed with the first argument, and also all
- prefixes of the argument (cut off at "/"), also prefixed with
- "arg0-slash-prefix".
-
- Similar for all further arguments that are strings up to 63, for the
- arguments and their "dot" and "slash" prefixes. On the first
- argument that is not a string, addition to the bloom filter should be
- stopped however.
-
-(Note that the bloom filter does not contain sender nor receiver
-names!)
-
-When a client wants to subscribe to messages matching a certain
-expression, it should calculate the bloom mask following the same
-algorithm. The kernel will then simply test the mask against the
-attached bloom filters.
-
-Note that bloom filters are probabilistic, which means that clients
-might get messages they did not expect. Your bus protocol
-implementation must be capable of dealing with these unexpected
-messages (which it needs to anyway, given that transfers are
-relatively unrestricted on kdbus and people can send you all kinds of
-non-sense).
-
-If a client connects to a bus whose bloom filter metrics (i.e. filter
-size and number of hash functions) are outside of the range the client
-supports it must immediately disconnect and continue connection with
-the next bus address of the bus connection string.
-
-INSTALLING MATCHES
-
-To install matches for broadcast messages, use the KDBUS_CMD_ADD_MATCH
-ioctl. It takes a structure that contains an encoded match expression,
-and that is followed by one or more items, which are combined in an
-AND way. (Meaning: a message is matched exactly when all items
-attached to the original ioctl struct match).
-
-To match against other user messages add a KDBUS_ITEM_BLOOM item in
-the match (see above). Note that the bloom filter does not include
-matches to the sender names. To additionally check against sender
-names, use the KDBUS_ITEM_ID (for unique id matches) and
-KDBUS_ITEM_NAME (for well-known name matches) item types.
-
-To match against kernel generated messages (see below) you should add
-items of the same type as the kernel messages include,
-i.e. KDBUS_ITEM_NAME_ADD, KDBUS_ITEM_NAME_REMOVE,
-KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD, KDBUS_ITEM_ID_REMOVE and
-fill them out. Note however, that you have some wildcards in this
-case, for example the .id field of KDBUS_ITEM_ID_ADD/KDBUS_ITEM_ID_REMOVE
-structures may be set to 0 to match against any id addition/removal.
-
-Note that dbus match strings do no map 1:1 to these ioctl() calls. In
-many cases (where the match string is "underspecified") you might need
-to issue up to six different ioctl() calls for the same match. For
-example, the empty match (which matches against all messages), would
-translate into one KDBUS_ITEM_BLOOM ioctl, one KDBUS_ITEM_NAME_ADD,
-one KDBUS_ITEM_NAME_CHANGE, one KDBUS_ITEM_NAME_REMOVE, one
-KDBUS_ITEM_ID_ADD and one KDBUS_ITEM_ID_REMOVE.
-
-When creating a match, you may attach a "cookie" value to them, which
-is used for deleting this match again. The cookie can be selected freely
-by the client. When issuing KDBUS_CMD_REMOVE_MATCH, simply pass the
-same cookie as before and all matches matching the same "cookie" value
-will be removed. This is particularly handy for the case where multiple
-ioctl()s are added for a single match strings.
-
-MEMFDS
-
-memfds may be sent across kdbus via KDBUS_ITEM_PAYLOAD_MEMFD items
-attached to messages. If this is done, the data included in the memfd
-is considered part of the payload stream of a message, and are treated
-the same way as KDBUS_ITEM_PAYLOAD_VEC by the receiving side. It is
-possible to interleave KDBUS_ITEM_PAYLOAD_MEMFD and
-KDBUS_ITEM_PAYLOAD_VEC items freely, by the reader they will be
-considered a single stream of bytes in the order these items appear in
-the message, that just happens to be split up at various places
-(regarding rules how they may be split up, see above). The kernel will
-refuse taking KDBUS_ITEM_PAYLOAD_MEMFD items that refer to memfds that
-are not sealed.
-
-Note that sealed memfds may be unsealed again if they are not mapped
-you have the only fd reference to them.
-
-Alternatively to sending memfds as KDBUS_ITEM_PAYLOAD_MEMFD items
-(where they are just a part of the payload stream of a message) you can
-also simply attach any memfd to a message using
-KDBUS_ITEM_PAYLOAD_FDS. In this case, the memfd contents is not
-considered part of the payload stream of the message, but simply fds
-like any other, that happen to be attached to the message.
-
-MESSAGES FROM THE KERNEL
-
-A couple of messages previously generated by the dbus1 bus driver are
-now generated by the kernel. Since the kernel does not understand the
-payload marshaling, they are generated by the kernel in a different
-format. This is indicated with the "payload type" field of the
-messages set to 0. Library implementations should take these messages
-and synthesize traditional driver messages for them on reception.
-
-More specifically:
-
- Instead of the NameOwnerChanged, NameLost, NameAcquired signals
- there are kernel messages containing KDBUS_ITEM_NAME_ADD,
- KDBUS_ITEM_NAME_REMOVE, KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD,
- KDBUS_ITEM_ID_REMOVE items are generated (each message will contain
- exactly one of these items). Note that in libsystemd we have
- obsoleted NameLost/NameAcquired messages, since they are entirely
- redundant to NameOwnerChanged. This library will hence only
- synthesize NameOwnerChanged messages from these kernel messages,
- and never generate NameLost/NameAcquired. If your library needs to
- stay compatible to the old dbus1 userspace, you possibly might need
- to synthesize both a NameOwnerChanged and NameLost/NameAcquired
- message from the same kernel message.
-
- When a method call times out, a KDBUS_ITEM_REPLY_TIMEOUT message is
- generated. This should be synthesized into a method error reply
- message to the original call.
-
- When a method call fails because the peer terminated the connection
- before responding, a KDBUS_ITEM_REPLY_DEAD message is
- generated. Similarly, it should be synthesized into a method error
- reply message.
-
-For synthesized messages we recommend setting the cookie field to
-(uint32_t) -1 (and not (uint64_t) -1!), so that the cookie is not 0
-(which the dbus1 spec does not allow), but clearly recognizable as
-synthetic.
-
-Note that the KDBUS_ITEM_NAME_XYZ messages will actually inform you
-about all kinds of names, including activatable ones. Classic dbus1
-NameOwnerChanged messages OTOH are only generated when a name is
-really acquired on the bus and not just simply activatable. This means
-you must explicitly check for the case where an activatable name
-becomes acquired or an acquired name is lost and returns to be
-activatable.
-
-NAME REGISTRY
-
-To acquire names on the bus, use the KDBUS_CMD_NAME_ACQUIRE ioctl(). It
-takes a flags field similar to dbus1's RequestName() bus driver call,
-however the NO_QUEUE flag got inverted into a QUEUE flag instead.
-
-To release a previously acquired name use the KDBUS_CMD_NAME_RELEASE
-ioctl().
-
-To list acquired names use the KDBUS_CMD_CONN_INFO ioctl. It may be
-used to list unique names, well known names as well as activatable
-names and clients currently queuing for ownership of a well-known
-name. The ioctl will return an offset into the memory pool. After
-reading all the data you need, you need to release this via the
-KDBUS_CMD_FREE ioctl(), similar how you release a received message.
-
-CREDENTIALS
-
-kdbus can optionally attach various kinds of metadata about the sender at
-the point of time of sending ("credentials") to messages, on request
-of the receiver. This is both supported on directed and undirected
-(broadcast) messages. The metadata to attach is selected at time of
-the HELLO ioctl of the receiver via a flags field (see above). Note
-that clients must be able to handle that messages contain more
-metadata than they asked for themselves, to simplify implementation of
-broadcasting in the kernel. The receiver should not rely on this data
-to be around though, even though it will be correct if it happens to
-be attached. In order to avoid programming errors in applications, we
-recommend though not passing this data on to clients that did not
-explicitly ask for it.
-
-Credentials may also be queried for a well-known or unique name. Use
-the KDBUS_CMD_CONN_INFO for this. It will return an offset to the pool
-area again, which will contain the same credential items as messages
-have attached. Note that when issuing the ioctl, you can select a
-different set of credentials to gather, than what was originally requested
-for being attached to incoming messages.
-
-Credentials are always specific to the sender's domain that was
-current at the time of sending, and of the process that opened the
-bus connection at the time of opening it. Note that this latter data
-is cached!
-
-POLICY
-
-The kernel enforces only very limited policy on names. It will not do
-access filtering by userspace payload, and thus not by interface or
-method name.
-
-This ultimately means that most fine-grained policy enforcement needs
-to be done by the receiving process. We recommend using PolicyKit for
-any more complex checks. However, libraries should make simple static
-policy decisions regarding privileged/unprivileged method calls
-easy. We recommend doing this by enabling KDBUS_ATTACH_CAPS and
-KDBUS_ATTACH_CREDS for incoming messages, and then discerning client
-access by some capability, or if sender and receiver UIDs match.
-
-BUS ADDRESSES
-
-When connecting to kdbus use the "kernel:" protocol prefix in DBus
-address strings. The device node path is encoded in its "path="
-parameter.
-
-Client libraries should use the following connection string when
-connecting to the system bus:
-
- kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket
-
-This will ensure that kdbus is preferred over the legacy AF_UNIX
-socket, but compatibility is kept. For the user bus use:
-
- kernel:path=/sys/fs/kdbus/$UID-user/bus;unix:path=$XDG_RUNTIME_DIR/bus
-
-With $UID replaced by the callers numer user ID, and $XDG_RUNTIME_DIR
-following the XDG basedir spec.
-
-Of course the $DBUS_SYSTEM_BUS_ADDRESS and $DBUS_SESSION_BUS_ADDRESS
-variables should still take precedence.
-
-DBUS SERVICE FILES
-
-Activatable services for kdbus may not use classic dbus1 service
-activation files. Instead, programs should drop in native systemd
-.service and .busname unit files, so that they are treated uniformly
-with other types of units and activation of the system.
-
-Note that this results in a major difference to classic dbus1:
-activatable bus names can be established at any time in the boot process.
-This is unlike dbus1 where activatable names are unconditionally available
-as long as dbus-daemon is running. Being able to control when
-activatable names are established is essential to allow usage of kdbus
-during early boot and in initrds, without the risk of triggering
-services too early.
-
-DISCLAIMER
-
-This all is so far just the status quo. We are putting this together, because
-we are quite confident that further API changes will be smaller, but
-to make this very clear: this is all subject to change, still!
-
-We invite you to port over your favorite dbus library to this new
-scheme, but please be prepared to make minor changes when we still
-change these interfaces!
diff --git a/src/libsystemd/sd-bus/bus-bloom.c b/src/libsystemd/sd-bus/bus-bloom.c
deleted file mode 100644
index 112769fcb6..0000000000
--- a/src/libsystemd/sd-bus/bus-bloom.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-bloom.h"
-#include "siphash24.h"
-#include "util.h"
-
-static inline void set_bit(uint64_t filter[], unsigned long b) {
- filter[b >> 6] |= 1ULL << (b & 63);
-}
-
-static const sd_id128_t hash_keys[] = {
- SD_ID128_ARRAY(b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15),
- SD_ID128_ARRAY(aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b),
- SD_ID128_ARRAY(63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8),
- SD_ID128_ARRAY(23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5),
- SD_ID128_ARRAY(56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10),
- SD_ID128_ARRAY(31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29),
- SD_ID128_ARRAY(7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d),
- SD_ID128_ARRAY(f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35),
-};
-
-static void bloom_add_data(
- uint64_t filter[], /* The filter bits */
- size_t size, /* Size of the filter in bytes */
- unsigned k, /* Number of hash functions */
- const void *data, /* Data to hash */
- size_t n) { /* Size of data to hash in bytes */
-
- uint64_t h;
- uint64_t m;
- unsigned w, i, c = 0;
- unsigned hash_index;
-
- assert(size > 0);
- assert(k > 0);
-
- /* Determine bits in filter */
- m = size * 8;
-
- /* Determine how many bytes we need to generate a bit index 0..m for this filter */
- w = (u64log2(m) + 7) / 8;
-
- assert(w <= sizeof(uint64_t));
-
- /* Make sure we have enough hash keys to generate m * k bits
- * of hash value. Note that SipHash24 generates 64 bits of
- * hash value for each 128 bits of hash key. */
- assert(k * w <= ELEMENTSOF(hash_keys) * 8);
-
- for (i = 0, hash_index = 0; i < k; i++) {
- uint64_t p = 0;
- unsigned d;
-
- for (d = 0; d < w; d++) {
- if (c <= 0) {
- h = siphash24(data, n, hash_keys[hash_index++].bytes);
- c += 8;
- }
-
- p = (p << 8ULL) | (uint64_t) ((uint8_t *)&h)[8 - c];
- c--;
- }
-
- p &= m - 1;
- set_bit(filter, p);
- }
-
- /* log_debug("bloom: adding <%.*s>", (int) n, (char*) data); */
-}
-
-void bloom_add_pair(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b) {
- size_t n;
- char *c;
-
- assert(filter);
- assert(a);
- assert(b);
-
- n = strlen(a) + 1 + strlen(b);
- c = alloca(n + 1);
- strcpy(stpcpy(stpcpy(c, a), ":"), b);
-
- bloom_add_data(filter, size, k, c, n);
-}
-
-void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned k, const char *a, const char *b, char sep) {
- size_t n;
- char *c, *p;
-
- assert(filter);
- assert(a);
- assert(b);
-
- n = strlen(a) + 1 + strlen(b);
- c = alloca(n + 1);
-
- p = stpcpy(stpcpy(c, a), ":");
- strcpy(p, b);
-
- bloom_add_data(filter, size, k, c, n);
-
- for (;;) {
- char *e;
-
- e = strrchr(p, sep);
- if (!e)
- break;
-
- *(e + 1) = 0;
- bloom_add_data(filter, size, k, c, e - c + 1);
-
- if (e == p)
- break;
-
- *e = 0;
- bloom_add_data(filter, size, k, c, e - c);
- }
-}
-
-bool bloom_validate_parameters(size_t size, unsigned k) {
- uint64_t m;
- unsigned w;
-
- if (size <= 0)
- return false;
-
- if (k <= 0)
- return false;
-
- m = size * 8;
- w = (u64log2(m) + 7) / 8;
- if (w > sizeof(uint64_t))
- return false;
-
- if (k * w > ELEMENTSOF(hash_keys) * 8)
- return false;
-
- return true;
-}
diff --git a/src/libsystemd/sd-bus/bus-bloom.h b/src/libsystemd/sd-bus/bus-bloom.h
deleted file mode 100644
index c824622b95..0000000000
--- a/src/libsystemd/sd-bus/bus-bloom.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-/*
- * Our default bloom filter has the following parameters:
- *
- * m=512 (bits in the filter)
- * k=8 (hash functions)
- *
- * We use SipHash24 as hash function with a number of (originally
- * randomized) but fixed hash keys.
- *
- */
-
-#define DEFAULT_BLOOM_SIZE (512/8) /* m: filter size */
-#define DEFAULT_BLOOM_N_HASH 8 /* k: number of hash functions */
-
-void bloom_add_pair(uint64_t filter[], size_t size, unsigned n_hash, const char *a, const char *b);
-void bloom_add_prefixes(uint64_t filter[], size_t size, unsigned n_hash, const char *a, const char *b, char sep);
-
-bool bloom_validate_parameters(size_t size, unsigned n_hash);
diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c
deleted file mode 100644
index d2a826bf6e..0000000000
--- a/src/libsystemd/sd-bus/bus-common-errors.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-
-#include "sd-bus.h"
-
-#include "bus-common-errors.h"
-#include "bus-error.h"
-
-BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT),
- SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST),
- SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_JOB, ENOENT),
- SD_BUS_ERROR_MAP(BUS_ERROR_NOT_SUBSCRIBED, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_ALREADY_SUBSCRIBED, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_ONLY_BY_DEPENDENCY, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLK),
- SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, EDEADLK),
- SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLK),
- SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, ESHUTDOWN),
- SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_GENERATED, EADDRNOTAVAIL),
- SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_LINKED, ELOOP),
- SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, EBADR),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM),
- SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED),
- SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
- SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
-
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING, ENXIO),
-
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_USER_FOR_PID, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SEAT, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_NOT_ON_SEAT, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_NOT_IN_CONTROL, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_IS_TAKEN, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS),
- SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP),
- SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY),
-
- SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
-
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH),
-
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS, ESRCH),
- SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY, EINVAL),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR, ENOENT),
- SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP, EDEADLK),
- SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED, ECANCELED),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SERVICE, EUNATCH),
- SD_BUS_ERROR_MAP(BUS_ERROR_DNSSEC_FAILED, EHOSTUNREACH),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_TRUST_ANCHOR, EHOSTUNREACH),
- SD_BUS_ERROR_MAP(BUS_ERROR_RR_TYPE_UNSUPPORTED, EOPNOTSUPP),
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
- SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
-
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR", EBADMSG),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL", EHOSTDOWN),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN", ENXIO),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP", ENOSYS),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED", EACCES),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN", EEXIST),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET", EEXIST),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET", ENOENT),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH", EACCES),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE", EREMOTE),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS", EBADMSG),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY", EKEYREJECTED),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME", EBADMSG),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE", EBADMSG),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME", EBADMSG),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG", EBADMSG),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC", EBADMSG),
- SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE", EBADR),
-
- SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO),
- SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),
-
- SD_BUS_ERROR_MAP_END
-};
diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h
deleted file mode 100644
index 525b79fa77..0000000000
--- a/src/libsystemd/sd-bus/bus-common-errors.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-error.h"
-
-#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
-#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
-#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID"
-#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
-#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
-#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
-#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
-#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
-#define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed"
-#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
-#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
-#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
-#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
-#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
-#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated"
-#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked"
-#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
-#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
-#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
-#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
-#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
-#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
-
-#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
-#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
-#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
-#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
-#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
-#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
-#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
-
-#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
-#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
-#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
-#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
-#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
-#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
-#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
-#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
-#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
-#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
-#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
-#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
-
-#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
-
-#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
-
-#define BUS_ERROR_NO_NAME_SERVERS "org.freedesktop.resolve1.NoNameServers"
-#define BUS_ERROR_INVALID_REPLY "org.freedesktop.resolve1.InvalidReply"
-#define BUS_ERROR_NO_SUCH_RR "org.freedesktop.resolve1.NoSuchRR"
-#define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop"
-#define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted"
-#define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService"
-#define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed"
-#define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor"
-#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported"
-#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
-#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
-#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
-#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
-
-#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
-#define BUS_ERROR_TRANSFER_IN_PROGRESS "org.freedesktop.import1.TransferInProgress"
-
-BUS_ERROR_MAP_ELF_USE(bus_common_errors);
diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c
deleted file mode 100644
index 3191d27ded..0000000000
--- a/src/libsystemd/sd-bus/bus-container.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "bus-container.h"
-#include "bus-internal.h"
-#include "bus-socket.h"
-#include "fd-util.h"
-#include "process-util.h"
-#include "util.h"
-
-int bus_container_connect_socket(sd_bus *b) {
- _cleanup_close_pair_ int pair[2] = { -1, -1 };
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
- pid_t child;
- siginfo_t si;
- int r, error_buf = 0;
- ssize_t n;
-
- assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->nspid > 0 || b->machine);
-
- if (b->nspid <= 0) {
- r = container_get_leader(b->machine, &b->nspid);
- if (r < 0)
- return r;
- }
-
- r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
- if (r < 0)
- return r;
-
- b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (b->input_fd < 0)
- return -errno;
-
- b->output_fd = b->input_fd;
-
- bus_socket_setup(b);
-
- if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
- return -errno;
-
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
- pid_t grandchild;
-
- pair[0] = safe_close(pair[0]);
-
- r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- /* We just changed PID namespace, however it will only
- * take effect on the children we now fork. Hence,
- * let's fork another time, and connect from this
- * grandchild, so that SO_PEERCRED of our connection
- * comes from a process from within the container, and
- * not outside of it */
-
- grandchild = fork();
- if (grandchild < 0)
- _exit(EXIT_FAILURE);
-
- if (grandchild == 0) {
-
- r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
- if (r < 0) {
- /* Try to send error up */
- error_buf = errno;
- (void) write(pair[1], &error_buf, sizeof(error_buf));
- _exit(EXIT_FAILURE);
- }
-
- _exit(EXIT_SUCCESS);
- }
-
- r = wait_for_terminate(grandchild, &si);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- if (si.si_code != CLD_EXITED)
- _exit(EXIT_FAILURE);
-
- _exit(si.si_status);
- }
-
- pair[1] = safe_close(pair[1]);
-
- r = wait_for_terminate(child, &si);
- if (r < 0)
- return r;
-
- n = read(pair[0], &error_buf, sizeof(error_buf));
- if (n < 0)
- return -errno;
-
- if (n > 0) {
- if (n != sizeof(error_buf))
- return -EIO;
-
- if (error_buf < 0)
- return -EIO;
-
- if (error_buf == EINPROGRESS)
- return 1;
-
- if (error_buf > 0)
- return -error_buf;
- }
-
- if (si.si_code != CLD_EXITED)
- return -EIO;
-
- if (si.si_status != EXIT_SUCCESS)
- return -EIO;
-
- return bus_socket_start_auth(b);
-}
-
-int bus_container_connect_kernel(sd_bus *b) {
- _cleanup_close_pair_ int pair[2] = { -1, -1 };
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int))];
- } control = {};
- int error_buf = 0;
- struct iovec iov = {
- .iov_base = &error_buf,
- .iov_len = sizeof(error_buf),
- };
- struct msghdr mh = {
- .msg_control = &control,
- .msg_controllen = sizeof(control),
- .msg_iov = &iov,
- .msg_iovlen = 1,
- };
- struct cmsghdr *cmsg;
- pid_t child;
- siginfo_t si;
- int r, fd = -1;
- ssize_t n;
-
- assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->nspid > 0 || b->machine);
-
- if (b->nspid <= 0) {
- r = container_get_leader(b->machine, &b->nspid);
- if (r < 0)
- return r;
- }
-
- r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
- if (r < 0)
- return r;
-
- if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
- return -errno;
-
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
- pid_t grandchild;
-
- pair[0] = safe_close(pair[0]);
-
- r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- /* We just changed PID namespace, however it will only
- * take effect on the children we now fork. Hence,
- * let's fork another time, and connect from this
- * grandchild, so that kdbus only sees the credentials
- * of this process which comes from within the
- * container, and not outside of it */
-
- grandchild = fork();
- if (grandchild < 0)
- _exit(EXIT_FAILURE);
-
- if (grandchild == 0) {
- fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- /* Try to send error up */
- error_buf = errno;
- (void) write(pair[1], &error_buf, sizeof(error_buf));
- _exit(EXIT_FAILURE);
- }
-
- r = send_one_fd(pair[1], fd, 0);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- _exit(EXIT_SUCCESS);
- }
-
- r = wait_for_terminate(grandchild, &si);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- if (si.si_code != CLD_EXITED)
- _exit(EXIT_FAILURE);
-
- _exit(si.si_status);
- }
-
- pair[1] = safe_close(pair[1]);
-
- r = wait_for_terminate(child, &si);
- if (r < 0)
- return r;
-
- n = recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
- if (n < 0)
- return -errno;
-
- CMSG_FOREACH(cmsg, &mh) {
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
- int *fds;
- unsigned n_fds;
-
- assert(fd < 0);
-
- fds = (int*) CMSG_DATA(cmsg);
- n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
-
- if (n_fds != 1) {
- close_many(fds, n_fds);
- return -EIO;
- }
-
- fd = fds[0];
- }
- }
-
- /* If there's an fd passed, we are good. */
- if (fd >= 0) {
- b->input_fd = b->output_fd = fd;
- return bus_kernel_take_fd(b);
- }
-
- /* If there's an error passed, use it */
- if (n == sizeof(error_buf) && error_buf > 0)
- return -error_buf;
-
- /* Otherwise, we have no clue */
- return -EIO;
-}
diff --git a/src/libsystemd/sd-bus/bus-container.h b/src/libsystemd/sd-bus/bus-container.h
deleted file mode 100644
index 509ef45624..0000000000
--- a/src/libsystemd/sd-bus/bus-container.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-int bus_container_connect_socket(sd_bus *b);
-int bus_container_connect_kernel(sd_bus *b);
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
deleted file mode 100644
index 52128e7b5c..0000000000
--- a/src/libsystemd/sd-bus/bus-control.c
+++ /dev/null
@@ -1,1588 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-#include <valgrind/memcheck.h>
-#endif
-
-#include <errno.h>
-#include <stddef.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-bloom.h"
-#include "bus-control.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "capability-util.h"
-#include "stdio-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
-
-_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(unique, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- r = bus_ensure_running(bus);
- if (r < 0)
- return r;
-
- *unique = bus->unique_name;
- return 0;
-}
-
-static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
- struct kdbus_cmd *n;
- size_t size, l;
- int r;
-
- assert(bus);
- assert(name);
-
- l = strlen(name) + 1;
- size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
- n = alloca0_align(size, 8);
- n->size = size;
- n->flags = request_name_flags_to_kdbus(flags);
-
- n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
- n->items[0].type = KDBUS_ITEM_NAME;
- memcpy(n->items[0].str, name, l);
-
-#ifdef HAVE_VALGRIND_MEMCHECK_H
- VALGRIND_MAKE_MEM_DEFINED(n, n->size);
-#endif
-
- r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
- if (r < 0)
- return -errno;
-
- if (n->return_flags & KDBUS_NAME_IN_QUEUE)
- return 0;
-
- return 1;
-}
-
-static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- uint32_t ret, param = 0;
- int r;
-
- assert(bus);
- assert(name);
-
- if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
- param |= BUS_NAME_ALLOW_REPLACEMENT;
- if (flags & SD_BUS_NAME_REPLACE_EXISTING)
- param |= BUS_NAME_REPLACE_EXISTING;
- if (!(flags & SD_BUS_NAME_QUEUE))
- param |= BUS_NAME_DO_NOT_QUEUE;
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "RequestName",
- NULL,
- &reply,
- "su",
- name,
- param);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply, "u", &ret);
- if (r < 0)
- return r;
-
- if (ret == BUS_NAME_ALREADY_OWNER)
- return -EALREADY;
- else if (ret == BUS_NAME_EXISTS)
- return -EEXIST;
- else if (ret == BUS_NAME_IN_QUEUE)
- return 0;
- else if (ret == BUS_NAME_PRIMARY_OWNER)
- return 1;
-
- return -EIO;
-}
-
-_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
- assert_return(bus, -EINVAL);
- assert_return(name, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
- assert_return(service_name_is_valid(name), -EINVAL);
- assert_return(name[0] != ':', -EINVAL);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- /* Don't allow requesting the special driver and local names */
- if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
- return -EINVAL;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->is_kernel)
- return bus_request_name_kernel(bus, name, flags);
- else
- return bus_request_name_dbus1(bus, name, flags);
-}
-
-static int bus_release_name_kernel(sd_bus *bus, const char *name) {
- struct kdbus_cmd *n;
- size_t size, l;
- int r;
-
- assert(bus);
- assert(name);
-
- l = strlen(name) + 1;
- size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
- n = alloca0_align(size, 8);
- n->size = size;
-
- n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
- n->items[0].type = KDBUS_ITEM_NAME;
- memcpy(n->items[0].str, name, l);
-
-#ifdef HAVE_VALGRIND_MEMCHECK_H
- VALGRIND_MAKE_MEM_DEFINED(n, n->size);
-#endif
- r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- uint32_t ret;
- int r;
-
- assert(bus);
- assert(name);
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "ReleaseName",
- NULL,
- &reply,
- "s",
- name);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply, "u", &ret);
- if (r < 0)
- return r;
- if (ret == BUS_NAME_NON_EXISTENT)
- return -ESRCH;
- if (ret == BUS_NAME_NOT_OWNER)
- return -EADDRINUSE;
- if (ret == BUS_NAME_RELEASED)
- return 0;
-
- return -EINVAL;
-}
-
-_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
- assert_return(bus, -EINVAL);
- assert_return(name, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(service_name_is_valid(name), -EINVAL);
- assert_return(name[0] != ':', -EINVAL);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- /* Don't allow releasing the special driver and local names */
- if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
- return -EINVAL;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->is_kernel)
- return bus_release_name_kernel(bus, name);
- else
- return bus_release_name_dbus1(bus, name);
-}
-
-static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
- struct kdbus_cmd_list cmd = {
- .size = sizeof(cmd),
- .flags = flags,
- };
- struct kdbus_info *name_list, *name;
- uint64_t previous_id = 0;
- int r;
-
- /* Caller will free half-constructed list on failure... */
-
- r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
- if (r < 0)
- return -errno;
-
- name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
-
- KDBUS_FOREACH(name, name_list, cmd.list_size) {
- struct kdbus_item *item;
-
- if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
- char *n;
-
- if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = strv_consume(x, n);
- if (r < 0)
- goto fail;
-
- previous_id = name->id;
- }
-
- KDBUS_ITEM_FOREACH(item, name, items) {
- if (item->type == KDBUS_ITEM_OWNED_NAME) {
- if (service_name_is_valid(item->name.name)) {
- r = strv_extend(x, item->name.name);
- if (r < 0) {
- r = -ENOMEM;
- goto fail;
- }
- }
- }
- }
- }
-
- r = 0;
-
-fail:
- bus_kernel_cmd_free(bus, cmd.offset);
- return r;
-}
-
-static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
- _cleanup_strv_free_ char **x = NULL, **y = NULL;
- int r;
-
- if (acquired) {
- r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
- if (r < 0)
- return r;
- }
-
- if (activatable) {
- r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
- if (r < 0)
- return r;
-
- *activatable = y;
- y = NULL;
- }
-
- if (acquired) {
- *acquired = x;
- x = NULL;
- }
-
- return 0;
-}
-
-static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_strv_free_ char **x = NULL, **y = NULL;
- int r;
-
- if (acquired) {
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "ListNames",
- NULL,
- &reply,
- NULL);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read_strv(reply, &x);
- if (r < 0)
- return r;
-
- reply = sd_bus_message_unref(reply);
- }
-
- if (activatable) {
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "ListActivatableNames",
- NULL,
- &reply,
- NULL);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read_strv(reply, &y);
- if (r < 0)
- return r;
-
- *activatable = y;
- y = NULL;
- }
-
- if (acquired) {
- *acquired = x;
- x = NULL;
- }
-
- return 0;
-}
-
-_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
- assert_return(bus, -EINVAL);
- assert_return(acquired || activatable, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->is_kernel)
- return bus_list_names_kernel(bus, acquired, activatable);
- else
- return bus_list_names_dbus1(bus, acquired, activatable);
-}
-
-static int bus_populate_creds_from_items(
- sd_bus *bus,
- struct kdbus_info *info,
- uint64_t mask,
- sd_bus_creds *c) {
-
- struct kdbus_item *item;
- uint64_t m;
- int r;
-
- assert(bus);
- assert(info);
- assert(c);
-
- KDBUS_ITEM_FOREACH(item, info, items) {
-
- switch (item->type) {
-
- case KDBUS_ITEM_PIDS:
-
- if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
- c->pid = (pid_t) item->pids.pid;
- c->mask |= SD_BUS_CREDS_PID;
- }
-
- if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
- c->tid = (pid_t) item->pids.tid;
- c->mask |= SD_BUS_CREDS_TID;
- }
-
- if (mask & SD_BUS_CREDS_PPID) {
- if (item->pids.ppid > 0) {
- c->ppid = (pid_t) item->pids.ppid;
- c->mask |= SD_BUS_CREDS_PPID;
- } else if (item->pids.pid == 1) {
- /* The structure doesn't
- * really distinguish the case
- * where a process has no
- * parent and where we don't
- * know it because it could
- * not be translated due to
- * namespaces. However, we
- * know that PID 1 has no
- * parent process, hence let's
- * patch that in, manually. */
- c->ppid = 0;
- c->mask |= SD_BUS_CREDS_PPID;
- }
- }
-
- break;
-
- case KDBUS_ITEM_CREDS:
-
- if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
- c->uid = (uid_t) item->creds.uid;
- c->mask |= SD_BUS_CREDS_UID;
- }
-
- if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
- c->euid = (uid_t) item->creds.euid;
- c->mask |= SD_BUS_CREDS_EUID;
- }
-
- if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
- c->suid = (uid_t) item->creds.suid;
- c->mask |= SD_BUS_CREDS_SUID;
- }
-
- if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
- c->fsuid = (uid_t) item->creds.fsuid;
- c->mask |= SD_BUS_CREDS_FSUID;
- }
-
- if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
- c->gid = (gid_t) item->creds.gid;
- c->mask |= SD_BUS_CREDS_GID;
- }
-
- if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
- c->egid = (gid_t) item->creds.egid;
- c->mask |= SD_BUS_CREDS_EGID;
- }
-
- if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
- c->sgid = (gid_t) item->creds.sgid;
- c->mask |= SD_BUS_CREDS_SGID;
- }
-
- if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
- c->fsgid = (gid_t) item->creds.fsgid;
- c->mask |= SD_BUS_CREDS_FSGID;
- }
-
- break;
-
- case KDBUS_ITEM_PID_COMM:
- if (mask & SD_BUS_CREDS_COMM) {
- r = free_and_strdup(&c->comm, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_COMM;
- }
- break;
-
- case KDBUS_ITEM_TID_COMM:
- if (mask & SD_BUS_CREDS_TID_COMM) {
- r = free_and_strdup(&c->tid_comm, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_TID_COMM;
- }
- break;
-
- case KDBUS_ITEM_EXE:
- if (mask & SD_BUS_CREDS_EXE) {
- r = free_and_strdup(&c->exe, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_EXE;
- }
- break;
-
- case KDBUS_ITEM_CMDLINE:
- if (mask & SD_BUS_CREDS_CMDLINE) {
- c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
- c->cmdline = memdup(item->data, c->cmdline_size);
- if (!c->cmdline)
- return -ENOMEM;
-
- c->mask |= SD_BUS_CREDS_CMDLINE;
- }
- break;
-
- case KDBUS_ITEM_CGROUP:
- m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
- SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
- SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
-
- if (m) {
- r = free_and_strdup(&c->cgroup, item->str);
- if (r < 0)
- return r;
-
- r = bus_get_root_path(bus);
- if (r < 0)
- return r;
-
- r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
- if (r < 0)
- return r;
-
- c->mask |= m;
- }
- break;
-
- case KDBUS_ITEM_CAPS:
- m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
- SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
-
- if (m) {
- if (item->caps.last_cap != cap_last_cap() ||
- item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
- return -EBADMSG;
-
- c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
- if (!c->capability)
- return -ENOMEM;
-
- c->mask |= m;
- }
- break;
-
- case KDBUS_ITEM_SECLABEL:
- if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
- r = free_and_strdup(&c->label, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
- }
- break;
-
- case KDBUS_ITEM_AUDIT:
- if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
- c->audit_session_id = (uint32_t) item->audit.sessionid;
- c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
- }
-
- if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
- c->audit_login_uid = (uid_t) item->audit.loginuid;
- c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
- }
- break;
-
- case KDBUS_ITEM_OWNED_NAME:
- if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
- r = strv_extend(&c->well_known_names, item->name.name);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
- }
- break;
-
- case KDBUS_ITEM_CONN_DESCRIPTION:
- if (mask & SD_BUS_CREDS_DESCRIPTION) {
- r = free_and_strdup(&c->description, item->str);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_DESCRIPTION;
- }
- break;
-
- case KDBUS_ITEM_AUXGROUPS:
- if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
- size_t i, n;
- uid_t *g;
-
- n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
- g = new(gid_t, n);
- if (!g)
- return -ENOMEM;
-
- for (i = 0; i < n; i++)
- g[i] = item->data64[i];
-
- free(c->supplementary_gids);
- c->supplementary_gids = g;
- c->n_supplementary_gids = n;
-
- c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
- }
- break;
- }
- }
-
- return 0;
-}
-
-int bus_get_name_creds_kdbus(
- sd_bus *bus,
- const char *name,
- uint64_t mask,
- bool allow_activator,
- sd_bus_creds **creds) {
-
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- struct kdbus_cmd_info *cmd;
- struct kdbus_info *conn_info;
- size_t size, l;
- uint64_t id;
- int r;
-
- if (streq(name, "org.freedesktop.DBus"))
- return -EOPNOTSUPP;
-
- r = bus_kernel_parse_unique_name(name, &id);
- if (r < 0)
- return r;
- if (r > 0) {
- size = offsetof(struct kdbus_cmd_info, items);
- cmd = alloca0_align(size, 8);
- cmd->id = id;
- } else {
- l = strlen(name) + 1;
- size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
- cmd = alloca0_align(size, 8);
- cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
- cmd->items[0].type = KDBUS_ITEM_NAME;
- memcpy(cmd->items[0].str, name, l);
- }
-
- /* If augmentation is on, and the bus didn't provide us
- * the bits we want, then ask for the PID/TID so that we
- * can read the rest from /proc. */
- if ((mask & SD_BUS_CREDS_AUGMENT) &&
- (mask & (SD_BUS_CREDS_PPID|
- SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
- SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
- SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
- SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
- SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
- SD_BUS_CREDS_SELINUX_CONTEXT|
- SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
- mask |= SD_BUS_CREDS_PID;
-
- cmd->size = size;
- cmd->attach_flags = attach_flags_to_kdbus(mask);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
- if (r < 0)
- return -errno;
-
- conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
-
- /* Non-activated names are considered not available */
- if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
- if (name[0] == ':')
- r = -ENXIO;
- else
- r = -ESRCH;
- goto fail;
- }
-
- c = bus_creds_new();
- if (!c) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
- if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
- }
-
- /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
- them in case the service has no names. This does not mean
- however that the list of owned names could not be
- acquired. Hence, let's explicitly clarify that the data is
- complete. */
- c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
-
- r = bus_populate_creds_from_items(bus, conn_info, mask, c);
- if (r < 0)
- goto fail;
-
- r = bus_creds_add_more(c, mask, 0, 0);
- if (r < 0)
- goto fail;
-
- if (creds) {
- *creds = c;
- c = NULL;
- }
-
- r = 0;
-
-fail:
- bus_kernel_cmd_free(bus, cmd->offset);
- return r;
-}
-
-static int bus_get_name_creds_dbus1(
- sd_bus *bus,
- const char *name,
- uint64_t mask,
- sd_bus_creds **creds) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- const char *unique = NULL;
- pid_t pid = 0;
- int r;
-
- /* Only query the owner if the caller wants to know it or if
- * the caller just wants to check whether a name exists */
- if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "GetNameOwner",
- NULL,
- &reply_unique,
- "s",
- name);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply_unique, "s", &unique);
- if (r < 0)
- return r;
- }
-
- if (mask != 0) {
- c = bus_creds_new();
- if (!c)
- return -ENOMEM;
-
- if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
- c->unique_name = strdup(unique);
- if (!c->unique_name)
- return -ENOMEM;
-
- c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
- }
-
- if ((mask & SD_BUS_CREDS_PID) ||
- ((mask & SD_BUS_CREDS_AUGMENT) &&
- (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
- SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
- SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
- SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
- SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
- SD_BUS_CREDS_SELINUX_CONTEXT|
- SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
-
- uint32_t u;
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "GetConnectionUnixProcessID",
- NULL,
- &reply,
- "s",
- unique ? unique : name);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply, "u", &u);
- if (r < 0)
- return r;
-
- pid = u;
- if (mask & SD_BUS_CREDS_PID) {
- c->pid = u;
- c->mask |= SD_BUS_CREDS_PID;
- }
-
- reply = sd_bus_message_unref(reply);
- }
-
- if (mask & SD_BUS_CREDS_EUID) {
- uint32_t u;
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "GetConnectionUnixUser",
- NULL,
- &reply,
- "s",
- unique ? unique : name);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply, "u", &u);
- if (r < 0)
- return r;
-
- c->euid = u;
- c->mask |= SD_BUS_CREDS_EUID;
-
- reply = sd_bus_message_unref(reply);
- }
-
- if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const void *p = NULL;
- size_t sz = 0;
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "GetConnectionSELinuxSecurityContext",
- &error,
- &reply,
- "s",
- unique ? unique : name);
- if (r < 0) {
- if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
- return r;
- } else {
- r = sd_bus_message_read_array(reply, 'y', &p, &sz);
- if (r < 0)
- return r;
-
- c->label = strndup(p, sz);
- if (!c->label)
- return -ENOMEM;
-
- c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
- }
- }
-
- r = bus_creds_add_more(c, mask, pid, 0);
- if (r < 0)
- return r;
- }
-
- if (creds) {
- *creds = c;
- c = NULL;
- }
-
- return 0;
-}
-
-_public_ int sd_bus_get_name_creds(
- sd_bus *bus,
- const char *name,
- uint64_t mask,
- sd_bus_creds **creds) {
-
- assert_return(bus, -EINVAL);
- assert_return(name, -EINVAL);
- assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
- assert_return(mask == 0 || creds, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(service_name_is_valid(name), -EINVAL);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- if (streq(name, "org.freedesktop.DBus.Local"))
- return -EINVAL;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->is_kernel)
- return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
- else
- return bus_get_name_creds_dbus1(bus, name, mask, creds);
-}
-
-static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- struct kdbus_cmd_info cmd = {
- .size = sizeof(struct kdbus_cmd_info),
- };
- struct kdbus_info *creator_info;
- pid_t pid = 0;
- int r;
-
- c = bus_creds_new();
- if (!c)
- return -ENOMEM;
-
- /* If augmentation is on, and the bus doesn't didn't allow us
- * to get the bits we want, then ask for the PID/TID so that we
- * can read the rest from /proc. */
- if ((mask & SD_BUS_CREDS_AUGMENT) &&
- (mask & (SD_BUS_CREDS_PPID|
- SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
- SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
- SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
- SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
- SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
- SD_BUS_CREDS_SELINUX_CONTEXT|
- SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
- mask |= SD_BUS_CREDS_PID;
-
- cmd.attach_flags = attach_flags_to_kdbus(mask);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
- if (r < 0)
- return -errno;
-
- creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
-
- r = bus_populate_creds_from_items(bus, creator_info, mask, c);
- bus_kernel_cmd_free(bus, cmd.offset);
- if (r < 0)
- return r;
-
- r = bus_creds_add_more(c, mask, pid, 0);
- if (r < 0)
- return r;
-
- *ret = c;
- c = NULL;
- return 0;
-}
-
-static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
- pid_t pid = 0;
- bool do_label;
- int r;
-
- assert(bus);
-
- do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
-
- /* Avoid allocating anything if we have no chance of returning useful data */
- if (!bus->ucred_valid && !do_label)
- return -ENODATA;
-
- c = bus_creds_new();
- if (!c)
- return -ENOMEM;
-
- if (bus->ucred_valid) {
- if (bus->ucred.pid > 0) {
- pid = c->pid = bus->ucred.pid;
- c->mask |= SD_BUS_CREDS_PID & mask;
- }
-
- if (bus->ucred.uid != UID_INVALID) {
- c->euid = bus->ucred.uid;
- c->mask |= SD_BUS_CREDS_EUID & mask;
- }
-
- if (bus->ucred.gid != GID_INVALID) {
- c->egid = bus->ucred.gid;
- c->mask |= SD_BUS_CREDS_EGID & mask;
- }
- }
-
- if (do_label) {
- c->label = strdup(bus->label);
- if (!c->label)
- return -ENOMEM;
-
- c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
- }
-
- r = bus_creds_add_more(c, mask, pid, 0);
- if (r < 0)
- return r;
-
- *ret = c;
- c = NULL;
- return 0;
-}
-
-_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
- assert_return(bus, -EINVAL);
- assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
- assert_return(ret, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->is_kernel)
- return bus_get_owner_creds_kdbus(bus, mask, ret);
- else
- return bus_get_owner_creds_dbus1(bus, mask, ret);
-}
-
-static int add_name_change_match(sd_bus *bus,
- uint64_t cookie,
- const char *name,
- const char *old_owner,
- const char *new_owner) {
-
- uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
- int is_name_id = -1, r;
- struct kdbus_item *item;
-
- assert(bus);
-
- /* If we encounter a match that could match against
- * NameOwnerChanged messages, then we need to create
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
- * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
- * multiple if the match is underspecified.
- *
- * The NameOwnerChanged signals take three parameters with
- * unique or well-known names, but only some forms actually
- * exist:
- *
- * WELLKNOWN, "", UNIQUE → KDBUS_ITEM_NAME_ADD
- * WELLKNOWN, UNIQUE, "" → KDBUS_ITEM_NAME_REMOVE
- * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_ITEM_NAME_CHANGE
- * UNIQUE, "", UNIQUE → KDBUS_ITEM_ID_ADD
- * UNIQUE, UNIQUE, "" → KDBUS_ITEM_ID_REMOVE
- *
- * For the latter two the two unique names must be identical.
- *
- * */
-
- if (name) {
- is_name_id = bus_kernel_parse_unique_name(name, &name_id);
- if (is_name_id < 0)
- return 0;
- }
-
- if (!isempty(old_owner)) {
- r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
- if (r < 0)
- return 0;
- if (r == 0)
- return 0;
- if (is_name_id > 0 && old_owner_id != name_id)
- return 0;
- } else
- old_owner_id = KDBUS_MATCH_ID_ANY;
-
- if (!isempty(new_owner)) {
- r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
- if (is_name_id > 0 && new_owner_id != name_id)
- return 0;
- } else
- new_owner_id = KDBUS_MATCH_ID_ANY;
-
- if (is_name_id <= 0) {
- struct kdbus_cmd_match *m;
- size_t sz, l;
-
- /* If the name argument is missing or is a well-known
- * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
- * matches for it */
-
- l = name ? strlen(name) + 1 : 0;
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
- offsetof(struct kdbus_item, name_change) +
- offsetof(struct kdbus_notify_name_change, name) +
- l);
-
- m = alloca0_align(sz, 8);
- m->size = sz;
- m->cookie = cookie;
-
- item = m->items;
- item->size =
- offsetof(struct kdbus_item, name_change) +
- offsetof(struct kdbus_notify_name_change, name) +
- l;
-
- item->name_change.old_id.id = old_owner_id;
- item->name_change.new_id.id = new_owner_id;
-
- memcpy_safe(item->name_change.name, name, l);
-
- /* If the old name is unset or empty, then
- * this can match against added names */
- if (isempty(old_owner)) {
- item->type = KDBUS_ITEM_NAME_ADD;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- /* If the new name is unset or empty, then
- * this can match against removed names */
- if (isempty(new_owner)) {
- item->type = KDBUS_ITEM_NAME_REMOVE;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- /* The CHANGE match we need in either case, because
- * what is reported as a name change by the kernel
- * might just be an owner change between starter and
- * normal clients. For userspace such a change should
- * be considered a removal/addition, hence let's
- * subscribe to this unconditionally. */
- item->type = KDBUS_ITEM_NAME_CHANGE;
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- if (is_name_id != 0) {
- struct kdbus_cmd_match *m;
- uint64_t sz;
-
- /* If the name argument is missing or is a unique
- * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
- * for it */
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
- offsetof(struct kdbus_item, id_change) +
- sizeof(struct kdbus_notify_id_change));
-
- m = alloca0_align(sz, 8);
- m->size = sz;
- m->cookie = cookie;
-
- item = m->items;
- item->size =
- offsetof(struct kdbus_item, id_change) +
- sizeof(struct kdbus_notify_id_change);
- item->id_change.id = name_id;
-
- /* If the old name is unset or empty, then this can
- * match against added ids */
- if (isempty(old_owner)) {
- item->type = KDBUS_ITEM_ID_ADD;
- if (!isempty(new_owner))
- item->id_change.id = new_owner_id;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
-
- /* If thew new name is unset or empty, then this can
- * match against removed ids */
- if (isempty(new_owner)) {
- item->type = KDBUS_ITEM_ID_REMOVE;
- if (!isempty(old_owner))
- item->id_change.id = old_owner_id;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
- }
- }
-
- return 0;
-}
-
-int bus_add_match_internal_kernel(
- sd_bus *bus,
- struct bus_match_component *components,
- unsigned n_components,
- uint64_t cookie) {
-
- struct kdbus_cmd_match *m;
- struct kdbus_item *item;
- uint64_t *bloom;
- size_t sz;
- const char *sender = NULL;
- size_t sender_length = 0;
- uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
- bool using_bloom = false;
- unsigned i;
- bool matches_name_change = true;
- const char *name_change_arg[3] = {};
- int r;
-
- assert(bus);
-
- /* Monitor streams don't support matches, make this a NOP */
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- bloom = alloca0(bus->bloom_size);
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
-
- for (i = 0; i < n_components; i++) {
- struct bus_match_component *c = &components[i];
-
- switch (c->type) {
-
- case BUS_MATCH_SENDER:
- if (!streq(c->value_str, "org.freedesktop.DBus"))
- matches_name_change = false;
-
- r = bus_kernel_parse_unique_name(c->value_str, &src_id);
- if (r < 0)
- return r;
- else if (r > 0)
- sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
- else {
- sender = c->value_str;
- sender_length = strlen(sender);
- sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
- }
-
- break;
-
- case BUS_MATCH_MESSAGE_TYPE:
- if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
- using_bloom = true;
- break;
-
- case BUS_MATCH_INTERFACE:
- if (!streq(c->value_str, "org.freedesktop.DBus"))
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_MEMBER:
- if (!streq(c->value_str, "NameOwnerChanged"))
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_PATH:
- if (!streq(c->value_str, "/org/freedesktop/DBus"))
- matches_name_change = false;
-
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_PATH_NAMESPACE:
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
- using_bloom = true;
- break;
-
- case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
- char buf[sizeof("arg")-1 + 2 + 1];
-
- if (c->type - BUS_MATCH_ARG < 3)
- name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
-
- xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
- using_bloom = true;
- break;
- }
-
- case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
- char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
-
- xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
- using_bloom = true;
- break;
- }
-
- case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
- /*
- * XXX: DBus spec defines arg[0..63]path= matching to be
- * a two-way glob. That is, if either string is a prefix
- * of the other, it matches.
- * This is really hard to realize in bloom-filters, as
- * we would have to create a bloom-match for each prefix
- * of @c->value_str. This is excessive, hence we just
- * ignore all those matches and accept everything from
- * the kernel. People should really avoid those matches.
- * If they're used in real-life some day, we will have
- * to properly support multiple-matches here.
- */
- break;
-
- case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
- char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
-
- xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
- bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
- using_bloom = true;
- break;
- }
-
- case BUS_MATCH_DESTINATION:
- /*
- * Kernel only supports matching on destination IDs, but
- * not on destination names. So just skip the
- * destination name restriction and verify it in
- * user-space on retrieval.
- */
- r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
- if (r < 0)
- return r;
- else if (r > 0)
- sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
-
- /* if not a broadcast, it cannot be a name-change */
- if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
- matches_name_change = false;
-
- break;
-
- case BUS_MATCH_ROOT:
- case BUS_MATCH_VALUE:
- case BUS_MATCH_LEAF:
- case _BUS_MATCH_NODE_TYPE_MAX:
- case _BUS_MATCH_NODE_TYPE_INVALID:
- assert_not_reached("Invalid match type?");
- }
- }
-
- if (using_bloom)
- sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
-
- m = alloca0_align(sz, 8);
- m->size = sz;
- m->cookie = cookie;
-
- item = m->items;
-
- if (src_id != KDBUS_MATCH_ID_ANY) {
- item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
- item->type = KDBUS_ITEM_ID;
- item->id = src_id;
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (dst_id != KDBUS_MATCH_ID_ANY) {
- item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
- item->type = KDBUS_ITEM_DST_ID;
- item->id = dst_id;
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (using_bloom) {
- item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
- item->type = KDBUS_ITEM_BLOOM_MASK;
- memcpy(item->data64, bloom, bus->bloom_size);
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (sender) {
- item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
- item->type = KDBUS_ITEM_NAME;
- memcpy(item->str, sender, sender_length + 1);
- }
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
- if (r < 0)
- return -errno;
-
- if (matches_name_change) {
-
- /* If this match could theoretically match
- * NameOwnerChanged messages, we need to
- * install a second non-bloom filter explitly
- * for it */
-
- r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-#define internal_match(bus, m) \
- ((bus)->hello_flags & KDBUS_HELLO_MONITOR \
- ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
- : (m))
-
-static int bus_add_match_internal_dbus1(
- sd_bus *bus,
- const char *match) {
-
- const char *e;
-
- assert(bus);
- assert(match);
-
- e = internal_match(bus, match);
-
- return sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "AddMatch",
- NULL,
- NULL,
- "s",
- e);
-}
-
-int bus_add_match_internal(
- sd_bus *bus,
- const char *match,
- struct bus_match_component *components,
- unsigned n_components,
- uint64_t cookie) {
-
- assert(bus);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- if (bus->is_kernel)
- return bus_add_match_internal_kernel(bus, components, n_components, cookie);
- else
- return bus_add_match_internal_dbus1(bus, match);
-}
-
-int bus_remove_match_internal_kernel(
- sd_bus *bus,
- uint64_t cookie) {
-
- struct kdbus_cmd_match m = {
- .size = offsetof(struct kdbus_cmd_match, items),
- .cookie = cookie,
- };
- int r;
-
- assert(bus);
-
- /* Monitor streams don't support matches, make this a NOP */
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-static int bus_remove_match_internal_dbus1(
- sd_bus *bus,
- const char *match) {
-
- const char *e;
-
- assert(bus);
- assert(match);
-
- e = internal_match(bus, match);
-
- return sd_bus_call_method(
- bus,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "RemoveMatch",
- NULL,
- NULL,
- "s",
- e);
-}
-
-int bus_remove_match_internal(
- sd_bus *bus,
- const char *match,
- uint64_t cookie) {
-
- assert(bus);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- if (bus->is_kernel)
- return bus_remove_match_internal_kernel(bus, cookie);
- else
- return bus_remove_match_internal_dbus1(bus, match);
-}
-
-_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
- const char *mid;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(name, -EINVAL);
- assert_return(machine, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(service_name_is_valid(name), -EINVAL);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (streq_ptr(name, bus->unique_name))
- return sd_id128_get_machine(machine);
-
- r = sd_bus_message_new_method_call(
- bus,
- &m,
- name,
- "/",
- "org.freedesktop.DBus.Peer",
- "GetMachineId");
- if (r < 0)
- return r;
-
- r = sd_bus_message_set_auto_start(m, false);
- if (r < 0)
- return r;
-
- r = sd_bus_call(bus, m, 0, NULL, &reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(reply, "s", &mid);
- if (r < 0)
- return r;
-
- return sd_id128_from_string(mid, machine);
-}
diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h
deleted file mode 100644
index c181aa7959..0000000000
--- a/src/libsystemd/sd-bus/bus-control.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "bus-match.h"
-
-int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
-int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie);
-
-int bus_add_match_internal_kernel(sd_bus *bus, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
-int bus_remove_match_internal_kernel(sd_bus *bus, uint64_t cookie);
-
-int bus_get_name_creds_kdbus(sd_bus *bus, const char *name, uint64_t mask, bool allow_activator, sd_bus_creds **creds);
diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c
deleted file mode 100644
index 2d06bf541f..0000000000
--- a/src/libsystemd/sd-bus/bus-convenience.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-signature.h"
-#include "bus-type.h"
-#include "bus-util.h"
-#include "string-util.h"
-
-_public_ int sd_bus_emit_signal(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *member,
- const char *types, ...) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- r = sd_bus_message_new_signal(bus, &m, path, interface, member);
- if (r < 0)
- return r;
-
- if (!isempty(types)) {
- va_list ap;
-
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- return r;
- }
-
- return sd_bus_send(bus, m, NULL);
-}
-
-_public_ int sd_bus_call_method_async(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member,
- sd_bus_message_handler_t callback,
- void *userdata,
- const char *types, ...) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
- if (r < 0)
- return r;
-
- if (!isempty(types)) {
- va_list ap;
-
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- return r;
- }
-
- return sd_bus_call_async(bus, slot, m, callback, userdata, 0);
-}
-
-_public_ int sd_bus_call_method(
- sd_bus *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member,
- sd_bus_error *error,
- sd_bus_message **reply,
- const char *types, ...) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- bus_assert_return(bus, -EINVAL, error);
- bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
-
- if (!BUS_IS_OPEN(bus->state)) {
- r = -ENOTCONN;
- goto fail;
- }
-
- r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
- if (r < 0)
- goto fail;
-
- if (!isempty(types)) {
- va_list ap;
-
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- goto fail;
- }
-
- return sd_bus_call(bus, m, 0, error, reply);
-
-fail:
- return sd_bus_error_set_errno(error, r);
-}
-
-_public_ int sd_bus_reply_method_return(
- sd_bus_message *call,
- const char *types, ...) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(call->bus, -EINVAL);
- assert_return(!bus_pid_changed(call->bus), -ECHILD);
-
- if (!BUS_IS_OPEN(call->bus->state))
- return -ENOTCONN;
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- r = sd_bus_message_new_method_return(call, &m);
- if (r < 0)
- return r;
-
- if (!isempty(types)) {
- va_list ap;
-
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
- if (r < 0)
- return r;
- }
-
- return sd_bus_send(call->bus, m, NULL);
-}
-
-_public_ int sd_bus_reply_method_error(
- sd_bus_message *call,
- const sd_bus_error *e) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(sd_bus_error_is_set(e), -EINVAL);
- assert_return(call->bus, -EINVAL);
- assert_return(!bus_pid_changed(call->bus), -ECHILD);
-
- if (!BUS_IS_OPEN(call->bus->state))
- return -ENOTCONN;
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- r = sd_bus_message_new_method_error(call, &m, e);
- if (r < 0)
- return r;
-
- return sd_bus_send(call->bus, m, NULL);
-}
-
-_public_ int sd_bus_reply_method_errorf(
- sd_bus_message *call,
- const char *name,
- const char *format,
- ...) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- va_list ap;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(call->bus, -EINVAL);
- assert_return(!bus_pid_changed(call->bus), -ECHILD);
-
- if (!BUS_IS_OPEN(call->bus->state))
- return -ENOTCONN;
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- va_start(ap, format);
- bus_error_setfv(&error, name, format, ap);
- va_end(ap);
-
- return sd_bus_reply_method_error(call, &error);
-}
-
-_public_ int sd_bus_reply_method_errno(
- sd_bus_message *call,
- int error,
- const sd_bus_error *p) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(call->bus, -EINVAL);
- assert_return(!bus_pid_changed(call->bus), -ECHILD);
-
- if (!BUS_IS_OPEN(call->bus->state))
- return -ENOTCONN;
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- if (sd_bus_error_is_set(p))
- return sd_bus_reply_method_error(call, p);
-
- sd_bus_error_set_errno(&berror, error);
-
- return sd_bus_reply_method_error(call, &berror);
-}
-
-_public_ int sd_bus_reply_method_errnof(
- sd_bus_message *call,
- int error,
- const char *format,
- ...) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
- va_list ap;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(call->bus, -EINVAL);
- assert_return(!bus_pid_changed(call->bus), -ECHILD);
-
- if (!BUS_IS_OPEN(call->bus->state))
- return -ENOTCONN;
-
- if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 0;
-
- va_start(ap, format);
- sd_bus_error_set_errnofv(&berror, error, format, ap);
- va_end(ap);
-
- return sd_bus_reply_method_error(call, &berror);
-}
-
-_public_ int sd_bus_get_property(
- sd_bus *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member,
- sd_bus_error *error,
- sd_bus_message **reply,
- const char *type) {
-
- sd_bus_message *rep = NULL;
- int r;
-
- bus_assert_return(bus, -EINVAL, error);
- bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
- bus_assert_return(member_name_is_valid(member), -EINVAL, error);
- bus_assert_return(reply, -EINVAL, error);
- bus_assert_return(signature_is_single(type, false), -EINVAL, error);
- bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
-
- if (!BUS_IS_OPEN(bus->state)) {
- r = -ENOTCONN;
- goto fail;
- }
-
- r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
- if (r < 0)
- return r;
-
- r = sd_bus_message_enter_container(rep, 'v', type);
- if (r < 0) {
- sd_bus_message_unref(rep);
- goto fail;
- }
-
- *reply = rep;
- return 0;
-
-fail:
- return sd_bus_error_set_errno(error, r);
-}
-
-_public_ int sd_bus_get_property_trivial(
- sd_bus *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member,
- sd_bus_error *error,
- char type, void *ptr) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- int r;
-
- bus_assert_return(bus, -EINVAL, error);
- bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
- bus_assert_return(member_name_is_valid(member), -EINVAL, error);
- bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
- bus_assert_return(ptr, -EINVAL, error);
- bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
-
- if (!BUS_IS_OPEN(bus->state)) {
- r = -ENOTCONN;
- goto fail;
- }
-
- r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
- if (r < 0)
- return r;
-
- r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
- if (r < 0)
- goto fail;
-
- r = sd_bus_message_read_basic(reply, type, ptr);
- if (r < 0)
- goto fail;
-
- return 0;
-
-fail:
- return sd_bus_error_set_errno(error, r);
-}
-
-_public_ int sd_bus_get_property_string(
- sd_bus *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member,
- sd_bus_error *error,
- char **ret) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *s;
- char *n;
- int r;
-
- bus_assert_return(bus, -EINVAL, error);
- bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
- bus_assert_return(member_name_is_valid(member), -EINVAL, error);
- bus_assert_return(ret, -EINVAL, error);
- bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
-
- if (!BUS_IS_OPEN(bus->state)) {
- r = -ENOTCONN;
- goto fail;
- }
-
- r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
- if (r < 0)
- return r;
-
- r = sd_bus_message_enter_container(reply, 'v', "s");
- if (r < 0)
- goto fail;
-
- r = sd_bus_message_read_basic(reply, 's', &s);
- if (r < 0)
- goto fail;
-
- n = strdup(s);
- if (!n) {
- r = -ENOMEM;
- goto fail;
- }
-
- *ret = n;
- return 0;
-
-fail:
- return sd_bus_error_set_errno(error, r);
-}
-
-_public_ int sd_bus_get_property_strv(
- sd_bus *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member,
- sd_bus_error *error,
- char ***ret) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- int r;
-
- bus_assert_return(bus, -EINVAL, error);
- bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
- bus_assert_return(member_name_is_valid(member), -EINVAL, error);
- bus_assert_return(ret, -EINVAL, error);
- bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
-
- if (!BUS_IS_OPEN(bus->state)) {
- r = -ENOTCONN;
- goto fail;
- }
-
- r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
- if (r < 0)
- return r;
-
- r = sd_bus_message_enter_container(reply, 'v', NULL);
- if (r < 0)
- goto fail;
-
- r = sd_bus_message_read_strv(reply, ret);
- if (r < 0)
- goto fail;
-
- return 0;
-
-fail:
- return sd_bus_error_set_errno(error, r);
-}
-
-_public_ int sd_bus_set_property(
- sd_bus *bus,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member,
- sd_bus_error *error,
- const char *type, ...) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- va_list ap;
- int r;
-
- bus_assert_return(bus, -EINVAL, error);
- bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
- bus_assert_return(member_name_is_valid(member), -EINVAL, error);
- bus_assert_return(signature_is_single(type, false), -EINVAL, error);
- bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
-
- if (!BUS_IS_OPEN(bus->state)) {
- r = -ENOTCONN;
- goto fail;
- }
-
- r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
- if (r < 0)
- goto fail;
-
- r = sd_bus_message_append(m, "ss", strempty(interface), member);
- if (r < 0)
- goto fail;
-
- r = sd_bus_message_open_container(m, 'v', type);
- if (r < 0)
- goto fail;
-
- va_start(ap, type);
- r = bus_message_append_ap(m, type, ap);
- va_end(ap);
- if (r < 0)
- goto fail;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- goto fail;
-
- return sd_bus_call(bus, m, 0, error, NULL);
-
-fail:
- return sd_bus_error_set_errno(error, r);
-}
-
-_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
- sd_bus_creds *c;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->bus, -EINVAL);
- assert_return(!bus_pid_changed(call->bus), -ECHILD);
-
- if (!BUS_IS_OPEN(call->bus->state))
- return -ENOTCONN;
-
- c = sd_bus_message_get_creds(call);
-
- /* All data we need? */
- if (c && (mask & ~c->mask) == 0) {
- *creds = sd_bus_creds_ref(c);
- return 0;
- }
-
- /* No data passed? Or not enough data passed to retrieve the missing bits? */
- if (!c || !(c->mask & SD_BUS_CREDS_PID)) {
- /* We couldn't read anything from the call, let's try
- * to get it from the sender or peer. */
-
- if (call->sender)
- /* There's a sender, but the creds are
- * missing. This means we are talking via
- * dbus1, or are getting a message that was
- * sent to us via kdbus, but was converted
- * from a dbus1 message by the bus-proxy and
- * thus also lacks the creds. */
- return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
- else
- /* There's no sender, hence we are on a dbus1
- * direct connection. For direct connections
- * the credentials of the AF_UNIX peer matter,
- * which may be queried via
- * sd_bus_get_owner_creds(). */
- return sd_bus_get_owner_creds(call->bus, mask, creds);
- }
-
- return bus_creds_extend_by_pid(c, mask, creds);
-}
-
-_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- uid_t our_uid;
- bool know_caps = false;
- int r;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->bus, -EINVAL);
- assert_return(!bus_pid_changed(call->bus), -ECHILD);
-
- if (!BUS_IS_OPEN(call->bus->state))
- return -ENOTCONN;
-
- if (capability >= 0) {
-
- r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
- if (r < 0)
- return r;
-
- /* We cannot use augmented caps for authorization,
- * since then data is acquired raceful from
- * /proc. This can never actually happen, but let's
- * better be safe than sorry, and do an extra check
- * here. */
- assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);
-
- /* Note that not even on kdbus we might have the caps
- * field, due to faked identities, or namespace
- * translation issues. */
- r = sd_bus_creds_has_effective_cap(creds, capability);
- if (r > 0)
- return 1;
- if (r == 0)
- know_caps = true;
- } else {
- r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
- if (r < 0)
- return r;
- }
-
- /* Now, check the UID, but only if the capability check wasn't
- * sufficient */
- our_uid = getuid();
- if (our_uid != 0 || !know_caps || capability < 0) {
- uid_t sender_uid;
-
- /* We cannot use augmented uid/euid for authorization,
- * since then data is acquired raceful from
- * /proc. This can never actually happen, but let's
- * better be safe than sorry, and do an extra check
- * here. */
- assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM);
-
- /* Try to use the EUID, if we have it. */
- r = sd_bus_creds_get_euid(creds, &sender_uid);
- if (r < 0)
- r = sd_bus_creds_get_uid(creds, &sender_uid);
-
- if (r >= 0) {
- /* Sender has same UID as us, then let's grant access */
- if (sender_uid == our_uid)
- return 1;
-
- /* Sender is root, we are not root. */
- if (our_uid != 0 && sender_uid == 0)
- return 1;
- }
- }
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
deleted file mode 100644
index c4f693dee9..0000000000
--- a/src/libsystemd/sd-bus/bus-creds.c
+++ /dev/null
@@ -1,1349 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <linux/capability.h>
-#include <stdlib.h>
-
-#include "alloc-util.h"
-#include "audit-util.h"
-#include "bus-creds.h"
-#include "bus-label.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "capability-util.h"
-#include "cgroup-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "hexdecoct.h"
-#include "parse-util.h"
-#include "process-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "terminal-util.h"
-#include "user-util.h"
-#include "util.h"
-
-enum {
- CAP_OFFSET_INHERITABLE = 0,
- CAP_OFFSET_PERMITTED = 1,
- CAP_OFFSET_EFFECTIVE = 2,
- CAP_OFFSET_BOUNDING = 3
-};
-
-void bus_creds_done(sd_bus_creds *c) {
- assert(c);
-
- /* For internal bus cred structures that are allocated by
- * something else */
-
- free(c->session);
- free(c->unit);
- free(c->user_unit);
- free(c->slice);
- free(c->user_slice);
- free(c->unescaped_description);
- free(c->supplementary_gids);
- free(c->tty);
-
- free(c->well_known_names); /* note that this is an strv, but
- * we only free the array, not the
- * strings the array points to. The
- * full strv we only free if
- * c->allocated is set, see
- * below. */
-
- strv_free(c->cmdline_array);
-}
-
-_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) {
-
- if (!c)
- return NULL;
-
- if (c->allocated) {
- assert(c->n_ref > 0);
- c->n_ref++;
- } else {
- sd_bus_message *m;
-
- /* If this is an embedded creds structure, then
- * forward ref counting to the message */
- m = container_of(c, sd_bus_message, creds);
- sd_bus_message_ref(m);
- }
-
- return c;
-}
-
-_public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) {
-
- if (!c)
- return NULL;
-
- if (c->allocated) {
- assert(c->n_ref > 0);
- c->n_ref--;
-
- if (c->n_ref == 0) {
- free(c->comm);
- free(c->tid_comm);
- free(c->exe);
- free(c->cmdline);
- free(c->cgroup);
- free(c->capability);
- free(c->label);
- free(c->unique_name);
- free(c->cgroup_root);
- free(c->description);
-
- c->supplementary_gids = mfree(c->supplementary_gids);
-
- c->well_known_names = strv_free(c->well_known_names);
-
- bus_creds_done(c);
-
- free(c);
- }
- } else {
- sd_bus_message *m;
-
- m = container_of(c, sd_bus_message, creds);
- sd_bus_message_unref(m);
- }
-
-
- return NULL;
-}
-
-_public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) {
- assert_return(c, 0);
-
- return c->mask;
-}
-
-_public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) {
- assert_return(c, 0);
-
- return c->augmented;
-}
-
-sd_bus_creds* bus_creds_new(void) {
- sd_bus_creds *c;
-
- c = new0(sd_bus_creds, 1);
- if (!c)
- return NULL;
-
- c->allocated = true;
- c->n_ref = 1;
- return c;
-}
-
-_public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) {
- sd_bus_creds *c;
- int r;
-
- assert_return(pid >= 0, -EINVAL);
- assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
- assert_return(ret, -EINVAL);
-
- if (pid == 0)
- pid = getpid();
-
- c = bus_creds_new();
- if (!c)
- return -ENOMEM;
-
- r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
- if (r < 0) {
- sd_bus_creds_unref(c);
- return r;
- }
-
- /* Check if the process existed at all, in case we haven't
- * figured that out already */
- if (!pid_is_alive(pid)) {
- sd_bus_creds_unref(c);
- return -ESRCH;
- }
-
- *ret = c;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
- assert_return(c, -EINVAL);
- assert_return(uid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_UID))
- return -ENODATA;
-
- *uid = c->uid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
- assert_return(c, -EINVAL);
- assert_return(euid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_EUID))
- return -ENODATA;
-
- *euid = c->euid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
- assert_return(c, -EINVAL);
- assert_return(suid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_SUID))
- return -ENODATA;
-
- *suid = c->suid;
- return 0;
-}
-
-
-_public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
- assert_return(c, -EINVAL);
- assert_return(fsuid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_FSUID))
- return -ENODATA;
-
- *fsuid = c->fsuid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
- assert_return(c, -EINVAL);
- assert_return(gid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_GID))
- return -ENODATA;
-
- *gid = c->gid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
- assert_return(c, -EINVAL);
- assert_return(egid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_EGID))
- return -ENODATA;
-
- *egid = c->egid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
- assert_return(c, -EINVAL);
- assert_return(sgid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_SGID))
- return -ENODATA;
-
- *sgid = c->sgid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
- assert_return(c, -EINVAL);
- assert_return(fsgid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_FSGID))
- return -ENODATA;
-
- *fsgid = c->fsgid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) {
- assert_return(c, -EINVAL);
- assert_return(gids, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS))
- return -ENODATA;
-
- *gids = c->supplementary_gids;
- return (int) c->n_supplementary_gids;
-}
-
-_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
- assert_return(c, -EINVAL);
- assert_return(pid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_PID))
- return -ENODATA;
-
- assert(c->pid > 0);
- *pid = c->pid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) {
- assert_return(c, -EINVAL);
- assert_return(ppid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_PPID))
- return -ENODATA;
-
- /* PID 1 has no parent process. Let's distinguish the case of
- * not knowing and not having a parent process by the returned
- * error code. */
- if (c->ppid == 0)
- return -ENXIO;
-
- *ppid = c->ppid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) {
- assert_return(c, -EINVAL);
- assert_return(tid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_TID))
- return -ENODATA;
-
- assert(c->tid > 0);
- *tid = c->tid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) {
- assert_return(c, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
- return -ENODATA;
-
- assert(c->label);
- *ret = c->label;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) {
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_COMM))
- return -ENODATA;
-
- assert(c->comm);
- *ret = c->comm;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) {
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_TID_COMM))
- return -ENODATA;
-
- assert(c->tid_comm);
- *ret = c->tid_comm;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) {
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_EXE))
- return -ENODATA;
-
- if (!c->exe)
- return -ENXIO;
-
- *ret = c->exe;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) {
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_CGROUP))
- return -ENODATA;
-
- assert(c->cgroup);
- *ret = c->cgroup;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) {
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_UNIT))
- return -ENODATA;
-
- assert(c->cgroup);
-
- if (!c->unit) {
- const char *shifted;
-
- r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
- if (r < 0)
- return r;
-
- r = cg_path_get_unit(shifted, (char**) &c->unit);
- if (r < 0)
- return r;
- }
-
- *ret = c->unit;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) {
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_USER_UNIT))
- return -ENODATA;
-
- assert(c->cgroup);
-
- if (!c->user_unit) {
- const char *shifted;
-
- r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
- if (r < 0)
- return r;
-
- r = cg_path_get_user_unit(shifted, (char**) &c->user_unit);
- if (r < 0)
- return r;
- }
-
- *ret = c->user_unit;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) {
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_SLICE))
- return -ENODATA;
-
- assert(c->cgroup);
-
- if (!c->slice) {
- const char *shifted;
-
- r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
- if (r < 0)
- return r;
-
- r = cg_path_get_slice(shifted, (char**) &c->slice);
- if (r < 0)
- return r;
- }
-
- *ret = c->slice;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) {
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_USER_SLICE))
- return -ENODATA;
-
- assert(c->cgroup);
-
- if (!c->user_slice) {
- const char *shifted;
-
- r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
- if (r < 0)
- return r;
-
- r = cg_path_get_user_slice(shifted, (char**) &c->user_slice);
- if (r < 0)
- return r;
- }
-
- *ret = c->user_slice;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) {
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_SESSION))
- return -ENODATA;
-
- assert(c->cgroup);
-
- if (!c->session) {
- const char *shifted;
-
- r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
- if (r < 0)
- return r;
-
- r = cg_path_get_session(shifted, (char**) &c->session);
- if (r < 0)
- return r;
- }
-
- *ret = c->session;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) {
- const char *shifted;
- int r;
-
- assert_return(c, -EINVAL);
- assert_return(uid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_OWNER_UID))
- return -ENODATA;
-
- assert(c->cgroup);
-
- r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted);
- if (r < 0)
- return r;
-
- return cg_path_get_owner_uid(shifted, uid);
-}
-
-_public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) {
- assert_return(c, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_CMDLINE))
- return -ENODATA;
-
- if (!c->cmdline)
- return -ENXIO;
-
- if (!c->cmdline_array) {
- c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size);
- if (!c->cmdline_array)
- return -ENOMEM;
- }
-
- *cmdline = c->cmdline_array;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) {
- assert_return(c, -EINVAL);
- assert_return(sessionid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID))
- return -ENODATA;
-
- if (c->audit_session_id == AUDIT_SESSION_INVALID)
- return -ENXIO;
-
- *sessionid = c->audit_session_id;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) {
- assert_return(c, -EINVAL);
- assert_return(uid, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID))
- return -ENODATA;
-
- if (c->audit_login_uid == UID_INVALID)
- return -ENXIO;
-
- *uid = c->audit_login_uid;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) {
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_TTY))
- return -ENODATA;
-
- if (!c->tty)
- return -ENXIO;
-
- *ret = c->tty;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) {
- assert_return(c, -EINVAL);
- assert_return(unique_name, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME))
- return -ENODATA;
-
- *unique_name = c->unique_name;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) {
- assert_return(c, -EINVAL);
- assert_return(well_known_names, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES))
- return -ENODATA;
-
- /* As a special hack we return the bus driver as well-known
- * names list when this is requested. */
- if (c->well_known_names_driver) {
- static const char* const wkn[] = {
- "org.freedesktop.DBus",
- NULL
- };
-
- *well_known_names = (char**) wkn;
- return 0;
- }
-
- if (c->well_known_names_local) {
- static const char* const wkn[] = {
- "org.freedesktop.DBus.Local",
- NULL
- };
-
- *well_known_names = (char**) wkn;
- return 0;
- }
-
- *well_known_names = c->well_known_names;
- return 0;
-}
-
-_public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) {
- assert_return(c, -EINVAL);
- assert_return(ret, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_DESCRIPTION))
- return -ENODATA;
-
- assert(c->description);
-
- if (!c->unescaped_description) {
- c->unescaped_description = bus_label_unescape(c->description);
- if (!c->unescaped_description)
- return -ENOMEM;
- }
-
- *ret = c->unescaped_description;
- return 0;
-}
-
-static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
- size_t sz;
-
- assert(c);
- assert(capability >= 0);
- assert(c->capability);
-
- if ((unsigned) capability > cap_last_cap())
- return 0;
-
- sz = DIV_ROUND_UP(cap_last_cap(), 32U);
-
- return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
-}
-
-_public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {
- assert_return(c, -EINVAL);
- assert_return(capability >= 0, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS))
- return -ENODATA;
-
- return has_cap(c, CAP_OFFSET_EFFECTIVE, capability);
-}
-
-_public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) {
- assert_return(c, -EINVAL);
- assert_return(capability >= 0, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS))
- return -ENODATA;
-
- return has_cap(c, CAP_OFFSET_PERMITTED, capability);
-}
-
-_public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) {
- assert_return(c, -EINVAL);
- assert_return(capability >= 0, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS))
- return -ENODATA;
-
- return has_cap(c, CAP_OFFSET_INHERITABLE, capability);
-}
-
-_public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) {
- assert_return(c, -EINVAL);
- assert_return(capability >= 0, -EINVAL);
-
- if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS))
- return -ENODATA;
-
- return has_cap(c, CAP_OFFSET_BOUNDING, capability);
-}
-
-static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) {
- size_t sz, max;
- unsigned i, j;
-
- assert(c);
- assert(p);
-
- max = DIV_ROUND_UP(cap_last_cap(), 32U);
- p += strspn(p, WHITESPACE);
-
- sz = strlen(p);
- if (sz % 8 != 0)
- return -EINVAL;
-
- sz /= 8;
- if (sz > max)
- return -EINVAL;
-
- if (!c->capability) {
- c->capability = new0(uint32_t, max * 4);
- if (!c->capability)
- return -ENOMEM;
- }
-
- for (i = 0; i < sz; i ++) {
- uint32_t v = 0;
-
- for (j = 0; j < 8; ++j) {
- int t;
-
- t = unhexchar(*p++);
- if (t < 0)
- return -EINVAL;
-
- v = (v << 4) | t;
- }
-
- c->capability[offset * max + (sz - i - 1)] = v;
- }
-
- return 0;
-}
-
-int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
- uint64_t missing;
- int r;
-
- assert(c);
- assert(c->allocated);
-
- if (!(mask & SD_BUS_CREDS_AUGMENT))
- return 0;
-
- /* Try to retrieve PID from creds if it wasn't passed to us */
- if (pid > 0) {
- c->pid = pid;
- c->mask |= SD_BUS_CREDS_PID;
- } else if (c->mask & SD_BUS_CREDS_PID)
- pid = c->pid;
- else
- /* Without pid we cannot do much... */
- return 0;
-
- /* Try to retrieve TID from creds if it wasn't passed to us */
- if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID))
- tid = c->tid;
-
- /* Calculate what we shall and can add */
- missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT);
- if (missing == 0)
- return 0;
-
- if (tid > 0) {
- c->tid = tid;
- c->mask |= SD_BUS_CREDS_TID;
- }
-
- if (missing & (SD_BUS_CREDS_PPID |
- SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
- SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
- SD_BUS_CREDS_SUPPLEMENTARY_GIDS |
- SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
- SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
-
- _cleanup_fclose_ FILE *f = NULL;
- const char *p;
-
- p = procfs_file_alloca(pid, "status");
-
- f = fopen(p, "re");
- if (!f) {
- if (errno == ENOENT)
- return -ESRCH;
- else if (errno != EPERM && errno != EACCES)
- return -errno;
- } else {
- char line[LINE_MAX];
-
- FOREACH_LINE(line, f, return -errno) {
- truncate_nl(line);
-
- if (missing & SD_BUS_CREDS_PPID) {
- p = startswith(line, "PPid:");
- if (p) {
- p += strspn(p, WHITESPACE);
-
- /* Explicitly check for PPID 0 (which is the case for PID 1) */
- if (!streq(p, "0")) {
- r = parse_pid(p, &c->ppid);
- if (r < 0)
- return r;
-
- } else
- c->ppid = 0;
-
- c->mask |= SD_BUS_CREDS_PPID;
- continue;
- }
- }
-
- if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
- p = startswith(line, "Uid:");
- if (p) {
- unsigned long uid, euid, suid, fsuid;
-
- p += strspn(p, WHITESPACE);
- if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
- return -EIO;
-
- if (missing & SD_BUS_CREDS_UID)
- c->uid = (uid_t) uid;
- if (missing & SD_BUS_CREDS_EUID)
- c->euid = (uid_t) euid;
- if (missing & SD_BUS_CREDS_SUID)
- c->suid = (uid_t) suid;
- if (missing & SD_BUS_CREDS_FSUID)
- c->fsuid = (uid_t) fsuid;
-
- c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
- continue;
- }
- }
-
- if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
- p = startswith(line, "Gid:");
- if (p) {
- unsigned long gid, egid, sgid, fsgid;
-
- p += strspn(p, WHITESPACE);
- if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
- return -EIO;
-
- if (missing & SD_BUS_CREDS_GID)
- c->gid = (gid_t) gid;
- if (missing & SD_BUS_CREDS_EGID)
- c->egid = (gid_t) egid;
- if (missing & SD_BUS_CREDS_SGID)
- c->sgid = (gid_t) sgid;
- if (missing & SD_BUS_CREDS_FSGID)
- c->fsgid = (gid_t) fsgid;
-
- c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
- continue;
- }
- }
-
- if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
- p = startswith(line, "Groups:");
- if (p) {
- size_t allocated = 0;
-
- for (;;) {
- unsigned long g;
- int n = 0;
-
- p += strspn(p, WHITESPACE);
- if (*p == 0)
- break;
-
- if (sscanf(p, "%lu%n", &g, &n) != 1)
- return -EIO;
-
- if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1))
- return -ENOMEM;
-
- c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g;
- p += n;
- }
-
- c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
- continue;
- }
- }
-
- if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
- p = startswith(line, "CapEff:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
- continue;
- }
- }
-
- if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
- p = startswith(line, "CapPrm:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
- continue;
- }
- }
-
- if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
- p = startswith(line, "CapInh:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
- continue;
- }
- }
-
- if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
- p = startswith(line, "CapBnd:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
- continue;
- }
- }
- }
- }
- }
-
- if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
- const char *p;
-
- p = procfs_file_alloca(pid, "attr/current");
- r = read_one_line_file(p, &c->label);
- if (r < 0) {
- if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
- return r;
- } else
- c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
- }
-
- if (missing & SD_BUS_CREDS_COMM) {
- r = get_process_comm(pid, &c->comm);
- if (r < 0) {
- if (r != -EPERM && r != -EACCES)
- return r;
- } else
- c->mask |= SD_BUS_CREDS_COMM;
- }
-
- if (missing & SD_BUS_CREDS_EXE) {
- r = get_process_exe(pid, &c->exe);
- if (r == -ESRCH) {
- /* Unfortunately we cannot really distinguish
- * the case here where the process does not
- * exist, and /proc/$PID/exe being unreadable
- * because $PID is a kernel thread. Hence,
- * assume it is a kernel thread, and rely on
- * that this case is caught with a later
- * call. */
- c->exe = NULL;
- c->mask |= SD_BUS_CREDS_EXE;
- } else if (r < 0) {
- if (r != -EPERM && r != -EACCES)
- return r;
- } else
- c->mask |= SD_BUS_CREDS_EXE;
- }
-
- if (missing & SD_BUS_CREDS_CMDLINE) {
- const char *p;
-
- p = procfs_file_alloca(pid, "cmdline");
- r = read_full_file(p, &c->cmdline, &c->cmdline_size);
- if (r == -ENOENT)
- return -ESRCH;
- if (r < 0) {
- if (r != -EPERM && r != -EACCES)
- return r;
- } else {
- if (c->cmdline_size == 0)
- c->cmdline = mfree(c->cmdline);
-
- c->mask |= SD_BUS_CREDS_CMDLINE;
- }
- }
-
- if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
- _cleanup_free_ char *p = NULL;
-
- if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, &c->tid_comm);
- if (r == -ENOENT)
- return -ESRCH;
- if (r < 0) {
- if (r != -EPERM && r != -EACCES)
- return r;
- } else
- c->mask |= SD_BUS_CREDS_TID_COMM;
- }
-
- if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
-
- if (!c->cgroup) {
- r = cg_pid_get_path(NULL, pid, &c->cgroup);
- if (r < 0) {
- if (r != -EPERM && r != -EACCES)
- return r;
- }
- }
-
- if (!c->cgroup_root) {
- r = cg_get_root_path(&c->cgroup_root);
- if (r < 0)
- return r;
- }
-
- if (c->cgroup)
- c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
- }
-
- if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
- r = audit_session_from_pid(pid, &c->audit_session_id);
- if (r == -ENODATA) {
- /* ENODATA means: no audit session id assigned */
- c->audit_session_id = AUDIT_SESSION_INVALID;
- c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
- } else if (r < 0) {
- if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
- return r;
- } else
- c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
- }
-
- if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
- r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
- if (r == -ENODATA) {
- /* ENODATA means: no audit login uid assigned */
- c->audit_login_uid = UID_INVALID;
- c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
- } else if (r < 0) {
- if (r != -EOPNOTSUPP && r != -ENOENT && r != -EPERM && r != -EACCES)
- return r;
- } else
- c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
- }
-
- if (missing & SD_BUS_CREDS_TTY) {
- r = get_ctty(pid, NULL, &c->tty);
- if (r == -ENXIO) {
- /* ENXIO means: process has no controlling TTY */
- c->tty = NULL;
- c->mask |= SD_BUS_CREDS_TTY;
- } else if (r < 0) {
- if (r != -EPERM && r != -EACCES && r != -ENOENT)
- return r;
- } else
- c->mask |= SD_BUS_CREDS_TTY;
- }
-
- /* In case only the exe path was to be read we cannot
- * distinguish the case where the exe path was unreadable
- * because the process was a kernel thread, or when the
- * process didn't exist at all. Hence, let's do a final check,
- * to be sure. */
- if (!pid_is_alive(pid))
- return -ESRCH;
-
- if (tid > 0 && tid != pid && !pid_is_unwaited(tid))
- return -ESRCH;
-
- c->augmented = missing & c->mask;
-
- return 0;
-}
-
-int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL;
- int r;
-
- assert(c);
- assert(ret);
-
- if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
- /* There's already all data we need, or augmentation
- * wasn't turned on. */
-
- *ret = sd_bus_creds_ref(c);
- return 0;
- }
-
- n = bus_creds_new();
- if (!n)
- return -ENOMEM;
-
- /* Copy the original data over */
-
- if (c->mask & mask & SD_BUS_CREDS_PID) {
- n->pid = c->pid;
- n->mask |= SD_BUS_CREDS_PID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_TID) {
- n->tid = c->tid;
- n->mask |= SD_BUS_CREDS_TID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_PPID) {
- n->ppid = c->ppid;
- n->mask |= SD_BUS_CREDS_PPID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_UID) {
- n->uid = c->uid;
- n->mask |= SD_BUS_CREDS_UID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_EUID) {
- n->euid = c->euid;
- n->mask |= SD_BUS_CREDS_EUID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_SUID) {
- n->suid = c->suid;
- n->mask |= SD_BUS_CREDS_SUID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_FSUID) {
- n->fsuid = c->fsuid;
- n->mask |= SD_BUS_CREDS_FSUID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_GID) {
- n->gid = c->gid;
- n->mask |= SD_BUS_CREDS_GID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_EGID) {
- n->egid = c->egid;
- n->mask |= SD_BUS_CREDS_EGID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_SGID) {
- n->sgid = c->sgid;
- n->mask |= SD_BUS_CREDS_SGID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_FSGID) {
- n->fsgid = c->fsgid;
- n->mask |= SD_BUS_CREDS_FSGID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
- if (c->supplementary_gids) {
- n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids);
- if (!n->supplementary_gids)
- return -ENOMEM;
- n->n_supplementary_gids = c->n_supplementary_gids;
- } else {
- n->supplementary_gids = NULL;
- n->n_supplementary_gids = 0;
- }
-
- n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_COMM) {
- assert(c->comm);
-
- n->comm = strdup(c->comm);
- if (!n->comm)
- return -ENOMEM;
-
- n->mask |= SD_BUS_CREDS_COMM;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_TID_COMM) {
- assert(c->tid_comm);
-
- n->tid_comm = strdup(c->tid_comm);
- if (!n->tid_comm)
- return -ENOMEM;
-
- n->mask |= SD_BUS_CREDS_TID_COMM;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_EXE) {
- if (c->exe) {
- n->exe = strdup(c->exe);
- if (!n->exe)
- return -ENOMEM;
- } else
- n->exe = NULL;
-
- n->mask |= SD_BUS_CREDS_EXE;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_CMDLINE) {
- if (c->cmdline) {
- n->cmdline = memdup(c->cmdline, c->cmdline_size);
- if (!n->cmdline)
- return -ENOMEM;
-
- n->cmdline_size = c->cmdline_size;
- } else {
- n->cmdline = NULL;
- n->cmdline_size = 0;
- }
-
- n->mask |= SD_BUS_CREDS_CMDLINE;
- }
-
- if (c->mask & mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) {
- assert(c->cgroup);
-
- n->cgroup = strdup(c->cgroup);
- if (!n->cgroup)
- return -ENOMEM;
-
- n->cgroup_root = strdup(c->cgroup_root);
- if (!n->cgroup_root)
- return -ENOMEM;
-
- n->mask |= mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID);
- }
-
- if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) {
- assert(c->capability);
-
- n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap(), 32U) * 4 * 4);
- if (!n->capability)
- return -ENOMEM;
-
- n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS);
- }
-
- if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
- assert(c->label);
-
- n->label = strdup(c->label);
- if (!n->label)
- return -ENOMEM;
- n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
- n->audit_session_id = c->audit_session_id;
- n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
- }
- if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
- n->audit_login_uid = c->audit_login_uid;
- n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_TTY) {
- if (c->tty) {
- n->tty = strdup(c->tty);
- if (!n->tty)
- return -ENOMEM;
- } else
- n->tty = NULL;
- n->mask |= SD_BUS_CREDS_TTY;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) {
- assert(c->unique_name);
-
- n->unique_name = strdup(c->unique_name);
- if (!n->unique_name)
- return -ENOMEM;
- n->mask |= SD_BUS_CREDS_UNIQUE_NAME;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
- if (strv_isempty(c->well_known_names))
- n->well_known_names = NULL;
- else {
- n->well_known_names = strv_copy(c->well_known_names);
- if (!n->well_known_names)
- return -ENOMEM;
- }
- n->well_known_names_driver = c->well_known_names_driver;
- n->well_known_names_local = c->well_known_names_local;
- n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
- }
-
- if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) {
- assert(c->description);
- n->description = strdup(c->description);
- if (!n->description)
- return -ENOMEM;
- n->mask |= SD_BUS_CREDS_DESCRIPTION;
- }
-
- n->augmented = c->augmented & n->mask;
-
- /* Get more data */
-
- r = bus_creds_add_more(n, mask, 0, 0);
- if (r < 0)
- return r;
-
- *ret = n;
- n = NULL;
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/bus-creds.h b/src/libsystemd/sd-bus/bus-creds.h
deleted file mode 100644
index df8a1f1005..0000000000
--- a/src/libsystemd/sd-bus/bus-creds.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include "sd-bus.h"
-
-struct sd_bus_creds {
- bool allocated;
- unsigned n_ref;
-
- uint64_t mask;
- uint64_t augmented;
-
- uid_t uid;
- uid_t euid;
- uid_t suid;
- uid_t fsuid;
- gid_t gid;
- gid_t egid;
- gid_t sgid;
- gid_t fsgid;
-
- gid_t *supplementary_gids;
- unsigned n_supplementary_gids;
-
- pid_t ppid;
- pid_t pid;
- pid_t tid;
-
- char *comm;
- char *tid_comm;
- char *exe;
-
- char *cmdline;
- size_t cmdline_size;
- char **cmdline_array;
-
- char *cgroup;
- char *session;
- char *unit;
- char *user_unit;
- char *slice;
- char *user_slice;
-
- char *tty;
-
- uint32_t *capability;
-
- uint32_t audit_session_id;
- uid_t audit_login_uid;
-
- char *label;
-
- char *unique_name;
-
- char **well_known_names;
- bool well_known_names_driver:1;
- bool well_known_names_local:1;
-
- char *cgroup_root;
-
- char *description, *unescaped_description;
-};
-
-sd_bus_creds* bus_creds_new(void);
-
-void bus_creds_done(sd_bus_creds *c);
-
-int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid);
-
-int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret);
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
deleted file mode 100644
index 21a6b20a11..0000000000
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "alloc-util.h"
-#include "bus-dump.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-type.h"
-#include "cap-list.h"
-#include "capability-util.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "locale-util.h"
-#include "macro.h"
-#include "string-util.h"
-#include "strv.h"
-#include "terminal-util.h"
-#include "util.h"
-
-static char *indent(unsigned level, unsigned flags) {
- char *p;
- unsigned n, i = 0;
-
- n = 0;
-
- if (flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY && level > 0)
- level -= 1;
-
- if (flags & BUS_MESSAGE_DUMP_WITH_HEADER)
- n += 2;
-
- p = new(char, n + level*8 + 1);
- if (!p)
- return NULL;
-
- if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
- p[i++] = ' ';
- p[i++] = ' ';
- }
-
- memset(p + i, ' ', level*8);
- p[i + level*8] = 0;
-
- return p;
-}
-
-int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
- unsigned level = 1;
- int r;
-
- assert(m);
-
- if (!f)
- f = stdout;
-
- if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
- fprintf(f,
- "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64,
- m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
- m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() :
- m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", special_glyph(TRIANGULAR_BULLET), ansi_normal(),
- ansi_highlight(), bus_message_type_to_string(m->header->type), ansi_normal(),
- m->header->endian,
- m->header->flags,
- m->header->version,
- m->priority);
-
- /* Display synthetic message serial number in a more readable
- * format than (uint32_t) -1 */
- if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL)
- fprintf(f, " Cookie=-1");
- else
- fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m));
-
- if (m->reply_cookie != 0)
- fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie);
-
- fputs("\n", f);
-
- if (m->sender)
- fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_normal());
- if (m->destination)
- fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_normal());
- if (m->path)
- fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_normal());
- if (m->interface)
- fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_normal());
- if (m->member)
- fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_normal());
-
- if (m->sender || m->destination || m->path || m->interface || m->member)
- fputs("\n", f);
-
- if (sd_bus_error_is_set(&m->error))
- fprintf(f,
- " ErrorName=%s%s%s"
- " ErrorMessage=%s\"%s\"%s\n",
- ansi_highlight_red(), strna(m->error.name), ansi_normal(),
- ansi_highlight_red(), strna(m->error.message), ansi_normal());
-
- if (m->monotonic != 0)
- fprintf(f, " Monotonic="USEC_FMT, m->monotonic);
- if (m->realtime != 0)
- fprintf(f, " Realtime="USEC_FMT, m->realtime);
- if (m->seqnum != 0)
- fprintf(f, " SequenceNumber=%"PRIu64, m->seqnum);
-
- if (m->monotonic != 0 || m->realtime != 0 || m->seqnum != 0)
- fputs("\n", f);
-
- bus_creds_dump(&m->creds, f, true);
- }
-
- r = sd_bus_message_rewind(m, !(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY));
- if (r < 0)
- return log_error_errno(r, "Failed to rewind: %m");
-
- if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
- _cleanup_free_ char *prefix = NULL;
-
- prefix = indent(0, flags);
- if (!prefix)
- return log_oom();
-
- fprintf(f, "%sMESSAGE \"%s\" {\n", prefix, strempty(m->root_container.signature));
- }
-
- for (;;) {
- _cleanup_free_ char *prefix = NULL;
- const char *contents = NULL;
- char type;
- union {
- uint8_t u8;
- uint16_t u16;
- int16_t s16;
- uint32_t u32;
- int32_t s32;
- uint64_t u64;
- int64_t s64;
- double d64;
- const char *string;
- int i;
- } basic;
-
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r < 0)
- return log_error_errno(r, "Failed to peek type: %m");
-
- if (r == 0) {
- if (level <= 1)
- break;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return log_error_errno(r, "Failed to exit container: %m");
-
- level--;
-
- prefix = indent(level, flags);
- if (!prefix)
- return log_oom();
-
- fprintf(f, "%s};\n", prefix);
- continue;
- }
-
- prefix = indent(level, flags);
- if (!prefix)
- return log_oom();
-
- if (bus_type_is_container(type) > 0) {
- r = sd_bus_message_enter_container(m, type, contents);
- if (r < 0)
- return log_error_errno(r, "Failed to enter container: %m");
-
- if (type == SD_BUS_TYPE_ARRAY)
- fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents);
- else if (type == SD_BUS_TYPE_VARIANT)
- fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents);
- else if (type == SD_BUS_TYPE_STRUCT)
- fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents);
- else if (type == SD_BUS_TYPE_DICT_ENTRY)
- fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents);
-
- level++;
-
- continue;
- }
-
- r = sd_bus_message_read_basic(m, type, &basic);
- if (r < 0)
- return log_error_errno(r, "Failed to get basic: %m");
-
- assert(r > 0);
-
- switch (type) {
-
- case SD_BUS_TYPE_BYTE:
- fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_normal());
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
- fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_normal());
- break;
-
- case SD_BUS_TYPE_INT16:
- fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_normal());
- break;
-
- case SD_BUS_TYPE_UINT16:
- fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_normal());
- break;
-
- case SD_BUS_TYPE_INT32:
- fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_normal());
- break;
-
- case SD_BUS_TYPE_UINT32:
- fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_normal());
- break;
-
- case SD_BUS_TYPE_INT64:
- fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_normal());
- break;
-
- case SD_BUS_TYPE_UINT64:
- fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_normal());
- break;
-
- case SD_BUS_TYPE_DOUBLE:
- fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_normal());
- break;
-
- case SD_BUS_TYPE_STRING:
- fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal());
- break;
-
- case SD_BUS_TYPE_OBJECT_PATH:
- fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal());
- break;
-
- case SD_BUS_TYPE_SIGNATURE:
- fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal());
- break;
-
- case SD_BUS_TYPE_UNIX_FD:
- fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_normal());
- break;
-
- default:
- assert_not_reached("Unknown basic type.");
- }
- }
-
- if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) {
- _cleanup_free_ char *prefix = NULL;
-
- prefix = indent(0, flags);
- if (!prefix)
- return log_oom();
-
- fprintf(f, "%s};\n\n", prefix);
- }
-
- return 0;
-}
-
-static void dump_capabilities(
- sd_bus_creds *c,
- FILE *f,
- const char *name,
- bool terse,
- int (*has)(sd_bus_creds *c, int capability)) {
-
- unsigned long i, last_cap;
- unsigned n = 0;
- int r;
-
- assert(c);
- assert(f);
- assert(name);
- assert(has);
-
- i = 0;
- r = has(c, i);
- if (r < 0)
- return;
-
- fprintf(f, "%s%s=%s", terse ? " " : "", name, terse ? "" : ansi_highlight());
- last_cap = cap_last_cap();
-
- for (;;) {
- if (r > 0) {
-
- if (n > 0)
- fputc(' ', f);
- if (n % 4 == 3)
- fprintf(f, terse ? "\n " : "\n ");
-
- fprintf(f, "%s", strna(capability_to_name(i)));
- n++;
- }
-
- i++;
-
- if (i > last_cap)
- break;
-
- r = has(c, i);
- }
-
- fputs("\n", f);
-
- if (!terse)
- fputs(ansi_normal(), f);
-}
-
-int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
- uid_t owner, audit_loginuid;
- uint32_t audit_sessionid;
- char **cmdline = NULL, **well_known = NULL;
- const char *prefix, *color, *suffix, *s;
- int r, q, v, w, z;
-
- assert(c);
-
- if (!f)
- f = stdout;
-
- if (terse) {
- prefix = " ";
- suffix = "";
- color = "";
- } else {
- const char *off;
-
- prefix = "";
- color = ansi_highlight();
-
- off = ansi_normal();
- suffix = strjoina(off, "\n");
- }
-
- if (c->mask & SD_BUS_CREDS_PID)
- fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix);
- if (c->mask & SD_BUS_CREDS_TID)
- fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
- if (c->mask & SD_BUS_CREDS_PPID) {
- if (c->ppid == 0)
- fprintf(f, "%sPPID=%sn/a%s", prefix, color, suffix);
- else
- fprintf(f, "%sPPID=%s"PID_FMT"%s", prefix, color, c->ppid, suffix);
- }
- if (c->mask & SD_BUS_CREDS_TTY)
- fprintf(f, "%sTTY=%s%s%s", prefix, color, strna(c->tty), suffix);
-
- if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID|SD_BUS_CREDS_TTY))))
- fputs("\n", f);
-
- if (c->mask & SD_BUS_CREDS_UID)
- fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix);
- if (c->mask & SD_BUS_CREDS_EUID)
- fprintf(f, "%sEUID=%s"UID_FMT"%s", prefix, color, c->euid, suffix);
- if (c->mask & SD_BUS_CREDS_SUID)
- fprintf(f, "%sSUID=%s"UID_FMT"%s", prefix, color, c->suid, suffix);
- if (c->mask & SD_BUS_CREDS_FSUID)
- fprintf(f, "%sFSUID=%s"UID_FMT"%s", prefix, color, c->fsuid, suffix);
- r = sd_bus_creds_get_owner_uid(c, &owner);
- if (r >= 0)
- fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix);
- if (c->mask & SD_BUS_CREDS_GID)
- fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix);
- if (c->mask & SD_BUS_CREDS_EGID)
- fprintf(f, "%sEGID=%s"GID_FMT"%s", prefix, color, c->egid, suffix);
- if (c->mask & SD_BUS_CREDS_SGID)
- fprintf(f, "%sSGID=%s"GID_FMT"%s", prefix, color, c->sgid, suffix);
- if (c->mask & SD_BUS_CREDS_FSGID)
- fprintf(f, "%sFSGID=%s"GID_FMT"%s", prefix, color, c->fsgid, suffix);
-
- if (c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
- unsigned i;
-
- fprintf(f, "%sSupplementaryGIDs=%s", prefix, color);
- for (i = 0; i < c->n_supplementary_gids; i++)
- fprintf(f, "%s" GID_FMT, i > 0 ? " " : "", c->supplementary_gids[i]);
- fprintf(f, "%s", suffix);
- }
-
- if (terse && ((c->mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
- SD_BUS_CREDS_SUPPLEMENTARY_GIDS)) || r >= 0))
- fputs("\n", f);
-
- if (c->mask & SD_BUS_CREDS_COMM)
- fprintf(f, "%sComm=%s%s%s", prefix, color, c->comm, suffix);
- if (c->mask & SD_BUS_CREDS_TID_COMM)
- fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix);
- if (c->mask & SD_BUS_CREDS_EXE)
- fprintf(f, "%sExe=%s%s%s", prefix, color, strna(c->exe), suffix);
-
- if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM)))
- fputs("\n", f);
-
- r = sd_bus_creds_get_cmdline(c, &cmdline);
- if (r >= 0) {
- char **i;
-
- fprintf(f, "%sCommandLine=%s", prefix, color);
- STRV_FOREACH(i, cmdline) {
- if (i != cmdline)
- fputc(' ', f);
-
- fputs(*i, f);
- }
-
- fprintf(f, "%s", suffix);
- } else if (r != -ENODATA)
- fprintf(f, "%sCommandLine=%sn/a%s", prefix, color, suffix);
-
- if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)
- fprintf(f, "%sLabel=%s%s%s", prefix, color, c->label, suffix);
- if (c->mask & SD_BUS_CREDS_DESCRIPTION)
- fprintf(f, "%sDescription=%s%s%s", prefix, color, c->description, suffix);
-
- if (terse && (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION)))
- fputs("\n", f);
-
- if (c->mask & SD_BUS_CREDS_CGROUP)
- fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix);
- s = NULL;
- r = sd_bus_creds_get_unit(c, &s);
- if (r != -ENODATA)
- fprintf(f, "%sUnit=%s%s%s", prefix, color, strna(s), suffix);
- s = NULL;
- v = sd_bus_creds_get_slice(c, &s);
- if (v != -ENODATA)
- fprintf(f, "%sSlice=%s%s%s", prefix, color, strna(s), suffix);
- s = NULL;
- q = sd_bus_creds_get_user_unit(c, &s);
- if (q != -ENODATA)
- fprintf(f, "%sUserUnit=%s%s%s", prefix, color, strna(s), suffix);
- s = NULL;
- w = sd_bus_creds_get_user_slice(c, &s);
- if (w != -ENODATA)
- fprintf(f, "%sUserSlice=%s%s%s", prefix, color, strna(s), suffix);
- s = NULL;
- z = sd_bus_creds_get_session(c, &s);
- if (z != -ENODATA)
- fprintf(f, "%sSession=%s%s%s", prefix, color, strna(s), suffix);
-
- if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || r != -ENODATA || q != -ENODATA || v != -ENODATA || w != -ENODATA || z != -ENODATA))
- fputs("\n", f);
-
- r = sd_bus_creds_get_audit_login_uid(c, &audit_loginuid);
- if (r >= 0)
- fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix);
- else if (r != -ENODATA)
- fprintf(f, "%sAuditLoginUID=%sn/a%s", prefix, color, suffix);
- q = sd_bus_creds_get_audit_session_id(c, &audit_sessionid);
- if (q >= 0)
- fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix);
- else if (q != -ENODATA)
- fprintf(f, "%sAuditSessionID=%sn/a%s", prefix, color, suffix);
-
- if (terse && (r != -ENODATA || q != -ENODATA))
- fputs("\n", f);
-
- if (c->mask & SD_BUS_CREDS_UNIQUE_NAME)
- fprintf(f, "%sUniqueName=%s%s%s", prefix, color, c->unique_name, suffix);
-
- if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) {
- char **i;
-
- fprintf(f, "%sWellKnownNames=%s", prefix, color);
- STRV_FOREACH(i, well_known) {
- if (i != well_known)
- fputc(' ', f);
-
- fputs(*i, f);
- }
-
- fprintf(f, "%s", suffix);
- }
-
- if (terse && (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known))
- fputc('\n', f);
-
- dump_capabilities(c, f, "EffectiveCapabilities", terse, sd_bus_creds_has_effective_cap);
- dump_capabilities(c, f, "PermittedCapabilities", terse, sd_bus_creds_has_permitted_cap);
- dump_capabilities(c, f, "InheritableCapabilities", terse, sd_bus_creds_has_inheritable_cap);
- dump_capabilities(c, f, "BoundingCapabilities", terse, sd_bus_creds_has_bounding_cap);
-
- return 0;
-}
-
-/*
- * For details about the file format, see:
- *
- * http://wiki.wireshark.org/Development/LibpcapFileFormat
- */
-
-typedef struct _packed_ pcap_hdr_s {
- uint32_t magic_number; /* magic number */
- uint16_t version_major; /* major version number */
- uint16_t version_minor; /* minor version number */
- int32_t thiszone; /* GMT to local correction */
- uint32_t sigfigs; /* accuracy of timestamps */
- uint32_t snaplen; /* max length of captured packets, in octets */
- uint32_t network; /* data link type */
-} pcap_hdr_t ;
-
-typedef struct _packed_ pcaprec_hdr_s {
- uint32_t ts_sec; /* timestamp seconds */
- uint32_t ts_usec; /* timestamp microseconds */
- uint32_t incl_len; /* number of octets of packet saved in file */
- uint32_t orig_len; /* actual length of packet */
-} pcaprec_hdr_t;
-
-int bus_pcap_header(size_t snaplen, FILE *f) {
-
- pcap_hdr_t hdr = {
- .magic_number = 0xa1b2c3d4U,
- .version_major = 2,
- .version_minor = 4,
- .thiszone = 0, /* UTC */
- .sigfigs = 0,
- .network = 231, /* D-Bus */
- };
-
- if (!f)
- f = stdout;
-
- assert(snaplen > 0);
- assert((size_t) (uint32_t) snaplen == snaplen);
-
- hdr.snaplen = (uint32_t) snaplen;
-
- fwrite(&hdr, 1, sizeof(hdr), f);
-
- return fflush_and_check(f);
-}
-
-int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) {
- struct bus_body_part *part;
- pcaprec_hdr_t hdr = {};
- struct timeval tv;
- unsigned i;
- size_t w;
-
- if (!f)
- f = stdout;
-
- assert(m);
- assert(snaplen > 0);
- assert((size_t) (uint32_t) snaplen == snaplen);
-
- if (m->realtime != 0)
- timeval_store(&tv, m->realtime);
- else
- assert_se(gettimeofday(&tv, NULL) >= 0);
-
- hdr.ts_sec = tv.tv_sec;
- hdr.ts_usec = tv.tv_usec;
- hdr.orig_len = BUS_MESSAGE_SIZE(m);
- hdr.incl_len = MIN(hdr.orig_len, snaplen);
-
- /* write the pcap header */
- fwrite(&hdr, 1, sizeof(hdr), f);
-
- /* write the dbus header */
- w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen);
- fwrite(m->header, 1, w, f);
- snaplen -= w;
-
- /* write the dbus body */
- MESSAGE_FOREACH_PART(part, i, m) {
- if (snaplen <= 0)
- break;
-
- w = MIN(part->size, snaplen);
- fwrite(part->data, 1, w, f);
- snaplen -= w;
- }
-
- return fflush_and_check(f);
-}
diff --git a/src/libsystemd/sd-bus/bus-dump.h b/src/libsystemd/sd-bus/bus-dump.h
deleted file mode 100644
index 874e86d09c..0000000000
--- a/src/libsystemd/sd-bus/bus-dump.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include <stdio.h>
-
-#include "sd-bus.h"
-
-enum {
- BUS_MESSAGE_DUMP_WITH_HEADER = 1,
- BUS_MESSAGE_DUMP_SUBTREE_ONLY = 2,
-};
-
-int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags);
-
-int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse);
-
-int bus_pcap_header(size_t snaplen, FILE *f);
-int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f);
diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c
deleted file mode 100644
index 378f7a377a..0000000000
--- a/src/libsystemd/sd-bus/bus-error.c
+++ /dev/null
@@ -1,606 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-error.h"
-#include "errno-list.h"
-#include "string-util.h"
-#include "util.h"
-
-BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed", EACCES),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoMemory", ENOMEM),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ServiceUnknown", EHOSTUNREACH),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NameHasNoOwner", ENXIO),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoReply", ETIMEDOUT),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.IOError", EIO),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.BadAddress", EADDRNOTAVAIL),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NotSupported", EOPNOTSUPP),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.LimitsExceeded", ENOBUFS),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AccessDenied", EACCES),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AuthFailed", EACCES),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired", EACCES),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoServer", EHOSTDOWN),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Timeout", ETIMEDOUT),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoNetwork", ENONET),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AddressInUse", EADDRINUSE),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Disconnected", ECONNRESET),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidArgs", EINVAL),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileNotFound", ENOENT),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileExists", EEXIST),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownMethod", EBADR),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownObject", EBADR),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownInterface", EBADR),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownProperty", EBADR),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.PropertyReadOnly", EROFS),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnixProcessIdUnknown", ESRCH),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidSignature", EINVAL),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InconsistentMessage", EBADMSG),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.TimedOut", ETIMEDOUT),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleInvalid", EINVAL),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidFileContent", EINVAL),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleNotFound", ENOENT),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown", ESRCH),
- SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ObjectPathInUse", EBUSY),
- SD_BUS_ERROR_MAP_END
-};
-
-/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */
-extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
-extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];
-
-/* Additional maps registered with sd_bus_error_add_map() are in this
- * NULL terminated array */
-static const sd_bus_error_map **additional_error_maps = NULL;
-
-static int bus_error_name_to_errno(const char *name) {
- const sd_bus_error_map **map, *m;
- const char *p;
- int r;
-
- if (!name)
- return EINVAL;
-
- p = startswith(name, "System.Error.");
- if (p) {
- r = errno_from_name(p);
- if (r < 0)
- return EIO;
-
- return r;
- }
-
- if (additional_error_maps)
- for (map = additional_error_maps; *map; map++)
- for (m = *map;; m++) {
- /* For additional error maps the end marker is actually the end marker */
- if (m->code == BUS_ERROR_MAP_END_MARKER)
- break;
-
- if (streq(m->name, name))
- return m->code;
- }
-
- m = __start_BUS_ERROR_MAP;
- while (m < __stop_BUS_ERROR_MAP) {
- /* For magic ELF error maps, the end marker might
- * appear in the middle of things, since multiple maps
- * might appear in the same section. Hence, let's skip
- * over it, but realign the pointer to the next 8 byte
- * boundary, which is the selected alignment for the
- * arrays. */
- if (m->code == BUS_ERROR_MAP_END_MARKER) {
- m = ALIGN8_PTR(m+1);
- continue;
- }
-
- if (streq(m->name, name))
- return m->code;
-
- m++;
- }
-
- return EIO;
-}
-
-static sd_bus_error errno_to_bus_error_const(int error) {
-
- if (error < 0)
- error = -error;
-
- switch (error) {
-
- case ENOMEM:
- return BUS_ERROR_OOM;
-
- case EPERM:
- case EACCES:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ACCESS_DENIED, "Access denied");
-
- case EINVAL:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid argument");
-
- case ESRCH:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "No such process");
-
- case ENOENT:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_NOT_FOUND, "File not found");
-
- case EEXIST:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "File exists");
-
- case ETIMEDOUT:
- case ETIME:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_TIMEOUT, "Timed out");
-
- case EIO:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_IO_ERROR, "Input/output error");
-
- case ENETRESET:
- case ECONNABORTED:
- case ECONNRESET:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_DISCONNECTED, "Disconnected");
-
- case EOPNOTSUPP:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NOT_SUPPORTED, "Not supported");
-
- case EADDRNOTAVAIL:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_BAD_ADDRESS, "Address not available");
-
- case ENOBUFS:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_LIMITS_EXCEEDED, "Limits exceeded");
-
- case EADDRINUSE:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ADDRESS_IN_USE, "Address in use");
-
- case EBADMSG:
- return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Inconsistent message");
- }
-
- return SD_BUS_ERROR_NULL;
-}
-
-static int errno_to_bus_error_name_new(int error, char **ret) {
- const char *name;
- char *n;
-
- if (error < 0)
- error = -error;
-
- name = errno_to_name(error);
- if (!name)
- return 0;
-
- n = strappend("System.Error.", name);
- if (!n)
- return -ENOMEM;
-
- *ret = n;
- return 1;
-}
-
-bool bus_error_is_dirty(sd_bus_error *e) {
- if (!e)
- return false;
-
- return e->name || e->message || e->_need_free != 0;
-}
-
-_public_ void sd_bus_error_free(sd_bus_error *e) {
- if (!e)
- return;
-
- if (e->_need_free > 0) {
- free((void*) e->name);
- free((void*) e->message);
- }
-
- e->name = e->message = NULL;
- e->_need_free = 0;
-}
-
-_public_ int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) {
-
- if (!name)
- return 0;
- if (!e)
- goto finish;
-
- assert_return(!bus_error_is_dirty(e), -EINVAL);
-
- e->name = strdup(name);
- if (!e->name) {
- *e = BUS_ERROR_OOM;
- return -ENOMEM;
- }
-
- if (message)
- e->message = strdup(message);
-
- e->_need_free = 1;
-
-finish:
- return -bus_error_name_to_errno(name);
-}
-
-int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) {
-
- if (!name)
- return 0;
-
- if (e) {
- assert_return(!bus_error_is_dirty(e), -EINVAL);
-
- e->name = strdup(name);
- if (!e->name) {
- *e = BUS_ERROR_OOM;
- return -ENOMEM;
- }
-
- /* If we hit OOM on formatting the pretty message, we ignore
- * this, since we at least managed to write the error name */
- if (format)
- (void) vasprintf((char**) &e->message, format, ap);
-
- e->_need_free = 1;
- }
-
- return -bus_error_name_to_errno(name);
-}
-
-_public_ int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) {
-
- if (format) {
- int r;
- va_list ap;
-
- va_start(ap, format);
- r = bus_error_setfv(e, name, format, ap);
- va_end(ap);
-
- return r;
- }
-
- return sd_bus_error_set(e, name, NULL);
-}
-
-_public_ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) {
-
- if (!sd_bus_error_is_set(e))
- return 0;
- if (!dest)
- goto finish;
-
- assert_return(!bus_error_is_dirty(dest), -EINVAL);
-
- /*
- * _need_free < 0 indicates that the error is temporarily const, needs deep copying
- * _need_free == 0 indicates that the error is perpetually const, needs no deep copying
- * _need_free > 0 indicates that the error is fully dynamic, needs deep copying
- */
-
- if (e->_need_free == 0)
- *dest = *e;
- else {
- dest->name = strdup(e->name);
- if (!dest->name) {
- *dest = BUS_ERROR_OOM;
- return -ENOMEM;
- }
-
- if (e->message)
- dest->message = strdup(e->message);
-
- dest->_need_free = 1;
- }
-
-finish:
- return -bus_error_name_to_errno(e->name);
-}
-
-_public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) {
- if (!name)
- return 0;
- if (!e)
- goto finish;
-
- assert_return(!bus_error_is_dirty(e), -EINVAL);
-
- *e = SD_BUS_ERROR_MAKE_CONST(name, message);
-
-finish:
- return -bus_error_name_to_errno(name);
-}
-
-_public_ int sd_bus_error_is_set(const sd_bus_error *e) {
- if (!e)
- return 0;
-
- return !!e->name;
-}
-
-_public_ int sd_bus_error_has_name(const sd_bus_error *e, const char *name) {
- if (!e)
- return 0;
-
- return streq_ptr(e->name, name);
-}
-
-_public_ int sd_bus_error_get_errno(const sd_bus_error* e) {
- if (!e)
- return 0;
-
- if (!e->name)
- return 0;
-
- return bus_error_name_to_errno(e->name);
-}
-
-static void bus_error_strerror(sd_bus_error *e, int error) {
- size_t k = 64;
- char *m;
-
- assert(e);
-
- for (;;) {
- char *x;
-
- m = new(char, k);
- if (!m)
- return;
-
- errno = 0;
- x = strerror_r(error, m, k);
- if (errno == ERANGE || strlen(x) >= k - 1) {
- free(m);
- k *= 2;
- continue;
- }
-
- if (errno) {
- free(m);
- return;
- }
-
- if (x == m) {
- if (e->_need_free > 0) {
- /* Error is already dynamic, let's just update the message */
- free((char*) e->message);
- e->message = x;
-
- } else {
- char *t;
- /* Error was const so far, let's make it dynamic, if we can */
-
- t = strdup(e->name);
- if (!t) {
- free(m);
- return;
- }
-
- e->_need_free = 1;
- e->name = t;
- e->message = x;
- }
- } else {
- free(m);
-
- if (e->_need_free > 0) {
- char *t;
-
- /* Error is dynamic, let's hence make the message also dynamic */
- t = strdup(x);
- if (!t)
- return;
-
- free((char*) e->message);
- e->message = t;
- } else {
- /* Error is const, hence we can just override */
- e->message = x;
- }
- }
-
- return;
- }
-}
-
-_public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) {
-
- if (error < 0)
- error = -error;
-
- if (!e)
- return -error;
- if (error == 0)
- return -error;
-
- assert_return(!bus_error_is_dirty(e), -EINVAL);
-
- /* First, try a const translation */
- *e = errno_to_bus_error_const(error);
-
- if (!sd_bus_error_is_set(e)) {
- int k;
-
- /* If that didn't work, try a dynamic one. */
-
- k = errno_to_bus_error_name_new(error, (char**) &e->name);
- if (k > 0)
- e->_need_free = 1;
- else if (k < 0) {
- *e = BUS_ERROR_OOM;
- return -error;
- } else
- *e = BUS_ERROR_FAILED;
- }
-
- /* Now, fill in the message from strerror() if we can */
- bus_error_strerror(e, error);
- return -error;
-}
-
-_public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) {
- PROTECT_ERRNO;
- int r;
-
- if (error < 0)
- error = -error;
-
- if (!e)
- return -error;
- if (error == 0)
- return 0;
-
- assert_return(!bus_error_is_dirty(e), -EINVAL);
-
- /* First, try a const translation */
- *e = errno_to_bus_error_const(error);
-
- if (!sd_bus_error_is_set(e)) {
- int k;
-
- /* If that didn't work, try a dynamic one */
-
- k = errno_to_bus_error_name_new(error, (char**) &e->name);
- if (k > 0)
- e->_need_free = 1;
- else if (k < 0) {
- *e = BUS_ERROR_OOM;
- return -ENOMEM;
- } else
- *e = BUS_ERROR_FAILED;
- }
-
- if (format) {
- char *m;
-
- /* Then, let's try to fill in the supplied message */
-
- errno = error; /* Make sure that %m resolves to the specified error */
- r = vasprintf(&m, format, ap);
- if (r >= 0) {
-
- if (e->_need_free <= 0) {
- char *t;
-
- t = strdup(e->name);
- if (t) {
- e->_need_free = 1;
- e->name = t;
- e->message = m;
- return -error;
- }
-
- free(m);
- } else {
- free((char*) e->message);
- e->message = m;
- return -error;
- }
- }
- }
-
- /* If that didn't work, use strerror() for the message */
- bus_error_strerror(e, error);
- return -error;
-}
-
-_public_ int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) {
- int r;
-
- if (error < 0)
- error = -error;
-
- if (!e)
- return -error;
- if (error == 0)
- return 0;
-
- assert_return(!bus_error_is_dirty(e), -EINVAL);
-
- if (format) {
- va_list ap;
-
- va_start(ap, format);
- r = sd_bus_error_set_errnofv(e, error, format, ap);
- va_end(ap);
-
- return r;
- }
-
- return sd_bus_error_set_errno(e, error);
-}
-
-const char *bus_error_message(const sd_bus_error *e, int error) {
-
- if (e) {
- /* Sometimes, the D-Bus server is a little bit too verbose with
- * its error messages, so let's override them here */
- if (sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED))
- return "Access denied";
-
- if (e->message)
- return e->message;
- }
-
- if (error < 0)
- error = -error;
-
- return strerror(error);
-}
-
-static bool map_ok(const sd_bus_error_map *map) {
- for (; map->code != BUS_ERROR_MAP_END_MARKER; map++)
- if (!map->name || map->code <=0)
- return false;
- return true;
-}
-
-_public_ int sd_bus_error_add_map(const sd_bus_error_map *map) {
- const sd_bus_error_map **maps = NULL;
- unsigned n = 0;
-
- assert_return(map, -EINVAL);
- assert_return(map_ok(map), -EINVAL);
-
- if (additional_error_maps)
- for (; additional_error_maps[n] != NULL; n++)
- if (additional_error_maps[n] == map)
- return 0;
-
- maps = realloc_multiply(additional_error_maps, sizeof(struct sd_bus_error_map*), n + 2);
- if (!maps)
- return -ENOMEM;
-
- maps[n] = map;
- maps[n+1] = NULL;
-
- additional_error_maps = maps;
- return 1;
-}
diff --git a/src/libsystemd/sd-bus/bus-error.h b/src/libsystemd/sd-bus/bus-error.h
deleted file mode 100644
index e2c4cf4b3f..0000000000
--- a/src/libsystemd/sd-bus/bus-error.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include "sd-bus.h"
-
-#include "macro.h"
-
-bool bus_error_is_dirty(sd_bus_error *e);
-
-const char *bus_error_message(const sd_bus_error *e, int error);
-
-int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) _printf_(3,0);
-int bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) _printf_(3,0);
-
-#define BUS_ERROR_OOM SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_MEMORY, "Out of memory")
-#define BUS_ERROR_FAILED SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FAILED, "Operation failed")
-
-/*
- * There are two ways to register error maps with the error translation
- * logic: by using BUS_ERROR_MAP_ELF_REGISTER, which however only
- * works when linked into the same ELF module, or via
- * sd_bus_error_add_map() which is the official, external API, that
- * works from any module.
- *
- * Note that BUS_ERROR_MAP_ELF_REGISTER has to be used as decorator in
- * the bus error table, and BUS_ERROR_MAP_ELF_USE has to be used at
- * least once per compilation unit (i.e. per library), to ensure that
- * the error map is really added to the final binary.
- */
-
-#define BUS_ERROR_MAP_ELF_REGISTER \
- __attribute__ ((__section__("BUS_ERROR_MAP"))) \
- __attribute__ ((__used__)) \
- __attribute__ ((aligned(8)))
-
-#define BUS_ERROR_MAP_ELF_USE(errors) \
- extern const sd_bus_error_map errors[]; \
- __attribute__ ((used)) static const sd_bus_error_map * const CONCATENATE(errors ## _copy_, __COUNTER__) = errors;
-
-/* We use something exotic as end marker, to ensure people build the
- * maps using the macsd-ros. */
-#define BUS_ERROR_MAP_END_MARKER -'x'
-
-BUS_ERROR_MAP_ELF_USE(bus_standard_errors);
diff --git a/src/libsystemd/sd-bus/bus-gvariant.c b/src/libsystemd/sd-bus/bus-gvariant.c
deleted file mode 100644
index 58782767fa..0000000000
--- a/src/libsystemd/sd-bus/bus-gvariant.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#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("Unknown signature type");
- }
-
- 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("Unknown signature type");
- }
-
- 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("Unknown signature type");
- }
-
- 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("unknown word width");
-}
-
-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("unknown word width");
-
- memcpy(p, &x, sz);
-}
diff --git a/src/libsystemd/sd-bus/bus-gvariant.h b/src/libsystemd/sd-bus/bus-gvariant.h
deleted file mode 100644
index 6da637fb05..0000000000
--- a/src/libsystemd/sd-bus/bus-gvariant.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#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);
diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c
deleted file mode 100644
index caca679086..0000000000
--- a/src/libsystemd/sd-bus/bus-internal.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "hexdecoct.h"
-#include "string-util.h"
-
-bool object_path_is_valid(const char *p) {
- const char *q;
- bool slash;
-
- if (!p)
- return false;
-
- if (p[0] != '/')
- return false;
-
- if (p[1] == 0)
- return true;
-
- for (slash = true, q = p+1; *q; q++)
- if (*q == '/') {
- if (slash)
- return false;
-
- slash = true;
- } else {
- bool good;
-
- good =
- (*q >= 'a' && *q <= 'z') ||
- (*q >= 'A' && *q <= 'Z') ||
- (*q >= '0' && *q <= '9') ||
- *q == '_';
-
- if (!good)
- return false;
-
- slash = false;
- }
-
- if (slash)
- return false;
-
- return true;
-}
-
-char* object_path_startswith(const char *a, const char *b) {
- const char *p;
-
- if (!object_path_is_valid(a) ||
- !object_path_is_valid(b))
- return NULL;
-
- if (streq(b, "/"))
- return (char*) a + 1;
-
- p = startswith(a, b);
- if (!p)
- return NULL;
-
- if (*p == 0)
- return (char*) p;
-
- if (*p == '/')
- return (char*) p + 1;
-
- return NULL;
-}
-
-bool interface_name_is_valid(const char *p) {
- const char *q;
- bool dot, found_dot = false;
-
- if (isempty(p))
- return false;
-
- for (dot = true, q = p; *q; q++)
- if (*q == '.') {
- if (dot)
- return false;
-
- found_dot = dot = true;
- } else {
- bool good;
-
- good =
- (*q >= 'a' && *q <= 'z') ||
- (*q >= 'A' && *q <= 'Z') ||
- (!dot && *q >= '0' && *q <= '9') ||
- *q == '_';
-
- if (!good)
- return false;
-
- dot = false;
- }
-
- if (q - p > 255)
- return false;
-
- if (dot)
- return false;
-
- if (!found_dot)
- return false;
-
- return true;
-}
-
-bool service_name_is_valid(const char *p) {
- const char *q;
- bool dot, found_dot = false, unique;
-
- if (isempty(p))
- return false;
-
- unique = p[0] == ':';
-
- for (dot = true, q = unique ? p+1 : p; *q; q++)
- if (*q == '.') {
- if (dot)
- return false;
-
- found_dot = dot = true;
- } else {
- bool good;
-
- good =
- (*q >= 'a' && *q <= 'z') ||
- (*q >= 'A' && *q <= 'Z') ||
- ((!dot || unique) && *q >= '0' && *q <= '9') ||
- *q == '_' || *q == '-';
-
- if (!good)
- return false;
-
- dot = false;
- }
-
- if (q - p > 255)
- return false;
-
- if (dot)
- return false;
-
- if (!found_dot)
- return false;
-
- return true;
-}
-
-char* service_name_startswith(const char *a, const char *b) {
- const char *p;
-
- if (!service_name_is_valid(a) ||
- !service_name_is_valid(b))
- return NULL;
-
- p = startswith(a, b);
- if (!p)
- return NULL;
-
- if (*p == 0)
- return (char*) p;
-
- if (*p == '.')
- return (char*) p + 1;
-
- return NULL;
-}
-
-bool member_name_is_valid(const char *p) {
- const char *q;
-
- if (isempty(p))
- return false;
-
- for (q = p; *q; q++) {
- bool good;
-
- good =
- (*q >= 'a' && *q <= 'z') ||
- (*q >= 'A' && *q <= 'Z') ||
- (*q >= '0' && *q <= '9') ||
- *q == '_';
-
- if (!good)
- return false;
- }
-
- if (q - p > 255)
- return false;
-
- return true;
-}
-
-/*
- * Complex pattern match
- * This checks whether @a is a 'complex-prefix' of @b, or @b is a
- * 'complex-prefix' of @a, based on strings that consist of labels with @c as
- * spearator. This function returns true if:
- * - both strings are equal
- * - either is a prefix of the other and ends with @c
- * The second rule makes sure that either string needs to be fully included in
- * the other, and the string which is considered the prefix needs to end with a
- * separator.
- */
-static bool complex_pattern_check(char c, const char *a, const char *b) {
- bool separator = false;
-
- if (!a && !b)
- return true;
-
- if (!a || !b)
- return false;
-
- for (;;) {
- if (*a != *b)
- return (separator && (*a == 0 || *b == 0));
-
- if (*a == 0)
- return true;
-
- separator = *a == c;
-
- a++, b++;
- }
-}
-
-bool namespace_complex_pattern(const char *pattern, const char *value) {
- return complex_pattern_check('.', pattern, value);
-}
-
-bool path_complex_pattern(const char *pattern, const char *value) {
- return complex_pattern_check('/', pattern, value);
-}
-
-/*
- * Simple pattern match
- * This checks whether @a is a 'simple-prefix' of @b, based on strings that
- * consist of labels with @c as separator. This function returns true, if:
- * - if @a and @b are equal
- * - if @a is a prefix of @b, and the first following character in @b (or the
- * last character in @a) is @c
- * The second rule basically makes sure that if @a is a prefix of @b, then @b
- * must follow with a new label separated by @c. It cannot extend the label.
- */
-static bool simple_pattern_check(char c, const char *a, const char *b) {
- bool separator = false;
-
- if (!a && !b)
- return true;
-
- if (!a || !b)
- return false;
-
- for (;;) {
- if (*a != *b)
- return *a == 0 && (*b == c || separator);
-
- if (*a == 0)
- return true;
-
- separator = *a == c;
-
- a++, b++;
- }
-}
-
-bool namespace_simple_pattern(const char *pattern, const char *value) {
- return simple_pattern_check('.', pattern, value);
-}
-
-bool path_simple_pattern(const char *pattern, const char *value) {
- return simple_pattern_check('/', pattern, value);
-}
-
-int bus_message_type_from_string(const char *s, uint8_t *u) {
- if (streq(s, "signal"))
- *u = SD_BUS_MESSAGE_SIGNAL;
- else if (streq(s, "method_call"))
- *u = SD_BUS_MESSAGE_METHOD_CALL;
- else if (streq(s, "error"))
- *u = SD_BUS_MESSAGE_METHOD_ERROR;
- else if (streq(s, "method_return"))
- *u = SD_BUS_MESSAGE_METHOD_RETURN;
- else
- return -EINVAL;
-
- return 0;
-}
-
-const char *bus_message_type_to_string(uint8_t u) {
- if (u == SD_BUS_MESSAGE_SIGNAL)
- return "signal";
- else if (u == SD_BUS_MESSAGE_METHOD_CALL)
- return "method_call";
- else if (u == SD_BUS_MESSAGE_METHOD_ERROR)
- return "error";
- else if (u == SD_BUS_MESSAGE_METHOD_RETURN)
- return "method_return";
- else
- return NULL;
-}
-
-char *bus_address_escape(const char *v) {
- const char *a;
- char *r, *b;
-
- r = new(char, strlen(v)*3+1);
- if (!r)
- return NULL;
-
- for (a = v, b = r; *a; a++) {
-
- if ((*a >= '0' && *a <= '9') ||
- (*a >= 'a' && *a <= 'z') ||
- (*a >= 'A' && *a <= 'Z') ||
- strchr("_-/.", *a))
- *(b++) = *a;
- else {
- *(b++) = '%';
- *(b++) = hexchar(*a >> 4);
- *(b++) = hexchar(*a & 0xF);
- }
- }
-
- *b = 0;
- return r;
-}
-
-int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
- assert(m);
-
- if (r < 0) {
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- sd_bus_reply_method_errno(m, r, error);
-
- } else if (sd_bus_error_is_set(error)) {
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- sd_bus_reply_method_error(m, error);
- } else
- return r;
-
- log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
- bus_message_type_to_string(m->header->type),
- strna(m->sender),
- strna(m->path),
- strna(m->interface),
- strna(m->member),
- strna(m->root_container.signature),
- bus_error_message(error, r));
-
- return 1;
-}
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
deleted file mode 100644
index bb0414c4d6..0000000000
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ /dev/null
@@ -1,403 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <pthread.h>
-#include <sys/socket.h>
-
-#include "sd-bus.h"
-
-#include "bus-error.h"
-#include "bus-kernel.h"
-#include "bus-match.h"
-#include "hashmap.h"
-#include "kdbus.h"
-#include "list.h"
-#include "prioq.h"
-#include "refcnt.h"
-#include "socket-util.h"
-#include "util.h"
-
-struct reply_callback {
- sd_bus_message_handler_t callback;
- usec_t timeout;
- uint64_t cookie;
- unsigned prioq_idx;
-};
-
-struct filter_callback {
- sd_bus_message_handler_t callback;
-
- unsigned last_iteration;
-
- LIST_FIELDS(struct filter_callback, callbacks);
-};
-
-struct match_callback {
- sd_bus_message_handler_t callback;
-
- uint64_t cookie;
- unsigned last_iteration;
-
- char *match_string;
-
- struct bus_match_node *match_node;
-};
-
-struct node {
- char *path;
- struct node *parent;
- LIST_HEAD(struct node, child);
- LIST_FIELDS(struct node, siblings);
-
- LIST_HEAD(struct node_callback, callbacks);
- LIST_HEAD(struct node_vtable, vtables);
- LIST_HEAD(struct node_enumerator, enumerators);
- LIST_HEAD(struct node_object_manager, object_managers);
-};
-
-struct node_callback {
- struct node *node;
-
- bool is_fallback;
- sd_bus_message_handler_t callback;
-
- unsigned last_iteration;
-
- LIST_FIELDS(struct node_callback, callbacks);
-};
-
-struct node_enumerator {
- struct node *node;
-
- sd_bus_node_enumerator_t callback;
-
- unsigned last_iteration;
-
- LIST_FIELDS(struct node_enumerator, enumerators);
-};
-
-struct node_object_manager {
- struct node *node;
-
- LIST_FIELDS(struct node_object_manager, object_managers);
-};
-
-struct node_vtable {
- struct node *node;
-
- char *interface;
- bool is_fallback;
- const sd_bus_vtable *vtable;
- sd_bus_object_find_t find;
-
- unsigned last_iteration;
-
- LIST_FIELDS(struct node_vtable, vtables);
-};
-
-struct vtable_member {
- const char *path;
- const char *interface;
- const char *member;
- struct node_vtable *parent;
- unsigned last_iteration;
- const sd_bus_vtable *vtable;
-};
-
-typedef enum BusSlotType {
- BUS_REPLY_CALLBACK,
- BUS_FILTER_CALLBACK,
- BUS_MATCH_CALLBACK,
- BUS_NODE_CALLBACK,
- BUS_NODE_ENUMERATOR,
- BUS_NODE_VTABLE,
- BUS_NODE_OBJECT_MANAGER,
- _BUS_SLOT_INVALID = -1,
-} BusSlotType;
-
-struct sd_bus_slot {
- unsigned n_ref;
- sd_bus *bus;
- void *userdata;
- BusSlotType type:5;
- bool floating:1;
- bool match_added:1;
- char *description;
-
- LIST_FIELDS(sd_bus_slot, slots);
-
- union {
- struct reply_callback reply_callback;
- struct filter_callback filter_callback;
- struct match_callback match_callback;
- struct node_callback node_callback;
- struct node_enumerator node_enumerator;
- struct node_object_manager node_object_manager;
- struct node_vtable node_vtable;
- };
-};
-
-enum bus_state {
- BUS_UNSET,
- BUS_OPENING,
- BUS_AUTHENTICATING,
- BUS_HELLO,
- BUS_RUNNING,
- BUS_CLOSING,
- BUS_CLOSED
-};
-
-static inline bool BUS_IS_OPEN(enum bus_state state) {
- return state > BUS_UNSET && state < BUS_CLOSING;
-}
-
-enum bus_auth {
- _BUS_AUTH_INVALID,
- BUS_AUTH_EXTERNAL,
- BUS_AUTH_ANONYMOUS
-};
-
-struct sd_bus {
- /* We use atomic ref counting here since sd_bus_message
- objects retain references to their originating sd_bus but
- we want to allow them to be processed in a different
- thread. We won't provide full thread safety, but only the
- bare minimum that makes it possible to use sd_bus and
- sd_bus_message objects independently and on different
- threads as long as each object is used only once at the
- same time. */
- RefCount n_ref;
-
- enum bus_state state;
- int input_fd, output_fd;
- int message_version;
- int message_endian;
-
- bool is_kernel:1;
- bool can_fds:1;
- bool bus_client:1;
- bool ucred_valid:1;
- bool is_server:1;
- bool anonymous_auth:1;
- bool prefer_readv:1;
- bool prefer_writev:1;
- bool match_callbacks_modified:1;
- bool filter_callbacks_modified:1;
- bool nodes_modified:1;
- bool trusted:1;
- bool fake_creds_valid:1;
- bool fake_pids_valid:1;
- bool manual_peer_interface:1;
- bool is_system:1;
- bool is_user:1;
- bool allow_interactive_authorization:1;
- bool exit_on_disconnect:1;
- bool exited:1;
- bool exit_triggered:1;
-
- int use_memfd;
-
- void *rbuffer;
- size_t rbuffer_size;
-
- sd_bus_message **rqueue;
- unsigned rqueue_size;
- size_t rqueue_allocated;
-
- sd_bus_message **wqueue;
- unsigned wqueue_size;
- size_t windex;
- size_t wqueue_allocated;
-
- uint64_t cookie;
-
- char *unique_name;
- uint64_t unique_id;
-
- struct bus_match_node match_callbacks;
- Prioq *reply_callbacks_prioq;
- OrderedHashmap *reply_callbacks;
- LIST_HEAD(struct filter_callback, filter_callbacks);
-
- Hashmap *nodes;
- Hashmap *vtable_methods;
- Hashmap *vtable_properties;
-
- union sockaddr_union sockaddr;
- socklen_t sockaddr_size;
-
- char *kernel;
- char *machine;
- pid_t nspid;
-
- sd_id128_t server_id;
-
- char *address;
- unsigned address_index;
-
- int last_connect_error;
-
- enum bus_auth auth;
- size_t auth_rbegin;
- struct iovec auth_iovec[3];
- unsigned auth_index;
- char *auth_buffer;
- usec_t auth_timeout;
-
- struct ucred ucred;
- char *label;
-
- uint64_t creds_mask;
-
- int *fds;
- unsigned n_fds;
-
- char *exec_path;
- char **exec_argv;
-
- unsigned iteration_counter;
-
- void *kdbus_buffer;
-
- /* We do locking around the memfd cache, since we want to
- * allow people to process a sd_bus_message in a different
- * thread then it was generated on and free it there. Since
- * adding something to the memfd cache might happen when a
- * message is released, we hence need to protect this bit with
- * a mutex. */
- pthread_mutex_t memfd_cache_mutex;
- struct memfd_cache memfd_cache[MEMFD_CACHE_MAX];
- unsigned n_memfd_cache;
-
- pid_t original_pid;
-
- uint64_t hello_flags;
- uint64_t attach_flags;
-
- uint64_t match_cookie;
-
- sd_event_source *input_io_event_source;
- sd_event_source *output_io_event_source;
- sd_event_source *time_event_source;
- sd_event_source *quit_event_source;
- sd_event *event;
- int event_priority;
-
- sd_bus_message *current_message;
- sd_bus_slot *current_slot;
- sd_bus_message_handler_t current_handler;
- void *current_userdata;
-
- sd_bus **default_bus_ptr;
- pid_t tid;
-
- struct kdbus_creds fake_creds;
- struct kdbus_pids fake_pids;
- char *fake_label;
-
- char *cgroup_root;
-
- char *description;
-
- size_t bloom_size;
- unsigned bloom_n_hash;
-
- sd_bus_track *track_queue;
-
- LIST_HEAD(sd_bus_slot, slots);
- LIST_HEAD(sd_bus_track, tracks);
-};
-
-#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
-
-#define BUS_WQUEUE_MAX (192*1024)
-#define BUS_RQUEUE_MAX (192*1024)
-
-#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
-#define BUS_AUTH_SIZE_MAX (64*1024)
-
-#define BUS_CONTAINER_DEPTH 128
-
-/* Defined by the specification as maximum size of an array in
- * bytes */
-#define BUS_ARRAY_MAX_SIZE 67108864
-
-#define BUS_FDS_MAX 1024
-
-#define BUS_EXEC_ARGV_MAX 256
-
-bool interface_name_is_valid(const char *p) _pure_;
-bool service_name_is_valid(const char *p) _pure_;
-char* service_name_startswith(const char *a, const char *b);
-bool member_name_is_valid(const char *p) _pure_;
-bool object_path_is_valid(const char *p) _pure_;
-char *object_path_startswith(const char *a, const char *b) _pure_;
-
-bool namespace_complex_pattern(const char *pattern, const char *value) _pure_;
-bool path_complex_pattern(const char *pattern, const char *value) _pure_;
-
-bool namespace_simple_pattern(const char *pattern, const char *value) _pure_;
-bool path_simple_pattern(const char *pattern, const char *value) _pure_;
-
-int bus_message_type_from_string(const char *s, uint8_t *u) _pure_;
-const char *bus_message_type_to_string(uint8_t u) _pure_;
-
-#define error_name_is_valid interface_name_is_valid
-
-int bus_ensure_running(sd_bus *bus);
-int bus_start_running(sd_bus *bus);
-int bus_next_address(sd_bus *bus);
-
-int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m);
-
-int bus_rqueue_make_room(sd_bus *bus);
-
-bool bus_pid_changed(sd_bus *bus);
-
-char *bus_address_escape(const char *v);
-
-#define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \
- for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \
- _slash && !(_slash[(_slash) == (prefix)] = 0); \
- _slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/'))
-
-/* If we are invoking callbacks of a bus object, ensure unreffing the
- * bus from the callback doesn't destroy the object we are working
- * on */
-#define BUS_DONT_DESTROY(bus) \
- _cleanup_(sd_bus_unrefp) _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus)
-
-int bus_set_address_system(sd_bus *bus);
-int bus_set_address_user(sd_bus *bus);
-int bus_set_address_system_remote(sd_bus *b, const char *host);
-int bus_set_address_system_machine(sd_bus *b, const char *machine);
-
-int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
-
-int bus_get_root_path(sd_bus *bus);
-
-int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
-
-#define bus_assert_return(expr, r, error) \
- do { \
- if (!assert_log(expr, #expr)) \
- return sd_bus_error_set_errno(error, r); \
- } while (false)
diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c
deleted file mode 100644
index 8f93edb8da..0000000000
--- a/src/libsystemd/sd-bus/bus-introspect.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-internal.h"
-#include "bus-introspect.h"
-#include "bus-protocol.h"
-#include "bus-signature.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "string-util.h"
-#include "util.h"
-
-int introspect_begin(struct introspect *i, bool trusted) {
- assert(i);
-
- zero(*i);
- i->trusted = trusted;
-
- i->f = open_memstream(&i->introspection, &i->size);
- if (!i->f)
- return -ENOMEM;
-
- fputs(BUS_INTROSPECT_DOCTYPE
- "<node>\n", i->f);
-
- return 0;
-}
-
-int introspect_write_default_interfaces(struct introspect *i, bool object_manager) {
- assert(i);
-
- fputs(BUS_INTROSPECT_INTERFACE_PEER
- BUS_INTROSPECT_INTERFACE_INTROSPECTABLE
- BUS_INTROSPECT_INTERFACE_PROPERTIES, i->f);
-
- if (object_manager)
- fputs(BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER, i->f);
-
- return 0;
-}
-
-int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) {
- char *node;
-
- assert(i);
- assert(prefix);
-
- while ((node = set_steal_first(s))) {
- const char *e;
-
- e = object_path_startswith(node, prefix);
- if (e && e[0])
- fprintf(i->f, " <node name=\"%s\"/>\n", e);
-
- free(node);
- }
-
- return 0;
-}
-
-static void introspect_write_flags(struct introspect *i, int type, int flags) {
- if (flags & SD_BUS_VTABLE_DEPRECATED)
- fputs(" <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i->f);
-
- if (type == _SD_BUS_VTABLE_METHOD && (flags & SD_BUS_VTABLE_METHOD_NO_REPLY))
- fputs(" <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n", i->f);
-
- if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) {
- if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
- fputs(" <annotation name=\"org.freedesktop.systemd1.Explicit\" value=\"true\"/>\n", i->f);
-
- if (flags & SD_BUS_VTABLE_PROPERTY_CONST)
- fputs(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n", i->f);
- else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)
- fputs(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"invalidates\"/>\n", i->f);
- else if (!(flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
- fputs(" <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"false\"/>\n", i->f);
- }
-
- if (!i->trusted &&
- (type == _SD_BUS_VTABLE_METHOD || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) &&
- !(flags & SD_BUS_VTABLE_UNPRIVILEGED))
- fputs(" <annotation name=\"org.freedesktop.systemd1.Privileged\" value=\"true\"/>\n", i->f);
-}
-
-static int introspect_write_arguments(struct introspect *i, const char *signature, const char *direction) {
- int r;
-
- for (;;) {
- size_t l;
-
- if (!*signature)
- return 0;
-
- r = signature_element_length(signature, &l);
- if (r < 0)
- return r;
-
- fprintf(i->f, " <arg type=\"%.*s\"", (int) l, signature);
-
- if (direction)
- fprintf(i->f, " direction=\"%s\"/>\n", direction);
- else
- fputs("/>\n", i->f);
-
- signature += l;
- }
-}
-
-int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
- assert(i);
- assert(v);
-
- for (; v->type != _SD_BUS_VTABLE_END; v++) {
-
- /* Ignore methods, signals and properties that are
- * marked "hidden", but do show the interface
- * itself */
-
- if (v->type != _SD_BUS_VTABLE_START && (v->flags & SD_BUS_VTABLE_HIDDEN))
- continue;
-
- switch (v->type) {
-
- case _SD_BUS_VTABLE_START:
- if (v->flags & SD_BUS_VTABLE_DEPRECATED)
- fputs(" <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n", i->f);
- break;
-
- case _SD_BUS_VTABLE_METHOD:
- fprintf(i->f, " <method name=\"%s\">\n", v->x.method.member);
- introspect_write_arguments(i, strempty(v->x.method.signature), "in");
- introspect_write_arguments(i, strempty(v->x.method.result), "out");
- introspect_write_flags(i, v->type, v->flags);
- fputs(" </method>\n", i->f);
- break;
-
- case _SD_BUS_VTABLE_PROPERTY:
- case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
- fprintf(i->f, " <property name=\"%s\" type=\"%s\" access=\"%s\">\n",
- v->x.property.member,
- v->x.property.signature,
- v->type == _SD_BUS_VTABLE_WRITABLE_PROPERTY ? "readwrite" : "read");
- introspect_write_flags(i, v->type, v->flags);
- fputs(" </property>\n", i->f);
- break;
-
- case _SD_BUS_VTABLE_SIGNAL:
- fprintf(i->f, " <signal name=\"%s\">\n", v->x.signal.member);
- introspect_write_arguments(i, strempty(v->x.signal.signature), NULL);
- introspect_write_flags(i, v->type, v->flags);
- fputs(" </signal>\n", i->f);
- break;
- }
-
- }
-
- return 0;
-}
-
-int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply) {
- sd_bus_message *q;
- int r;
-
- assert(i);
- assert(m);
- assert(reply);
-
- fputs("</node>\n", i->f);
-
- r = fflush_and_check(i->f);
- if (r < 0)
- return r;
-
- r = sd_bus_message_new_method_return(m, &q);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(q, "s", i->introspection);
- if (r < 0) {
- sd_bus_message_unref(q);
- return r;
- }
-
- *reply = q;
- return 0;
-}
-
-void introspect_free(struct introspect *i) {
- assert(i);
-
- safe_fclose(i->f);
-
- free(i->introspection);
- zero(*i);
-}
diff --git a/src/libsystemd/sd-bus/bus-introspect.h b/src/libsystemd/sd-bus/bus-introspect.h
deleted file mode 100644
index 8e2f3800ca..0000000000
--- a/src/libsystemd/sd-bus/bus-introspect.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-
-#include "sd-bus.h"
-
-#include "set.h"
-
-struct introspect {
- FILE *f;
- char *introspection;
- size_t size;
- bool trusted;
-};
-
-int introspect_begin(struct introspect *i, bool trusted);
-int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
-int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
-int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v);
-int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply);
-void introspect_free(struct introspect *i);
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
deleted file mode 100644
index 59398b841d..0000000000
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ /dev/null
@@ -1,1782 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-#include <valgrind/memcheck.h>
-#endif
-
-#include <fcntl.h>
-#include <malloc.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-
-/* When we include libgen.h because we need dirname() we immediately
- * undefine basename() since libgen.h defines it as a macro to the POSIX
- * version which is really broken. We prefer GNU basename(). */
-#include <libgen.h>
-#undef basename
-
-#include "alloc-util.h"
-#include "bus-bloom.h"
-#include "bus-internal.h"
-#include "bus-kernel.h"
-#include "bus-label.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "capability-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "formats-util.h"
-#include "memfd-util.h"
-#include "parse-util.h"
-#include "stdio-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "user-util.h"
-#include "util.h"
-
-#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
-
-int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
- int r;
-
- assert(s);
- assert(id);
-
- if (!startswith(s, ":1."))
- return 0;
-
- r = safe_atou64(s + 3, id);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
- assert(d);
- assert(sz > 0);
-
- *d = ALIGN8_PTR(*d);
-
- /* Note that p can be NULL, which encodes a region full of
- * zeroes, which is useful to optimize certain padding
- * conditions */
-
- (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
- (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
- (*d)->vec.address = PTR_TO_UINT64(p);
- (*d)->vec.size = sz;
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t start, size_t sz) {
- assert(d);
- assert(memfd >= 0);
- assert(sz > 0);
-
- *d = ALIGN8_PTR(*d);
- (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
- (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
- (*d)->memfd.fd = memfd;
- (*d)->memfd.start = start;
- (*d)->memfd.size = sz;
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
- assert(d);
- assert(s);
-
- *d = ALIGN8_PTR(*d);
-
- (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
- (*d)->type = KDBUS_ITEM_DST_NAME;
- memcpy((*d)->str, s, length + 1);
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
- struct kdbus_item *i;
-
- assert(d);
-
- i = ALIGN8_PTR(*d);
-
- i->size = offsetof(struct kdbus_item, bloom_filter) +
- offsetof(struct kdbus_bloom_filter, data) +
- length;
- i->type = KDBUS_ITEM_BLOOM_FILTER;
-
- *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
-
- return &i->bloom_filter;
-}
-
-static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
- assert(d);
- assert(fds);
- assert(n_fds > 0);
-
- *d = ALIGN8_PTR(*d);
- (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
- (*d)->type = KDBUS_ITEM_FDS;
- memcpy((*d)->fds, fds, sizeof(int) * n_fds);
-
- *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
-}
-
-static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
- char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
- char *e;
-
- assert(data);
- assert(size > 0);
- assert(i < 64);
- assert(t);
-
- e = stpcpy(buf, "arg");
- if (i < 10)
- *(e++) = '0' + (char) i;
- else {
- *(e++) = '0' + (char) (i / 10);
- *(e++) = '0' + (char) (i % 10);
- }
-
- *e = 0;
- bloom_add_pair(data, size, n_hash, buf, t);
-
- strcpy(e, "-dot-prefix");
- bloom_add_prefixes(data, size, n_hash, buf, t, '.');
- strcpy(e, "-slash-prefix");
- bloom_add_prefixes(data, size, n_hash, buf, t, '/');
-}
-
-static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
- char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
- char *e;
-
- assert(data);
- assert(size > 0);
- assert(i < 64);
- assert(t);
-
- e = stpcpy(buf, "arg");
- if (i < 10)
- *(e++) = '0' + (char) i;
- else {
- *(e++) = '0' + (char) (i / 10);
- *(e++) = '0' + (char) (i % 10);
- }
-
- strcpy(e, "-has");
- bloom_add_pair(data, size, n_hash, buf, t);
-}
-
-static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
- void *data;
- unsigned i;
- int r;
-
- assert(m);
- assert(bloom);
-
- data = bloom->data;
- memzero(data, m->bus->bloom_size);
- bloom->generation = 0;
-
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
-
- if (m->interface)
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
- if (m->member)
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
- if (m->path) {
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
- bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
- bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
- }
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- for (i = 0; i < 64; i++) {
- const char *t, *contents;
- char type;
-
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r < 0)
- return r;
-
- if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
-
- /* The bloom filter includes simple strings of any kind */
- r = sd_bus_message_read_basic(m, type, &t);
- if (r < 0)
- return r;
-
- add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
- }
-
- if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
-
- /* As well as array of simple strings of any kinds */
- r = sd_bus_message_enter_container(m, type, contents);
- if (r < 0)
- return r;
-
- while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
- add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- } else
- /* Stop adding to bloom filter as soon as we
- * run into the first argument we cannot add
- * to it. */
- break;
- }
-
- return 0;
-}
-
-static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
- struct bus_body_part *part;
- struct kdbus_item *d;
- const char *destination;
- bool well_known = false;
- uint64_t dst_id;
- size_t sz, dl;
- unsigned i;
- int r;
-
- assert(b);
- assert(m);
- assert(m->sealed);
-
- /* We put this together only once, if this message is reused
- * we reuse the earlier-built version */
- if (m->kdbus)
- return 0;
-
- destination = m->destination ?: m->destination_ptr;
-
- if (destination) {
- r = bus_kernel_parse_unique_name(destination, &dst_id);
- if (r < 0)
- return r;
- if (r == 0) {
- well_known = true;
-
- /* verify_destination_id will usually be 0, which makes the kernel
- * driver only look at the provided well-known name. Otherwise,
- * the kernel will make sure the provided destination id matches
- * the owner of the provided well-known-name, and fail if they
- * differ. Currently, this is only needed for bus-proxyd. */
- dst_id = m->verify_destination_id;
- }
- } else
- dst_id = KDBUS_DST_ID_BROADCAST;
-
- sz = offsetof(struct kdbus_msg, items);
-
- /* Add in fixed header, fields header and payload */
- sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) +
- MAX(sizeof(struct kdbus_vec),
- sizeof(struct kdbus_memfd)));
-
- /* Add space for bloom filter */
- sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
- offsetof(struct kdbus_bloom_filter, data) +
- m->bus->bloom_size);
-
- /* Add in well-known destination header */
- if (well_known) {
- dl = strlen(destination);
- sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
- }
-
- /* Add space for unix fds */
- if (m->n_fds > 0)
- sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
-
- m->kdbus = memalign(8, sz);
- if (!m->kdbus) {
- r = -ENOMEM;
- goto fail;
- }
-
- m->free_kdbus = true;
- memzero(m->kdbus, sz);
-
- m->kdbus->flags =
- ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
- ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) |
- ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0);
-
- m->kdbus->dst_id = dst_id;
- m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
- m->kdbus->cookie = m->header->dbus2.cookie;
- m->kdbus->priority = m->priority;
-
- if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- m->kdbus->cookie_reply = m->reply_cookie;
- else {
- struct timespec now;
-
- assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
- m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
- m->timeout * NSEC_PER_USEC;
- }
-
- d = m->kdbus->items;
-
- if (well_known)
- append_destination(&d, destination, dl);
-
- append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
-
- MESSAGE_FOREACH_PART(part, i, m) {
- if (part->is_zero) {
- /* If this is padding then simply send a
- * vector with a NULL data pointer which the
- * kernel will just pass through. This is the
- * most efficient way to encode zeroes */
-
- append_payload_vec(&d, NULL, part->size);
- continue;
- }
-
- if (part->memfd >= 0 && part->sealed && destination) {
- /* Try to send a memfd, if the part is
- * sealed and this is not a broadcast. Since we can only */
-
- append_payload_memfd(&d, part->memfd, part->memfd_offset, part->size);
- continue;
- }
-
- /* Otherwise, let's send a vector to the actual data.
- * For that, we need to map it first. */
- r = bus_body_part_map(part);
- if (r < 0)
- goto fail;
-
- append_payload_vec(&d, part->data, part->size);
- }
-
- if (m->header->type == SD_BUS_MESSAGE_SIGNAL) {
- struct kdbus_bloom_filter *bloom;
-
- bloom = append_bloom(&d, m->bus->bloom_size);
- r = bus_message_setup_bloom(m, bloom);
- if (r < 0)
- goto fail;
- }
-
- if (m->n_fds > 0)
- append_fds(&d, m->fds, m->n_fds);
-
- m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
- assert(m->kdbus->size <= sz);
-
- return 0;
-
-fail:
- m->poisoned = true;
- return r;
-}
-
-static void unset_memfds(struct sd_bus_message *m) {
- struct bus_body_part *part;
- unsigned i;
-
- assert(m);
-
- /* Make sure the memfds are not freed twice */
- MESSAGE_FOREACH_PART(part, i, m)
- if (part->memfd >= 0)
- part->memfd = -1;
-}
-
-static void message_set_timestamp(sd_bus *bus, sd_bus_message *m, const struct kdbus_timestamp *ts) {
- assert(bus);
- assert(m);
-
- if (!ts)
- return;
-
- if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP))
- return;
-
- m->realtime = ts->realtime_ns / NSEC_PER_USEC;
- m->monotonic = ts->monotonic_ns / NSEC_PER_USEC;
- m->seqnum = ts->seqnum;
-}
-
-static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
- sd_bus_message *m = NULL;
- struct kdbus_item *d;
- unsigned n_fds = 0;
- _cleanup_free_ int *fds = NULL;
- struct bus_header *header = NULL;
- void *footer = NULL;
- size_t header_size = 0, footer_size = 0;
- size_t n_bytes = 0, idx = 0;
- const char *destination = NULL, *seclabel = NULL;
- bool last_was_memfd = false;
- int r;
-
- assert(bus);
- assert(k);
- assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- size_t l;
-
- l = d->size - offsetof(struct kdbus_item, data);
-
- switch (d->type) {
-
- case KDBUS_ITEM_PAYLOAD_OFF:
- if (!header) {
- header = (struct bus_header*)((uint8_t*) k + d->vec.offset);
- header_size = d->vec.size;
- }
-
- footer = (uint8_t*) k + d->vec.offset;
- footer_size = d->vec.size;
-
- n_bytes += d->vec.size;
- last_was_memfd = false;
- break;
-
- case KDBUS_ITEM_PAYLOAD_MEMFD:
- if (!header) /* memfd cannot be first part */
- return -EBADMSG;
-
- n_bytes += d->memfd.size;
- last_was_memfd = true;
- break;
-
- case KDBUS_ITEM_FDS: {
- int *f;
- unsigned j;
-
- j = l / sizeof(int);
- f = realloc(fds, sizeof(int) * (n_fds + j));
- if (!f)
- return -ENOMEM;
-
- fds = f;
- memcpy(fds + n_fds, d->fds, sizeof(int) * j);
- n_fds += j;
- break;
- }
-
- case KDBUS_ITEM_SECLABEL:
- seclabel = d->str;
- break;
- }
- }
-
- if (last_was_memfd) /* memfd cannot be last part */
- return -EBADMSG;
-
- if (!header)
- return -EBADMSG;
-
- if (header_size < sizeof(struct bus_header))
- return -EBADMSG;
-
- /* on kdbus we only speak native endian gvariant, never dbus1
- * marshalling or reverse endian */
- if (header->version != 2 ||
- header->endian != BUS_NATIVE_ENDIAN)
- return -EPROTOTYPE;
-
- r = bus_message_from_header(
- bus,
- header, header_size,
- footer, footer_size,
- n_bytes,
- fds, n_fds,
- seclabel, 0, &m);
- if (r < 0)
- return r;
-
- /* The well-known names list is different from the other
- credentials. If we asked for it, but nothing is there, this
- means that the list of well-known names is simply empty, not
- that we lack any data */
-
- m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- size_t l;
-
- l = d->size - offsetof(struct kdbus_item, data);
-
- switch (d->type) {
-
- case KDBUS_ITEM_PAYLOAD_OFF: {
- size_t begin_body;
-
- begin_body = BUS_MESSAGE_BODY_BEGIN(m);
-
- if (idx + d->vec.size > begin_body) {
- struct bus_body_part *part;
-
- /* Contains body material */
-
- part = message_append_part(m);
- if (!part) {
- r = -ENOMEM;
- goto fail;
- }
-
- /* A -1 offset is NUL padding. */
- part->is_zero = d->vec.offset == ~0ULL;
-
- if (idx >= begin_body) {
- if (!part->is_zero)
- part->data = (uint8_t* )k + d->vec.offset;
- part->size = d->vec.size;
- } else {
- if (!part->is_zero)
- part->data = (uint8_t*) k + d->vec.offset + (begin_body - idx);
- part->size = d->vec.size - (begin_body - idx);
- }
-
- part->sealed = true;
- }
-
- idx += d->vec.size;
- break;
- }
-
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- struct bus_body_part *part;
-
- if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
- r = -EBADMSG;
- goto fail;
- }
-
- part = message_append_part(m);
- if (!part) {
- r = -ENOMEM;
- goto fail;
- }
-
- part->memfd = d->memfd.fd;
- part->memfd_offset = d->memfd.start;
- part->size = d->memfd.size;
- part->sealed = true;
-
- idx += d->memfd.size;
- break;
- }
-
- case KDBUS_ITEM_PIDS:
-
- /* The PID/TID might be missing, when the data
- * is faked by a bus proxy and it lacks that
- * information about the real client (since
- * SO_PEERCRED is used for that). Also kernel
- * namespacing might make some of this data
- * unavailable when untranslatable. */
-
- if (d->pids.pid > 0) {
- m->creds.pid = (pid_t) d->pids.pid;
- m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
- }
-
- if (d->pids.tid > 0) {
- m->creds.tid = (pid_t) d->pids.tid;
- m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
- }
-
- if (d->pids.ppid > 0) {
- m->creds.ppid = (pid_t) d->pids.ppid;
- m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
- } else if (d->pids.pid == 1) {
- m->creds.ppid = 0;
- m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
- }
-
- break;
-
- case KDBUS_ITEM_CREDS:
-
- /* EUID/SUID/FSUID/EGID/SGID/FSGID might be
- * missing too (see above). */
-
- if ((uid_t) d->creds.uid != UID_INVALID) {
- m->creds.uid = (uid_t) d->creds.uid;
- m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
- }
-
- if ((uid_t) d->creds.euid != UID_INVALID) {
- m->creds.euid = (uid_t) d->creds.euid;
- m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
- }
-
- if ((uid_t) d->creds.suid != UID_INVALID) {
- m->creds.suid = (uid_t) d->creds.suid;
- m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
- }
-
- if ((uid_t) d->creds.fsuid != UID_INVALID) {
- m->creds.fsuid = (uid_t) d->creds.fsuid;
- m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.gid != GID_INVALID) {
- m->creds.gid = (gid_t) d->creds.gid;
- m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.egid != GID_INVALID) {
- m->creds.egid = (gid_t) d->creds.egid;
- m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.sgid != GID_INVALID) {
- m->creds.sgid = (gid_t) d->creds.sgid;
- m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
- }
-
- if ((gid_t) d->creds.fsgid != GID_INVALID) {
- m->creds.fsgid = (gid_t) d->creds.fsgid;
- m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
- }
-
- break;
-
- case KDBUS_ITEM_TIMESTAMP:
- message_set_timestamp(bus, m, &d->timestamp);
- break;
-
- case KDBUS_ITEM_PID_COMM:
- m->creds.comm = d->str;
- m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_TID_COMM:
- m->creds.tid_comm = d->str;
- m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_EXE:
- m->creds.exe = d->str;
- m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_CMDLINE:
- m->creds.cmdline = d->str;
- m->creds.cmdline_size = l;
- m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_CGROUP:
- m->creds.cgroup = d->str;
- m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
-
- r = bus_get_root_path(bus);
- if (r < 0)
- goto fail;
-
- m->creds.cgroup_root = bus->cgroup_root;
- break;
-
- case KDBUS_ITEM_AUDIT:
- m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
- m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
-
- m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
- m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_CAPS:
- if (d->caps.last_cap != cap_last_cap() ||
- d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) {
- r = -EBADMSG;
- goto fail;
- }
-
- m->creds.capability = d->caps.caps;
- m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_DST_NAME:
- if (!service_name_is_valid(d->str)) {
- r = -EBADMSG;
- goto fail;
- }
-
- destination = d->str;
- break;
-
- case KDBUS_ITEM_OWNED_NAME:
- if (!service_name_is_valid(d->name.name)) {
- r = -EBADMSG;
- goto fail;
- }
-
- if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
- char **wkn;
- size_t n;
-
- /* We just extend the array here, but
- * do not allocate the strings inside
- * of it, instead we just point to our
- * buffer directly. */
- n = strv_length(m->creds.well_known_names);
- wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
- if (!wkn) {
- r = -ENOMEM;
- goto fail;
- }
-
- wkn[n] = d->name.name;
- wkn[n+1] = NULL;
- m->creds.well_known_names = wkn;
-
- m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
- }
- break;
-
- case KDBUS_ITEM_CONN_DESCRIPTION:
- m->creds.description = d->str;
- m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
- break;
-
- case KDBUS_ITEM_AUXGROUPS:
-
- if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
- size_t i, n;
- gid_t *g;
-
- n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
- g = new(gid_t, n);
- if (!g) {
- r = -ENOMEM;
- goto fail;
- }
-
- for (i = 0; i < n; i++)
- g[i] = d->data64[i];
-
- m->creds.supplementary_gids = g;
- m->creds.n_supplementary_gids = n;
- m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
- }
-
- break;
-
- case KDBUS_ITEM_FDS:
- case KDBUS_ITEM_SECLABEL:
- case KDBUS_ITEM_BLOOM_FILTER:
- break;
-
- default:
- log_debug("Got unknown field from kernel %llu", d->type);
- }
- }
-
- /* If we requested the list of well-known names to be appended
- * and the sender had none no item for it will be
- * attached. However, this does *not* mean that the kernel
- * didn't want to provide this information to us. Hence, let's
- * explicitly mark this information as available if it was
- * requested. */
- m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
-
- r = bus_message_parse_fields(m);
- if (r < 0)
- goto fail;
-
- /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
- if ((uint64_t) m->header->dbus2.cookie != k->cookie) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Refuse messages where the reply flag doesn't match up */
- if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Refuse reply messages where the reply cookie doesn't match up */
- if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Refuse messages where the autostart flag doesn't match up */
- if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) {
- r = -EBADMSG;
- goto fail;
- }
-
- /* Override information from the user header with data from the kernel */
- if (k->src_id == KDBUS_SRC_ID_KERNEL)
- bus_message_set_sender_driver(bus, m);
- else {
- xsprintf(m->sender_buffer, ":1.%llu",
- (unsigned long long)k->src_id);
- m->sender = m->creds.unique_name = m->sender_buffer;
- }
-
- if (destination)
- m->destination = destination;
- else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
- m->destination = NULL;
- else if (k->dst_id == KDBUS_DST_ID_NAME)
- m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
- else {
- xsprintf(m->destination_buffer, ":1.%llu",
- (unsigned long long)k->dst_id);
- m->destination = m->destination_buffer;
- }
-
- /* We take possession of the kmsg struct now */
- m->kdbus = k;
- m->release_kdbus = true;
- m->free_fds = true;
- fds = NULL;
-
- bus->rqueue[bus->rqueue_size++] = m;
-
- return 1;
-
-fail:
- unset_memfds(m);
- sd_bus_message_unref(m);
-
- return r;
-}
-
-int bus_kernel_take_fd(sd_bus *b) {
- struct kdbus_bloom_parameter *bloom = NULL;
- struct kdbus_item *items, *item;
- struct kdbus_cmd_hello *hello;
- _cleanup_free_ char *g = NULL;
- const char *name;
- size_t l = 0, m = 0, sz;
- int r;
-
- assert(b);
-
- if (b->is_server)
- return -EINVAL;
-
- b->use_memfd = 1;
-
- if (b->description) {
- g = bus_label_escape(b->description);
- if (!g)
- return -ENOMEM;
-
- name = g;
- } else {
- char pr[17] = {};
-
- /* If no name is explicitly set, we'll include a hint
- * indicating the library implementation, a hint which
- * kind of bus this is and the thread name */
-
- assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
-
- if (isempty(pr)) {
- name = b->is_system ? "sd-system" :
- b->is_user ? "sd-user" : "sd";
- } else {
- _cleanup_free_ char *e = NULL;
-
- e = bus_label_escape(pr);
- if (!e)
- return -ENOMEM;
-
- g = strappend(b->is_system ? "sd-system-" :
- b->is_user ? "sd-user-" : "sd-",
- e);
- if (!g)
- return -ENOMEM;
-
- name = g;
- }
-
- b->description = bus_label_unescape(name);
- if (!b->description)
- return -ENOMEM;
- }
-
- m = strlen(name);
-
- sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
- ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
-
- if (b->fake_creds_valid)
- sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
-
- if (b->fake_pids_valid)
- sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
-
- if (b->fake_label) {
- l = strlen(b->fake_label);
- sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
- }
-
- hello = alloca0_align(sz, 8);
- hello->size = sz;
- hello->flags = b->hello_flags;
- hello->attach_flags_send = _KDBUS_ATTACH_ANY;
- hello->attach_flags_recv = b->attach_flags;
- hello->pool_size = KDBUS_POOL_SIZE;
-
- item = hello->items;
-
- item->size = offsetof(struct kdbus_item, str) + m + 1;
- item->type = KDBUS_ITEM_CONN_DESCRIPTION;
- memcpy(item->str, name, m + 1);
- item = KDBUS_ITEM_NEXT(item);
-
- if (b->fake_creds_valid) {
- item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
- item->type = KDBUS_ITEM_CREDS;
- item->creds = b->fake_creds;
-
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (b->fake_pids_valid) {
- item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
- item->type = KDBUS_ITEM_PIDS;
- item->pids = b->fake_pids;
-
- item = KDBUS_ITEM_NEXT(item);
- }
-
- if (b->fake_label) {
- item->size = offsetof(struct kdbus_item, str) + l + 1;
- item->type = KDBUS_ITEM_SECLABEL;
- memcpy(item->str, b->fake_label, l+1);
- }
-
- r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
- if (r < 0) {
- if (errno == ENOTTY)
- /* If the ioctl is not supported we assume that the
- * API version changed in a major incompatible way,
- * let's indicate an API incompatibility in this
- * case. */
- return -ESOCKTNOSUPPORT;
-
- return -errno;
- }
-
- if (!b->kdbus_buffer) {
- b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
- if (b->kdbus_buffer == MAP_FAILED) {
- b->kdbus_buffer = NULL;
- r = -errno;
- goto fail;
- }
- }
-
- /* The higher 32bit of the bus_flags fields are considered
- * 'incompatible flags'. Refuse them all for now. */
- if (hello->bus_flags > 0xFFFFFFFFULL) {
- r = -ESOCKTNOSUPPORT;
- goto fail;
- }
-
- /* extract bloom parameters from items */
- items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset);
- KDBUS_FOREACH(item, items, hello->items_size) {
- switch (item->type) {
- case KDBUS_ITEM_BLOOM_PARAMETER:
- bloom = &item->bloom_parameter;
- break;
- }
- }
-
- if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
- r = -EOPNOTSUPP;
- goto fail;
- }
-
- b->bloom_size = (size_t) bloom->size;
- b->bloom_n_hash = (unsigned) bloom->n_hash;
-
- if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- b->unique_id = hello->id;
-
- b->is_kernel = true;
- b->bus_client = true;
- b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
- b->message_version = 2;
- b->message_endian = BUS_NATIVE_ENDIAN;
-
- /* the kernel told us the UUID of the underlying bus */
- memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
-
- /* free returned items */
- (void) bus_kernel_cmd_free(b, hello->offset);
- return bus_start_running(b);
-
-fail:
- (void) bus_kernel_cmd_free(b, hello->offset);
- return r;
-}
-
-int bus_kernel_connect(sd_bus *b) {
- assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->kernel);
-
- if (b->is_server)
- return -EINVAL;
-
- b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (b->input_fd < 0)
- return -errno;
-
- b->output_fd = b->input_fd;
-
- return bus_kernel_take_fd(b);
-}
-
-int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
- struct kdbus_cmd_free cmd = {
- .size = sizeof(cmd),
- .offset = offset,
- };
- int r;
-
- assert(bus);
- assert(bus->is_kernel);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
- if (r < 0)
- return -errno;
-
- return 0;
-}
-
-static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
- struct kdbus_item *d;
-
- assert(bus);
- assert(k);
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- if (d->type == KDBUS_ITEM_FDS)
- close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
- else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
- safe_close(d->memfd.fd);
- }
-
- bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
-}
-
-int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
- struct kdbus_cmd_send cmd = { };
- int r;
-
- assert(bus);
- assert(m);
- assert(bus->state == BUS_RUNNING);
-
- /* If we can't deliver, we want room for the error message */
- r = bus_rqueue_make_room(bus);
- if (r < 0)
- return r;
-
- r = bus_message_setup_kmsg(bus, m);
- if (r < 0)
- return r;
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)m->kdbus;
-
- /* If this is a synchronous method call, then let's tell the
- * kernel, so that it can pass CPU time/scheduling to the
- * destination for the time, if it wants to. If we
- * synchronously wait for the result anyway, we won't need CPU
- * anyway. */
- if (hint_sync_call) {
- m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY;
- cmd.flags |= KDBUS_SEND_SYNC_REPLY;
- }
-
- r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
- if (r < 0) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- sd_bus_message *reply;
-
- if (errno == EAGAIN || errno == EINTR)
- return 0;
- else if (errno == ENXIO || errno == ESRCH) {
-
- /* ENXIO: unique name not known
- * ESRCH: well-known name not known */
-
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
- else {
- log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
- return 0;
- }
-
- } else if (errno == EADDRNOTAVAIL) {
-
- /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
-
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
- sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
- else {
- log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
- return 0;
- }
- } else
- return -errno;
-
- r = bus_message_new_synthetic_error(
- bus,
- BUS_MESSAGE_COOKIE(m),
- &error,
- &reply);
-
- if (r < 0)
- return r;
-
- r = bus_seal_synthetic_message(bus, reply);
- if (r < 0)
- return r;
-
- bus->rqueue[bus->rqueue_size++] = reply;
-
- } else if (hint_sync_call) {
- struct kdbus_msg *k;
-
- k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset);
- assert(k);
-
- if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
-
- r = bus_kernel_make_message(bus, k);
- if (r < 0) {
- close_kdbus_msg(bus, k);
-
- /* Anybody can send us invalid messages, let's just drop them. */
- if (r == -EBADMSG || r == -EPROTOTYPE)
- log_debug_errno(r, "Ignoring invalid synchronous reply: %m");
- else
- return r;
- }
- } else {
- log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
- close_kdbus_msg(bus, k);
- }
- }
-
- return 1;
-}
-
-static int push_name_owner_changed(
- sd_bus *bus,
- const char *name,
- const char *old_owner,
- const char *new_owner,
- const struct kdbus_timestamp *ts) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(bus);
-
- r = sd_bus_message_new_signal(
- bus,
- &m,
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "NameOwnerChanged");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
- if (r < 0)
- return r;
-
- bus_message_set_sender_driver(bus, m);
- message_set_timestamp(bus, m, ts);
-
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
-
- bus->rqueue[bus->rqueue_size++] = m;
- m = NULL;
-
- return 1;
-}
-
-static int translate_name_change(
- sd_bus *bus,
- const struct kdbus_msg *k,
- const struct kdbus_item *d,
- const struct kdbus_timestamp *ts) {
-
- char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
-
- assert(bus);
- assert(k);
- assert(d);
-
- if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
- old_owner[0] = 0;
- else
- sprintf(old_owner, ":1.%llu", (unsigned long long) d->name_change.old_id.id);
-
- if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
-
- if (isempty(old_owner))
- return 0;
-
- new_owner[0] = 0;
- } else
- sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id);
-
- return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts);
-}
-
-static int translate_id_change(
- sd_bus *bus,
- const struct kdbus_msg *k,
- const struct kdbus_item *d,
- const struct kdbus_timestamp *ts) {
-
- char owner[UNIQUE_NAME_MAX];
-
- assert(bus);
- assert(k);
- assert(d);
-
- sprintf(owner, ":1.%llu", d->id_change.id);
-
- return push_name_owner_changed(
- bus, owner,
- d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
- d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
- ts);
-}
-
-static int translate_reply(
- sd_bus *bus,
- const struct kdbus_msg *k,
- const struct kdbus_item *d,
- const struct kdbus_timestamp *ts) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(bus);
- assert(k);
- assert(d);
-
- r = bus_message_new_synthetic_error(
- bus,
- k->cookie_reply,
- d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
- &m);
- if (r < 0)
- return r;
-
- message_set_timestamp(bus, m, ts);
-
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
-
- bus->rqueue[bus->rqueue_size++] = m;
- m = NULL;
-
- return 1;
-}
-
-static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
- static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = {
- [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
- [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
- [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
-
- [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
- [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
-
- [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
- [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
- };
-
- struct kdbus_item *d, *found = NULL;
- struct kdbus_timestamp *ts = NULL;
-
- assert(bus);
- assert(k);
- assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
-
- KDBUS_ITEM_FOREACH(d, k, items) {
- if (d->type == KDBUS_ITEM_TIMESTAMP)
- ts = &d->timestamp;
- else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
- if (found)
- return -EBADMSG;
- found = d;
- } else
- log_debug("Got unknown field from kernel %llu", d->type);
- }
-
- if (!found) {
- log_debug("Didn't find a kernel message to translate.");
- return 0;
- }
-
- return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts);
-}
-
-int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
- struct kdbus_msg *k;
- int r;
-
- assert(bus);
-
- r = bus_rqueue_make_room(bus);
- if (r < 0)
- return r;
-
- if (hint_priority) {
- recv.flags |= KDBUS_RECV_USE_PRIORITY;
- recv.priority = priority;
- }
-
- r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv);
- if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS)
- log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
- if (r < 0) {
- if (errno == EAGAIN)
- return 0;
-
- return -errno;
- }
-
- k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset);
- if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
- r = bus_kernel_make_message(bus, k);
-
- /* Anybody can send us invalid messages, let's just drop them. */
- if (r == -EBADMSG || r == -EPROTOTYPE) {
- log_debug_errno(r, "Ignoring invalid message: %m");
- r = 0;
- }
-
- if (r <= 0)
- close_kdbus_msg(bus, k);
- } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) {
- r = bus_kernel_translate_message(bus, k);
- close_kdbus_msg(bus, k);
- } else {
- log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
- r = 0;
- close_kdbus_msg(bus, k);
- }
-
- return r < 0 ? r : 1;
-}
-
-int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
- struct memfd_cache *c;
- int fd;
-
- assert(address);
- assert(mapped);
- assert(allocated);
-
- if (!bus || !bus->is_kernel)
- return -EOPNOTSUPP;
-
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
-
- if (bus->n_memfd_cache <= 0) {
- int r;
-
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-
- r = memfd_new(bus->description);
- if (r < 0)
- return r;
-
- *address = NULL;
- *mapped = 0;
- *allocated = 0;
- return r;
- }
-
- c = &bus->memfd_cache[--bus->n_memfd_cache];
-
- assert(c->fd >= 0);
- assert(c->mapped == 0 || c->address);
-
- *address = c->address;
- *mapped = c->mapped;
- *allocated = c->allocated;
- fd = c->fd;
-
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-
- return fd;
-}
-
-static void close_and_munmap(int fd, void *address, size_t size) {
- if (size > 0)
- assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
-
- safe_close(fd);
-}
-
-void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated) {
- struct memfd_cache *c;
- uint64_t max_mapped = PAGE_ALIGN(MEMFD_CACHE_ITEM_SIZE_MAX);
-
- assert(fd >= 0);
- assert(mapped == 0 || address);
-
- if (!bus || !bus->is_kernel) {
- close_and_munmap(fd, address, mapped);
- return;
- }
-
- assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
-
- if (bus->n_memfd_cache >= ELEMENTSOF(bus->memfd_cache)) {
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-
- close_and_munmap(fd, address, mapped);
- return;
- }
-
- c = &bus->memfd_cache[bus->n_memfd_cache++];
- c->fd = fd;
- c->address = address;
-
- /* If overly long, let's return a bit to the OS */
- if (mapped > max_mapped) {
- assert_se(memfd_set_size(fd, max_mapped) >= 0);
- assert_se(munmap((uint8_t*) address + max_mapped, PAGE_ALIGN(mapped - max_mapped)) >= 0);
- c->mapped = c->allocated = max_mapped;
- } else {
- c->mapped = mapped;
- c->allocated = allocated;
- }
-
- assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
-}
-
-void bus_kernel_flush_memfd(sd_bus *b) {
- unsigned i;
-
- assert(b);
-
- for (i = 0; i < b->n_memfd_cache; i++)
- close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
-}
-
-uint64_t request_name_flags_to_kdbus(uint64_t flags) {
- uint64_t f = 0;
-
- if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
- f |= KDBUS_NAME_ALLOW_REPLACEMENT;
-
- if (flags & SD_BUS_NAME_REPLACE_EXISTING)
- f |= KDBUS_NAME_REPLACE_EXISTING;
-
- if (flags & SD_BUS_NAME_QUEUE)
- f |= KDBUS_NAME_QUEUE;
-
- return f;
-}
-
-uint64_t attach_flags_to_kdbus(uint64_t mask) {
- uint64_t m = 0;
-
- if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
- SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
- m |= KDBUS_ATTACH_CREDS;
-
- if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID))
- m |= KDBUS_ATTACH_PIDS;
-
- if (mask & SD_BUS_CREDS_COMM)
- m |= KDBUS_ATTACH_PID_COMM;
-
- if (mask & SD_BUS_CREDS_TID_COMM)
- m |= KDBUS_ATTACH_TID_COMM;
-
- if (mask & SD_BUS_CREDS_EXE)
- m |= KDBUS_ATTACH_EXE;
-
- if (mask & SD_BUS_CREDS_CMDLINE)
- m |= KDBUS_ATTACH_CMDLINE;
-
- if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
- m |= KDBUS_ATTACH_CGROUP;
-
- if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
- m |= KDBUS_ATTACH_CAPS;
-
- if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
- m |= KDBUS_ATTACH_SECLABEL;
-
- if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
- m |= KDBUS_ATTACH_AUDIT;
-
- if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
- m |= KDBUS_ATTACH_NAMES;
-
- if (mask & SD_BUS_CREDS_DESCRIPTION)
- m |= KDBUS_ATTACH_CONN_DESCRIPTION;
-
- if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
- m |= KDBUS_ATTACH_AUXGROUPS;
-
- return m;
-}
-
-int bus_kernel_create_bus(const char *name, bool world, char **s) {
- struct kdbus_cmd *make;
- struct kdbus_item *n;
- size_t l;
- int fd;
-
- assert(name);
- assert(s);
-
- fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- l = strlen(name);
- make = alloca0_align(offsetof(struct kdbus_cmd, items) +
- ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
- ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
- ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
- 8);
-
- make->size = offsetof(struct kdbus_cmd, items);
-
- /* Set the bloom parameters */
- n = make->items;
- n->size = offsetof(struct kdbus_item, bloom_parameter) +
- sizeof(struct kdbus_bloom_parameter);
- n->type = KDBUS_ITEM_BLOOM_PARAMETER;
- n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
- n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
-
- assert_cc(DEFAULT_BLOOM_SIZE > 0);
- assert_cc(DEFAULT_BLOOM_N_HASH > 0);
-
- make->size += ALIGN8(n->size);
-
- /* Provide all metadata via bus-owner queries */
- n = KDBUS_ITEM_NEXT(n);
- n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
- n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
- n->data64[0] = _KDBUS_ATTACH_ANY;
- make->size += ALIGN8(n->size);
-
- /* Set the a good name */
- n = KDBUS_ITEM_NEXT(n);
- sprintf(n->str, UID_FMT "-%s", getuid(), name);
- n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
- n->type = KDBUS_ITEM_MAKE_NAME;
- make->size += ALIGN8(n->size);
-
- make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
-
- if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
- safe_close(fd);
-
- /* Major API change? then the ioctls got shuffled around. */
- if (errno == ENOTTY)
- return -ESOCKTNOSUPPORT;
-
- return -errno;
- }
-
- if (s) {
- char *p;
-
- p = strjoin("/sys/fs/kdbus/", n->str, "/bus", NULL);
- if (!p) {
- safe_close(fd);
- return -ENOMEM;
- }
-
- *s = p;
- }
-
- return fd;
-}
-
-int bus_kernel_open_bus_fd(const char *bus, char **path) {
- char *p;
- int fd;
- size_t len;
-
- assert(bus);
-
- len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
-
- if (path) {
- p = new(char, len);
- if (!p)
- return -ENOMEM;
- } else
- p = newa(char, len);
-
- sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
-
- fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
- if (fd < 0) {
- if (path)
- free(p);
-
- return -errno;
- }
-
- if (path)
- *path = p;
-
- return fd;
-}
-
-int bus_kernel_try_close(sd_bus *bus) {
- struct kdbus_cmd byebye = { .size = sizeof(byebye) };
-
- assert(bus);
- assert(bus->is_kernel);
-
- if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0)
- return -errno;
-
- return 0;
-}
-
-int bus_kernel_drop_one(int fd) {
- struct kdbus_cmd_recv recv = {
- .size = sizeof(recv),
- .flags = KDBUS_RECV_DROP,
- };
-
- assert(fd >= 0);
-
- if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0)
- return -errno;
-
- return 0;
-}
-
-int bus_kernel_realize_attach_flags(sd_bus *bus) {
- struct kdbus_cmd *update;
- struct kdbus_item *n;
-
- assert(bus);
- assert(bus->is_kernel);
-
- update = alloca0_align(offsetof(struct kdbus_cmd, items) +
- ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
- 8);
-
- n = update->items;
- n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
- n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
- n->data64[0] = bus->attach_flags;
-
- update->size =
- offsetof(struct kdbus_cmd, items) +
- ALIGN8(n->size);
-
- if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0)
- return -errno;
-
- return 0;
-}
-
-int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
- struct kdbus_cmd_info cmd = {
- .size = sizeof(struct kdbus_cmd_info),
- };
- struct kdbus_info *info;
- struct kdbus_item *item;
- char *n = NULL;
- int r;
-
- assert(bus);
- assert(name);
- assert(bus->is_kernel);
-
- r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
- if (r < 0)
- return -errno;
-
- info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
-
- KDBUS_ITEM_FOREACH(item, info, items)
- if (item->type == KDBUS_ITEM_MAKE_NAME) {
- r = free_and_strdup(&n, item->str);
- break;
- }
-
- bus_kernel_cmd_free(bus, cmd.offset);
-
- if (r < 0)
- return r;
- if (!n)
- return -EIO;
-
- *name = n;
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h
deleted file mode 100644
index 53ba3bdcf3..0000000000
--- a/src/libsystemd/sd-bus/bus-kernel.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include "sd-bus.h"
-
-#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))
-
-#define KDBUS_ITEM_FOREACH(part, head, first) \
- for (part = (head)->first; \
- ((uint8_t *)(part) < (uint8_t *)(head) + (head)->size) && \
- ((uint8_t *) part >= (uint8_t *) head); \
- part = KDBUS_ITEM_NEXT(part))
-#define KDBUS_FOREACH(iter, first, _size) \
- for (iter = (first); \
- ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
- ((uint8_t *)(iter) >= (uint8_t *)(first)); \
- iter = (void*)(((uint8_t *)iter) + ALIGN8((iter)->size)))
-
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(s) ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
-
-#define MEMFD_CACHE_MAX 32
-
-/* When we cache a memfd block for reuse, we will truncate blocks
- * longer than this in order not to keep too much data around. */
-#define MEMFD_CACHE_ITEM_SIZE_MAX (128*1024)
-
-/* This determines at which minimum size we prefer sending memfds over
- * sending vectors */
-#define MEMFD_MIN_SIZE (512*1024)
-
-/* The size of the per-connection memory pool that we set up and where
- * the kernel places our incoming messages */
-#define KDBUS_POOL_SIZE (16*1024*1024)
-
-struct memfd_cache {
- int fd;
- void *address;
- size_t mapped;
- size_t allocated;
-};
-
-int bus_kernel_connect(sd_bus *b);
-int bus_kernel_take_fd(sd_bus *b);
-
-int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call);
-int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority);
-
-int bus_kernel_open_bus_fd(const char *bus, char **path);
-
-int bus_kernel_create_bus(const char *name, bool world, char **s);
-int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **path);
-
-int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated);
-void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated);
-
-void bus_kernel_flush_memfd(sd_bus *bus);
-
-int bus_kernel_parse_unique_name(const char *s, uint64_t *id);
-
-uint64_t request_name_flags_to_kdbus(uint64_t sd_bus_flags);
-uint64_t attach_flags_to_kdbus(uint64_t sd_bus_flags);
-
-int bus_kernel_try_close(sd_bus *bus);
-
-int bus_kernel_drop_one(int fd);
-
-int bus_kernel_realize_attach_flags(sd_bus *bus);
-
-int bus_kernel_get_bus_name(sd_bus *bus, char **name);
-
-int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset);
diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c
deleted file mode 100644
index db01f21135..0000000000
--- a/src/libsystemd/sd-bus/bus-match.c
+++ /dev/null
@@ -1,1221 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-match.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "fd-util.h"
-#include "fileio.h"
-#include "hexdecoct.h"
-#include "string-util.h"
-#include "strv.h"
-
-/* Example:
- *
- * A: type=signal,sender=foo,interface=bar
- * B: type=signal,sender=quux,interface=fips
- * C: type=signal,sender=quux,interface=waldo
- * D: type=signal,member=test
- * E: sender=miau
- * F: type=signal
- * G: type=signal
- *
- * results in this tree:
- *
- * BUS_MATCH_ROOT
- * + BUS_MATCH_MESSAGE_TYPE
- * | ` BUS_MATCH_VALUE: value == signal
- * | + DBUS_MATCH_SENDER
- * | | + BUS_MATCH_VALUE: value == foo
- * | | | ` DBUS_MATCH_INTERFACE
- * | | | ` BUS_MATCH_VALUE: value == bar
- * | | | ` BUS_MATCH_LEAF: A
- * | | ` BUS_MATCH_VALUE: value == quux
- * | | ` DBUS_MATCH_INTERFACE
- * | | | BUS_MATCH_VALUE: value == fips
- * | | | ` BUS_MATCH_LEAF: B
- * | | ` BUS_MATCH_VALUE: value == waldo
- * | | ` BUS_MATCH_LEAF: C
- * | + DBUS_MATCH_MEMBER
- * | | ` BUS_MATCH_VALUE: value == test
- * | | ` BUS_MATCH_LEAF: D
- * | + BUS_MATCH_LEAF: F
- * | ` BUS_MATCH_LEAF: G
- * ` BUS_MATCH_SENDER
- * ` BUS_MATCH_VALUE: value == miau
- * ` BUS_MATCH_LEAF: E
- */
-
-static inline bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) {
- return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_HAS_LAST;
-}
-
-static inline bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) {
- return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) ||
- (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST) ||
- (t >= BUS_MATCH_ARG_HAS && t <= BUS_MATCH_ARG_HAS_LAST);
-}
-
-static void bus_match_node_free(struct bus_match_node *node) {
- assert(node);
- assert(node->parent);
- assert(!node->child);
- assert(node->type != BUS_MATCH_ROOT);
- assert(node->type < _BUS_MATCH_NODE_TYPE_MAX);
-
- if (node->parent->child) {
- /* We are apparently linked into the parent's child
- * list. Let's remove us from there. */
- if (node->prev) {
- assert(node->prev->next == node);
- node->prev->next = node->next;
- } else {
- assert(node->parent->child == node);
- node->parent->child = node->next;
- }
-
- if (node->next)
- node->next->prev = node->prev;
- }
-
- if (node->type == BUS_MATCH_VALUE) {
- /* We might be in the parent's hash table, so clean
- * this up */
-
- if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
- hashmap_remove(node->parent->compare.children, UINT_TO_PTR(node->value.u8));
- else if (BUS_MATCH_CAN_HASH(node->parent->type) && node->value.str)
- hashmap_remove(node->parent->compare.children, node->value.str);
-
- free(node->value.str);
- }
-
- if (BUS_MATCH_IS_COMPARE(node->type)) {
- assert(hashmap_isempty(node->compare.children));
- hashmap_free(node->compare.children);
- }
-
- free(node);
-}
-
-static bool bus_match_node_maybe_free(struct bus_match_node *node) {
- assert(node);
-
- if (node->type == BUS_MATCH_ROOT)
- return false;
-
- if (node->child)
- return false;
-
- if (BUS_MATCH_IS_COMPARE(node->type) && !hashmap_isempty(node->compare.children))
- return true;
-
- bus_match_node_free(node);
- return true;
-}
-
-static bool value_node_test(
- struct bus_match_node *node,
- enum bus_match_node_type parent_type,
- uint8_t value_u8,
- const char *value_str,
- char **value_strv,
- sd_bus_message *m) {
-
- assert(node);
- assert(node->type == BUS_MATCH_VALUE);
-
- /* Tests parameters against this value node, doing prefix
- * magic and stuff. */
-
- switch (parent_type) {
-
- case BUS_MATCH_MESSAGE_TYPE:
- return node->value.u8 == value_u8;
-
- case BUS_MATCH_SENDER:
- if (streq_ptr(node->value.str, value_str))
- return true;
-
- if (m->creds.mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
- char **i;
-
- /* on kdbus we have the well known names list
- * in the credentials, let's make use of that
- * for an accurate match */
-
- STRV_FOREACH(i, m->creds.well_known_names)
- if (streq_ptr(node->value.str, *i))
- return true;
-
- } else {
-
- /* If we don't have kdbus, we don't know the
- * well-known names of the senders. In that,
- * let's just hope that dbus-daemon doesn't
- * send us stuff we didn't want. */
-
- if (node->value.str[0] != ':' && value_str && value_str[0] == ':')
- return true;
- }
-
- return false;
-
- case BUS_MATCH_DESTINATION:
- case BUS_MATCH_INTERFACE:
- case BUS_MATCH_MEMBER:
- case BUS_MATCH_PATH:
- case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
-
- if (value_str)
- return streq_ptr(node->value.str, value_str);
-
- return false;
-
- case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: {
- char **i;
-
- STRV_FOREACH(i, value_strv)
- if (streq_ptr(node->value.str, *i))
- return true;
-
- return false;
- }
-
- case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
- if (value_str)
- return namespace_simple_pattern(node->value.str, value_str);
-
- return false;
-
- case BUS_MATCH_PATH_NAMESPACE:
- return path_simple_pattern(node->value.str, value_str);
-
- case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
- if (value_str)
- return path_complex_pattern(node->value.str, value_str);
-
- return false;
-
- default:
- assert_not_reached("Invalid node type");
- }
-}
-
-static bool value_node_same(
- struct bus_match_node *node,
- enum bus_match_node_type parent_type,
- uint8_t value_u8,
- const char *value_str) {
-
- /* Tests parameters against this value node, not doing prefix
- * magic and stuff, i.e. this one actually compares the match
- * itself. */
-
- assert(node);
- assert(node->type == BUS_MATCH_VALUE);
-
- switch (parent_type) {
-
- case BUS_MATCH_MESSAGE_TYPE:
- return node->value.u8 == value_u8;
-
- case BUS_MATCH_SENDER:
- case BUS_MATCH_DESTINATION:
- case BUS_MATCH_INTERFACE:
- case BUS_MATCH_MEMBER:
- case BUS_MATCH_PATH:
- case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
- case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
- case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
- case BUS_MATCH_PATH_NAMESPACE:
- case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
- return streq(node->value.str, value_str);
-
- default:
- assert_not_reached("Invalid node type");
- }
-}
-
-int bus_match_run(
- sd_bus *bus,
- struct bus_match_node *node,
- sd_bus_message *m) {
-
- _cleanup_strv_free_ char **test_strv = NULL;
- const char *test_str = NULL;
- uint8_t test_u8 = 0;
- int r;
-
- assert(m);
-
- if (!node)
- return 0;
-
- if (bus && bus->match_callbacks_modified)
- return 0;
-
- /* Not these special semantics: when traversing the tree we
- * usually let bus_match_run() when called for a node
- * recursively invoke bus_match_run(). There's are two
- * exceptions here though, which are BUS_NODE_ROOT (which
- * cannot have a sibling), and BUS_NODE_VALUE (whose siblings
- * are invoked anyway by its parent. */
-
- switch (node->type) {
-
- case BUS_MATCH_ROOT:
-
- /* Run all children. Since we cannot have any siblings
- * we won't call any. The children of the root node
- * are compares or leaves, they will automatically
- * call their siblings. */
- return bus_match_run(bus, node->child, m);
-
- case BUS_MATCH_VALUE:
-
- /* Run all children. We don't execute any siblings, we
- * assume our caller does that. The children of value
- * nodes are compares or leaves, they will
- * automatically call their siblings */
-
- assert(node->child);
- return bus_match_run(bus, node->child, m);
-
- case BUS_MATCH_LEAF:
-
- if (bus) {
- if (node->leaf.callback->last_iteration == bus->iteration_counter)
- return 0;
-
- node->leaf.callback->last_iteration = bus->iteration_counter;
- }
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- /* Run the callback. And then invoke siblings. */
- if (node->leaf.callback->callback) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- sd_bus_slot *slot;
-
- slot = container_of(node->leaf.callback, sd_bus_slot, match_callback);
- if (bus) {
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = node->leaf.callback->callback;
- bus->current_userdata = slot->userdata;
- }
- r = node->leaf.callback->callback(m, slot->userdata, &error_buffer);
- if (bus) {
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = sd_bus_slot_unref(slot);
- }
-
- r = bus_maybe_reply_error(m, r, &error_buffer);
- if (r != 0)
- return r;
-
- if (bus && bus->match_callbacks_modified)
- return 0;
- }
-
- return bus_match_run(bus, node->next, m);
-
- case BUS_MATCH_MESSAGE_TYPE:
- test_u8 = m->header->type;
- break;
-
- case BUS_MATCH_SENDER:
- test_str = m->sender;
- /* FIXME: resolve test_str from a well-known to a unique name first */
- break;
-
- case BUS_MATCH_DESTINATION:
- test_str = m->destination;
- break;
-
- case BUS_MATCH_INTERFACE:
- test_str = m->interface;
- break;
-
- case BUS_MATCH_MEMBER:
- test_str = m->member;
- break;
-
- case BUS_MATCH_PATH:
- case BUS_MATCH_PATH_NAMESPACE:
- test_str = m->path;
- break;
-
- case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
- (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str);
- break;
-
- case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
- (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str);
- break;
-
- case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
- (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str);
- break;
-
- case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
- (void) bus_message_get_arg_strv(m, node->type - BUS_MATCH_ARG_HAS, &test_strv);
- break;
-
- default:
- assert_not_reached("Unknown match type.");
- }
-
- if (BUS_MATCH_CAN_HASH(node->type)) {
- struct bus_match_node *found;
-
- /* Lookup via hash table, nice! So let's jump directly. */
-
- if (test_str)
- found = hashmap_get(node->compare.children, test_str);
- else if (test_strv) {
- char **i;
-
- STRV_FOREACH(i, test_strv) {
- found = hashmap_get(node->compare.children, *i);
- if (found) {
- r = bus_match_run(bus, found, m);
- if (r != 0)
- return r;
- }
- }
-
- found = NULL;
- } else if (node->type == BUS_MATCH_MESSAGE_TYPE)
- found = hashmap_get(node->compare.children, UINT_TO_PTR(test_u8));
- else
- found = NULL;
-
- if (found) {
- r = bus_match_run(bus, found, m);
- if (r != 0)
- return r;
- }
- } else {
- struct bus_match_node *c;
-
- /* No hash table, so let's iterate manually... */
-
- for (c = node->child; c; c = c->next) {
- if (!value_node_test(c, node->type, test_u8, test_str, test_strv, m))
- continue;
-
- r = bus_match_run(bus, c, m);
- if (r != 0)
- return r;
-
- if (bus && bus->match_callbacks_modified)
- return 0;
- }
- }
-
- if (bus && bus->match_callbacks_modified)
- return 0;
-
- /* And now, let's invoke our siblings */
- return bus_match_run(bus, node->next, m);
-}
-
-static int bus_match_add_compare_value(
- struct bus_match_node *where,
- enum bus_match_node_type t,
- uint8_t value_u8,
- const char *value_str,
- struct bus_match_node **ret) {
-
- struct bus_match_node *c = NULL, *n = NULL;
- int r;
-
- assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
- assert(BUS_MATCH_IS_COMPARE(t));
- assert(ret);
-
- for (c = where->child; c && c->type != t; c = c->next)
- ;
-
- if (c) {
- /* Comparison node already exists? Then let's see if
- * the value node exists too. */
-
- if (t == BUS_MATCH_MESSAGE_TYPE)
- n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
- else if (BUS_MATCH_CAN_HASH(t))
- n = hashmap_get(c->compare.children, value_str);
- else {
- for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
- ;
- }
-
- if (n) {
- *ret = n;
- return 0;
- }
- } else {
- /* Comparison node, doesn't exist yet? Then let's
- * create it. */
-
- c = new0(struct bus_match_node, 1);
- if (!c) {
- r = -ENOMEM;
- goto fail;
- }
-
- c->type = t;
- c->parent = where;
- c->next = where->child;
- if (c->next)
- c->next->prev = c;
- where->child = c;
-
- if (t == BUS_MATCH_MESSAGE_TYPE) {
- c->compare.children = hashmap_new(NULL);
- if (!c->compare.children) {
- r = -ENOMEM;
- goto fail;
- }
- } else if (BUS_MATCH_CAN_HASH(t)) {
- c->compare.children = hashmap_new(&string_hash_ops);
- if (!c->compare.children) {
- r = -ENOMEM;
- goto fail;
- }
- }
- }
-
- n = new0(struct bus_match_node, 1);
- if (!n) {
- r = -ENOMEM;
- goto fail;
- }
-
- n->type = BUS_MATCH_VALUE;
- n->value.u8 = value_u8;
- if (value_str) {
- n->value.str = strdup(value_str);
- if (!n->value.str) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- n->parent = c;
- if (c->compare.children) {
-
- if (t == BUS_MATCH_MESSAGE_TYPE)
- r = hashmap_put(c->compare.children, UINT_TO_PTR(value_u8), n);
- else
- r = hashmap_put(c->compare.children, n->value.str, n);
-
- if (r < 0)
- goto fail;
- } else {
- n->next = c->child;
- if (n->next)
- n->next->prev = n;
- c->child = n;
- }
-
- *ret = n;
- return 1;
-
-fail:
- if (c)
- bus_match_node_maybe_free(c);
-
- if (n) {
- free(n->value.str);
- free(n);
- }
-
- return r;
-}
-
-static int bus_match_find_compare_value(
- struct bus_match_node *where,
- enum bus_match_node_type t,
- uint8_t value_u8,
- const char *value_str,
- struct bus_match_node **ret) {
-
- struct bus_match_node *c, *n;
-
- assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
- assert(BUS_MATCH_IS_COMPARE(t));
- assert(ret);
-
- for (c = where->child; c && c->type != t; c = c->next)
- ;
-
- if (!c)
- return 0;
-
- if (t == BUS_MATCH_MESSAGE_TYPE)
- n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8));
- else if (BUS_MATCH_CAN_HASH(t))
- n = hashmap_get(c->compare.children, value_str);
- else {
- for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next)
- ;
- }
-
- if (n) {
- *ret = n;
- return 1;
- }
-
- return 0;
-}
-
-static int bus_match_add_leaf(
- struct bus_match_node *where,
- struct match_callback *callback) {
-
- struct bus_match_node *n;
-
- assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
- assert(callback);
-
- n = new0(struct bus_match_node, 1);
- if (!n)
- return -ENOMEM;
-
- n->type = BUS_MATCH_LEAF;
- n->parent = where;
- n->next = where->child;
- if (n->next)
- n->next->prev = n;
-
- n->leaf.callback = callback;
- callback->match_node = n;
-
- where->child = n;
-
- return 1;
-}
-
-static int bus_match_find_leaf(
- struct bus_match_node *where,
- sd_bus_message_handler_t callback,
- void *userdata,
- struct bus_match_node **ret) {
-
- struct bus_match_node *c;
-
- assert(where);
- assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
- assert(ret);
-
- for (c = where->child; c; c = c->next) {
- sd_bus_slot *s;
-
- s = container_of(c->leaf.callback, sd_bus_slot, match_callback);
-
- if (c->type == BUS_MATCH_LEAF &&
- c->leaf.callback->callback == callback &&
- s->userdata == userdata) {
- *ret = c;
- return 1;
- }
- }
-
- return 0;
-}
-
-enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) {
- assert(k);
-
- if (n == 4 && startswith(k, "type"))
- return BUS_MATCH_MESSAGE_TYPE;
- if (n == 6 && startswith(k, "sender"))
- return BUS_MATCH_SENDER;
- if (n == 11 && startswith(k, "destination"))
- return BUS_MATCH_DESTINATION;
- if (n == 9 && startswith(k, "interface"))
- return BUS_MATCH_INTERFACE;
- if (n == 6 && startswith(k, "member"))
- return BUS_MATCH_MEMBER;
- if (n == 4 && startswith(k, "path"))
- return BUS_MATCH_PATH;
- if (n == 14 && startswith(k, "path_namespace"))
- return BUS_MATCH_PATH_NAMESPACE;
-
- if (n == 4 && startswith(k, "arg")) {
- int j;
-
- j = undecchar(k[3]);
- if (j < 0)
- return -EINVAL;
-
- return BUS_MATCH_ARG + j;
- }
-
- if (n == 5 && startswith(k, "arg")) {
- int a, b;
- enum bus_match_node_type t;
-
- a = undecchar(k[3]);
- b = undecchar(k[4]);
- if (a <= 0 || b < 0)
- return -EINVAL;
-
- t = BUS_MATCH_ARG + a * 10 + b;
- if (t > BUS_MATCH_ARG_LAST)
- return -EINVAL;
-
- return t;
- }
-
- if (n == 8 && startswith(k, "arg") && startswith(k + 4, "path")) {
- int j;
-
- j = undecchar(k[3]);
- if (j < 0)
- return -EINVAL;
-
- return BUS_MATCH_ARG_PATH + j;
- }
-
- if (n == 9 && startswith(k, "arg") && startswith(k + 5, "path")) {
- enum bus_match_node_type t;
- int a, b;
-
- a = undecchar(k[3]);
- b = undecchar(k[4]);
- if (a <= 0 || b < 0)
- return -EINVAL;
-
- t = BUS_MATCH_ARG_PATH + a * 10 + b;
- if (t > BUS_MATCH_ARG_PATH_LAST)
- return -EINVAL;
-
- return t;
- }
-
- if (n == 13 && startswith(k, "arg") && startswith(k + 4, "namespace")) {
- int j;
-
- j = undecchar(k[3]);
- if (j < 0)
- return -EINVAL;
-
- return BUS_MATCH_ARG_NAMESPACE + j;
- }
-
- if (n == 14 && startswith(k, "arg") && startswith(k + 5, "namespace")) {
- enum bus_match_node_type t;
- int a, b;
-
- a = undecchar(k[3]);
- b = undecchar(k[4]);
- if (a <= 0 || b < 0)
- return -EINVAL;
-
- t = BUS_MATCH_ARG_NAMESPACE + a * 10 + b;
- if (t > BUS_MATCH_ARG_NAMESPACE_LAST)
- return -EINVAL;
-
- return t;
- }
-
- if (n == 7 && startswith(k, "arg") && startswith(k + 4, "has")) {
- int j;
-
- j = undecchar(k[3]);
- if (j < 0)
- return -EINVAL;
-
- return BUS_MATCH_ARG_HAS + j;
- }
-
- if (n == 8 && startswith(k, "arg") && startswith(k + 5, "has")) {
- enum bus_match_node_type t;
- int a, b;
-
- a = undecchar(k[3]);
- b = undecchar(k[4]);
- if (a <= 0 || b < 0)
- return -EINVAL;
-
- t = BUS_MATCH_ARG_HAS + a * 10 + b;
- if (t > BUS_MATCH_ARG_HAS_LAST)
- return -EINVAL;
-
- return t;
- }
-
- return -EINVAL;
-}
-
-static int match_component_compare(const void *a, const void *b) {
- const struct bus_match_component *x = a, *y = b;
-
- if (x->type < y->type)
- return -1;
- if (x->type > y->type)
- return 1;
-
- return 0;
-}
-
-void bus_match_parse_free(struct bus_match_component *components, unsigned n_components) {
- unsigned i;
-
- for (i = 0; i < n_components; i++)
- free(components[i].value_str);
-
- free(components);
-}
-
-int bus_match_parse(
- const char *match,
- struct bus_match_component **_components,
- unsigned *_n_components) {
-
- const char *p = match;
- struct bus_match_component *components = NULL;
- size_t components_allocated = 0;
- unsigned n_components = 0, i;
- _cleanup_free_ char *value = NULL;
- int r;
-
- assert(match);
- assert(_components);
- assert(_n_components);
-
- while (*p != 0) {
- const char *eq, *q;
- enum bus_match_node_type t;
- unsigned j = 0;
- size_t value_allocated = 0;
- bool escaped = false, quoted;
- uint8_t u;
-
- /* Avahi's match rules appear to include whitespace, skip over it */
- p += strspn(p, " ");
-
- eq = strchr(p, '=');
- if (!eq)
- return -EINVAL;
-
- t = bus_match_node_type_from_string(p, eq - p);
- if (t < 0)
- return -EINVAL;
-
- quoted = eq[1] == '\'';
-
- for (q = eq + 1 + quoted;; q++) {
-
- if (*q == 0) {
-
- if (quoted) {
- r = -EINVAL;
- goto fail;
- } else {
- if (value)
- value[j] = 0;
- break;
- }
- }
-
- if (!escaped) {
- if (*q == '\\') {
- escaped = true;
- continue;
- }
-
- if (quoted) {
- if (*q == '\'') {
- if (value)
- value[j] = 0;
- break;
- }
- } else {
- if (*q == ',') {
- if (value)
- value[j] = 0;
-
- break;
- }
- }
- }
-
- if (!GREEDY_REALLOC(value, value_allocated, j + 2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- value[j++] = *q;
- escaped = false;
- }
-
- if (!value) {
- value = strdup("");
- if (!value) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (t == BUS_MATCH_MESSAGE_TYPE) {
- r = bus_message_type_from_string(value, &u);
- if (r < 0)
- goto fail;
-
- value = mfree(value);
- } else
- u = 0;
-
- if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) {
- r = -ENOMEM;
- goto fail;
- }
-
- components[n_components].type = t;
- components[n_components].value_str = value;
- components[n_components].value_u8 = u;
- n_components++;
-
- value = NULL;
-
- if (q[quoted] == 0)
- break;
-
- if (q[quoted] != ',') {
- r = -EINVAL;
- goto fail;
- }
-
- p = q + 1 + quoted;
- }
-
- /* Order the whole thing, so that we always generate the same tree */
- qsort_safe(components, n_components, sizeof(struct bus_match_component), match_component_compare);
-
- /* Check for duplicates */
- for (i = 0; i+1 < n_components; i++)
- if (components[i].type == components[i+1].type) {
- r = -EINVAL;
- goto fail;
- }
-
- *_components = components;
- *_n_components = n_components;
-
- return 0;
-
-fail:
- bus_match_parse_free(components, n_components);
- return r;
-}
-
-char *bus_match_to_string(struct bus_match_component *components, unsigned n_components) {
- _cleanup_fclose_ FILE *f = NULL;
- char *buffer = NULL;
- size_t size = 0;
- unsigned i;
- int r;
-
- if (n_components <= 0)
- return strdup("");
-
- assert(components);
-
- f = open_memstream(&buffer, &size);
- if (!f)
- return NULL;
-
- for (i = 0; i < n_components; i++) {
- char buf[32];
-
- if (i != 0)
- fputc(',', f);
-
- fputs(bus_match_node_type_to_string(components[i].type, buf, sizeof(buf)), f);
- fputc('=', f);
- fputc('\'', f);
-
- if (components[i].type == BUS_MATCH_MESSAGE_TYPE)
- fputs(bus_message_type_to_string(components[i].value_u8), f);
- else
- fputs(components[i].value_str, f);
-
- fputc('\'', f);
- }
-
- r = fflush_and_check(f);
- if (r < 0)
- return NULL;
-
- return buffer;
-}
-
-int bus_match_add(
- struct bus_match_node *root,
- struct bus_match_component *components,
- unsigned n_components,
- struct match_callback *callback) {
-
- unsigned i;
- struct bus_match_node *n;
- int r;
-
- assert(root);
- assert(callback);
-
- n = root;
- for (i = 0; i < n_components; i++) {
- r = bus_match_add_compare_value(
- n, components[i].type,
- components[i].value_u8, components[i].value_str, &n);
- if (r < 0)
- return r;
- }
-
- return bus_match_add_leaf(n, callback);
-}
-
-int bus_match_remove(
- struct bus_match_node *root,
- struct match_callback *callback) {
-
- struct bus_match_node *node, *pp;
-
- assert(root);
- assert(callback);
-
- node = callback->match_node;
- if (!node)
- return 0;
-
- assert(node->type == BUS_MATCH_LEAF);
-
- callback->match_node = NULL;
-
- /* Free the leaf */
- pp = node->parent;
- bus_match_node_free(node);
-
- /* Prune the tree above */
- while (pp) {
- node = pp;
- pp = node->parent;
-
- if (!bus_match_node_maybe_free(node))
- break;
- }
-
- return 1;
-}
-
-int bus_match_find(
- struct bus_match_node *root,
- struct bus_match_component *components,
- unsigned n_components,
- sd_bus_message_handler_t callback,
- void *userdata,
- struct match_callback **ret) {
-
- struct bus_match_node *n, **gc;
- unsigned i;
- int r;
-
- assert(root);
- assert(ret);
-
- gc = newa(struct bus_match_node*, n_components);
-
- n = root;
- for (i = 0; i < n_components; i++) {
- r = bus_match_find_compare_value(
- n, components[i].type,
- components[i].value_u8, components[i].value_str,
- &n);
- if (r <= 0)
- return r;
-
- gc[i] = n;
- }
-
- r = bus_match_find_leaf(n, callback, userdata, &n);
- if (r <= 0)
- return r;
-
- *ret = n->leaf.callback;
- return 1;
-}
-
-void bus_match_free(struct bus_match_node *node) {
- struct bus_match_node *c;
-
- if (!node)
- return;
-
- if (BUS_MATCH_CAN_HASH(node->type)) {
- Iterator i;
-
- HASHMAP_FOREACH(c, node->compare.children, i)
- bus_match_free(c);
-
- assert(hashmap_isempty(node->compare.children));
- }
-
- while ((c = node->child))
- bus_match_free(c);
-
- if (node->type != BUS_MATCH_ROOT)
- bus_match_node_free(node);
-}
-
-const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l) {
- switch (t) {
-
- case BUS_MATCH_ROOT:
- return "root";
-
- case BUS_MATCH_VALUE:
- return "value";
-
- case BUS_MATCH_LEAF:
- return "leaf";
-
- case BUS_MATCH_MESSAGE_TYPE:
- return "type";
-
- case BUS_MATCH_SENDER:
- return "sender";
-
- case BUS_MATCH_DESTINATION:
- return "destination";
-
- case BUS_MATCH_INTERFACE:
- return "interface";
-
- case BUS_MATCH_MEMBER:
- return "member";
-
- case BUS_MATCH_PATH:
- return "path";
-
- case BUS_MATCH_PATH_NAMESPACE:
- return "path_namespace";
-
- case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST:
- snprintf(buf, l, "arg%i", t - BUS_MATCH_ARG);
- return buf;
-
- case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST:
- snprintf(buf, l, "arg%ipath", t - BUS_MATCH_ARG_PATH);
- return buf;
-
- case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST:
- snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE);
- return buf;
-
- case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST:
- snprintf(buf, l, "arg%ihas", t - BUS_MATCH_ARG_HAS);
- return buf;
-
- default:
- return NULL;
- }
-}
-
-void bus_match_dump(struct bus_match_node *node, unsigned level) {
- struct bus_match_node *c;
- _cleanup_free_ char *pfx = NULL;
- char buf[32];
-
- if (!node)
- return;
-
- pfx = strrep(" ", level);
- printf("%s[%s]", strempty(pfx), bus_match_node_type_to_string(node->type, buf, sizeof(buf)));
-
- if (node->type == BUS_MATCH_VALUE) {
- if (node->parent->type == BUS_MATCH_MESSAGE_TYPE)
- printf(" <%u>\n", node->value.u8);
- else
- printf(" <%s>\n", node->value.str);
- } else if (node->type == BUS_MATCH_ROOT)
- puts(" root");
- else if (node->type == BUS_MATCH_LEAF)
- printf(" %p/%p\n", node->leaf.callback->callback, container_of(node->leaf.callback, sd_bus_slot, match_callback)->userdata);
- else
- putchar('\n');
-
- if (BUS_MATCH_CAN_HASH(node->type)) {
- Iterator i;
-
- HASHMAP_FOREACH(c, node->compare.children, i)
- bus_match_dump(c, level + 1);
- }
-
- for (c = node->child; c; c = c->next)
- bus_match_dump(c, level + 1);
-}
-
-enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components) {
- bool found_driver = false;
- unsigned i;
-
- if (n_components <= 0)
- return BUS_MATCH_GENERIC;
-
- assert(components);
-
- /* Checks whether the specified match can only match the
- * pseudo-service for local messages, which we detect by
- * sender, interface or path. If a match is not restricted to
- * local messages, then we check if it only matches on the
- * driver. */
-
- for (i = 0; i < n_components; i++) {
- const struct bus_match_component *c = components + i;
-
- if (c->type == BUS_MATCH_SENDER) {
- if (streq_ptr(c->value_str, "org.freedesktop.DBus.Local"))
- return BUS_MATCH_LOCAL;
-
- if (streq_ptr(c->value_str, "org.freedesktop.DBus"))
- found_driver = true;
- }
-
- if (c->type == BUS_MATCH_INTERFACE && streq_ptr(c->value_str, "org.freedesktop.DBus.Local"))
- return BUS_MATCH_LOCAL;
-
- if (c->type == BUS_MATCH_PATH && streq_ptr(c->value_str, "/org/freedesktop/DBus/Local"))
- return BUS_MATCH_LOCAL;
- }
-
- return found_driver ? BUS_MATCH_DRIVER : BUS_MATCH_GENERIC;
-
-}
diff --git a/src/libsystemd/sd-bus/bus-match.h b/src/libsystemd/sd-bus/bus-match.h
deleted file mode 100644
index 8cbbb63b11..0000000000
--- a/src/libsystemd/sd-bus/bus-match.h
+++ /dev/null
@@ -1,100 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "hashmap.h"
-
-enum bus_match_node_type {
- BUS_MATCH_ROOT,
- BUS_MATCH_VALUE,
- BUS_MATCH_LEAF,
-
- /* The following are all different kinds of compare nodes */
- BUS_MATCH_SENDER,
- BUS_MATCH_MESSAGE_TYPE,
- BUS_MATCH_DESTINATION,
- BUS_MATCH_INTERFACE,
- BUS_MATCH_MEMBER,
- BUS_MATCH_PATH,
- BUS_MATCH_PATH_NAMESPACE,
- BUS_MATCH_ARG,
- BUS_MATCH_ARG_LAST = BUS_MATCH_ARG + 63,
- BUS_MATCH_ARG_PATH,
- BUS_MATCH_ARG_PATH_LAST = BUS_MATCH_ARG_PATH + 63,
- BUS_MATCH_ARG_NAMESPACE,
- BUS_MATCH_ARG_NAMESPACE_LAST = BUS_MATCH_ARG_NAMESPACE + 63,
- BUS_MATCH_ARG_HAS,
- BUS_MATCH_ARG_HAS_LAST = BUS_MATCH_ARG_HAS + 63,
- _BUS_MATCH_NODE_TYPE_MAX,
- _BUS_MATCH_NODE_TYPE_INVALID = -1
-};
-
-struct bus_match_node {
- enum bus_match_node_type type;
- struct bus_match_node *parent, *next, *prev, *child;
-
- union {
- struct {
- char *str;
- uint8_t u8;
- } value;
- struct {
- struct match_callback *callback;
- } leaf;
- struct {
- /* If this is set, then the child is NULL */
- Hashmap *children;
- } compare;
- };
-};
-
-struct bus_match_component {
- enum bus_match_node_type type;
- uint8_t value_u8;
- char *value_str;
-};
-
-enum bus_match_scope {
- BUS_MATCH_GENERIC,
- BUS_MATCH_LOCAL,
- BUS_MATCH_DRIVER,
-};
-
-int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m);
-
-int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback);
-int bus_match_remove(struct bus_match_node *root, struct match_callback *callback);
-
-int bus_match_find(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, struct match_callback **ret);
-
-void bus_match_free(struct bus_match_node *node);
-
-void bus_match_dump(struct bus_match_node *node, unsigned level);
-
-const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l);
-enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n);
-
-int bus_match_parse(const char *match, struct bus_match_component **_components, unsigned *_n_components);
-void bus_match_parse_free(struct bus_match_component *components, unsigned n_components);
-char *bus_match_to_string(struct bus_match_component *components, unsigned n_components);
-
-enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components);
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
deleted file mode 100644
index 5cec804e32..0000000000
--- a/src/libsystemd/sd-bus/bus-message.c
+++ /dev/null
@@ -1,5939 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-gvariant.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-signature.h"
-#include "bus-type.h"
-#include "bus-util.h"
-#include "fd-util.h"
-#include "io-util.h"
-#include "memfd-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "time-util.h"
-#include "utf8.h"
-#include "util.h"
-
-static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
-
-static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
-
- if (p == NULL)
- return NULL;
-
- if (old_base == new_base)
- return (void*) p;
-
- if ((uint8_t*) p < (uint8_t*) old_base)
- return (void*) p;
-
- if ((uint8_t*) p >= (uint8_t*) old_base + sz)
- return (void*) p;
-
- return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
-}
-
-static void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
- assert(m);
- assert(part);
-
- if (part->memfd >= 0) {
- /* If we can reuse the memfd, try that. For that it
- * can't be sealed yet. */
-
- if (!part->sealed) {
- assert(part->memfd_offset == 0);
- assert(part->data == part->mmap_begin);
- bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
- } else {
- if (part->mapped > 0)
- assert_se(munmap(part->mmap_begin, part->mapped) == 0);
-
- safe_close(part->memfd);
- }
-
- } else if (part->munmap_this)
- munmap(part->mmap_begin, part->mapped);
- else if (part->free_this)
- free(part->data);
-
- if (part != &m->body)
- free(part);
-}
-
-static void message_reset_parts(sd_bus_message *m) {
- struct bus_body_part *part;
-
- assert(m);
-
- part = &m->body;
- while (m->n_body_parts > 0) {
- struct bus_body_part *next = part->next;
- message_free_part(m, part);
- part = next;
- m->n_body_parts--;
- }
-
- m->body_end = NULL;
-
- m->cached_rindex_part = NULL;
- m->cached_rindex_part_begin = 0;
-}
-
-static void message_reset_containers(sd_bus_message *m) {
- unsigned i;
-
- assert(m);
-
- for (i = 0; i < m->n_containers; i++) {
- free(m->containers[i].signature);
- free(m->containers[i].offsets);
- }
-
- m->containers = mfree(m->containers);
-
- m->n_containers = m->containers_allocated = 0;
- m->root_container.index = 0;
-}
-
-static void message_free(sd_bus_message *m) {
- assert(m);
-
- if (m->free_header)
- free(m->header);
-
- message_reset_parts(m);
-
- if (m->release_kdbus)
- bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
-
- if (m->free_kdbus)
- free(m->kdbus);
-
- sd_bus_unref(m->bus);
-
- if (m->free_fds) {
- close_many(m->fds, m->n_fds);
- free(m->fds);
- }
-
- if (m->iovec != m->iovec_fixed)
- free(m->iovec);
-
- m->destination_ptr = mfree(m->destination_ptr);
- message_reset_containers(m);
- free(m->root_container.signature);
- free(m->root_container.offsets);
-
- free(m->root_container.peeked_signature);
-
- bus_creds_done(&m->creds);
- free(m);
-}
-
-static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
- void *op, *np;
- size_t old_size, new_size, start;
-
- assert(m);
-
- if (m->poisoned)
- return NULL;
-
- old_size = sizeof(struct bus_header) + m->fields_size;
- start = ALIGN_TO(old_size, align);
- new_size = start + sz;
-
- if (new_size < start ||
- new_size > (size_t) ((uint32_t) -1))
- goto poison;
-
- if (old_size == new_size)
- return (uint8_t*) m->header + old_size;
-
- if (m->free_header) {
- np = realloc(m->header, ALIGN8(new_size));
- if (!np)
- goto poison;
- } else {
- /* Initially, the header is allocated as part of
- * the sd_bus_message itself, let's replace it by
- * dynamic data */
-
- np = malloc(ALIGN8(new_size));
- if (!np)
- goto poison;
-
- memcpy(np, m->header, sizeof(struct bus_header));
- }
-
- /* Zero out padding */
- if (start > old_size)
- memzero((uint8_t*) np + old_size, start - old_size);
-
- op = m->header;
- m->header = np;
- m->fields_size = new_size - sizeof(struct bus_header);
-
- /* Adjust quick access pointers */
- m->path = adjust_pointer(m->path, op, old_size, m->header);
- m->interface = adjust_pointer(m->interface, op, old_size, m->header);
- m->member = adjust_pointer(m->member, op, old_size, m->header);
- m->destination = adjust_pointer(m->destination, op, old_size, m->header);
- m->sender = adjust_pointer(m->sender, op, old_size, m->header);
- m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
-
- m->free_header = true;
-
- if (add_offset) {
- if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
- goto poison;
-
- m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
- }
-
- return (uint8_t*) np + start;
-
-poison:
- m->poisoned = true;
- return NULL;
-}
-
-static int message_append_field_string(
- sd_bus_message *m,
- uint64_t h,
- char type,
- const char *s,
- const char **ret) {
-
- size_t l;
- uint8_t *p;
-
- assert(m);
-
- /* dbus1 only allows 8bit header field ids */
- if (h > 0xFF)
- return -EINVAL;
-
- /* dbus1 doesn't allow strings over 32bit, let's enforce this
- * globally, to not risk convertability */
- l = strlen(s);
- if (l > (size_t) (uint32_t) -1)
- return -EINVAL;
-
- /* Signature "(yv)" where the variant contains "s" */
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */
- p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true);
- if (!p)
- return -ENOMEM;
-
- *((uint64_t*) p) = h;
- memcpy(p+8, s, l);
- p[8+l] = 0;
- p[8+l+1] = 0;
- p[8+l+2] = type;
-
- if (ret)
- *ret = (char*) p + 8;
-
- } else {
- /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
- p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
- if (!p)
- return -ENOMEM;
-
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = type;
- p[3] = 0;
-
- ((uint32_t*) p)[1] = l;
- memcpy(p + 8, s, l + 1);
-
- if (ret)
- *ret = (char*) p + 8;
- }
-
- return 0;
-}
-
-static int message_append_field_signature(
- sd_bus_message *m,
- uint64_t h,
- const char *s,
- const char **ret) {
-
- size_t l;
- uint8_t *p;
-
- assert(m);
-
- /* dbus1 only allows 8bit header field ids */
- if (h > 0xFF)
- return -EINVAL;
-
- /* dbus1 doesn't allow signatures over 8bit, let's enforce
- * this globally, to not risk convertability */
- l = strlen(s);
- if (l > 255)
- return -EINVAL;
-
- /* Signature "(yv)" where the variant contains "g" */
-
- if (BUS_MESSAGE_IS_GVARIANT(m))
- /* For gvariant the serialization is the same as for normal strings */
- return message_append_field_string(m, h, 'g', s, ret);
- else {
- /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */
- p = message_extend_fields(m, 8, 4 + 1 + l + 1, false);
- if (!p)
- return -ENOMEM;
-
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = SD_BUS_TYPE_SIGNATURE;
- p[3] = 0;
- p[4] = l;
- memcpy(p + 5, s, l + 1);
-
- if (ret)
- *ret = (const char*) p + 5;
- }
-
- return 0;
-}
-
-static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) {
- uint8_t *p;
-
- assert(m);
-
- /* dbus1 only allows 8bit header field ids */
- if (h > 0xFF)
- return -EINVAL;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* (field id 64bit + ((value + NUL + signature string 'u') */
-
- p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true);
- if (!p)
- return -ENOMEM;
-
- *((uint64_t*) p) = h;
- *((uint32_t*) (p + 8)) = x;
- p[12] = 0;
- p[13] = 'u';
- } else {
- /* (field id byte + (signature length + signature 'u' + NUL) + value) */
- p = message_extend_fields(m, 8, 4 + 4, false);
- if (!p)
- return -ENOMEM;
-
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = 'u';
- p[3] = 0;
-
- ((uint32_t*) p)[1] = x;
- }
-
- return 0;
-}
-
-static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) {
- uint8_t *p;
-
- assert(m);
-
- /* dbus1 only allows 8bit header field ids */
- if (h > 0xFF)
- return -EINVAL;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* (field id 64bit + ((value + NUL + signature string 't') */
-
- p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true);
- if (!p)
- return -ENOMEM;
-
- *((uint64_t*) p) = h;
- *((uint64_t*) (p + 8)) = x;
- p[16] = 0;
- p[17] = 't';
- } else {
- /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */
- p = message_extend_fields(m, 8, 4 + 4 + 8, false);
- if (!p)
- return -ENOMEM;
-
- p[0] = (uint8_t) h;
- p[1] = 1;
- p[2] = 't';
- p[3] = 0;
- p[4] = 0;
- p[5] = 0;
- p[6] = 0;
- p[7] = 0;
-
- ((uint64_t*) p)[1] = x;
- }
-
- return 0;
-}
-
-static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) {
- assert(m);
-
- if (BUS_MESSAGE_IS_GVARIANT(m))
- return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie);
- else {
- /* 64bit cookies are not supported on dbus1 */
- if (cookie > 0xffffffffUL)
- return -EOPNOTSUPP;
-
- return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie);
- }
-}
-
-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,
- unsigned n_fds,
- const char *label,
- size_t extra,
- sd_bus_message **ret) {
-
- _cleanup_free_ sd_bus_message *m = NULL;
- struct bus_header *h;
- size_t a, label_sz;
-
- assert(bus);
- assert(header || header_accessible <= 0);
- assert(footer || footer_accessible <= 0);
- assert(fds || n_fds <= 0);
- assert(ret);
-
- if (header_accessible < sizeof(struct bus_header))
- return -EBADMSG;
-
- if (header_accessible > message_size)
- return -EBADMSG;
- if (footer_accessible > message_size)
- return -EBADMSG;
-
- h = header;
- if (!IN_SET(h->version, 1, 2))
- return -EBADMSG;
-
- if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
- return -EBADMSG;
-
- if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
- return -EBADMSG;
-
- /* Note that we are happy with unknown flags in the flags header! */
-
- a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
-
- if (label) {
- label_sz = strlen(label);
- a += label_sz + 1;
- }
-
- m = malloc0(a);
- if (!m)
- return -ENOMEM;
-
- m->n_ref = 1;
- m->sealed = true;
- m->header = header;
- m->header_accessible = header_accessible;
- m->footer = footer;
- m->footer_accessible = footer_accessible;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t ws;
-
- if (h->dbus2.cookie == 0)
- return -EBADMSG;
-
- /* dbus2 derives the sizes from the message size and
- the offset table at the end, since it is formatted as
- gvariant "yyyyuta{tv}v". Since the message itself is a
- structure with precisely to variable sized entries,
- there's only one offset in the table, which marks the
- end of the fields array. */
-
- ws = bus_gvariant_determine_word_size(message_size, 0);
- if (footer_accessible < ws)
- return -EBADMSG;
-
- m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws);
- if (ALIGN8(m->fields_size) > message_size - ws)
- return -EBADMSG;
- if (m->fields_size < sizeof(struct bus_header))
- return -EBADMSG;
-
- m->fields_size -= sizeof(struct bus_header);
- m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size));
- } else {
- if (h->dbus1.serial == 0)
- return -EBADMSG;
-
- /* dbus1 has the sizes in the header */
- m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size);
- m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size);
-
- if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size)
- return -EBADMSG;
- }
-
- m->fds = fds;
- m->n_fds = n_fds;
-
- if (label) {
- m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra);
- memcpy(m->creds.label, label, label_sz + 1);
-
- m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
- }
-
- m->bus = sd_bus_ref(bus);
- *ret = m;
- m = NULL;
-
- return 0;
-}
-
-int bus_message_from_malloc(
- sd_bus *bus,
- void *buffer,
- size_t length,
- int *fds,
- unsigned n_fds,
- const char *label,
- sd_bus_message **ret) {
-
- sd_bus_message *m;
- size_t sz;
- int r;
-
- r = bus_message_from_header(
- bus,
- buffer, length, /* in this case the initial bytes and the final bytes are the same */
- buffer, length,
- length,
- fds, n_fds,
- label,
- 0, &m);
- if (r < 0)
- return r;
-
- sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size);
- if (sz > 0) {
- m->n_body_parts = 1;
- m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size);
- m->body.size = sz;
- m->body.sealed = true;
- m->body.memfd = -1;
- }
-
- m->n_iovec = 1;
- m->iovec = m->iovec_fixed;
- m->iovec[0].iov_base = buffer;
- m->iovec[0].iov_len = length;
-
- r = bus_message_parse_fields(m);
- if (r < 0)
- goto fail;
-
- /* We take possession of the memory and fds now */
- m->free_header = true;
- m->free_fds = true;
-
- *ret = m;
- return 0;
-
-fail:
- message_free(m);
- return r;
-}
-
-static sd_bus_message *message_new(sd_bus *bus, uint8_t type) {
- sd_bus_message *m;
-
- assert(bus);
-
- m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
- if (!m)
- return NULL;
-
- m->n_ref = 1;
- m->header = (struct bus_header*) ((uint8_t*) m + ALIGN(sizeof(struct sd_bus_message)));
- m->header->endian = BUS_NATIVE_ENDIAN;
- m->header->type = type;
- m->header->version = bus->message_version;
- m->allow_fds = bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING);
- m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m);
- m->bus = sd_bus_ref(bus);
-
- if (bus->allow_interactive_authorization)
- m->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION;
-
- return m;
-}
-
-_public_ int sd_bus_message_new_signal(
- sd_bus *bus,
- sd_bus_message **m,
- const char *path,
- const char *interface,
- const char *member) {
-
- sd_bus_message *t;
- int r;
-
- assert_return(bus, -ENOTCONN);
- assert_return(bus->state != BUS_UNSET, -ENOTCONN);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(interface_name_is_valid(interface), -EINVAL);
- assert_return(member_name_is_valid(member), -EINVAL);
- assert_return(m, -EINVAL);
-
- t = message_new(bus, SD_BUS_MESSAGE_SIGNAL);
- if (!t)
- return -ENOMEM;
-
- t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
-
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
- if (r < 0)
- goto fail;
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
- if (r < 0)
- goto fail;
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
- if (r < 0)
- goto fail;
-
- *m = t;
- return 0;
-
-fail:
- sd_bus_message_unref(t);
- return r;
-}
-
-_public_ int sd_bus_message_new_method_call(
- sd_bus *bus,
- sd_bus_message **m,
- const char *destination,
- const char *path,
- const char *interface,
- const char *member) {
-
- sd_bus_message *t;
- int r;
-
- assert_return(bus, -ENOTCONN);
- assert_return(bus->state != BUS_UNSET, -ENOTCONN);
- assert_return(!destination || service_name_is_valid(destination), -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
- assert_return(member_name_is_valid(member), -EINVAL);
- assert_return(m, -EINVAL);
-
- t = message_new(bus, SD_BUS_MESSAGE_METHOD_CALL);
- if (!t)
- return -ENOMEM;
-
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
- if (r < 0)
- goto fail;
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
- if (r < 0)
- goto fail;
-
- if (interface) {
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
- if (r < 0)
- goto fail;
- }
-
- if (destination) {
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
- if (r < 0)
- goto fail;
- }
-
- *m = t;
- return 0;
-
-fail:
- message_free(t);
- return r;
-}
-
-static int message_new_reply(
- sd_bus_message *call,
- uint8_t type,
- sd_bus_message **m) {
-
- sd_bus_message *t;
- int r;
-
- assert_return(call, -EINVAL);
- assert_return(call->sealed, -EPERM);
- assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(call->bus->state != BUS_UNSET, -ENOTCONN);
- assert_return(m, -EINVAL);
-
- t = message_new(call->bus, type);
- if (!t)
- return -ENOMEM;
-
- t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
- t->reply_cookie = BUS_MESSAGE_COOKIE(call);
- if (t->reply_cookie == 0)
- return -EOPNOTSUPP;
-
- r = message_append_reply_cookie(t, t->reply_cookie);
- if (r < 0)
- goto fail;
-
- if (call->sender) {
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
- if (r < 0)
- goto fail;
- }
-
- t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
- t->enforced_reply_signature = call->enforced_reply_signature;
-
- *m = t;
- return 0;
-
-fail:
- message_free(t);
- return r;
-}
-
-_public_ int sd_bus_message_new_method_return(
- sd_bus_message *call,
- sd_bus_message **m) {
-
- return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m);
-}
-
-_public_ int sd_bus_message_new_method_error(
- sd_bus_message *call,
- sd_bus_message **m,
- const sd_bus_error *e) {
-
- sd_bus_message *t;
- int r;
-
- assert_return(sd_bus_error_is_set(e), -EINVAL);
- assert_return(m, -EINVAL);
-
- r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t);
- if (r < 0)
- return r;
-
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
- if (r < 0)
- goto fail;
-
- if (e->message) {
- r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
- if (r < 0)
- goto fail;
- }
-
- t->error._need_free = -1;
-
- *m = t;
- return 0;
-
-fail:
- message_free(t);
- return r;
-}
-
-_public_ int sd_bus_message_new_method_errorf(
- sd_bus_message *call,
- sd_bus_message **m,
- const char *name,
- const char *format,
- ...) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- va_list ap;
-
- assert_return(name, -EINVAL);
- assert_return(m, -EINVAL);
-
- va_start(ap, format);
- bus_error_setfv(&error, name, format, ap);
- va_end(ap);
-
- return sd_bus_message_new_method_error(call, m, &error);
-}
-
-_public_ int sd_bus_message_new_method_errno(
- sd_bus_message *call,
- sd_bus_message **m,
- int error,
- const sd_bus_error *p) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
-
- if (sd_bus_error_is_set(p))
- return sd_bus_message_new_method_error(call, m, p);
-
- sd_bus_error_set_errno(&berror, error);
-
- return sd_bus_message_new_method_error(call, m, &berror);
-}
-
-_public_ int sd_bus_message_new_method_errnof(
- sd_bus_message *call,
- sd_bus_message **m,
- int error,
- const char *format,
- ...) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
- va_list ap;
-
- va_start(ap, format);
- sd_bus_error_set_errnofv(&berror, error, format, ap);
- va_end(ap);
-
- return sd_bus_message_new_method_error(call, m, &berror);
-}
-
-void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) {
- assert(bus);
- assert(m);
-
- m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local";
- m->creds.well_known_names_local = true;
- m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
-}
-
-void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) {
- assert(bus);
- assert(m);
-
- m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
- m->creds.well_known_names_driver = true;
- m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
-}
-
-int bus_message_new_synthetic_error(
- sd_bus *bus,
- uint64_t cookie,
- const sd_bus_error *e,
- sd_bus_message **m) {
-
- sd_bus_message *t;
- int r;
-
- assert(bus);
- assert(sd_bus_error_is_set(e));
- assert(m);
-
- t = message_new(bus, SD_BUS_MESSAGE_METHOD_ERROR);
- if (!t)
- return -ENOMEM;
-
- t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
- t->reply_cookie = cookie;
-
- r = message_append_reply_cookie(t, t->reply_cookie);
- if (r < 0)
- goto fail;
-
- if (bus && bus->unique_name) {
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
- if (r < 0)
- goto fail;
- }
-
- r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
- if (r < 0)
- goto fail;
-
- if (e->message) {
- r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
- if (r < 0)
- goto fail;
- }
-
- t->error._need_free = -1;
-
- bus_message_set_sender_driver(bus, t);
-
- *m = t;
- return 0;
-
-fail:
- message_free(t);
- return r;
-}
-
-_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
-
- if (!m)
- return NULL;
-
- assert(m->n_ref > 0);
- m->n_ref++;
-
- return m;
-}
-
-_public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) {
-
- if (!m)
- return NULL;
-
- assert(m->n_ref > 0);
- m->n_ref--;
-
- if (m->n_ref > 0)
- return NULL;
-
- message_free(m);
- return NULL;
-}
-
-_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) {
- assert_return(m, -EINVAL);
- assert_return(type, -EINVAL);
-
- *type = m->header->type;
- return 0;
-}
-
-_public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) {
- uint64_t c;
-
- assert_return(m, -EINVAL);
- assert_return(cookie, -EINVAL);
-
- c = BUS_MESSAGE_COOKIE(m);
- if (c == 0)
- return -ENODATA;
-
- *cookie = BUS_MESSAGE_COOKIE(m);
- return 0;
-}
-
-_public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) {
- assert_return(m, -EINVAL);
- assert_return(cookie, -EINVAL);
-
- if (m->reply_cookie == 0)
- return -ENODATA;
-
- *cookie = m->reply_cookie;
- return 0;
-}
-
-_public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) {
- assert_return(m, -EINVAL);
-
- return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
- !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
-}
-
-_public_ int sd_bus_message_get_auto_start(sd_bus_message *m) {
- assert_return(m, -EINVAL);
-
- return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START);
-}
-
-_public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) {
- assert_return(m, -EINVAL);
-
- return m->header->type == SD_BUS_MESSAGE_METHOD_CALL &&
- (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION);
-}
-
-_public_ const char *sd_bus_message_get_path(sd_bus_message *m) {
- assert_return(m, NULL);
-
- return m->path;
-}
-
-_public_ const char *sd_bus_message_get_interface(sd_bus_message *m) {
- assert_return(m, NULL);
-
- return m->interface;
-}
-
-_public_ const char *sd_bus_message_get_member(sd_bus_message *m) {
- assert_return(m, NULL);
-
- return m->member;
-}
-
-_public_ const char *sd_bus_message_get_destination(sd_bus_message *m) {
- assert_return(m, NULL);
-
- return m->destination;
-}
-
-_public_ const char *sd_bus_message_get_sender(sd_bus_message *m) {
- assert_return(m, NULL);
-
- return m->sender;
-}
-
-_public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) {
- assert_return(m, NULL);
-
- if (!sd_bus_error_is_set(&m->error))
- return NULL;
-
- return &m->error;
-}
-
-_public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) {
- assert_return(m, -EINVAL);
- assert_return(usec, -EINVAL);
-
- if (m->monotonic <= 0)
- return -ENODATA;
-
- *usec = m->monotonic;
- return 0;
-}
-
-_public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) {
- assert_return(m, -EINVAL);
- assert_return(usec, -EINVAL);
-
- if (m->realtime <= 0)
- return -ENODATA;
-
- *usec = m->realtime;
- return 0;
-}
-
-_public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) {
- assert_return(m, -EINVAL);
- assert_return(seqnum, -EINVAL);
-
- if (m->seqnum <= 0)
- return -ENODATA;
-
- *seqnum = m->seqnum;
- return 0;
-}
-
-_public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) {
- assert_return(m, NULL);
-
- if (m->creds.mask == 0)
- return NULL;
-
- return &m->creds;
-}
-
-_public_ int sd_bus_message_is_signal(
- sd_bus_message *m,
- const char *interface,
- const char *member) {
-
- assert_return(m, -EINVAL);
-
- if (m->header->type != SD_BUS_MESSAGE_SIGNAL)
- return 0;
-
- if (interface && (!m->interface || !streq(m->interface, interface)))
- return 0;
-
- if (member && (!m->member || !streq(m->member, member)))
- return 0;
-
- return 1;
-}
-
-_public_ int sd_bus_message_is_method_call(
- sd_bus_message *m,
- const char *interface,
- const char *member) {
-
- assert_return(m, -EINVAL);
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
- return 0;
-
- if (interface && (!m->interface || !streq(m->interface, interface)))
- return 0;
-
- if (member && (!m->member || !streq(m->member, member)))
- return 0;
-
- return 1;
-}
-
-_public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) {
- assert_return(m, -EINVAL);
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
- return 0;
-
- if (name && (!m->error.name || !streq(m->error.name, name)))
- return 0;
-
- return 1;
-}
-
-_public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) {
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM);
-
- SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b);
-
- return 0;
-}
-
-_public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) {
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
-
- SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b);
-
- return 0;
-}
-
-_public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) {
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
-
- SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b);
-
- return 0;
-}
-
-static struct bus_container *message_get_container(sd_bus_message *m) {
- assert(m);
-
- if (m->n_containers == 0)
- return &m->root_container;
-
- assert(m->containers);
- return m->containers + m->n_containers - 1;
-}
-
-struct bus_body_part *message_append_part(sd_bus_message *m) {
- struct bus_body_part *part;
-
- assert(m);
-
- if (m->poisoned)
- return NULL;
-
- if (m->n_body_parts <= 0) {
- part = &m->body;
- zero(*part);
- } else {
- assert(m->body_end);
-
- part = new0(struct bus_body_part, 1);
- if (!part) {
- m->poisoned = true;
- return NULL;
- }
-
- m->body_end->next = part;
- }
-
- part->memfd = -1;
- m->body_end = part;
- m->n_body_parts++;
-
- return part;
-}
-
-static void part_zero(struct bus_body_part *part, size_t sz) {
- assert(part);
- assert(sz > 0);
- assert(sz < 8);
-
- /* All other fields can be left in their defaults */
- assert(!part->data);
- assert(part->memfd < 0);
-
- part->size = sz;
- part->is_zero = true;
- part->sealed = true;
-}
-
-static int part_make_space(
- struct sd_bus_message *m,
- struct bus_body_part *part,
- size_t sz,
- void **q) {
-
- void *n;
- int r;
-
- assert(m);
- assert(part);
- assert(!part->sealed);
-
- if (m->poisoned)
- return -ENOMEM;
-
- if (!part->data && part->memfd < 0) {
- part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated);
- part->mmap_begin = part->data;
- }
-
- if (part->memfd >= 0) {
-
- if (part->allocated == 0 || sz > part->allocated) {
- uint64_t new_allocated;
-
- new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1);
- r = memfd_set_size(part->memfd, new_allocated);
- if (r < 0) {
- m->poisoned = true;
- return r;
- }
-
- part->allocated = new_allocated;
- }
-
- if (!part->data || sz > part->mapped) {
- size_t psz;
-
- psz = PAGE_ALIGN(sz > 0 ? sz : 1);
- if (part->mapped <= 0)
- n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0);
- else
- n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE);
-
- if (n == MAP_FAILED) {
- m->poisoned = true;
- return -errno;
- }
-
- part->mmap_begin = part->data = n;
- part->mapped = psz;
- part->memfd_offset = 0;
- }
-
- part->munmap_this = true;
- } else {
- if (part->allocated == 0 || sz > part->allocated) {
- size_t new_allocated;
-
- new_allocated = sz > 0 ? 2 * sz : 64;
- n = realloc(part->data, new_allocated);
- if (!n) {
- m->poisoned = true;
- return -ENOMEM;
- }
-
- part->data = n;
- part->allocated = new_allocated;
- part->free_this = true;
- }
- }
-
- if (q)
- *q = part->data ? (uint8_t*) part->data + part->size : NULL;
-
- part->size = sz;
- return 0;
-}
-
-static int message_add_offset(sd_bus_message *m, size_t offset) {
- struct bus_container *c;
-
- assert(m);
- assert(BUS_MESSAGE_IS_GVARIANT(m));
-
- /* Add offset to current container, unless this is the first
- * item in it, which will have the 0 offset, which we can
- * ignore. */
- c = message_get_container(m);
-
- if (!c->need_offsets)
- return 0;
-
- if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1))
- return -ENOMEM;
-
- c->offsets[c->n_offsets++] = offset;
- return 0;
-}
-
-static void message_extend_containers(sd_bus_message *m, size_t expand) {
- struct bus_container *c;
-
- assert(m);
-
- if (expand <= 0)
- return;
-
- /* Update counters */
- for (c = m->containers; c < m->containers + m->n_containers; c++) {
-
- if (c->array_size)
- *c->array_size += expand;
- }
-}
-
-static void *message_extend_body(
- sd_bus_message *m,
- size_t align,
- size_t sz,
- bool add_offset,
- bool force_inline) {
-
- size_t start_body, end_body, padding, added;
- void *p;
- int r;
-
- assert(m);
- assert(align > 0);
- assert(!m->sealed);
-
- if (m->poisoned)
- return NULL;
-
- start_body = ALIGN_TO((size_t) m->body_size, align);
- end_body = start_body + sz;
-
- padding = start_body - m->body_size;
- added = padding + sz;
-
- /* Check for 32bit overflows */
- if (end_body > (size_t) ((uint32_t) -1) ||
- end_body < start_body) {
- m->poisoned = true;
- return NULL;
- }
-
- if (added > 0) {
- struct bus_body_part *part = NULL;
- bool add_new_part;
-
- add_new_part =
- m->n_body_parts <= 0 ||
- m->body_end->sealed ||
- (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) ||
- (force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
-
- if (add_new_part) {
- if (padding > 0) {
- part = message_append_part(m);
- if (!part)
- return NULL;
-
- part_zero(part, padding);
- }
-
- part = message_append_part(m);
- if (!part)
- return NULL;
-
- r = part_make_space(m, part, sz, &p);
- if (r < 0)
- return NULL;
- } else {
- struct bus_container *c;
- void *op;
- size_t os, start_part, end_part;
-
- part = m->body_end;
- op = part->data;
- os = part->size;
-
- start_part = ALIGN_TO(part->size, align);
- end_part = start_part + sz;
-
- r = part_make_space(m, part, end_part, &p);
- if (r < 0)
- return NULL;
-
- if (padding > 0) {
- memzero(p, padding);
- p = (uint8_t*) p + padding;
- }
-
- /* Readjust pointers */
- for (c = m->containers; c < m->containers + m->n_containers; c++)
- c->array_size = adjust_pointer(c->array_size, op, os, part->data);
-
- m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
- }
- } else
- /* Return something that is not NULL and is aligned */
- p = (uint8_t *) NULL + align;
-
- m->body_size = end_body;
- message_extend_containers(m, added);
-
- if (add_offset) {
- r = message_add_offset(m, end_body);
- if (r < 0) {
- m->poisoned = true;
- return NULL;
- }
- }
-
- return p;
-}
-
-static int message_push_fd(sd_bus_message *m, int fd) {
- int *f, copy;
-
- assert(m);
-
- if (fd < 0)
- return -EINVAL;
-
- if (!m->allow_fds)
- return -EOPNOTSUPP;
-
- copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
- if (copy < 0)
- return -errno;
-
- f = realloc(m->fds, sizeof(int) * (m->n_fds + 1));
- if (!f) {
- m->poisoned = true;
- safe_close(copy);
- return -ENOMEM;
- }
-
- m->fds = f;
- m->fds[m->n_fds] = copy;
- m->free_fds = true;
-
- return copy;
-}
-
-int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) {
- _cleanup_close_ int fd = -1;
- struct bus_container *c;
- ssize_t align, sz;
- void *a;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(bus_type_is_basic(type), -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- c = message_get_container(m);
-
- if (c->signature && c->signature[c->index]) {
- /* Container signature is already set */
-
- if (c->signature[c->index] != type)
- return -ENXIO;
- } else {
- char *e;
-
- /* Maybe we can append to the signature? But only if this is the top-level container */
- if (c->enclosing != 0)
- return -ENXIO;
-
- e = strextend(&c->signature, CHAR_TO_STR(type), NULL);
- if (!e) {
- m->poisoned = true;
- return -ENOMEM;
- }
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- uint8_t u8;
- uint32_t u32;
-
- switch (type) {
-
- case SD_BUS_TYPE_SIGNATURE:
- case SD_BUS_TYPE_STRING:
- p = strempty(p);
-
- /* Fall through... */
- case SD_BUS_TYPE_OBJECT_PATH:
- if (!p)
- return -EINVAL;
-
- align = 1;
- sz = strlen(p) + 1;
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
-
- u8 = p && *(int*) p;
- p = &u8;
-
- align = sz = 1;
- break;
-
- case SD_BUS_TYPE_UNIX_FD:
-
- if (!p)
- return -EINVAL;
-
- fd = message_push_fd(m, *(int*) p);
- if (fd < 0)
- return fd;
-
- u32 = m->n_fds;
- p = &u32;
-
- align = sz = 4;
- break;
-
- default:
- align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
- sz = bus_gvariant_get_size(CHAR_TO_STR(type));
- break;
- }
-
- assert(align > 0);
- assert(sz > 0);
-
- a = message_extend_body(m, align, sz, true, false);
- if (!a)
- return -ENOMEM;
-
- memcpy(a, p, sz);
-
- if (stored)
- *stored = (const uint8_t*) a;
-
- } else {
- uint32_t u32;
-
- switch (type) {
-
- case SD_BUS_TYPE_STRING:
- /* To make things easy we'll serialize a NULL string
- * into the empty string */
- p = strempty(p);
-
- /* Fall through... */
- case SD_BUS_TYPE_OBJECT_PATH:
-
- if (!p)
- return -EINVAL;
-
- align = 4;
- sz = 4 + strlen(p) + 1;
- break;
-
- case SD_BUS_TYPE_SIGNATURE:
-
- p = strempty(p);
-
- align = 1;
- sz = 1 + strlen(p) + 1;
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
-
- u32 = p && *(int*) p;
- p = &u32;
-
- align = sz = 4;
- break;
-
- case SD_BUS_TYPE_UNIX_FD:
-
- if (!p)
- return -EINVAL;
-
- fd = message_push_fd(m, *(int*) p);
- if (fd < 0)
- return fd;
-
- u32 = m->n_fds;
- p = &u32;
-
- align = sz = 4;
- break;
-
- default:
- align = bus_type_get_alignment(type);
- sz = bus_type_get_size(type);
- break;
- }
-
- assert(align > 0);
- assert(sz > 0);
-
- a = message_extend_body(m, align, sz, false, false);
- if (!a)
- return -ENOMEM;
-
- if (type == SD_BUS_TYPE_STRING || type == SD_BUS_TYPE_OBJECT_PATH) {
- *(uint32_t*) a = sz - 5;
- memcpy((uint8_t*) a + 4, p, sz - 4);
-
- if (stored)
- *stored = (const uint8_t*) a + 4;
-
- } else if (type == SD_BUS_TYPE_SIGNATURE) {
- *(uint8_t*) a = sz - 2;
- memcpy((uint8_t*) a + 1, p, sz - 1);
-
- if (stored)
- *stored = (const uint8_t*) a + 1;
- } else {
- memcpy(a, p, sz);
-
- if (stored)
- *stored = a;
- }
- }
-
- if (type == SD_BUS_TYPE_UNIX_FD)
- m->n_fds++;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index++;
-
- fd = -1;
- return 0;
-}
-
-_public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) {
- return message_append_basic(m, type, p, NULL);
-}
-
-_public_ int sd_bus_message_append_string_space(
- sd_bus_message *m,
- size_t size,
- char **s) {
-
- struct bus_container *c;
- void *a;
-
- assert_return(m, -EINVAL);
- assert_return(s, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(!m->poisoned, -ESTALE);
-
- c = message_get_container(m);
-
- if (c->signature && c->signature[c->index]) {
- /* Container signature is already set */
-
- if (c->signature[c->index] != SD_BUS_TYPE_STRING)
- return -ENXIO;
- } else {
- char *e;
-
- /* Maybe we can append to the signature? But only if this is the top-level container */
- if (c->enclosing != 0)
- return -ENXIO;
-
- e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
- if (!e) {
- m->poisoned = true;
- return -ENOMEM;
- }
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- a = message_extend_body(m, 1, size + 1, true, false);
- if (!a)
- return -ENOMEM;
-
- *s = a;
- } else {
- a = message_extend_body(m, 4, 4 + size + 1, false, false);
- if (!a)
- return -ENOMEM;
-
- *(uint32_t*) a = size;
- *s = (char*) a + 4;
- }
-
- (*s)[size] = 0;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index++;
-
- return 0;
-}
-
-_public_ int sd_bus_message_append_string_iovec(
- sd_bus_message *m,
- const struct iovec *iov,
- unsigned n) {
-
- size_t size;
- unsigned i;
- char *p;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(iov || n == 0, -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- size = IOVEC_TOTAL_SIZE(iov, n);
-
- r = sd_bus_message_append_string_space(m, size, &p);
- if (r < 0)
- return r;
-
- for (i = 0; i < n; i++) {
-
- if (iov[i].iov_base)
- memcpy(p, iov[i].iov_base, iov[i].iov_len);
- else
- memset(p, ' ', iov[i].iov_len);
-
- p += iov[i].iov_len;
- }
-
- return 0;
-}
-
-static int bus_message_open_array(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- uint32_t **array_size,
- size_t *begin,
- bool *need_offsets) {
-
- unsigned nindex;
- int alignment, r;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(array_size);
- assert(begin);
- assert(need_offsets);
-
- if (!signature_is_single(contents, true))
- return -EINVAL;
-
- if (c->signature && c->signature[c->index]) {
-
- /* Verify the existing signature */
-
- if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
- return -ENXIO;
-
- if (!startswith(c->signature + c->index + 1, contents))
- return -ENXIO;
-
- nindex = c->index + 1 + strlen(contents);
- } else {
- char *e;
-
- if (c->enclosing != 0)
- return -ENXIO;
-
- /* Extend the existing signature */
-
- e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL);
- if (!e) {
- m->poisoned = true;
- return -ENOMEM;
- }
-
- nindex = e - c->signature;
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- alignment = bus_gvariant_get_alignment(contents);
- if (alignment < 0)
- return alignment;
-
- /* Add alignment padding and add to offset list */
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
-
- r = bus_gvariant_is_fixed_size(contents);
- if (r < 0)
- return r;
-
- *begin = m->body_size;
- *need_offsets = r == 0;
- } else {
- void *a, *op;
- size_t os;
- struct bus_body_part *o;
-
- alignment = bus_type_get_alignment(contents[0]);
- if (alignment < 0)
- return alignment;
-
- a = message_extend_body(m, 4, 4, false, false);
- if (!a)
- return -ENOMEM;
-
- o = m->body_end;
- op = m->body_end->data;
- os = m->body_end->size;
-
- /* Add alignment between size and first element */
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
-
- /* location of array size might have changed so let's readjust a */
- if (o == m->body_end)
- a = adjust_pointer(a, op, os, m->body_end->data);
-
- *(uint32_t*) a = 0;
- *array_size = a;
- }
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index = nindex;
-
- return 0;
-}
-
-static int bus_message_open_variant(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents) {
-
- assert(m);
- assert(c);
- assert(contents);
-
- if (!signature_is_single(contents, false))
- return -EINVAL;
-
- if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
- return -EINVAL;
-
- if (c->signature && c->signature[c->index]) {
-
- if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
- return -ENXIO;
-
- } else {
- char *e;
-
- if (c->enclosing != 0)
- return -ENXIO;
-
- e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL);
- if (!e) {
- m->poisoned = true;
- return -ENOMEM;
- }
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* Variants are always aligned to 8 */
-
- if (!message_extend_body(m, 8, 0, false, false))
- return -ENOMEM;
-
- } else {
- size_t l;
- void *a;
-
- l = strlen(contents);
- a = message_extend_body(m, 1, 1 + l + 1, false, false);
- if (!a)
- return -ENOMEM;
-
- *(uint8_t*) a = l;
- memcpy((uint8_t*) a + 1, contents, l + 1);
- }
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index++;
-
- return 0;
-}
-
-static int bus_message_open_struct(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- size_t *begin,
- bool *need_offsets) {
-
- size_t nindex;
- int r;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(begin);
- assert(need_offsets);
-
- if (!signature_is_valid(contents, false))
- return -EINVAL;
-
- if (c->signature && c->signature[c->index]) {
- size_t l;
-
- l = strlen(contents);
-
- if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
- !startswith(c->signature + c->index + 1, contents) ||
- c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
- return -ENXIO;
-
- nindex = c->index + 1 + l + 1;
- } else {
- char *e;
-
- if (c->enclosing != 0)
- return -ENXIO;
-
- e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
- if (!e) {
- m->poisoned = true;
- return -ENOMEM;
- }
-
- nindex = e - c->signature;
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- int alignment;
-
- alignment = bus_gvariant_get_alignment(contents);
- if (alignment < 0)
- return alignment;
-
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
-
- r = bus_gvariant_is_fixed_size(contents);
- if (r < 0)
- return r;
-
- *begin = m->body_size;
- *need_offsets = r == 0;
- } else {
- /* Align contents to 8 byte boundary */
- if (!message_extend_body(m, 8, 0, false, false))
- return -ENOMEM;
- }
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index = nindex;
-
- return 0;
-}
-
-static int bus_message_open_dict_entry(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- size_t *begin,
- bool *need_offsets) {
-
- int r;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(begin);
- assert(need_offsets);
-
- if (!signature_is_pair(contents))
- return -EINVAL;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- return -ENXIO;
-
- if (c->signature && c->signature[c->index]) {
- size_t l;
-
- l = strlen(contents);
-
- if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
- !startswith(c->signature + c->index + 1, contents) ||
- c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
- return -ENXIO;
- } else
- return -ENXIO;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- int alignment;
-
- alignment = bus_gvariant_get_alignment(contents);
- if (alignment < 0)
- return alignment;
-
- if (!message_extend_body(m, alignment, 0, false, false))
- return -ENOMEM;
-
- r = bus_gvariant_is_fixed_size(contents);
- if (r < 0)
- return r;
-
- *begin = m->body_size;
- *need_offsets = r == 0;
- } else {
- /* Align contents to 8 byte boundary */
- if (!message_extend_body(m, 8, 0, false, false))
- return -ENOMEM;
- }
-
- return 0;
-}
-
-_public_ int sd_bus_message_open_container(
- sd_bus_message *m,
- char type,
- const char *contents) {
-
- struct bus_container *c, *w;
- uint32_t *array_size = NULL;
- char *signature;
- size_t before, begin = 0;
- bool need_offsets = false;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(contents, -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- /* Make sure we have space for one more container */
- if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) {
- m->poisoned = true;
- return -ENOMEM;
- }
-
- c = message_get_container(m);
-
- signature = strdup(contents);
- if (!signature) {
- m->poisoned = true;
- return -ENOMEM;
- }
-
- /* Save old index in the parent container, in case we have to
- * abort this container */
- c->saved_index = c->index;
- before = m->body_size;
-
- if (type == SD_BUS_TYPE_ARRAY)
- r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets);
- else if (type == SD_BUS_TYPE_VARIANT)
- r = bus_message_open_variant(m, c, contents);
- else if (type == SD_BUS_TYPE_STRUCT)
- r = bus_message_open_struct(m, c, contents, &begin, &need_offsets);
- else if (type == SD_BUS_TYPE_DICT_ENTRY)
- r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets);
- else
- r = -EINVAL;
-
- if (r < 0) {
- free(signature);
- return r;
- }
-
- /* OK, let's fill it in */
- w = m->containers + m->n_containers++;
- w->enclosing = type;
- w->signature = signature;
- w->index = 0;
- w->array_size = array_size;
- w->before = before;
- w->begin = begin;
- w->n_offsets = w->offsets_allocated = 0;
- w->offsets = NULL;
- w->need_offsets = need_offsets;
-
- return 0;
-}
-
-static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) {
-
- assert(m);
- assert(c);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
-
- if (c->need_offsets) {
- size_t payload, sz, i;
- uint8_t *a;
-
- /* Variable-width arrays */
-
- payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0;
- sz = bus_gvariant_determine_word_size(payload, c->n_offsets);
-
- a = message_extend_body(m, 1, sz * c->n_offsets, true, false);
- if (!a)
- return -ENOMEM;
-
- for (i = 0; i < c->n_offsets; i++)
- bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin);
- } else {
- void *a;
-
- /* Fixed-width or empty arrays */
-
- a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */
- if (!a)
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) {
- uint8_t *a;
- size_t l;
-
- assert(m);
- assert(c);
- assert(c->signature);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
-
- l = strlen(c->signature);
-
- a = message_extend_body(m, 1, 1 + l, true, false);
- if (!a)
- return -ENOMEM;
-
- a[0] = 0;
- memcpy(a+1, c->signature, l);
-
- return 0;
-}
-
-static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) {
- bool fixed_size = true;
- size_t n_variable = 0;
- unsigned i = 0;
- const char *p;
- uint8_t *a;
- int r;
-
- assert(m);
- assert(c);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
-
- p = strempty(c->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_is_fixed_size(t);
- if (r < 0)
- return r;
- }
-
- assert(!c->need_offsets || i <= c->n_offsets);
-
- /* We need to add an offset for each item that has a
- * variable size and that is not the last one in the
- * list */
- if (r == 0)
- fixed_size = false;
- if (r == 0 && p[n] != 0)
- n_variable++;
-
- i++;
- p += n;
- }
-
- assert(!c->need_offsets || i == c->n_offsets);
- assert(c->need_offsets || n_variable == 0);
-
- if (isempty(c->signature)) {
- /* The unary type is encoded as fixed 1 byte padding */
- a = message_extend_body(m, 1, 1, add_offset, false);
- if (!a)
- return -ENOMEM;
-
- *a = 0;
- } else if (n_variable <= 0) {
- int alignment = 1;
-
- /* Structures with fixed-size members only have to be
- * fixed-size themselves. But gvariant requires all fixed-size
- * elements to be sized a multiple of their alignment. Hence,
- * we must *always* add final padding after the last member so
- * the overall size of the structure is properly aligned. */
- if (fixed_size)
- alignment = bus_gvariant_get_alignment(strempty(c->signature));
-
- assert(alignment > 0);
-
- a = message_extend_body(m, alignment, 0, add_offset, false);
- if (!a)
- return -ENOMEM;
- } else {
- size_t sz;
- unsigned j;
-
- assert(c->offsets[c->n_offsets-1] == m->body_size);
-
- sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable);
-
- a = message_extend_body(m, 1, sz * n_variable, add_offset, false);
- if (!a)
- return -ENOMEM;
-
- p = strempty(c->signature);
- for (i = 0, j = 0; i < c->n_offsets; i++) {
- unsigned k;
- 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;
-
- p += n;
-
- r = bus_gvariant_is_fixed_size(t);
- if (r < 0)
- return r;
- if (r > 0 || p[0] == 0)
- continue;
- }
-
- k = n_variable - 1 - j;
-
- bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin);
-
- j++;
- }
- }
-
- return 0;
-}
-
-_public_ int sd_bus_message_close_container(sd_bus_message *m) {
- struct bus_container *c;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(m->n_containers > 0, -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- c = message_get_container(m);
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- if (c->signature && c->signature[c->index] != 0)
- return -EINVAL;
-
- m->n_containers--;
-
- if (c->enclosing == SD_BUS_TYPE_ARRAY)
- r = bus_message_close_array(m, c);
- else if (c->enclosing == SD_BUS_TYPE_VARIANT)
- r = bus_message_close_variant(m, c);
- else if (c->enclosing == SD_BUS_TYPE_STRUCT || c->enclosing == SD_BUS_TYPE_DICT_ENTRY)
- r = bus_message_close_struct(m, c, true);
- else
- assert_not_reached("Unknown container type");
-
- free(c->signature);
- free(c->offsets);
-
- return r;
-}
-
-typedef struct {
- const char *types;
- unsigned n_struct;
- unsigned n_array;
-} TypeStack;
-
-static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
- assert(stack);
- assert(max > 0);
-
- if (*i >= max)
- return -EINVAL;
-
- stack[*i].types = types;
- stack[*i].n_struct = n_struct;
- stack[*i].n_array = n_array;
- (*i)++;
-
- return 0;
-}
-
-static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
- assert(stack);
- assert(max > 0);
- assert(types);
- assert(n_struct);
- assert(n_array);
-
- if (*i <= 0)
- return 0;
-
- (*i)--;
- *types = stack[*i].types;
- *n_struct = stack[*i].n_struct;
- *n_array = stack[*i].n_array;
-
- return 1;
-}
-
-int bus_message_append_ap(
- sd_bus_message *m,
- const char *types,
- va_list ap) {
-
- unsigned n_array, n_struct;
- TypeStack stack[BUS_CONTAINER_DEPTH];
- unsigned stack_ptr = 0;
- int r;
-
- assert(m);
-
- if (!types)
- return 0;
-
- n_array = (unsigned) -1;
- n_struct = strlen(types);
-
- for (;;) {
- const char *t;
-
- if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
- r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- continue;
- }
-
- t = types;
- if (n_array != (unsigned) -1)
- n_array--;
- else {
- types++;
- n_struct--;
- }
-
- switch (*t) {
-
- case SD_BUS_TYPE_BYTE: {
- uint8_t x;
-
- x = (uint8_t) va_arg(ap, int);
- r = sd_bus_message_append_basic(m, *t, &x);
- break;
- }
-
- case SD_BUS_TYPE_BOOLEAN:
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_UINT32:
- case SD_BUS_TYPE_UNIX_FD: {
- uint32_t x;
-
- /* We assume a boolean is the same as int32_t */
- assert_cc(sizeof(int32_t) == sizeof(int));
-
- x = va_arg(ap, uint32_t);
- r = sd_bus_message_append_basic(m, *t, &x);
- break;
- }
-
- case SD_BUS_TYPE_INT16:
- case SD_BUS_TYPE_UINT16: {
- uint16_t x;
-
- x = (uint16_t) va_arg(ap, int);
- r = sd_bus_message_append_basic(m, *t, &x);
- break;
- }
-
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT64: {
- uint64_t x;
-
- x = va_arg(ap, uint64_t);
- r = sd_bus_message_append_basic(m, *t, &x);
- break;
- }
-
- case SD_BUS_TYPE_DOUBLE: {
- double x;
-
- x = va_arg(ap, double);
- r = sd_bus_message_append_basic(m, *t, &x);
- break;
- }
-
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_SIGNATURE: {
- const char *x;
-
- x = va_arg(ap, const char*);
- r = sd_bus_message_append_basic(m, *t, x);
- break;
- }
-
- case SD_BUS_TYPE_ARRAY: {
- size_t k;
-
- r = signature_element_length(t + 1, &k);
- if (r < 0)
- return r;
-
- {
- char s[k + 1];
- memcpy(s, t + 1, k);
- s[k] = 0;
-
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
- if (r < 0)
- return r;
- }
-
- if (n_array == (unsigned) -1) {
- types += k;
- n_struct -= k;
- }
-
- r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
- if (r < 0)
- return r;
-
- types = t + 1;
- n_struct = k;
- n_array = va_arg(ap, unsigned);
-
- break;
- }
-
- case SD_BUS_TYPE_VARIANT: {
- const char *s;
-
- s = va_arg(ap, const char*);
- if (!s)
- return -EINVAL;
-
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s);
- if (r < 0)
- return r;
-
- r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
- if (r < 0)
- return r;
-
- types = s;
- n_struct = strlen(s);
- n_array = (unsigned) -1;
-
- break;
- }
-
- case SD_BUS_TYPE_STRUCT_BEGIN:
- case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
- size_t k;
-
- r = signature_element_length(t, &k);
- if (r < 0)
- return r;
-
- {
- char s[k - 1];
-
- memcpy(s, t + 1, k - 2);
- s[k - 2] = 0;
-
- r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
- if (r < 0)
- return r;
- }
-
- if (n_array == (unsigned) -1) {
- types += k - 1;
- n_struct -= k - 1;
- }
-
- r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
- if (r < 0)
- return r;
-
- types = t + 1;
- n_struct = k - 2;
- n_array = (unsigned) -1;
-
- break;
- }
-
- default:
- r = -EINVAL;
- }
-
- if (r < 0)
- return r;
- }
-
- return 1;
-}
-
-_public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) {
- va_list ap;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(types, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(!m->poisoned, -ESTALE);
-
- va_start(ap, types);
- r = bus_message_append_ap(m, types, ap);
- va_end(ap);
-
- return r;
-}
-
-_public_ int sd_bus_message_append_array_space(
- sd_bus_message *m,
- char type,
- size_t size,
- void **ptr) {
-
- ssize_t align, sz;
- void *a;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL);
- assert_return(ptr || size == 0, -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- /* alignment and size of the trivial types (except bool) is
- * identical for gvariant and dbus1 marshalling */
- align = bus_type_get_alignment(type);
- sz = bus_type_get_size(type);
-
- assert_se(align > 0);
- assert_se(sz > 0);
-
- if (size % sz != 0)
- return -EINVAL;
-
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
- if (r < 0)
- return r;
-
- a = message_extend_body(m, align, size, false, false);
- if (!a)
- return -ENOMEM;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- *ptr = a;
- return 0;
-}
-
-_public_ int sd_bus_message_append_array(
- sd_bus_message *m,
- char type,
- const void *ptr,
- size_t size) {
- int r;
- void *p;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(bus_type_is_trivial(type), -EINVAL);
- assert_return(ptr || size == 0, -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- r = sd_bus_message_append_array_space(m, type, size, &p);
- if (r < 0)
- return r;
-
- memcpy_safe(p, ptr, size);
-
- return 0;
-}
-
-_public_ int sd_bus_message_append_array_iovec(
- sd_bus_message *m,
- char type,
- const struct iovec *iov,
- unsigned n) {
-
- size_t size;
- unsigned i;
- void *p;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(bus_type_is_trivial(type), -EINVAL);
- assert_return(iov || n == 0, -EINVAL);
- assert_return(!m->poisoned, -ESTALE);
-
- size = IOVEC_TOTAL_SIZE(iov, n);
-
- r = sd_bus_message_append_array_space(m, type, size, &p);
- if (r < 0)
- return r;
-
- for (i = 0; i < n; i++) {
-
- if (iov[i].iov_base)
- memcpy(p, iov[i].iov_base, iov[i].iov_len);
- else
- memzero(p, iov[i].iov_len);
-
- p = (uint8_t*) p + iov[i].iov_len;
- }
-
- return 0;
-}
-
-_public_ int sd_bus_message_append_array_memfd(
- sd_bus_message *m,
- char type,
- int memfd,
- uint64_t offset,
- uint64_t size) {
-
- _cleanup_close_ int copy_fd = -1;
- struct bus_body_part *part;
- ssize_t align, sz;
- uint64_t real_size;
- void *a;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(memfd >= 0, -EBADF);
- assert_return(bus_type_is_trivial(type), -EINVAL);
- assert_return(size > 0, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(!m->poisoned, -ESTALE);
-
- r = memfd_set_sealed(memfd);
- if (r < 0)
- return r;
-
- copy_fd = dup(memfd);
- if (copy_fd < 0)
- return copy_fd;
-
- r = memfd_get_size(memfd, &real_size);
- if (r < 0)
- return r;
-
- if (offset == 0 && size == (uint64_t) -1)
- size = real_size;
- else if (offset + size > real_size)
- return -EMSGSIZE;
-
- align = bus_type_get_alignment(type);
- sz = bus_type_get_size(type);
-
- assert_se(align > 0);
- assert_se(sz > 0);
-
- if (offset % align != 0)
- return -EINVAL;
-
- if (size % sz != 0)
- return -EINVAL;
-
- if (size > (uint64_t) (uint32_t) -1)
- return -EINVAL;
-
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
- if (r < 0)
- return r;
-
- a = message_extend_body(m, align, 0, false, false);
- if (!a)
- return -ENOMEM;
-
- part = message_append_part(m);
- if (!part)
- return -ENOMEM;
-
- part->memfd = copy_fd;
- part->memfd_offset = offset;
- part->sealed = true;
- part->size = size;
- copy_fd = -1;
-
- m->body_size += size;
- message_extend_containers(m, size);
-
- return sd_bus_message_close_container(m);
-}
-
-_public_ int sd_bus_message_append_string_memfd(
- sd_bus_message *m,
- int memfd,
- uint64_t offset,
- uint64_t size) {
-
- _cleanup_close_ int copy_fd = -1;
- struct bus_body_part *part;
- struct bus_container *c;
- uint64_t real_size;
- void *a;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(memfd >= 0, -EBADF);
- assert_return(size > 0, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(!m->poisoned, -ESTALE);
-
- r = memfd_set_sealed(memfd);
- if (r < 0)
- return r;
-
- copy_fd = dup(memfd);
- if (copy_fd < 0)
- return copy_fd;
-
- r = memfd_get_size(memfd, &real_size);
- if (r < 0)
- return r;
-
- if (offset == 0 && size == (uint64_t) -1)
- size = real_size;
- else if (offset + size > real_size)
- return -EMSGSIZE;
-
- /* We require this to be NUL terminated */
- if (size == 0)
- return -EINVAL;
-
- if (size > (uint64_t) (uint32_t) -1)
- return -EINVAL;
-
- c = message_get_container(m);
- if (c->signature && c->signature[c->index]) {
- /* Container signature is already set */
-
- if (c->signature[c->index] != SD_BUS_TYPE_STRING)
- return -ENXIO;
- } else {
- char *e;
-
- /* Maybe we can append to the signature? But only if this is the top-level container */
- if (c->enclosing != 0)
- return -ENXIO;
-
- e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL);
- if (!e) {
- m->poisoned = true;
- return -ENOMEM;
- }
- }
-
- if (!BUS_MESSAGE_IS_GVARIANT(m)) {
- a = message_extend_body(m, 4, 4, false, false);
- if (!a)
- return -ENOMEM;
-
- *(uint32_t*) a = size - 1;
- }
-
- part = message_append_part(m);
- if (!part)
- return -ENOMEM;
-
- part->memfd = copy_fd;
- part->memfd_offset = offset;
- part->sealed = true;
- part->size = size;
- copy_fd = -1;
-
- m->body_size += size;
- message_extend_containers(m, size);
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- r = message_add_offset(m, m->body_size);
- if (r < 0) {
- m->poisoned = true;
- return -ENOMEM;
- }
- }
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index++;
-
- return 0;
-}
-
-_public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) {
- char **i;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(!m->poisoned, -ESTALE);
-
- r = sd_bus_message_open_container(m, 'a', "s");
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, l) {
- r = sd_bus_message_append_basic(m, 's', *i);
- if (r < 0)
- return r;
- }
-
- return sd_bus_message_close_container(m);
-}
-
-static int bus_message_close_header(sd_bus_message *m) {
-
- assert(m);
-
- /* The actual user data is finished now, we just complete the
- variant and struct now (at least on gvariant). Remember
- this position, so that during parsing we know where to
- put the outer container end. */
- m->user_body_size = m->body_size;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- const char *signature;
- size_t sz, l;
- void *d;
-
- /* Add offset table to end of fields array */
- if (m->n_header_offsets >= 1) {
- uint8_t *a;
- unsigned i;
-
- assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]);
-
- sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets);
- a = message_extend_fields(m, 1, sz * m->n_header_offsets, false);
- if (!a)
- return -ENOMEM;
-
- for (i = 0; i < m->n_header_offsets; i++)
- bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]);
- }
-
- /* Add gvariant NUL byte plus signature to the end of
- * the body, followed by the final offset pointing to
- * the end of the fields array */
-
- signature = strempty(m->root_container.signature);
- l = strlen(signature);
-
- sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1);
- d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true);
- if (!d)
- return -ENOMEM;
-
- *(uint8_t*) d = 0;
- *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN;
- memcpy((uint8_t*) d + 2, signature, l);
- *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END;
-
- bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size);
-
- m->footer = d;
- m->footer_accessible = 1 + l + 2 + sz;
- } else {
- m->header->dbus1.fields_size = m->fields_size;
- m->header->dbus1.body_size = m->body_size;
- }
-
- return 0;
-}
-
-int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) {
- struct bus_body_part *part;
- size_t a;
- unsigned i;
- int r;
-
- assert(m);
-
- if (m->sealed)
- return -EPERM;
-
- if (m->n_containers > 0)
- return -EBADMSG;
-
- if (m->poisoned)
- return -ESTALE;
-
- if (cookie > 0xffffffffULL &&
- !BUS_MESSAGE_IS_GVARIANT(m))
- return -EOPNOTSUPP;
-
- /* In vtables the return signature of method calls is listed,
- * let's check if they match if this is a response */
- if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
- m->enforced_reply_signature &&
- !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
- return -ENOMSG;
-
- /* If gvariant marshalling is used we need to close the body structure */
- r = bus_message_close_struct(m, &m->root_container, false);
- if (r < 0)
- return r;
-
- /* If there's a non-trivial signature set, then add it in
- * here, but only on dbus1 */
- if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) {
- r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
- if (r < 0)
- return r;
- }
-
- if (m->n_fds > 0) {
- r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds);
- if (r < 0)
- return r;
- }
-
- r = bus_message_close_header(m);
- if (r < 0)
- return r;
-
- if (BUS_MESSAGE_IS_GVARIANT(m))
- m->header->dbus2.cookie = cookie;
- else
- m->header->dbus1.serial = (uint32_t) cookie;
-
- m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout;
-
- /* Add padding at the end of the fields part, since we know
- * the body needs to start at an 8 byte alignment. We made
- * sure we allocated enough space for this, so all we need to
- * do here is to zero it out. */
- a = ALIGN8(m->fields_size) - m->fields_size;
- if (a > 0)
- memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a);
-
- /* If this is something we can send as memfd, then let's seal
- the memfd now. Note that we can send memfds as payload only
- for directed messages, and not for broadcasts. */
- if (m->destination && m->bus->use_memfd) {
- MESSAGE_FOREACH_PART(part, i, m)
- if (part->memfd >= 0 &&
- !part->sealed &&
- (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) &&
- part != m->body_end) { /* The last part may never be sent as memfd */
- uint64_t sz;
-
- /* Try to seal it if that makes
- * sense. First, unmap our own map to
- * make sure we don't keep it busy. */
- bus_body_part_unmap(part);
-
- /* Then, sync up real memfd size */
- sz = part->size;
- r = memfd_set_size(part->memfd, sz);
- if (r < 0)
- return r;
-
- /* Finally, try to seal */
- if (memfd_set_sealed(part->memfd) >= 0)
- part->sealed = true;
- }
- }
-
- m->root_container.end = m->user_body_size;
- m->root_container.index = 0;
- m->root_container.offset_index = 0;
- m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0;
-
- m->sealed = true;
-
- return 0;
-}
-
-int bus_body_part_map(struct bus_body_part *part) {
- void *p;
- size_t psz, shift;
-
- assert_se(part);
-
- if (part->data)
- return 0;
-
- if (part->size <= 0)
- return 0;
-
- /* For smaller zero parts (as used for padding) we don't need to map anything... */
- if (part->memfd < 0 && part->is_zero && part->size < 8) {
- static const uint8_t zeroes[7] = { };
- part->data = (void*) zeroes;
- return 0;
- }
-
- shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size());
- psz = PAGE_ALIGN(part->size + shift);
-
- if (part->memfd >= 0)
- p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift);
- else if (part->is_zero)
- p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- else
- return -EINVAL;
-
- if (p == MAP_FAILED)
- return -errno;
-
- part->mapped = psz;
- part->mmap_begin = p;
- part->data = (uint8_t*) p + shift;
- part->munmap_this = true;
-
- return 0;
-}
-
-void bus_body_part_unmap(struct bus_body_part *part) {
-
- assert_se(part);
-
- if (part->memfd < 0)
- return;
-
- if (!part->mmap_begin)
- return;
-
- if (!part->munmap_this)
- return;
-
- assert_se(munmap(part->mmap_begin, part->mapped) == 0);
-
- part->mmap_begin = NULL;
- part->data = NULL;
- part->mapped = 0;
- part->munmap_this = false;
-
- return;
-}
-
-static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
- size_t k, start, end;
-
- assert(rindex);
- assert(align > 0);
-
- start = ALIGN_TO((size_t) *rindex, align);
- end = start + nbytes;
-
- if (end > sz)
- return -EBADMSG;
-
- /* Verify that padding is 0 */
- for (k = *rindex; k < start; k++)
- if (((const uint8_t*) p)[k] != 0)
- return -EBADMSG;
-
- if (r)
- *r = (uint8_t*) p + start;
-
- *rindex = end;
-
- return 1;
-}
-
-static bool message_end_of_signature(sd_bus_message *m) {
- struct bus_container *c;
-
- assert(m);
-
- c = message_get_container(m);
- return !c->signature || c->signature[c->index] == 0;
-}
-
-static bool message_end_of_array(sd_bus_message *m, size_t index) {
- struct bus_container *c;
-
- assert(m);
-
- c = message_get_container(m);
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- return false;
-
- if (BUS_MESSAGE_IS_GVARIANT(m))
- return index >= c->end;
- else {
- assert(c->array_size);
- return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size);
- }
-}
-
-_public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) {
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
-
- if (complete && m->n_containers > 0)
- return false;
-
- if (message_end_of_signature(m))
- return true;
-
- if (message_end_of_array(m, m->rindex))
- return true;
-
- return false;
-}
-
-static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) {
- struct bus_body_part *part;
- size_t begin;
- int r;
-
- assert(m);
-
- if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) {
- part = m->cached_rindex_part;
- begin = m->cached_rindex_part_begin;
- } else {
- part = &m->body;
- begin = 0;
- }
-
- while (part) {
- if (index < begin)
- return NULL;
-
- if (index + sz <= begin + part->size) {
-
- r = bus_body_part_map(part);
- if (r < 0)
- return NULL;
-
- if (p)
- *p = (uint8_t*) part->data + index - begin;
-
- m->cached_rindex_part = part;
- m->cached_rindex_part_begin = begin;
-
- return part;
- }
-
- begin += part->size;
- part = part->next;
- }
-
- return NULL;
-}
-
-static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) {
- int r;
-
- assert(m);
- assert(c);
- assert(rindex);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- return 0;
-
- if (c->enclosing == SD_BUS_TYPE_ARRAY) {
- int sz;
-
- sz = bus_gvariant_get_size(c->signature);
- if (sz < 0) {
- int alignment;
-
- if (c->offset_index+1 >= c->n_offsets)
- goto end;
-
- /* Variable-size array */
-
- alignment = bus_gvariant_get_alignment(c->signature);
- assert(alignment > 0);
-
- *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
- c->item_size = c->offsets[c->offset_index+1] - *rindex;
- } else {
-
- if (c->offset_index+1 >= (c->end-c->begin)/sz)
- goto end;
-
- /* Fixed-size array */
- *rindex = c->begin + (c->offset_index+1) * sz;
- c->item_size = sz;
- }
-
- c->offset_index++;
-
- } else if (c->enclosing == 0 ||
- c->enclosing == SD_BUS_TYPE_STRUCT ||
- c->enclosing == SD_BUS_TYPE_DICT_ENTRY) {
-
- int alignment;
- size_t n, j;
-
- if (c->offset_index+1 >= c->n_offsets)
- goto end;
-
- r = signature_element_length(c->signature + c->index, &n);
- if (r < 0)
- return r;
-
- r = signature_element_length(c->signature + c->index + n, &j);
- if (r < 0)
- return r;
- else {
- char t[j+1];
- memcpy(t, c->signature + c->index + n, j);
- t[j] = 0;
-
- alignment = bus_gvariant_get_alignment(t);
- }
-
- assert(alignment > 0);
-
- *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
- c->item_size = c->offsets[c->offset_index+1] - *rindex;
-
- c->offset_index++;
-
- } else if (c->enclosing == SD_BUS_TYPE_VARIANT)
- goto end;
- else
- assert_not_reached("Unknown container type");
-
- return 0;
-
-end:
- /* Reached the end */
- *rindex = c->end;
- c->item_size = 0;
- return 0;
-}
-
-
-static int message_peek_body(
- sd_bus_message *m,
- size_t *rindex,
- size_t align,
- size_t nbytes,
- void **ret) {
-
- size_t k, start, end, padding;
- struct bus_body_part *part;
- uint8_t *q;
-
- assert(m);
- assert(rindex);
- assert(align > 0);
-
- start = ALIGN_TO((size_t) *rindex, align);
- padding = start - *rindex;
- end = start + nbytes;
-
- if (end > m->user_body_size)
- return -EBADMSG;
-
- part = find_part(m, *rindex, padding, (void**) &q);
- if (!part)
- return -EBADMSG;
-
- if (q) {
- /* Verify padding */
- for (k = 0; k < padding; k++)
- if (q[k] != 0)
- return -EBADMSG;
- }
-
- part = find_part(m, start, nbytes, (void**) &q);
- if (!part || (nbytes > 0 && !q))
- return -EBADMSG;
-
- *rindex = end;
-
- if (ret)
- *ret = q;
-
- return 0;
-}
-
-static bool validate_nul(const char *s, size_t l) {
-
- /* Check for NUL chars in the string */
- if (memchr(s, 0, l))
- return false;
-
- /* Check for NUL termination */
- if (s[l] != 0)
- return false;
-
- return true;
-}
-
-static bool validate_string(const char *s, size_t l) {
-
- if (!validate_nul(s, l))
- return false;
-
- /* Check if valid UTF8 */
- if (!utf8_is_valid(s))
- return false;
-
- return true;
-}
-
-static bool validate_signature(const char *s, size_t l) {
-
- if (!validate_nul(s, l))
- return false;
-
- /* Check if valid signature */
- if (!signature_is_valid(s, true))
- return false;
-
- return true;
-}
-
-static bool validate_object_path(const char *s, size_t l) {
-
- if (!validate_nul(s, l))
- return false;
-
- if (!object_path_is_valid(s))
- return false;
-
- return true;
-}
-
-_public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) {
- struct bus_container *c;
- size_t rindex;
- void *q;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
- assert_return(bus_type_is_basic(type), -EINVAL);
-
- if (message_end_of_signature(m))
- return -ENXIO;
-
- if (message_end_of_array(m, m->rindex))
- return 0;
-
- c = message_get_container(m);
- if (c->signature[c->index] != type)
- return -ENXIO;
-
- rindex = m->rindex;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
- bool ok;
-
- r = message_peek_body(m, &rindex, 1, c->item_size, &q);
- if (r < 0)
- return r;
-
- if (type == SD_BUS_TYPE_STRING)
- ok = validate_string(q, c->item_size-1);
- else if (type == SD_BUS_TYPE_OBJECT_PATH)
- ok = validate_object_path(q, c->item_size-1);
- else
- ok = validate_signature(q, c->item_size-1);
-
- if (!ok)
- return -EBADMSG;
-
- if (p)
- *(const char**) p = q;
- } else {
- int sz, align;
-
- sz = bus_gvariant_get_size(CHAR_TO_STR(type));
- assert(sz > 0);
- if ((size_t) sz != c->item_size)
- return -EBADMSG;
-
- align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
- assert(align > 0);
-
- r = message_peek_body(m, &rindex, align, c->item_size, &q);
- if (r < 0)
- return r;
-
- switch (type) {
-
- case SD_BUS_TYPE_BYTE:
- if (p)
- *(uint8_t*) p = *(uint8_t*) q;
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
- if (p)
- *(int*) p = !!*(uint8_t*) q;
- break;
-
- case SD_BUS_TYPE_INT16:
- case SD_BUS_TYPE_UINT16:
- if (p)
- *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
- break;
-
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_UINT32:
- if (p)
- *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- break;
-
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- if (p)
- *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
- break;
-
- case SD_BUS_TYPE_UNIX_FD: {
- uint32_t j;
-
- j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- if (j >= m->n_fds)
- return -EBADMSG;
-
- if (p)
- *(int*) p = m->fds[j];
-
- break;
- }
-
- default:
- assert_not_reached("unexpected type");
- }
- }
-
- r = container_next_item(m, c, &rindex);
- if (r < 0)
- return r;
- } else {
-
- if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) {
- uint32_t l;
- bool ok;
-
- r = message_peek_body(m, &rindex, 4, 4, &q);
- if (r < 0)
- return r;
-
- l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
-
- if (type == SD_BUS_TYPE_OBJECT_PATH)
- ok = validate_object_path(q, l);
- else
- ok = validate_string(q, l);
- if (!ok)
- return -EBADMSG;
-
- if (p)
- *(const char**) p = q;
-
- } else if (type == SD_BUS_TYPE_SIGNATURE) {
- uint8_t l;
-
- r = message_peek_body(m, &rindex, 1, 1, &q);
- if (r < 0)
- return r;
-
- l = *(uint8_t*) q;
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
-
- if (!validate_signature(q, l))
- return -EBADMSG;
-
- if (p)
- *(const char**) p = q;
-
- } else {
- ssize_t sz, align;
-
- align = bus_type_get_alignment(type);
- assert(align > 0);
-
- sz = bus_type_get_size(type);
- assert(sz > 0);
-
- r = message_peek_body(m, &rindex, align, sz, &q);
- if (r < 0)
- return r;
-
- switch (type) {
-
- case SD_BUS_TYPE_BYTE:
- if (p)
- *(uint8_t*) p = *(uint8_t*) q;
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
- if (p)
- *(int*) p = !!*(uint32_t*) q;
- break;
-
- case SD_BUS_TYPE_INT16:
- case SD_BUS_TYPE_UINT16:
- if (p)
- *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q);
- break;
-
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_UINT32:
- if (p)
- *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- break;
-
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- if (p)
- *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
- break;
-
- case SD_BUS_TYPE_UNIX_FD: {
- uint32_t j;
-
- j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
- if (j >= m->n_fds)
- return -EBADMSG;
-
- if (p)
- *(int*) p = m->fds[j];
- break;
- }
-
- default:
- assert_not_reached("Unknown basic type...");
- }
- }
- }
-
- m->rindex = rindex;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index++;
-
- return 1;
-}
-
-static int bus_message_enter_array(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- uint32_t **array_size,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
-
- size_t rindex;
- void *q;
- int r, alignment;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(array_size);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
-
- if (!signature_is_single(contents, true))
- return -EINVAL;
-
- if (!c->signature || c->signature[c->index] == 0)
- return -ENXIO;
-
- if (c->signature[c->index] != SD_BUS_TYPE_ARRAY)
- return -ENXIO;
-
- if (!startswith(c->signature + c->index + 1, contents))
- return -ENXIO;
-
- rindex = m->rindex;
-
- if (!BUS_MESSAGE_IS_GVARIANT(m)) {
- /* dbus1 */
-
- r = message_peek_body(m, &rindex, 4, 4, &q);
- if (r < 0)
- return r;
-
- if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE)
- return -EBADMSG;
-
- alignment = bus_type_get_alignment(contents[0]);
- if (alignment < 0)
- return alignment;
-
- r = message_peek_body(m, &rindex, alignment, 0, NULL);
- if (r < 0)
- return r;
-
- *array_size = (uint32_t*) q;
-
- } else if (c->item_size <= 0) {
-
- /* gvariant: empty array */
- *item_size = 0;
- *offsets = NULL;
- *n_offsets = 0;
-
- } else if (bus_gvariant_is_fixed_size(contents)) {
-
- /* gvariant: fixed length array */
- *item_size = bus_gvariant_get_size(contents);
- *offsets = NULL;
- *n_offsets = 0;
-
- } else {
- size_t where, p = 0, framing, sz;
- unsigned i;
-
- /* gvariant: variable length array */
- sz = bus_gvariant_determine_word_size(c->item_size, 0);
-
- where = rindex + c->item_size - sz;
- r = message_peek_body(m, &where, 1, sz, &q);
- if (r < 0)
- return r;
-
- framing = bus_gvariant_read_word_le(q, sz);
- if (framing > c->item_size - sz)
- return -EBADMSG;
- if ((c->item_size - framing) % sz != 0)
- return -EBADMSG;
-
- *n_offsets = (c->item_size - framing) / sz;
-
- where = rindex + framing;
- r = message_peek_body(m, &where, 1, *n_offsets * sz, &q);
- if (r < 0)
- return r;
-
- *offsets = new(size_t, *n_offsets);
- if (!*offsets)
- return -ENOMEM;
-
- for (i = 0; i < *n_offsets; i++) {
- size_t x;
-
- x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz);
- if (x > c->item_size - sz)
- return -EBADMSG;
- if (x < p)
- return -EBADMSG;
-
- (*offsets)[i] = rindex + x;
- p = x;
- }
-
- *item_size = (*offsets)[0] - rindex;
- }
-
- m->rindex = rindex;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index += 1 + strlen(contents);
-
- return 1;
-}
-
-static int bus_message_enter_variant(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- size_t *item_size) {
-
- size_t rindex;
- uint8_t l;
- void *q;
- int r;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(item_size);
-
- if (!signature_is_single(contents, false))
- return -EINVAL;
-
- if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
- return -EINVAL;
-
- if (!c->signature || c->signature[c->index] == 0)
- return -ENXIO;
-
- if (c->signature[c->index] != SD_BUS_TYPE_VARIANT)
- return -ENXIO;
-
- rindex = m->rindex;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t k, where;
-
- k = strlen(contents);
- if (1+k > c->item_size)
- return -EBADMSG;
-
- where = rindex + c->item_size - (1+k);
- r = message_peek_body(m, &where, 1, 1+k, &q);
- if (r < 0)
- return r;
-
- if (*(char*) q != 0)
- return -EBADMSG;
-
- if (memcmp((uint8_t*) q+1, contents, k))
- return -ENXIO;
-
- *item_size = c->item_size - (1+k);
-
- } else {
- r = message_peek_body(m, &rindex, 1, 1, &q);
- if (r < 0)
- return r;
-
- l = *(uint8_t*) q;
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
-
- if (!validate_signature(q, l))
- return -EBADMSG;
-
- if (!streq(q, contents))
- return -ENXIO;
- }
-
- m->rindex = rindex;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index++;
-
- return 1;
-}
-
-static int build_struct_offsets(
- sd_bus_message *m,
- const char *signature,
- size_t size,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
-
- unsigned n_variable = 0, n_total = 0, v;
- size_t previous = 0, where;
- const char *p;
- size_t sz;
- void *q;
- int r;
-
- assert(m);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
-
- if (isempty(signature)) {
- /* Unary type is encoded as *fixed* 1 byte padding */
- r = message_peek_body(m, &m->rindex, 1, 1, &q);
- if (r < 0)
- return r;
-
- if (*(uint8_t *) q != 0)
- return -EBADMSG;
-
- *item_size = 0;
- *offsets = NULL;
- *n_offsets = 0;
- return 0;
- }
-
- sz = bus_gvariant_determine_word_size(size, 0);
- if (sz <= 0)
- return -EBADMSG;
-
- /* First, loop over signature and count variable elements and
- * elements in general. We use this to know how large the
- * offset array is at the end of the structure. Note that
- * GVariant only stores offsets for all variable size elements
- * that are not the last item. */
-
- 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_is_fixed_size(t);
- }
-
- if (r < 0)
- return r;
- if (r == 0 && p[n] != 0) /* except the last item */
- n_variable++;
- n_total++;
-
- p += n;
- }
-
- if (size < n_variable * sz)
- return -EBADMSG;
-
- where = m->rindex + size - (n_variable * sz);
- r = message_peek_body(m, &where, 1, n_variable * sz, &q);
- if (r < 0)
- return r;
-
- v = n_variable;
-
- *offsets = new(size_t, n_total);
- if (!*offsets)
- return -ENOMEM;
-
- *n_offsets = 0;
-
- /* Second, loop again and build an offset table */
- p = signature;
- while (*p != 0) {
- size_t n, offset;
- int k;
-
- r = signature_element_length(p, &n);
- if (r < 0)
- return r;
- else {
- char t[n+1];
-
- memcpy(t, p, n);
- t[n] = 0;
-
- k = bus_gvariant_get_size(t);
- if (k < 0) {
- size_t x;
-
- /* variable size */
- if (v > 0) {
- v--;
-
- x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
- if (x >= size)
- return -EBADMSG;
- if (m->rindex + x < previous)
- return -EBADMSG;
- } else
- /* The last item's end
- * is determined from
- * the start of the
- * offset array */
- x = size - (n_variable * sz);
-
- offset = m->rindex + x;
-
- } else {
- size_t align;
-
- /* fixed size */
- align = bus_gvariant_get_alignment(t);
- assert(align > 0);
-
- offset = (*n_offsets == 0 ? m->rindex : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
- }
- }
-
- previous = (*offsets)[(*n_offsets)++] = offset;
- p += n;
- }
-
- assert(v == 0);
- assert(*n_offsets == n_total);
-
- *item_size = (*offsets)[0] - m->rindex;
- return 0;
-}
-
-static int enter_struct_or_dict_entry(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
-
- int r;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
-
- if (!BUS_MESSAGE_IS_GVARIANT(m)) {
-
- /* dbus1 */
- r = message_peek_body(m, &m->rindex, 8, 0, NULL);
- if (r < 0)
- return r;
-
- } else
- /* gvariant with contents */
- return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets);
-
- return 0;
-}
-
-static int bus_message_enter_struct(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
-
- size_t l;
- int r;
-
- assert(m);
- assert(c);
- assert(contents);
- assert(item_size);
- assert(offsets);
- assert(n_offsets);
-
- if (!signature_is_valid(contents, false))
- return -EINVAL;
-
- if (!c->signature || c->signature[c->index] == 0)
- return -ENXIO;
-
- l = strlen(contents);
-
- if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN ||
- !startswith(c->signature + c->index + 1, contents) ||
- c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END)
- return -ENXIO;
-
- r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
- if (r < 0)
- return r;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index += 1 + l + 1;
-
- return 1;
-}
-
-static int bus_message_enter_dict_entry(
- sd_bus_message *m,
- struct bus_container *c,
- const char *contents,
- size_t *item_size,
- size_t **offsets,
- size_t *n_offsets) {
-
- size_t l;
- int r;
-
- assert(m);
- assert(c);
- assert(contents);
-
- if (!signature_is_pair(contents))
- return -EINVAL;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- return -ENXIO;
-
- if (!c->signature || c->signature[c->index] == 0)
- return 0;
-
- l = strlen(contents);
-
- if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN ||
- !startswith(c->signature + c->index + 1, contents) ||
- c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END)
- return -ENXIO;
-
- r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets);
- if (r < 0)
- return r;
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY)
- c->index += 1 + l + 1;
-
- return 1;
-}
-
-_public_ int sd_bus_message_enter_container(sd_bus_message *m,
- char type,
- const char *contents) {
- struct bus_container *c, *w;
- uint32_t *array_size = NULL;
- char *signature;
- size_t before;
- size_t *offsets = NULL;
- size_t n_offsets = 0, item_size = 0;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
- assert_return(type != 0 || !contents, -EINVAL);
-
- if (type == 0 || !contents) {
- const char *cc;
- char tt;
-
- /* Allow entering into anonymous containers */
- r = sd_bus_message_peek_type(m, &tt, &cc);
- if (r < 0)
- return r;
-
- if (type != 0 && type != tt)
- return -ENXIO;
-
- if (contents && !streq(contents, cc))
- return -ENXIO;
-
- type = tt;
- contents = cc;
- }
-
- /*
- * We enforce a global limit on container depth, that is much
- * higher than the 32 structs and 32 arrays the specification
- * mandates. This is simpler to implement for us, and we need
- * this only to ensure our container array doesn't grow
- * without bounds. We are happy to return any data from a
- * message as long as the data itself is valid, even if the
- * overall message might be not.
- *
- * Note that the message signature is validated when
- * parsing the headers, and that validation does check the
- * 32/32 limit.
- *
- * Note that the specification defines no limits on the depth
- * of stacked variants, but we do.
- */
- if (m->n_containers >= BUS_CONTAINER_DEPTH)
- return -EBADMSG;
-
- if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1))
- return -ENOMEM;
-
- if (message_end_of_signature(m))
- return -ENXIO;
-
- if (message_end_of_array(m, m->rindex))
- return 0;
-
- c = message_get_container(m);
-
- signature = strdup(contents);
- if (!signature)
- return -ENOMEM;
-
- c->saved_index = c->index;
- before = m->rindex;
-
- if (type == SD_BUS_TYPE_ARRAY)
- r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets);
- else if (type == SD_BUS_TYPE_VARIANT)
- r = bus_message_enter_variant(m, c, contents, &item_size);
- else if (type == SD_BUS_TYPE_STRUCT)
- r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets);
- else if (type == SD_BUS_TYPE_DICT_ENTRY)
- r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets);
- else
- r = -EINVAL;
-
- if (r <= 0) {
- free(signature);
- free(offsets);
- return r;
- }
-
- /* OK, let's fill it in */
- w = m->containers + m->n_containers++;
- w->enclosing = type;
- w->signature = signature;
- w->peeked_signature = NULL;
- w->index = 0;
-
- w->before = before;
- w->begin = m->rindex;
-
- /* Unary type has fixed size of 1, but virtual size of 0 */
- if (BUS_MESSAGE_IS_GVARIANT(m) &&
- type == SD_BUS_TYPE_STRUCT &&
- isempty(signature))
- w->end = m->rindex + 0;
- else
- w->end = m->rindex + c->item_size;
-
- w->array_size = array_size;
- w->item_size = item_size;
- w->offsets = offsets;
- w->n_offsets = n_offsets;
- w->offset_index = 0;
-
- return 1;
-}
-
-_public_ int sd_bus_message_exit_container(sd_bus_message *m) {
- struct bus_container *c;
- unsigned saved;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
- assert_return(m->n_containers > 0, -ENXIO);
-
- c = message_get_container(m);
-
- if (c->enclosing != SD_BUS_TYPE_ARRAY) {
- if (c->signature && c->signature[c->index] != 0)
- return -EBUSY;
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- if (m->rindex < c->end)
- return -EBUSY;
-
- } else if (c->enclosing == SD_BUS_TYPE_ARRAY) {
- uint32_t l;
-
- l = BUS_MESSAGE_BSWAP32(m, *c->array_size);
- if (c->begin + l != m->rindex)
- return -EBUSY;
- }
-
- free(c->signature);
- free(c->peeked_signature);
- free(c->offsets);
- m->n_containers--;
-
- c = message_get_container(m);
-
- saved = c->index;
- c->index = c->saved_index;
- r = container_next_item(m, c, &m->rindex);
- c->index = saved;
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static void message_quit_container(sd_bus_message *m) {
- struct bus_container *c;
-
- assert(m);
- assert(m->sealed);
- assert(m->n_containers > 0);
-
- c = message_get_container(m);
-
- /* Undo seeks */
- assert(m->rindex >= c->before);
- m->rindex = c->before;
-
- /* Free container */
- free(c->signature);
- free(c->offsets);
- m->n_containers--;
-
- /* Correct index of new top-level container */
- c = message_get_container(m);
- c->index = c->saved_index;
-}
-
-_public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) {
- struct bus_container *c;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
-
- if (message_end_of_signature(m))
- goto eof;
-
- if (message_end_of_array(m, m->rindex))
- goto eof;
-
- c = message_get_container(m);
-
- if (bus_type_is_basic(c->signature[c->index])) {
- if (contents)
- *contents = NULL;
- if (type)
- *type = c->signature[c->index];
- return 1;
- }
-
- if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) {
-
- if (contents) {
- size_t l;
- char *sig;
-
- r = signature_element_length(c->signature+c->index+1, &l);
- if (r < 0)
- return r;
-
- assert(l >= 1);
-
- sig = strndup(c->signature + c->index + 1, l);
- if (!sig)
- return -ENOMEM;
-
- free(c->peeked_signature);
- *contents = c->peeked_signature = sig;
- }
-
- if (type)
- *type = SD_BUS_TYPE_ARRAY;
-
- return 1;
- }
-
- if (c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ||
- c->signature[c->index] == SD_BUS_TYPE_DICT_ENTRY_BEGIN) {
-
- if (contents) {
- size_t l;
- char *sig;
-
- r = signature_element_length(c->signature+c->index, &l);
- if (r < 0)
- return r;
-
- assert(l >= 2);
- sig = strndup(c->signature + c->index + 1, l - 2);
- if (!sig)
- return -ENOMEM;
-
- free(c->peeked_signature);
- *contents = c->peeked_signature = sig;
- }
-
- if (type)
- *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
-
- return 1;
- }
-
- if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) {
- if (contents) {
- void *q;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t k;
-
- if (c->item_size < 2)
- return -EBADMSG;
-
- /* Look for the NUL delimiter that
- separates the payload from the
- signature. Since the body might be
- in a different part that then the
- signature we map byte by byte. */
-
- for (k = 2; k <= c->item_size; k++) {
- size_t where;
-
- where = m->rindex + c->item_size - k;
- r = message_peek_body(m, &where, 1, k, &q);
- if (r < 0)
- return r;
-
- if (*(char*) q == 0)
- break;
- }
-
- if (k > c->item_size)
- return -EBADMSG;
-
- free(c->peeked_signature);
- c->peeked_signature = strndup((char*) q + 1, k - 1);
- if (!c->peeked_signature)
- return -ENOMEM;
-
- if (!signature_is_valid(c->peeked_signature, true))
- return -EBADMSG;
-
- *contents = c->peeked_signature;
- } else {
- size_t rindex, l;
-
- rindex = m->rindex;
- r = message_peek_body(m, &rindex, 1, 1, &q);
- if (r < 0)
- return r;
-
- l = *(uint8_t*) q;
- r = message_peek_body(m, &rindex, 1, l+1, &q);
- if (r < 0)
- return r;
-
- if (!validate_signature(q, l))
- return -EBADMSG;
-
- *contents = q;
- }
- }
-
- if (type)
- *type = SD_BUS_TYPE_VARIANT;
-
- return 1;
- }
-
- return -EINVAL;
-
-eof:
- if (type)
- *type = 0;
- if (contents)
- *contents = NULL;
- return 0;
-}
-
-_public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
- struct bus_container *c;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
-
- if (complete) {
- message_reset_containers(m);
- m->rindex = 0;
-
- c = message_get_container(m);
- } else {
- c = message_get_container(m);
-
- c->offset_index = 0;
- c->index = 0;
- m->rindex = c->begin;
- }
-
- c->offset_index = 0;
- c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin;
-
- return !isempty(c->signature);
-}
-
-static int message_read_ap(
- sd_bus_message *m,
- const char *types,
- va_list ap) {
-
- unsigned n_array, n_struct;
- TypeStack stack[BUS_CONTAINER_DEPTH];
- unsigned stack_ptr = 0;
- unsigned n_loop = 0;
- int r;
-
- assert(m);
-
- if (isempty(types))
- return 0;
-
- /* Ideally, we'd just call ourselves recursively on every
- * complex type. However, the state of a va_list that is
- * passed to a function is undefined after that function
- * returns. This means we need to docode the va_list linearly
- * in a single stackframe. We hence implement our own
- * home-grown stack in an array. */
-
- n_array = (unsigned) -1; /* length of current array entries */
- n_struct = strlen(types); /* length of current struct contents signature */
-
- for (;;) {
- const char *t;
-
- n_loop++;
-
- if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) {
- r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- continue;
- }
-
- t = types;
- if (n_array != (unsigned) -1)
- n_array--;
- else {
- types++;
- n_struct--;
- }
-
- switch (*t) {
-
- 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_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_SIGNATURE:
- case SD_BUS_TYPE_UNIX_FD: {
- void *p;
-
- p = va_arg(ap, void*);
- r = sd_bus_message_read_basic(m, *t, p);
- if (r < 0)
- return r;
- if (r == 0) {
- if (n_loop <= 1)
- return 0;
-
- return -ENXIO;
- }
-
- break;
- }
-
- case SD_BUS_TYPE_ARRAY: {
- size_t k;
-
- r = signature_element_length(t + 1, &k);
- if (r < 0)
- return r;
-
- {
- char s[k + 1];
- memcpy(s, t + 1, k);
- s[k] = 0;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
- if (r < 0)
- return r;
- if (r == 0) {
- if (n_loop <= 1)
- return 0;
-
- return -ENXIO;
- }
- }
-
- if (n_array == (unsigned) -1) {
- types += k;
- n_struct -= k;
- }
-
- r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
- if (r < 0)
- return r;
-
- types = t + 1;
- n_struct = k;
- n_array = va_arg(ap, unsigned);
-
- break;
- }
-
- case SD_BUS_TYPE_VARIANT: {
- const char *s;
-
- s = va_arg(ap, const char *);
- if (!s)
- return -EINVAL;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s);
- if (r < 0)
- return r;
- if (r == 0) {
- if (n_loop <= 1)
- return 0;
-
- return -ENXIO;
- }
-
- r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
- if (r < 0)
- return r;
-
- types = s;
- n_struct = strlen(s);
- n_array = (unsigned) -1;
-
- break;
- }
-
- case SD_BUS_TYPE_STRUCT_BEGIN:
- case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
- size_t k;
-
- r = signature_element_length(t, &k);
- if (r < 0)
- return r;
-
- {
- char s[k - 1];
- memcpy(s, t + 1, k - 2);
- s[k - 2] = 0;
-
- r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
- if (r < 0)
- return r;
- if (r == 0) {
- if (n_loop <= 1)
- return 0;
- return -ENXIO;
- }
- }
-
- if (n_array == (unsigned) -1) {
- types += k - 1;
- n_struct -= k - 1;
- }
-
- r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array);
- if (r < 0)
- return r;
-
- types = t + 1;
- n_struct = k - 2;
- n_array = (unsigned) -1;
-
- break;
- }
-
- default:
- return -EINVAL;
- }
- }
-
- return 1;
-}
-
-_public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) {
- va_list ap;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
- assert_return(types, -EINVAL);
-
- va_start(ap, types);
- r = message_read_ap(m, types, ap);
- va_end(ap);
-
- return r;
-}
-
-_public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) {
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
-
- /* If types is NULL, read exactly one element */
- if (!types) {
- struct bus_container *c;
- size_t l;
-
- if (message_end_of_signature(m))
- return -ENXIO;
-
- if (message_end_of_array(m, m->rindex))
- return 0;
-
- c = message_get_container(m);
-
- r = signature_element_length(c->signature + c->index, &l);
- if (r < 0)
- return r;
-
- types = strndupa(c->signature + c->index, l);
- }
-
- switch (*types) {
-
- case 0: /* Nothing to drop */
- 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_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_SIGNATURE:
- case SD_BUS_TYPE_UNIX_FD:
-
- r = sd_bus_message_read_basic(m, *types, NULL);
- if (r <= 0)
- return r;
-
- r = sd_bus_message_skip(m, types + 1);
- if (r < 0)
- return r;
-
- return 1;
-
- case SD_BUS_TYPE_ARRAY: {
- size_t k;
-
- r = signature_element_length(types + 1, &k);
- if (r < 0)
- return r;
-
- {
- char s[k+1];
- memcpy(s, types+1, k);
- s[k] = 0;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s);
- if (r <= 0)
- return r;
-
- for (;;) {
- r = sd_bus_message_skip(m, s);
- if (r < 0)
- return r;
- if (r == 0)
- break;
- }
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_skip(m, types + 1 + k);
- if (r < 0)
- return r;
-
- return 1;
- }
-
- case SD_BUS_TYPE_VARIANT: {
- const char *contents;
- char x;
-
- r = sd_bus_message_peek_type(m, &x, &contents);
- if (r <= 0)
- return r;
-
- if (x != SD_BUS_TYPE_VARIANT)
- return -ENXIO;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
- if (r <= 0)
- return r;
-
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return r;
- assert(r != 0);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_message_skip(m, types + 1);
- if (r < 0)
- return r;
-
- return 1;
- }
-
- case SD_BUS_TYPE_STRUCT_BEGIN:
- case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
- size_t k;
-
- r = signature_element_length(types, &k);
- if (r < 0)
- return r;
-
- {
- char s[k-1];
- memcpy(s, types+1, k-2);
- s[k-2] = 0;
-
- r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
- if (r <= 0)
- return r;
-
- r = sd_bus_message_skip(m, s);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_skip(m, types + k);
- if (r < 0)
- return r;
-
- return 1;
- }
-
- default:
- return -EINVAL;
- }
-}
-
-_public_ int sd_bus_message_read_array(
- sd_bus_message *m,
- char type,
- const void **ptr,
- size_t *size) {
-
- struct bus_container *c;
- void *p;
- size_t sz;
- ssize_t align;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
- assert_return(bus_type_is_trivial(type), -EINVAL);
- assert_return(ptr, -EINVAL);
- assert_return(size, -EINVAL);
- assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP);
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type));
- if (r <= 0)
- return r;
-
- c = message_get_container(m);
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- align = bus_gvariant_get_alignment(CHAR_TO_STR(type));
- if (align < 0)
- return align;
-
- sz = c->end - c->begin;
- } else {
- align = bus_type_get_alignment(type);
- if (align < 0)
- return align;
-
- sz = BUS_MESSAGE_BSWAP32(m, *c->array_size);
- }
-
- if (sz == 0)
- /* Zero length array, let's return some aligned
- * pointer that is not NULL */
- p = (uint8_t*) NULL + align;
- else {
- r = message_peek_body(m, &m->rindex, align, sz, &p);
- if (r < 0)
- goto fail;
- }
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- goto fail;
-
- *ptr = (const void*) p;
- *size = sz;
-
- return 1;
-
-fail:
- message_quit_container(m);
- return r;
-}
-
-static int message_peek_fields(
- sd_bus_message *m,
- size_t *rindex,
- size_t align,
- size_t nbytes,
- void **ret) {
-
- assert(m);
- assert(rindex);
- assert(align > 0);
-
- return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret);
-}
-
-static int message_peek_field_uint32(
- sd_bus_message *m,
- size_t *ri,
- size_t item_size,
- uint32_t *ret) {
-
- int r;
- void *q;
-
- assert(m);
- assert(ri);
-
- if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4)
- return -EBADMSG;
-
- /* identical for gvariant and dbus1 */
-
- r = message_peek_fields(m, ri, 4, 4, &q);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q);
-
- return 0;
-}
-
-static int message_peek_field_uint64(
- sd_bus_message *m,
- size_t *ri,
- size_t item_size,
- uint64_t *ret) {
-
- int r;
- void *q;
-
- assert(m);
- assert(ri);
-
- if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8)
- return -EBADMSG;
-
- /* identical for gvariant and dbus1 */
-
- r = message_peek_fields(m, ri, 8, 8, &q);
- if (r < 0)
- return r;
-
- if (ret)
- *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q);
-
- return 0;
-}
-
-static int message_peek_field_string(
- sd_bus_message *m,
- bool (*validate)(const char *p),
- size_t *ri,
- size_t item_size,
- const char **ret) {
-
- uint32_t l;
- int r;
- void *q;
-
- assert(m);
- assert(ri);
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- if (item_size <= 0)
- return -EBADMSG;
-
- r = message_peek_fields(m, ri, 1, item_size, &q);
- if (r < 0)
- return r;
-
- l = item_size - 1;
- } else {
- r = message_peek_field_uint32(m, ri, 4, &l);
- if (r < 0)
- return r;
-
- r = message_peek_fields(m, ri, 1, l+1, &q);
- if (r < 0)
- return r;
- }
-
- if (validate) {
- if (!validate_nul(q, l))
- return -EBADMSG;
-
- if (!validate(q))
- return -EBADMSG;
- } else {
- if (!validate_string(q, l))
- return -EBADMSG;
- }
-
- if (ret)
- *ret = q;
-
- return 0;
-}
-
-static int message_peek_field_signature(
- sd_bus_message *m,
- size_t *ri,
- size_t item_size,
- const char **ret) {
-
- size_t l;
- int r;
- void *q;
-
- assert(m);
- assert(ri);
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
-
- if (item_size <= 0)
- return -EBADMSG;
-
- r = message_peek_fields(m, ri, 1, item_size, &q);
- if (r < 0)
- return r;
-
- l = item_size - 1;
- } else {
- r = message_peek_fields(m, ri, 1, 1, &q);
- if (r < 0)
- return r;
-
- l = *(uint8_t*) q;
- r = message_peek_fields(m, ri, 1, l+1, &q);
- if (r < 0)
- return r;
- }
-
- if (!validate_signature(q, l))
- return -EBADMSG;
-
- if (ret)
- *ret = q;
-
- return 0;
-}
-
-static int message_skip_fields(
- sd_bus_message *m,
- size_t *ri,
- uint32_t array_size,
- const char **signature) {
-
- size_t original_index;
- int r;
-
- assert(m);
- assert(ri);
- assert(signature);
- assert(!BUS_MESSAGE_IS_GVARIANT(m));
-
- original_index = *ri;
-
- for (;;) {
- char t;
- size_t l;
-
- if (array_size != (uint32_t) -1 &&
- array_size <= *ri - original_index)
- return 0;
-
- t = **signature;
- if (!t)
- return 0;
-
- if (t == SD_BUS_TYPE_STRING) {
-
- r = message_peek_field_string(m, NULL, ri, 0, NULL);
- if (r < 0)
- return r;
-
- (*signature)++;
-
- } else if (t == SD_BUS_TYPE_OBJECT_PATH) {
-
- r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL);
- if (r < 0)
- return r;
-
- (*signature)++;
-
- } else if (t == SD_BUS_TYPE_SIGNATURE) {
-
- r = message_peek_field_signature(m, ri, 0, NULL);
- if (r < 0)
- return r;
-
- (*signature)++;
-
- } else if (bus_type_is_basic(t)) {
- ssize_t align, k;
-
- align = bus_type_get_alignment(t);
- k = bus_type_get_size(t);
- assert(align > 0 && k > 0);
-
- r = message_peek_fields(m, ri, align, k, NULL);
- if (r < 0)
- return r;
-
- (*signature)++;
-
- } else if (t == SD_BUS_TYPE_ARRAY) {
-
- r = signature_element_length(*signature+1, &l);
- if (r < 0)
- return r;
-
- assert(l >= 1);
- {
- char sig[l-1], *s;
- uint32_t nas;
- int alignment;
-
- strncpy(sig, *signature + 1, l-1);
- s = sig;
-
- alignment = bus_type_get_alignment(sig[0]);
- if (alignment < 0)
- return alignment;
-
- r = message_peek_field_uint32(m, ri, 0, &nas);
- if (r < 0)
- return r;
- if (nas > BUS_ARRAY_MAX_SIZE)
- return -EBADMSG;
-
- r = message_peek_fields(m, ri, alignment, 0, NULL);
- if (r < 0)
- return r;
-
- r = message_skip_fields(m, ri, nas, (const char**) &s);
- if (r < 0)
- return r;
- }
-
- (*signature) += 1 + l;
-
- } else if (t == SD_BUS_TYPE_VARIANT) {
- const char *s;
-
- r = message_peek_field_signature(m, ri, 0, &s);
- if (r < 0)
- return r;
-
- r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
- if (r < 0)
- return r;
-
- (*signature)++;
-
- } else if (t == SD_BUS_TYPE_STRUCT ||
- t == SD_BUS_TYPE_DICT_ENTRY) {
-
- r = signature_element_length(*signature, &l);
- if (r < 0)
- return r;
-
- assert(l >= 2);
- {
- char sig[l-1], *s;
- strncpy(sig, *signature + 1, l-1);
- s = sig;
-
- r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s);
- if (r < 0)
- return r;
- }
-
- *signature += l;
- } else
- return -EINVAL;
- }
-}
-
-int bus_message_parse_fields(sd_bus_message *m) {
- size_t ri;
- int r;
- uint32_t unix_fds = 0;
- bool unix_fds_set = false;
- void *offsets = NULL;
- unsigned n_offsets = 0;
- size_t sz = 0;
- unsigned i = 0;
-
- assert(m);
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- char *p;
-
- /* Read the signature from the end of the body variant first */
- sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0);
- if (m->footer_accessible < 1 + sz)
- return -EBADMSG;
-
- p = (char*) m->footer + m->footer_accessible - (1 + sz);
- for (;;) {
- if (p < (char*) m->footer)
- return -EBADMSG;
-
- if (*p == 0) {
- size_t l;
- char *c;
-
- /* We found the beginning of the signature
- * string, yay! We require the body to be a
- * structure, so verify it and then strip the
- * opening/closing brackets. */
-
- l = ((char*) m->footer + m->footer_accessible) - p - (1 + sz);
- if (l < 2 ||
- p[1] != SD_BUS_TYPE_STRUCT_BEGIN ||
- p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END)
- return -EBADMSG;
-
- c = strndup(p + 1 + 1, l - 2);
- if (!c)
- return -ENOMEM;
-
- free(m->root_container.signature);
- m->root_container.signature = c;
- break;
- }
-
- p--;
- }
-
- /* Calculate the actual user body size, by removing
- * the trailing variant signature and struct offset
- * table */
- m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
-
- /* Pull out the offset table for the fields array */
- sz = bus_gvariant_determine_word_size(m->fields_size, 0);
- if (sz > 0) {
- size_t framing;
- void *q;
-
- ri = m->fields_size - sz;
- r = message_peek_fields(m, &ri, 1, sz, &q);
- if (r < 0)
- return r;
-
- framing = bus_gvariant_read_word_le(q, sz);
- if (framing >= m->fields_size - sz)
- return -EBADMSG;
- if ((m->fields_size - framing) % sz != 0)
- return -EBADMSG;
-
- ri = framing;
- r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
- if (r < 0)
- return r;
-
- n_offsets = (m->fields_size - framing) / sz;
- }
- } else
- m->user_body_size = m->body_size;
-
- ri = 0;
- while (ri < m->fields_size) {
- _cleanup_free_ char *sig = NULL;
- const char *signature;
- uint64_t field_type;
- size_t item_size = (size_t) -1;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- uint64_t *u64;
-
- if (i >= n_offsets)
- break;
-
- if (i == 0)
- ri = 0;
- else
- ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8);
-
- r = message_peek_fields(m, &ri, 8, 8, (void**) &u64);
- if (r < 0)
- return r;
-
- field_type = BUS_MESSAGE_BSWAP64(m, *u64);
- } else {
- uint8_t *u8;
-
- r = message_peek_fields(m, &ri, 8, 1, (void**) &u8);
- if (r < 0)
- return r;
-
- field_type = *u8;
- }
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- size_t where, end;
- char *b;
- void *q;
-
- end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz);
-
- if (end < ri)
- return -EBADMSG;
-
- where = ri = ALIGN_TO(ri, 8);
- item_size = end - ri;
- r = message_peek_fields(m, &where, 1, item_size, &q);
- if (r < 0)
- return r;
-
- b = memrchr(q, 0, item_size);
- if (!b)
- return -EBADMSG;
-
- sig = strndup(b+1, item_size - (b+1-(char*) q));
- if (!sig)
- return -ENOMEM;
-
- signature = sig;
- item_size = b - (char*) q;
- } else {
- r = message_peek_field_signature(m, &ri, 0, &signature);
- if (r < 0)
- return r;
- }
-
- switch (field_type) {
-
- case _BUS_MESSAGE_HEADER_INVALID:
- return -EBADMSG;
-
- case BUS_MESSAGE_HEADER_PATH:
-
- if (m->path)
- return -EBADMSG;
-
- if (!streq(signature, "o"))
- return -EBADMSG;
-
- r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path);
- break;
-
- case BUS_MESSAGE_HEADER_INTERFACE:
-
- if (m->interface)
- return -EBADMSG;
-
- if (!streq(signature, "s"))
- return -EBADMSG;
-
- r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface);
- break;
-
- case BUS_MESSAGE_HEADER_MEMBER:
-
- if (m->member)
- return -EBADMSG;
-
- if (!streq(signature, "s"))
- return -EBADMSG;
-
- r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member);
- break;
-
- case BUS_MESSAGE_HEADER_ERROR_NAME:
-
- if (m->error.name)
- return -EBADMSG;
-
- if (!streq(signature, "s"))
- return -EBADMSG;
-
- r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name);
- if (r >= 0)
- m->error._need_free = -1;
-
- break;
-
- case BUS_MESSAGE_HEADER_DESTINATION:
-
- if (m->destination)
- return -EBADMSG;
-
- if (!streq(signature, "s"))
- return -EBADMSG;
-
- r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination);
- break;
-
- case BUS_MESSAGE_HEADER_SENDER:
-
- if (m->sender)
- return -EBADMSG;
-
- if (!streq(signature, "s"))
- return -EBADMSG;
-
- r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender);
-
- if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) {
- m->creds.unique_name = (char*) m->sender;
- m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask;
- }
-
- break;
-
-
- case BUS_MESSAGE_HEADER_SIGNATURE: {
- const char *s;
- char *c;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */
- return -EBADMSG;
-
- if (m->root_container.signature)
- return -EBADMSG;
-
- if (!streq(signature, "g"))
- return -EBADMSG;
-
- r = message_peek_field_signature(m, &ri, item_size, &s);
- if (r < 0)
- return r;
-
- c = strdup(s);
- if (!c)
- return -ENOMEM;
-
- free(m->root_container.signature);
- m->root_container.signature = c;
- break;
- }
-
- case BUS_MESSAGE_HEADER_REPLY_SERIAL:
-
- if (m->reply_cookie != 0)
- return -EBADMSG;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- /* 64bit on dbus2 */
-
- if (!streq(signature, "t"))
- return -EBADMSG;
-
- r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie);
- if (r < 0)
- return r;
- } else {
- /* 32bit on dbus1 */
- uint32_t serial;
-
- if (!streq(signature, "u"))
- return -EBADMSG;
-
- r = message_peek_field_uint32(m, &ri, item_size, &serial);
- if (r < 0)
- return r;
-
- m->reply_cookie = serial;
- }
-
- if (m->reply_cookie == 0)
- return -EBADMSG;
-
- break;
-
- case BUS_MESSAGE_HEADER_UNIX_FDS:
- if (unix_fds_set)
- return -EBADMSG;
-
- if (!streq(signature, "u"))
- return -EBADMSG;
-
- r = message_peek_field_uint32(m, &ri, item_size, &unix_fds);
- if (r < 0)
- return -EBADMSG;
-
- unix_fds_set = true;
- break;
-
- default:
- if (!BUS_MESSAGE_IS_GVARIANT(m))
- r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature);
- }
-
- if (r < 0)
- return r;
-
- i++;
- }
-
- if (m->n_fds != unix_fds)
- return -EBADMSG;
-
- switch (m->header->type) {
-
- case SD_BUS_MESSAGE_SIGNAL:
- if (!m->path || !m->interface || !m->member)
- return -EBADMSG;
-
- if (m->reply_cookie != 0)
- return -EBADMSG;
-
- break;
-
- case SD_BUS_MESSAGE_METHOD_CALL:
-
- if (!m->path || !m->member)
- return -EBADMSG;
-
- if (m->reply_cookie != 0)
- return -EBADMSG;
-
- break;
-
- case SD_BUS_MESSAGE_METHOD_RETURN:
-
- if (m->reply_cookie == 0)
- return -EBADMSG;
- break;
-
- case SD_BUS_MESSAGE_METHOD_ERROR:
-
- if (m->reply_cookie == 0 || !m->error.name)
- return -EBADMSG;
- break;
- }
-
- /* Refuse non-local messages that claim they are local */
- if (streq_ptr(m->path, "/org/freedesktop/DBus/Local"))
- return -EBADMSG;
- if (streq_ptr(m->interface, "org.freedesktop.DBus.Local"))
- return -EBADMSG;
- if (streq_ptr(m->sender, "org.freedesktop.DBus.Local"))
- return -EBADMSG;
-
- m->root_container.end = m->user_body_size;
-
- if (BUS_MESSAGE_IS_GVARIANT(m)) {
- r = build_struct_offsets(
- m,
- m->root_container.signature,
- m->user_body_size,
- &m->root_container.item_size,
- &m->root_container.offsets,
- &m->root_container.n_offsets);
- if (r < 0)
- return r;
- }
-
- /* Try to read the error message, but if we can't it's a non-issue */
- if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
- (void) sd_bus_message_read(m, "s", &m->error.message);
-
- return 0;
-}
-
-_public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) {
- assert_return(m, -EINVAL);
- assert_return(destination, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(!m->destination, -EEXIST);
-
- return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
-}
-
-int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
- size_t total;
- void *p, *e;
- unsigned i;
- struct bus_body_part *part;
-
- assert(m);
- assert(buffer);
- assert(sz);
-
- total = BUS_MESSAGE_SIZE(m);
-
- p = malloc(total);
- if (!p)
- return -ENOMEM;
-
- e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m));
- MESSAGE_FOREACH_PART(part, i, m)
- e = mempcpy(e, part->data, part->size);
-
- assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p));
-
- *buffer = p;
- *sz = total;
-
- return 0;
-}
-
-int bus_message_read_strv_extend(sd_bus_message *m, char ***l) {
- const char *s;
- int r;
-
- assert(m);
- assert(l);
-
- r = sd_bus_message_enter_container(m, 'a', "s");
- if (r <= 0)
- return r;
-
- while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) {
- r = strv_extend(l, s);
- if (r < 0)
- return r;
- }
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-_public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) {
- char **strv = NULL;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
- assert_return(l, -EINVAL);
-
- r = bus_message_read_strv_extend(m, &strv);
- if (r <= 0) {
- strv_free(strv);
- return r;
- }
-
- *l = strv;
- return 1;
-}
-
-static int bus_message_get_arg_skip(
- sd_bus_message *m,
- unsigned i,
- char *_type,
- const char **_contents) {
-
- unsigned j;
- int r;
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- for (j = 0;; j++) {
- const char *contents;
- char type;
-
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r < 0)
- return r;
- if (r == 0)
- return -ENXIO;
-
- /* Don't match against arguments after the first one we don't understand */
- if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) &&
- !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")))
- return -ENXIO;
-
- if (j >= i) {
- if (_contents)
- *_contents = contents;
- if (_type)
- *_type = type;
- return 0;
- }
-
- r = sd_bus_message_skip(m, NULL);
- if (r < 0)
- return r;
- }
-
-}
-
-int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) {
- char type;
- int r;
-
- assert(m);
- assert(str);
-
- r = bus_message_get_arg_skip(m, i, &type, NULL);
- if (r < 0)
- return r;
-
- if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE))
- return -ENXIO;
-
- return sd_bus_message_read_basic(m, type, str);
-}
-
-int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) {
- const char *contents;
- char type;
- int r;
-
- assert(m);
- assert(strv);
-
- r = bus_message_get_arg_skip(m, i, &type, &contents);
- if (r < 0)
- return r;
-
- if (type != SD_BUS_TYPE_ARRAY)
- return -ENXIO;
- if (!STR_IN_SET(contents, "s", "o", "g"))
- return -ENXIO;
-
- return sd_bus_message_read_strv(m, strv);
-}
-
-_public_ int sd_bus_message_get_errno(sd_bus_message *m) {
- assert_return(m, EINVAL);
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
- return 0;
-
- return sd_bus_error_get_errno(&m->error);
-}
-
-_public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) {
- struct bus_container *c;
-
- assert_return(m, NULL);
-
- c = complete ? &m->root_container : message_get_container(m);
- return strempty(c->signature);
-}
-
-_public_ int sd_bus_message_is_empty(sd_bus_message *m) {
- assert_return(m, -EINVAL);
-
- return isempty(m->root_container.signature);
-}
-
-_public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) {
- assert_return(m, -EINVAL);
-
- return streq(strempty(m->root_container.signature), strempty(signature));
-}
-
-_public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) {
- bool done_something = false;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(source, -EINVAL);
- assert_return(!m->sealed, -EPERM);
- assert_return(source->sealed, -EPERM);
-
- do {
- const char *contents;
- char type;
- union {
- uint8_t u8;
- uint16_t u16;
- int16_t s16;
- uint32_t u32;
- int32_t s32;
- uint64_t u64;
- int64_t s64;
- double d64;
- const char *string;
- int i;
- } basic;
-
- r = sd_bus_message_peek_type(source, &type, &contents);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- done_something = true;
-
- if (bus_type_is_container(type) > 0) {
-
- r = sd_bus_message_enter_container(source, type, contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, type, contents);
- if (r < 0)
- return r;
-
- r = sd_bus_message_copy(m, source, true);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(source);
- if (r < 0)
- return r;
-
- continue;
- }
-
- r = sd_bus_message_read_basic(source, type, &basic);
- if (r < 0)
- return r;
-
- assert(r > 0);
-
- if (type == SD_BUS_TYPE_OBJECT_PATH ||
- type == SD_BUS_TYPE_SIGNATURE ||
- type == SD_BUS_TYPE_STRING)
- r = sd_bus_message_append_basic(m, type, basic.string);
- else
- r = sd_bus_message_append_basic(m, type, &basic);
-
- if (r < 0)
- return r;
-
- } while (all);
-
- return done_something;
-}
-
-_public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) {
- const char *c;
- char t;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->sealed, -EPERM);
- assert_return(!type || bus_type_is_valid(type), -EINVAL);
- assert_return(!contents || signature_is_valid(contents, true), -EINVAL);
- assert_return(type || contents, -EINVAL);
- assert_return(!contents || !type || bus_type_is_container(type), -EINVAL);
-
- r = sd_bus_message_peek_type(m, &t, &c);
- if (r <= 0)
- return r;
-
- if (type != 0 && type != t)
- return 0;
-
- if (contents && !streq_ptr(contents, c))
- return 0;
-
- return 1;
-}
-
-_public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) {
- assert_return(m, NULL);
-
- return m->bus;
-}
-
-int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL;
- usec_t timeout;
- int r;
-
- assert(bus);
- assert(m);
- assert(*m);
-
- switch ((*m)->header->type) {
-
- case SD_BUS_MESSAGE_SIGNAL:
- r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member);
- if (r < 0)
- return r;
-
- break;
-
- case SD_BUS_MESSAGE_METHOD_CALL:
- r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
- if (r < 0)
- return r;
-
- break;
-
- case SD_BUS_MESSAGE_METHOD_RETURN:
- case SD_BUS_MESSAGE_METHOD_ERROR:
-
- n = message_new(bus, (*m)->header->type);
- if (!n)
- return -ENOMEM;
-
- n->reply_cookie = (*m)->reply_cookie;
-
- r = message_append_reply_cookie(n, n->reply_cookie);
- if (r < 0)
- return r;
-
- if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) {
- r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
- if (r < 0)
- return r;
-
- n->error._need_free = -1;
- }
-
- break;
-
- default:
- return -EINVAL;
- }
-
- if ((*m)->destination && !n->destination) {
- r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
- if (r < 0)
- return r;
- }
-
- if ((*m)->sender && !n->sender) {
- r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
- if (r < 0)
- return r;
- }
-
- n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
-
- r = sd_bus_message_copy(n, *m, true);
- if (r < 0)
- return r;
-
- timeout = (*m)->timeout;
- if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED))
- timeout = BUS_DEFAULT_TIMEOUT;
-
- r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout);
- if (r < 0)
- return r;
-
- sd_bus_message_unref(*m);
- *m = n;
- n = NULL;
-
- return 0;
-}
-
-int bus_message_append_sender(sd_bus_message *m, const char *sender) {
- assert(m);
- assert(sender);
-
- assert_return(!m->sealed, -EPERM);
- assert_return(!m->sender, -EPERM);
-
- return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
-}
-
-_public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) {
- assert_return(m, -EINVAL);
- assert_return(priority, -EINVAL);
-
- *priority = m->priority;
- return 0;
-}
-
-_public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) {
- assert_return(m, -EINVAL);
- assert_return(!m->sealed, -EPERM);
-
- m->priority = priority;
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h
deleted file mode 100644
index 4710c106b9..0000000000
--- a/src/libsystemd/sd-bus/bus-message.h
+++ /dev/null
@@ -1,244 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <byteswap.h>
-#include <stdbool.h>
-#include <sys/socket.h>
-
-#include "sd-bus.h"
-
-#include "bus-creds.h"
-#include "bus-protocol.h"
-#include "macro.h"
-#include "time-util.h"
-
-struct bus_container {
- char enclosing;
- bool need_offsets:1;
-
- /* 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 */
- uint32_t *array_size;
-
- /* gvariant: list of offsets to end of children if this is struct/dict entry/array */
- size_t *offsets, n_offsets, offsets_allocated, offset_index;
- size_t item_size;
-
- char *peeked_signature;
-};
-
-struct bus_body_part {
- struct bus_body_part *next;
- void *data;
- void *mmap_begin;
- size_t size;
- size_t mapped;
- size_t allocated;
- uint64_t memfd_offset;
- int memfd;
- bool free_this:1;
- bool munmap_this:1;
- bool sealed:1;
- bool is_zero:1;
-};
-
-struct sd_bus_message {
- unsigned n_ref;
-
- sd_bus *bus;
-
- uint64_t reply_cookie;
-
- const char *path;
- const char *interface;
- const char *member;
- const char *destination;
- const char *sender;
-
- sd_bus_error error;
-
- sd_bus_creds creds;
-
- usec_t monotonic;
- usec_t realtime;
- uint64_t seqnum;
- int64_t priority;
- uint64_t verify_destination_id;
-
- bool sealed:1;
- bool dont_send:1;
- bool allow_fds:1;
- bool free_header:1;
- bool free_kdbus:1;
- bool free_fds:1;
- bool release_kdbus:1;
- bool poisoned:1;
-
- /* The first and last 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;
- size_t user_body_size;
-
- struct bus_body_part body;
- struct bus_body_part *body_end;
- unsigned n_body_parts;
-
- size_t rindex;
- struct bus_body_part *cached_rindex_part;
- size_t cached_rindex_part_begin;
-
- uint32_t n_fds;
- int *fds;
-
- struct bus_container root_container, *containers;
- size_t n_containers;
- size_t containers_allocated;
-
- struct iovec *iovec;
- struct iovec iovec_fixed[2];
- unsigned n_iovec;
-
- struct kdbus_msg *kdbus;
-
- char *peeked_signature;
-
- /* If set replies to this message must carry the signature
- * specified here to successfully seal. This is initialized
- * from the vtable data */
- const char *enforced_reply_signature;
-
- usec_t timeout;
-
- char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
- char destination_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
- char *destination_ptr;
-
- size_t header_offsets[_BUS_MESSAGE_HEADER_MAX];
- unsigned n_header_offsets;
-};
-
-static inline bool BUS_MESSAGE_NEED_BSWAP(sd_bus_message *m) {
- return m->header->endian != BUS_NATIVE_ENDIAN;
-}
-
-static inline uint16_t BUS_MESSAGE_BSWAP16(sd_bus_message *m, uint16_t u) {
- return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_16(u) : u;
-}
-
-static inline uint32_t BUS_MESSAGE_BSWAP32(sd_bus_message *m, uint32_t u) {
- return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_32(u) : u;
-}
-
-static inline uint64_t BUS_MESSAGE_BSWAP64(sd_bus_message *m, uint64_t u) {
- return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_64(u) : 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);
-}
-
-static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) {
- return
- sizeof(struct bus_header) +
- ALIGN8(m->fields_size) +
- m->body_size;
-}
-
-static inline size_t BUS_MESSAGE_BODY_BEGIN(sd_bus_message *m) {
- return
- sizeof(struct bus_header) +
- ALIGN8(m->fields_size);
-}
-
-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_seal(sd_bus_message *m, uint64_t serial, usec_t timeout);
-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,
- unsigned n_fds,
- const char *label,
- size_t extra,
- sd_bus_message **ret);
-
-int bus_message_from_malloc(
- sd_bus *bus,
- void *buffer,
- size_t length,
- int *fds,
- unsigned n_fds,
- const char *label,
- sd_bus_message **ret);
-
-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_append_ap(sd_bus_message *m, const char *types, va_list ap);
-
-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);
-
-int bus_message_append_sender(sd_bus_message *m, const char *sender);
-
-void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m);
-void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m);
diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c
deleted file mode 100644
index 9bd07ffcab..0000000000
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ /dev/null
@@ -1,2806 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-introspect.h"
-#include "bus-message.h"
-#include "bus-objects.h"
-#include "bus-signature.h"
-#include "bus-slot.h"
-#include "bus-type.h"
-#include "bus-util.h"
-#include "set.h"
-#include "string-util.h"
-#include "strv.h"
-
-static int node_vtable_get_userdata(
- sd_bus *bus,
- const char *path,
- struct node_vtable *c,
- void **userdata,
- sd_bus_error *error) {
-
- sd_bus_slot *s;
- void *u;
- int r;
-
- assert(bus);
- assert(path);
- assert(c);
-
- s = container_of(c, sd_bus_slot, node_vtable);
- u = s->userdata;
- if (c->find) {
- bus->current_slot = sd_bus_slot_ref(s);
- bus->current_userdata = u;
- r = c->find(bus, path, c->interface, u, &u, error);
- bus->current_userdata = NULL;
- bus->current_slot = sd_bus_slot_unref(s);
-
- if (r < 0)
- return r;
- if (sd_bus_error_is_set(error))
- return -sd_bus_error_get_errno(error);
- if (r == 0)
- return r;
- }
-
- if (userdata)
- *userdata = u;
-
- return 1;
-}
-
-static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
- assert(p);
-
- return (uint8_t*) u + p->x.method.offset;
-}
-
-static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
- assert(p);
-
- return (uint8_t*) u + p->x.property.offset;
-}
-
-static int vtable_property_get_userdata(
- sd_bus *bus,
- const char *path,
- struct vtable_member *p,
- void **userdata,
- sd_bus_error *error) {
-
- void *u;
- int r;
-
- assert(bus);
- assert(path);
- assert(p);
- assert(userdata);
-
- r = node_vtable_get_userdata(bus, path, p->parent, &u, error);
- if (r <= 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- *userdata = vtable_property_convert_userdata(p->vtable, u);
- return 1;
-}
-
-static int add_enumerated_to_set(
- sd_bus *bus,
- const char *prefix,
- struct node_enumerator *first,
- Set *s,
- sd_bus_error *error) {
-
- struct node_enumerator *c;
- int r;
-
- assert(bus);
- assert(prefix);
- assert(s);
-
- LIST_FOREACH(enumerators, c, first) {
- char **children = NULL, **k;
- sd_bus_slot *slot;
-
- if (bus->nodes_modified)
- return 0;
-
- slot = container_of(c, sd_bus_slot, node_enumerator);
-
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_userdata = slot->userdata;
- r = c->callback(bus, prefix, slot->userdata, &children, error);
- bus->current_userdata = NULL;
- bus->current_slot = sd_bus_slot_unref(slot);
-
- if (r < 0)
- return r;
- if (sd_bus_error_is_set(error))
- return -sd_bus_error_get_errno(error);
-
- STRV_FOREACH(k, children) {
- if (r < 0) {
- free(*k);
- continue;
- }
-
- if (!object_path_is_valid(*k)) {
- free(*k);
- r = -EINVAL;
- continue;
- }
-
- if (!object_path_startswith(*k, prefix)) {
- free(*k);
- continue;
- }
-
- r = set_consume(s, *k);
- if (r == -EEXIST)
- r = 0;
- }
-
- free(children);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-enum {
- /* if set, add_subtree() works recursively */
- CHILDREN_RECURSIVE = (1U << 1),
- /* if set, add_subtree() scans object-manager hierarchies recursively */
- CHILDREN_SUBHIERARCHIES = (1U << 0),
-};
-
-static int add_subtree_to_set(
- sd_bus *bus,
- const char *prefix,
- struct node *n,
- unsigned int flags,
- Set *s,
- sd_bus_error *error) {
-
- struct node *i;
- int r;
-
- assert(bus);
- assert(prefix);
- assert(n);
- assert(s);
-
- r = add_enumerated_to_set(bus, prefix, n->enumerators, s, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- LIST_FOREACH(siblings, i, n->child) {
- char *t;
-
- if (!object_path_startswith(i->path, prefix))
- continue;
-
- t = strdup(i->path);
- if (!t)
- return -ENOMEM;
-
- r = set_consume(s, t);
- if (r < 0 && r != -EEXIST)
- return r;
-
- if ((flags & CHILDREN_RECURSIVE) &&
- ((flags & CHILDREN_SUBHIERARCHIES) || !i->object_managers)) {
- r = add_subtree_to_set(bus, prefix, i, flags, s, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
- }
-
- return 0;
-}
-
-static int get_child_nodes(
- sd_bus *bus,
- const char *prefix,
- struct node *n,
- unsigned int flags,
- Set **_s,
- sd_bus_error *error) {
-
- Set *s = NULL;
- int r;
-
- assert(bus);
- assert(prefix);
- assert(n);
- assert(_s);
-
- s = set_new(&string_hash_ops);
- if (!s)
- return -ENOMEM;
-
- r = add_subtree_to_set(bus, prefix, n, flags, s, error);
- if (r < 0) {
- set_free_free(s);
- return r;
- }
-
- *_s = s;
- return 0;
-}
-
-static int node_callbacks_run(
- sd_bus *bus,
- sd_bus_message *m,
- struct node_callback *first,
- bool require_fallback,
- bool *found_object) {
-
- struct node_callback *c;
- int r;
-
- assert(bus);
- assert(m);
- assert(found_object);
-
- LIST_FOREACH(callbacks, c, first) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- sd_bus_slot *slot;
-
- if (bus->nodes_modified)
- return 0;
-
- if (require_fallback && !c->is_fallback)
- continue;
-
- *found_object = true;
-
- if (c->last_iteration == bus->iteration_counter)
- continue;
-
- c->last_iteration = bus->iteration_counter;
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- slot = container_of(c, sd_bus_slot, node_callback);
-
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = sd_bus_slot_unref(slot);
-
- r = bus_maybe_reply_error(m, r, &error_buffer);
- if (r != 0)
- return r;
- }
-
- return 0;
-}
-
-#define CAPABILITY_SHIFT(x) (((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF)
-
-static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) {
- uint64_t cap;
- int r;
-
- assert(bus);
- assert(m);
- assert(c);
-
- /* If the entire bus is trusted let's grant access */
- if (bus->trusted)
- return 0;
-
- /* If the member is marked UNPRIVILEGED let's grant access */
- if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED)
- return 0;
-
- /* Check have the caller has the requested capability
- * set. Note that the flags value contains the capability
- * number plus one, which we need to subtract here. We do this
- * so that we have 0 as special value for "default
- * capability". */
- cap = CAPABILITY_SHIFT(c->vtable->flags);
- if (cap == 0)
- cap = CAPABILITY_SHIFT(c->parent->vtable[0].flags);
- if (cap == 0)
- cap = CAP_SYS_ADMIN;
- else
- cap--;
-
- r = sd_bus_query_sender_privilege(m, cap);
- if (r < 0)
- return r;
- if (r > 0)
- return 0;
-
- return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member);
-}
-
-static int method_callbacks_run(
- sd_bus *bus,
- sd_bus_message *m,
- struct vtable_member *c,
- bool require_fallback,
- bool *found_object) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *signature;
- void *u;
- int r;
-
- assert(bus);
- assert(m);
- assert(c);
- assert(found_object);
-
- if (require_fallback && !c->parent->is_fallback)
- return 0;
-
- r = check_access(bus, m, c, &error);
- if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
-
- r = node_vtable_get_userdata(bus, m->path, c->parent, &u, &error);
- if (r <= 0)
- return bus_maybe_reply_error(m, r, &error);
- if (bus->nodes_modified)
- return 0;
-
- u = vtable_method_convert_userdata(c->vtable, u);
-
- *found_object = true;
-
- if (c->last_iteration == bus->iteration_counter)
- return 0;
-
- c->last_iteration = bus->iteration_counter;
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- signature = sd_bus_message_get_signature(m, true);
- if (!signature)
- return -EINVAL;
-
- if (!streq(strempty(c->vtable->x.method.signature), signature))
- return sd_bus_reply_method_errorf(
- m,
- SD_BUS_ERROR_INVALID_ARGS,
- "Invalid arguments '%s' to call %s.%s(), expecting '%s'.",
- signature, c->interface, c->member, strempty(c->vtable->x.method.signature));
-
- /* Keep track what the signature of the reply to this message
- * should be, so that this can be enforced when sealing the
- * reply. */
- m->enforced_reply_signature = strempty(c->vtable->x.method.result);
-
- if (c->vtable->x.method.handler) {
- sd_bus_slot *slot;
-
- slot = container_of(c->parent, sd_bus_slot, node_vtable);
-
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->vtable->x.method.handler;
- bus->current_userdata = u;
- r = c->vtable->x.method.handler(m, u, &error);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = sd_bus_slot_unref(slot);
-
- return bus_maybe_reply_error(m, r, &error);
- }
-
- /* If the method callback is NULL, make this a successful NOP */
- r = sd_bus_reply_method_return(m, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int invoke_property_get(
- sd_bus *bus,
- sd_bus_slot *slot,
- const sd_bus_vtable *v,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- const void *p;
- int r;
-
- assert(bus);
- assert(slot);
- assert(v);
- assert(path);
- assert(interface);
- assert(property);
- assert(reply);
-
- if (v->x.property.get) {
-
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_userdata = userdata;
- r = v->x.property.get(bus, path, interface, property, reply, userdata, error);
- bus->current_userdata = NULL;
- bus->current_slot = sd_bus_slot_unref(slot);
-
- if (r < 0)
- return r;
- if (sd_bus_error_is_set(error))
- return -sd_bus_error_get_errno(error);
- return r;
- }
-
- /* Automatic handling if no callback is defined. */
-
- if (streq(v->x.property.signature, "as"))
- return sd_bus_message_append_strv(reply, *(char***) userdata);
-
- assert(signature_is_single(v->x.property.signature, false));
- assert(bus_type_is_basic(v->x.property.signature[0]));
-
- switch (v->x.property.signature[0]) {
-
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_SIGNATURE:
- p = strempty(*(char**) userdata);
- break;
-
- case SD_BUS_TYPE_OBJECT_PATH:
- p = *(char**) userdata;
- assert(p);
- break;
-
- default:
- p = userdata;
- break;
- }
-
- return sd_bus_message_append_basic(reply, v->x.property.signature[0], p);
-}
-
-static int invoke_property_set(
- sd_bus *bus,
- sd_bus_slot *slot,
- const sd_bus_vtable *v,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *value,
- void *userdata,
- sd_bus_error *error) {
-
- int r;
-
- assert(bus);
- assert(slot);
- assert(v);
- assert(path);
- assert(interface);
- assert(property);
- assert(value);
-
- if (v->x.property.set) {
-
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_userdata = userdata;
- r = v->x.property.set(bus, path, interface, property, value, userdata, error);
- bus->current_userdata = NULL;
- bus->current_slot = sd_bus_slot_unref(slot);
-
- if (r < 0)
- return r;
- if (sd_bus_error_is_set(error))
- return -sd_bus_error_get_errno(error);
- return r;
- }
-
- /* Automatic handling if no callback is defined. */
-
- assert(signature_is_single(v->x.property.signature, false));
- assert(bus_type_is_basic(v->x.property.signature[0]));
-
- switch (v->x.property.signature[0]) {
-
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_SIGNATURE: {
- const char *p;
- char *n;
-
- r = sd_bus_message_read_basic(value, v->x.property.signature[0], &p);
- if (r < 0)
- return r;
-
- n = strdup(p);
- if (!n)
- return -ENOMEM;
-
- free(*(char**) userdata);
- *(char**) userdata = n;
-
- break;
- }
-
- default:
- r = sd_bus_message_read_basic(value, v->x.property.signature[0], userdata);
- if (r < 0)
- return r;
-
- break;
- }
-
- return 1;
-}
-
-static int property_get_set_callbacks_run(
- sd_bus *bus,
- sd_bus_message *m,
- struct vtable_member *c,
- bool require_fallback,
- bool is_get,
- bool *found_object) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- sd_bus_slot *slot;
- void *u = NULL;
- int r;
-
- assert(bus);
- assert(m);
- assert(c);
- assert(found_object);
-
- if (require_fallback && !c->parent->is_fallback)
- return 0;
-
- r = vtable_property_get_userdata(bus, m->path, c, &u, &error);
- if (r <= 0)
- return bus_maybe_reply_error(m, r, &error);
- if (bus->nodes_modified)
- return 0;
-
- slot = container_of(c->parent, sd_bus_slot, node_vtable);
-
- *found_object = true;
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return r;
-
- if (is_get) {
- /* Note that we do not protect against reexecution
- * here (using the last_iteration check, see below),
- * should the node tree have changed and we got called
- * again. We assume that property Get() calls are
- * ultimately without side-effects or if they aren't
- * then at least idempotent. */
-
- r = sd_bus_message_open_container(reply, 'v', c->vtable->x.property.signature);
- if (r < 0)
- return r;
-
- /* Note that we do not do an access check here. Read
- * access to properties is always unrestricted, since
- * PropertiesChanged signals broadcast contents
- * anyway. */
-
- r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error);
- if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
-
- if (bus->nodes_modified)
- return 0;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- } else {
- const char *signature = NULL;
- char type = 0;
-
- if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
- return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member);
-
- /* Avoid that we call the set routine more than once
- * if the processing of this message got restarted
- * because the node tree changed. */
- if (c->last_iteration == bus->iteration_counter)
- return 0;
-
- c->last_iteration = bus->iteration_counter;
-
- r = sd_bus_message_peek_type(m, &type, &signature);
- if (r < 0)
- return r;
-
- if (type != 'v' || !streq(strempty(signature), strempty(c->vtable->x.property.signature)))
- return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Incorrect parameters for property '%s', expected '%s', got '%s'.", c->member, strempty(c->vtable->x.property.signature), strempty(signature));
-
- r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature);
- if (r < 0)
- return r;
-
- r = check_access(bus, m, c, &error);
- if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
-
- r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error);
- if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
-
- if (bus->nodes_modified)
- return 0;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_send(bus, reply, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int vtable_append_one_property(
- sd_bus *bus,
- sd_bus_message *reply,
- const char *path,
- struct node_vtable *c,
- const sd_bus_vtable *v,
- void *userdata,
- sd_bus_error *error) {
-
- sd_bus_slot *slot;
- int r;
-
- assert(bus);
- assert(reply);
- assert(path);
- assert(c);
- assert(v);
-
- r = sd_bus_message_open_container(reply, 'e', "sv");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(reply, "s", v->x.property.member);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(reply, 'v', v->x.property.signature);
- if (r < 0)
- return r;
-
- slot = container_of(c, sd_bus_slot, node_vtable);
-
- r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int vtable_append_all_properties(
- sd_bus *bus,
- sd_bus_message *reply,
- const char *path,
- struct node_vtable *c,
- void *userdata,
- sd_bus_error *error) {
-
- const sd_bus_vtable *v;
- int r;
-
- assert(bus);
- assert(reply);
- assert(path);
- assert(c);
-
- if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
- return 1;
-
- for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
- if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
- continue;
-
- if (v->flags & SD_BUS_VTABLE_HIDDEN)
- continue;
-
- if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
- continue;
-
- r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- return 1;
-}
-
-static int property_get_all_callbacks_run(
- sd_bus *bus,
- sd_bus_message *m,
- struct node_vtable *first,
- bool require_fallback,
- const char *iface,
- bool *found_object) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- struct node_vtable *c;
- bool found_interface;
- int r;
-
- assert(bus);
- assert(m);
- assert(found_object);
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(reply, 'a', "{sv}");
- if (r < 0)
- return r;
-
- found_interface = !iface ||
- streq(iface, "org.freedesktop.DBus.Properties") ||
- streq(iface, "org.freedesktop.DBus.Peer") ||
- streq(iface, "org.freedesktop.DBus.Introspectable");
-
- LIST_FOREACH(vtables, c, first) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- void *u;
-
- if (require_fallback && !c->is_fallback)
- continue;
-
- r = node_vtable_get_userdata(bus, m->path, c, &u, &error);
- if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
- if (bus->nodes_modified)
- return 0;
- if (r == 0)
- continue;
-
- *found_object = true;
-
- if (iface && !streq(c->interface, iface))
- continue;
- found_interface = true;
-
- r = vtable_append_all_properties(bus, reply, m->path, c, u, &error);
- if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
- if (bus->nodes_modified)
- return 0;
- }
-
- if (!found_interface) {
- r = sd_bus_reply_method_errorf(
- m,
- SD_BUS_ERROR_UNKNOWN_INTERFACE,
- "Unknown interface '%s'.", iface);
- if (r < 0)
- return r;
-
- return 1;
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- r = sd_bus_send(bus, reply, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int bus_node_exists(
- sd_bus *bus,
- struct node *n,
- const char *path,
- bool require_fallback) {
-
- struct node_vtable *c;
- struct node_callback *k;
- int r;
-
- assert(bus);
- assert(n);
- assert(path);
-
- /* Tests if there's anything attached directly to this node
- * for the specified path */
-
- if (!require_fallback && (n->enumerators || n->object_managers))
- return true;
-
- LIST_FOREACH(callbacks, k, n->callbacks) {
- if (require_fallback && !k->is_fallback)
- continue;
-
- return 1;
- }
-
- LIST_FOREACH(vtables, c, n->vtables) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
- if (require_fallback && !c->is_fallback)
- continue;
-
- r = node_vtable_get_userdata(bus, path, c, NULL, &error);
- if (r != 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- return 0;
-}
-
-static int process_introspect(
- sd_bus *bus,
- sd_bus_message *m,
- struct node *n,
- bool require_fallback,
- bool *found_object) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_set_free_free_ Set *s = NULL;
- const char *previous_interface = NULL;
- struct introspect intro;
- struct node_vtable *c;
- bool empty;
- int r;
-
- assert(bus);
- assert(m);
- assert(n);
- assert(found_object);
-
- r = get_child_nodes(bus, m->path, n, 0, &s, &error);
- if (r < 0)
- return bus_maybe_reply_error(m, r, &error);
- if (bus->nodes_modified)
- return 0;
-
- r = introspect_begin(&intro, bus->trusted);
- if (r < 0)
- return r;
-
- r = introspect_write_default_interfaces(&intro, !require_fallback && n->object_managers);
- if (r < 0)
- return r;
-
- empty = set_isempty(s);
-
- LIST_FOREACH(vtables, c, n->vtables) {
- if (require_fallback && !c->is_fallback)
- continue;
-
- r = node_vtable_get_userdata(bus, m->path, c, NULL, &error);
- if (r < 0) {
- r = bus_maybe_reply_error(m, r, &error);
- goto finish;
- }
- if (bus->nodes_modified) {
- r = 0;
- goto finish;
- }
- if (r == 0)
- continue;
-
- empty = false;
-
- if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
- continue;
-
- if (!streq_ptr(previous_interface, c->interface)) {
-
- if (previous_interface)
- fputs(" </interface>\n", intro.f);
-
- fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
- }
-
- r = introspect_write_interface(&intro, c->vtable);
- if (r < 0)
- goto finish;
-
- previous_interface = c->interface;
- }
-
- if (previous_interface)
- fputs(" </interface>\n", intro.f);
-
- if (empty) {
- /* Nothing?, let's see if we exist at all, and if not
- * refuse to do anything */
- r = bus_node_exists(bus, n, m->path, require_fallback);
- if (r <= 0)
- goto finish;
- if (bus->nodes_modified) {
- r = 0;
- goto finish;
- }
- }
-
- *found_object = true;
-
- r = introspect_write_child_nodes(&intro, s, m->path);
- if (r < 0)
- goto finish;
-
- r = introspect_finish(&intro, bus, m, &reply);
- if (r < 0)
- goto finish;
-
- r = sd_bus_send(bus, reply, NULL);
- if (r < 0)
- goto finish;
-
- r = 1;
-
-finish:
- introspect_free(&intro);
- return r;
-}
-
-static int object_manager_serialize_path(
- sd_bus *bus,
- sd_bus_message *reply,
- const char *prefix,
- const char *path,
- bool require_fallback,
- sd_bus_error *error) {
-
- const char *previous_interface = NULL;
- bool found_something = false;
- struct node_vtable *i;
- struct node *n;
- int r;
-
- assert(bus);
- assert(reply);
- assert(prefix);
- assert(path);
- assert(error);
-
- n = hashmap_get(bus->nodes, prefix);
- if (!n)
- return 0;
-
- LIST_FOREACH(vtables, i, n->vtables) {
- void *u;
-
- if (require_fallback && !i->is_fallback)
- continue;
-
- r = node_vtable_get_userdata(bus, path, i, &u, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- if (r == 0)
- continue;
-
- if (!found_something) {
-
- /* Open the object part */
-
- r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(reply, "o", path);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}");
- if (r < 0)
- return r;
-
- found_something = true;
- }
-
- if (!streq_ptr(previous_interface, i->interface)) {
-
- /* Maybe close the previous interface part */
-
- if (previous_interface) {
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
- }
-
- /* Open the new interface part */
-
- r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(reply, "s", i->interface);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(reply, 'a', "{sv}");
- if (r < 0)
- return r;
- }
-
- r = vtable_append_all_properties(bus, reply, path, i, u, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- previous_interface = i->interface;
- }
-
- if (previous_interface) {
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
- }
-
- if (found_something) {
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
- }
-
- return 1;
-}
-
-static int object_manager_serialize_path_and_fallbacks(
- sd_bus *bus,
- sd_bus_message *reply,
- const char *path,
- sd_bus_error *error) {
-
- char *prefix;
- int r;
-
- assert(bus);
- assert(reply);
- assert(path);
- assert(error);
-
- /* First, add all vtables registered for this path */
- r = object_manager_serialize_path(bus, reply, path, path, false, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- /* Second, add fallback vtables registered for any of the prefixes */
- prefix = alloca(strlen(path) + 1);
- OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
- r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- return 0;
-}
-
-static int process_get_managed_objects(
- sd_bus *bus,
- sd_bus_message *m,
- struct node *n,
- bool require_fallback,
- bool *found_object) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_set_free_free_ Set *s = NULL;
- Iterator i;
- char *path;
- int r;
-
- assert(bus);
- assert(m);
- assert(n);
- assert(found_object);
-
- /* Spec says, GetManagedObjects() is only implemented on the root of a
- * sub-tree. Therefore, we require a registered object-manager on
- * exactly the queried path, otherwise, we refuse to respond. */
-
- if (require_fallback || !n->object_managers)
- return 0;
-
- r = get_child_nodes(bus, m->path, n, CHILDREN_RECURSIVE, &s, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}");
- if (r < 0)
- return r;
-
- SET_FOREACH(path, s, i) {
- r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
- if (r < 0)
- return r;
-
- if (bus->nodes_modified)
- return 0;
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- r = sd_bus_send(bus, reply, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int object_find_and_run(
- sd_bus *bus,
- sd_bus_message *m,
- const char *p,
- bool require_fallback,
- bool *found_object) {
-
- struct node *n;
- struct vtable_member vtable_key, *v;
- int r;
-
- assert(bus);
- assert(m);
- assert(p);
- assert(found_object);
-
- n = hashmap_get(bus->nodes, p);
- if (!n)
- return 0;
-
- /* First, try object callbacks */
- r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object);
- if (r != 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- if (!m->interface || !m->member)
- return 0;
-
- /* Then, look for a known method */
- vtable_key.path = (char*) p;
- vtable_key.interface = m->interface;
- vtable_key.member = m->member;
-
- v = hashmap_get(bus->vtable_methods, &vtable_key);
- if (v) {
- r = method_callbacks_run(bus, m, v, require_fallback, found_object);
- if (r != 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- /* Then, look for a known property */
- if (streq(m->interface, "org.freedesktop.DBus.Properties")) {
- bool get = false;
-
- get = streq(m->member, "Get");
-
- if (get || streq(m->member, "Set")) {
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- vtable_key.path = (char*) p;
-
- r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member);
- if (r < 0)
- return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface and member parameters");
-
- v = hashmap_get(bus->vtable_properties, &vtable_key);
- if (v) {
- r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object);
- if (r != 0)
- return r;
- }
-
- } else if (streq(m->member, "GetAll")) {
- const char *iface;
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- r = sd_bus_message_read(m, "s", &iface);
- if (r < 0)
- return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface parameter");
-
- if (iface[0] == 0)
- iface = NULL;
-
- r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object);
- if (r != 0)
- return r;
- }
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-
- if (!isempty(sd_bus_message_get_signature(m, true)))
- return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
-
- r = process_introspect(bus, m, n, require_fallback, found_object);
- if (r != 0)
- return r;
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
-
- if (!isempty(sd_bus_message_get_signature(m, true)))
- return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
-
- r = process_get_managed_objects(bus, m, n, require_fallback, found_object);
- if (r != 0)
- return r;
- }
-
- if (bus->nodes_modified)
- return 0;
-
- if (!*found_object) {
- r = bus_node_exists(bus, n, m->path, require_fallback);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- if (r > 0)
- *found_object = true;
- }
-
- return 0;
-}
-
-int bus_process_object(sd_bus *bus, sd_bus_message *m) {
- int r;
- size_t pl;
- bool found_object = false;
-
- assert(bus);
- assert(m);
-
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
- return 0;
-
- if (hashmap_isempty(bus->nodes))
- return 0;
-
- /* Never respond to broadcast messages */
- if (bus->bus_client && !m->destination)
- return 0;
-
- assert(m->path);
- assert(m->member);
-
- pl = strlen(m->path);
- do {
- char prefix[pl+1];
-
- bus->nodes_modified = false;
-
- r = object_find_and_run(bus, m, m->path, false, &found_object);
- if (r != 0)
- return r;
-
- /* Look for fallback prefixes */
- OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) {
-
- if (bus->nodes_modified)
- break;
-
- r = object_find_and_run(bus, m, prefix, true, &found_object);
- if (r != 0)
- return r;
- }
-
- } while (bus->nodes_modified);
-
- if (!found_object)
- return 0;
-
- if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
- sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
- r = sd_bus_reply_method_errorf(
- m,
- SD_BUS_ERROR_UNKNOWN_PROPERTY,
- "Unknown property or interface.");
- else
- r = sd_bus_reply_method_errorf(
- m,
- SD_BUS_ERROR_UNKNOWN_METHOD,
- "Unknown method '%s' or interface '%s'.", m->member, m->interface);
-
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
- struct node *n, *parent;
- const char *e;
- _cleanup_free_ char *s = NULL;
- char *p;
- int r;
-
- assert(bus);
- assert(path);
- assert(path[0] == '/');
-
- n = hashmap_get(bus->nodes, path);
- if (n)
- return n;
-
- r = hashmap_ensure_allocated(&bus->nodes, &string_hash_ops);
- if (r < 0)
- return NULL;
-
- s = strdup(path);
- if (!s)
- return NULL;
-
- if (streq(path, "/"))
- parent = NULL;
- else {
- e = strrchr(path, '/');
- assert(e);
-
- p = strndupa(path, MAX(1, e - path));
-
- parent = bus_node_allocate(bus, p);
- if (!parent)
- return NULL;
- }
-
- n = new0(struct node, 1);
- if (!n)
- return NULL;
-
- n->parent = parent;
- n->path = s;
- s = NULL; /* do not free */
-
- r = hashmap_put(bus->nodes, n->path, n);
- if (r < 0) {
- free(n->path);
- free(n);
- return NULL;
- }
-
- if (parent)
- LIST_PREPEND(siblings, parent->child, n);
-
- return n;
-}
-
-void bus_node_gc(sd_bus *b, struct node *n) {
- assert(b);
-
- if (!n)
- return;
-
- if (n->child ||
- n->callbacks ||
- n->vtables ||
- n->enumerators ||
- n->object_managers)
- return;
-
- assert(hashmap_remove(b->nodes, n->path) == n);
-
- if (n->parent)
- LIST_REMOVE(siblings, n->parent->child, n);
-
- free(n->path);
- bus_node_gc(b, n->parent);
- free(n);
-}
-
-static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const char *path) {
- struct node *n;
-
- assert(bus);
- assert(path);
-
- n = hashmap_get(bus->nodes, path);
- if (!n) {
- char *prefix;
-
- prefix = alloca(strlen(path) + 1);
- OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
- n = hashmap_get(bus->nodes, prefix);
- if (n)
- break;
- }
- }
-
- while (n && !n->object_managers)
- n = n->parent;
-
- if (out)
- *out = n;
- return !!n;
-}
-
-static int bus_add_object(
- sd_bus *bus,
- sd_bus_slot **slot,
- bool fallback,
- const char *path,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- sd_bus_slot *s;
- struct node *n;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(callback, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- n = bus_node_allocate(bus, path);
- if (!n)
- return -ENOMEM;
-
- s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
- s->node_callback.callback = callback;
- s->node_callback.is_fallback = fallback;
-
- s->node_callback.node = n;
- LIST_PREPEND(callbacks, n->callbacks, &s->node_callback);
- bus->nodes_modified = true;
-
- if (slot)
- *slot = s;
-
- return 0;
-
-fail:
- sd_bus_slot_unref(s);
- bus_node_gc(bus, n);
-
- return r;
-}
-
-_public_ int sd_bus_add_object(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *path,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- return bus_add_object(bus, slot, false, path, callback, userdata);
-}
-
-_public_ int sd_bus_add_fallback(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *prefix,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- return bus_add_object(bus, slot, true, prefix, callback, userdata);
-}
-
-static void vtable_member_hash_func(const void *a, struct siphash *state) {
- const struct vtable_member *m = a;
-
- assert(m);
-
- string_hash_func(m->path, state);
- string_hash_func(m->interface, state);
- string_hash_func(m->member, state);
-}
-
-static int vtable_member_compare_func(const void *a, const void *b) {
- const struct vtable_member *x = a, *y = b;
- int r;
-
- assert(x);
- assert(y);
-
- r = strcmp(x->path, y->path);
- if (r != 0)
- return r;
-
- r = strcmp(x->interface, y->interface);
- if (r != 0)
- return r;
-
- return strcmp(x->member, y->member);
-}
-
-static const struct hash_ops vtable_member_hash_ops = {
- .hash = vtable_member_hash_func,
- .compare = vtable_member_compare_func
-};
-
-static int add_object_vtable_internal(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *path,
- const char *interface,
- const sd_bus_vtable *vtable,
- bool fallback,
- sd_bus_object_find_t find,
- void *userdata) {
-
- sd_bus_slot *s = NULL;
- struct node_vtable *i, *existing = NULL;
- const sd_bus_vtable *v;
- struct node *n;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(interface_name_is_valid(interface), -EINVAL);
- assert_return(vtable, -EINVAL);
- assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
- assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
- !streq(interface, "org.freedesktop.DBus.Introspectable") &&
- !streq(interface, "org.freedesktop.DBus.Peer") &&
- !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL);
-
- r = hashmap_ensure_allocated(&bus->vtable_methods, &vtable_member_hash_ops);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_allocated(&bus->vtable_properties, &vtable_member_hash_ops);
- if (r < 0)
- return r;
-
- n = bus_node_allocate(bus, path);
- if (!n)
- return -ENOMEM;
-
- LIST_FOREACH(vtables, i, n->vtables) {
- if (i->is_fallback != fallback) {
- r = -EPROTOTYPE;
- goto fail;
- }
-
- if (streq(i->interface, interface)) {
-
- if (i->vtable == vtable) {
- r = -EEXIST;
- goto fail;
- }
-
- existing = i;
- }
- }
-
- s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
- s->node_vtable.is_fallback = fallback;
- s->node_vtable.vtable = vtable;
- s->node_vtable.find = find;
-
- s->node_vtable.interface = strdup(interface);
- if (!s->node_vtable.interface) {
- r = -ENOMEM;
- goto fail;
- }
-
- for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
-
- switch (v->type) {
-
- case _SD_BUS_VTABLE_METHOD: {
- struct vtable_member *m;
-
- if (!member_name_is_valid(v->x.method.member) ||
- !signature_is_valid(strempty(v->x.method.signature), false) ||
- !signature_is_valid(strempty(v->x.method.result), false) ||
- !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) ||
- v->flags & (SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) {
- r = -EINVAL;
- goto fail;
- }
-
- m = new0(struct vtable_member, 1);
- if (!m) {
- r = -ENOMEM;
- goto fail;
- }
-
- m->parent = &s->node_vtable;
- m->path = n->path;
- m->interface = s->node_vtable.interface;
- m->member = v->x.method.member;
- m->vtable = v;
-
- r = hashmap_put(bus->vtable_methods, m, m);
- if (r < 0) {
- free(m);
- goto fail;
- }
-
- break;
- }
-
- case _SD_BUS_VTABLE_WRITABLE_PROPERTY:
-
- if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) {
- r = -EINVAL;
- goto fail;
- }
-
- if (v->flags & SD_BUS_VTABLE_PROPERTY_CONST) {
- r = -EINVAL;
- goto fail;
- }
-
- /* Fall through */
-
- case _SD_BUS_VTABLE_PROPERTY: {
- struct vtable_member *m;
-
- if (!member_name_is_valid(v->x.property.member) ||
- !signature_is_single(v->x.property.signature, false) ||
- !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) ||
- (v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ||
- (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 ||
- ((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) ||
- (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) {
- r = -EINVAL;
- goto fail;
- }
-
- m = new0(struct vtable_member, 1);
- if (!m) {
- r = -ENOMEM;
- goto fail;
- }
-
- m->parent = &s->node_vtable;
- m->path = n->path;
- m->interface = s->node_vtable.interface;
- m->member = v->x.property.member;
- m->vtable = v;
-
- r = hashmap_put(bus->vtable_properties, m, m);
- if (r < 0) {
- free(m);
- goto fail;
- }
-
- break;
- }
-
- case _SD_BUS_VTABLE_SIGNAL:
-
- if (!member_name_is_valid(v->x.signal.member) ||
- !signature_is_valid(strempty(v->x.signal.signature), false) ||
- v->flags & SD_BUS_VTABLE_UNPRIVILEGED) {
- r = -EINVAL;
- goto fail;
- }
-
- break;
-
- default:
- r = -EINVAL;
- goto fail;
- }
- }
-
- s->node_vtable.node = n;
- LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable);
- bus->nodes_modified = true;
-
- if (slot)
- *slot = s;
-
- return 0;
-
-fail:
- sd_bus_slot_unref(s);
- bus_node_gc(bus, n);
-
- return r;
-}
-
-_public_ int sd_bus_add_object_vtable(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *path,
- const char *interface,
- const sd_bus_vtable *vtable,
- void *userdata) {
-
- return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata);
-}
-
-_public_ int sd_bus_add_fallback_vtable(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *prefix,
- const char *interface,
- const sd_bus_vtable *vtable,
- sd_bus_object_find_t find,
- void *userdata) {
-
- return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata);
-}
-
-_public_ int sd_bus_add_node_enumerator(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *path,
- sd_bus_node_enumerator_t callback,
- void *userdata) {
-
- sd_bus_slot *s;
- struct node *n;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(callback, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- n = bus_node_allocate(bus, path);
- if (!n)
- return -ENOMEM;
-
- s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
- s->node_enumerator.callback = callback;
-
- s->node_enumerator.node = n;
- LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator);
- bus->nodes_modified = true;
-
- if (slot)
- *slot = s;
-
- return 0;
-
-fail:
- sd_bus_slot_unref(s);
- bus_node_gc(bus, n);
-
- return r;
-}
-
-static int emit_properties_changed_on_interface(
- sd_bus *bus,
- const char *prefix,
- const char *path,
- const char *interface,
- bool require_fallback,
- bool *found_interface,
- char **names) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- bool has_invalidating = false, has_changing = false;
- struct vtable_member key = {};
- struct node_vtable *c;
- struct node *n;
- char **property;
- void *u = NULL;
- int r;
-
- assert(bus);
- assert(prefix);
- assert(path);
- assert(interface);
- assert(found_interface);
-
- n = hashmap_get(bus->nodes, prefix);
- if (!n)
- return 0;
-
- r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "s", interface);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "{sv}");
- if (r < 0)
- return r;
-
- key.path = prefix;
- key.interface = interface;
-
- LIST_FOREACH(vtables, c, n->vtables) {
- if (require_fallback && !c->is_fallback)
- continue;
-
- if (!streq(c->interface, interface))
- continue;
-
- r = node_vtable_get_userdata(bus, path, c, &u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- if (r == 0)
- continue;
-
- *found_interface = true;
-
- if (names) {
- /* If the caller specified a list of
- * properties we include exactly those in the
- * PropertiesChanged message */
-
- STRV_FOREACH(property, names) {
- struct vtable_member *v;
-
- assert_return(member_name_is_valid(*property), -EINVAL);
-
- key.member = *property;
- v = hashmap_get(bus->vtable_properties, &key);
- if (!v)
- return -ENOENT;
-
- /* If there are two vtables for the same
- * interface, let's handle this property when
- * we come to that vtable. */
- if (c != v->parent)
- continue;
-
- assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE ||
- v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION, -EDOM);
-
- assert_return(!(v->vtable->flags & SD_BUS_VTABLE_HIDDEN), -EDOM);
-
- if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
- has_invalidating = true;
- continue;
- }
-
- has_changing = true;
-
- r = vtable_append_one_property(bus, m, m->path, c, v->vtable, u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
- } else {
- const sd_bus_vtable *v;
-
- /* If the caller specified no properties list
- * we include all properties that are marked
- * as changing in the message. */
-
- for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
- if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
- continue;
-
- if (v->flags & SD_BUS_VTABLE_HIDDEN)
- continue;
-
- if (v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) {
- has_invalidating = true;
- continue;
- }
-
- if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))
- continue;
-
- has_changing = true;
-
- r = vtable_append_one_property(bus, m, m->path, c, v, u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
- }
- }
-
- if (!has_invalidating && !has_changing)
- return 0;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "s");
- if (r < 0)
- return r;
-
- if (has_invalidating) {
- LIST_FOREACH(vtables, c, n->vtables) {
- if (require_fallback && !c->is_fallback)
- continue;
-
- if (!streq(c->interface, interface))
- continue;
-
- r = node_vtable_get_userdata(bus, path, c, &u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- if (r == 0)
- continue;
-
- if (names) {
- STRV_FOREACH(property, names) {
- struct vtable_member *v;
-
- key.member = *property;
- assert_se(v = hashmap_get(bus->vtable_properties, &key));
- assert(c == v->parent);
-
- if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
- continue;
-
- r = sd_bus_message_append(m, "s", *property);
- if (r < 0)
- return r;
- }
- } else {
- const sd_bus_vtable *v;
-
- for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
- if (v->type != _SD_BUS_VTABLE_PROPERTY && v->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY)
- continue;
-
- if (v->flags & SD_BUS_VTABLE_HIDDEN)
- continue;
-
- if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
- continue;
-
- r = sd_bus_message_append(m, "s", v->x.property.member);
- if (r < 0)
- return r;
- }
- }
- }
- }
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- r = sd_bus_send(bus, m, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-_public_ int sd_bus_emit_properties_changed_strv(
- sd_bus *bus,
- const char *path,
- const char *interface,
- char **names) {
-
- BUS_DONT_DESTROY(bus);
- bool found_interface = false;
- char *prefix;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(interface_name_is_valid(interface), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- /* A non-NULL but empty names list means nothing needs to be
- generated. A NULL list OTOH indicates that all properties
- that are set to EMITS_CHANGE or EMITS_INVALIDATION shall be
- included in the PropertiesChanged message. */
- if (names && names[0] == NULL)
- return 0;
-
- do {
- bus->nodes_modified = false;
-
- r = emit_properties_changed_on_interface(bus, path, path, interface, false, &found_interface, names);
- if (r != 0)
- return r;
- if (bus->nodes_modified)
- continue;
-
- prefix = alloca(strlen(path) + 1);
- OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
- r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names);
- if (r != 0)
- return r;
- if (bus->nodes_modified)
- break;
- }
-
- } while (bus->nodes_modified);
-
- return found_interface ? 0 : -ENOENT;
-}
-
-_public_ int sd_bus_emit_properties_changed(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *name, ...) {
-
- char **names;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(interface_name_is_valid(interface), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (!name)
- return 0;
-
- names = strv_from_stdarg_alloca(name);
-
- return sd_bus_emit_properties_changed_strv(bus, path, interface, names);
-}
-
-static int object_added_append_all_prefix(
- sd_bus *bus,
- sd_bus_message *m,
- Set *s,
- const char *prefix,
- const char *path,
- bool require_fallback) {
-
- const char *previous_interface = NULL;
- struct node_vtable *c;
- struct node *n;
- int r;
-
- assert(bus);
- assert(m);
- assert(s);
- assert(prefix);
- assert(path);
-
- n = hashmap_get(bus->nodes, prefix);
- if (!n)
- return 0;
-
- LIST_FOREACH(vtables, c, n->vtables) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- void *u = NULL;
-
- if (require_fallback && !c->is_fallback)
- continue;
-
- r = node_vtable_get_userdata(bus, path, c, &u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- if (r == 0)
- continue;
-
- if (!streq_ptr(c->interface, previous_interface)) {
- /* If a child-node already handled this interface, we
- * skip it on any of its parents. The child vtables
- * always fully override any conflicting vtables of
- * any parent node. */
- if (set_get(s, c->interface))
- continue;
-
- r = set_put(s, c->interface);
- if (r < 0)
- return r;
-
- if (previous_interface) {
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_message_open_container(m, 'e', "sa{sv}");
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "s", c->interface);
- if (r < 0)
- return r;
- r = sd_bus_message_open_container(m, 'a', "{sv}");
- if (r < 0)
- return r;
-
- previous_interface = c->interface;
- }
-
- r = vtable_append_all_properties(bus, m, path, c, u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- if (previous_interface) {
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
- _cleanup_set_free_ Set *s = NULL;
- char *prefix;
- int r;
-
- assert(bus);
- assert(m);
- assert(path);
-
- /*
- * This appends all interfaces registered on path @path. We first add
- * the builtin interfaces, which are always available and handled by
- * sd-bus. Then, we add all interfaces registered on the exact node,
- * followed by all fallback interfaces registered on any parent prefix.
- *
- * If an interface is registered multiple times on the same node with
- * different vtables, we merge all the properties across all vtables.
- * However, if a child node has the same interface registered as one of
- * its parent nodes has as fallback, we make the child overwrite the
- * parent instead of extending it. Therefore, we keep a "Set" of all
- * handled interfaces during parent traversal, so we skip interfaces on
- * a parent that were overwritten by a child.
- */
-
- s = set_new(&string_hash_ops);
- if (!s)
- return -ENOMEM;
-
- r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0);
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0);
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0);
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0);
- if (r < 0)
- return r;
-
- r = object_added_append_all_prefix(bus, m, s, path, path, false);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- prefix = alloca(strlen(path) + 1);
- OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
- r = object_added_append_all_prefix(bus, m, s, prefix, path, true);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- return 0;
-}
-
-_public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) {
- BUS_DONT_DESTROY(bus);
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct node *object_manager;
- int r;
-
- /*
- * This emits an InterfacesAdded signal on the given path, by iterating
- * all registered vtables and fallback vtables on the path. All
- * properties are queried and included in the signal.
- * This call is equivalent to sd_bus_emit_interfaces_added() with an
- * explicit list of registered interfaces. However, unlike
- * interfaces_added(), this call can figure out the list of supported
- * interfaces itself. Furthermore, it properly adds the builtin
- * org.freedesktop.DBus.* interfaces.
- */
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- r = bus_find_parent_object_manager(bus, &object_manager, path);
- if (r < 0)
- return r;
- if (r == 0)
- return -ESRCH;
-
- do {
- bus->nodes_modified = false;
- m = sd_bus_message_unref(m);
-
- r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_basic(m, 'o', path);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
- if (r < 0)
- return r;
-
- r = object_added_append_all(bus, m, path);
- if (r < 0)
- return r;
-
- if (bus->nodes_modified)
- continue;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- } while (bus->nodes_modified);
-
- return sd_bus_send(bus, m, NULL);
-}
-
-static int object_removed_append_all_prefix(
- sd_bus *bus,
- sd_bus_message *m,
- Set *s,
- const char *prefix,
- const char *path,
- bool require_fallback) {
-
- const char *previous_interface = NULL;
- struct node_vtable *c;
- struct node *n;
- int r;
-
- assert(bus);
- assert(m);
- assert(s);
- assert(prefix);
- assert(path);
-
- n = hashmap_get(bus->nodes, prefix);
- if (!n)
- return 0;
-
- LIST_FOREACH(vtables, c, n->vtables) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- void *u = NULL;
-
- if (require_fallback && !c->is_fallback)
- continue;
- if (streq_ptr(c->interface, previous_interface))
- continue;
-
- /* If a child-node already handled this interface, we
- * skip it on any of its parents. The child vtables
- * always fully override any conflicting vtables of
- * any parent node. */
- if (set_get(s, c->interface))
- continue;
-
- r = node_vtable_get_userdata(bus, path, c, &u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- if (r == 0)
- continue;
-
- r = set_put(s, c->interface);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(m, "s", c->interface);
- if (r < 0)
- return r;
-
- previous_interface = c->interface;
- }
-
- return 0;
-}
-
-static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
- _cleanup_set_free_ Set *s = NULL;
- char *prefix;
- int r;
-
- assert(bus);
- assert(m);
- assert(path);
-
- /* see sd_bus_emit_object_added() for details */
-
- s = set_new(&string_hash_ops);
- if (!s)
- return -ENOMEM;
-
- r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Peer");
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Introspectable");
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Properties");
- if (r < 0)
- return r;
- r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.ObjectManager");
- if (r < 0)
- return r;
-
- r = object_removed_append_all_prefix(bus, m, s, path, path, false);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- prefix = alloca(strlen(path) + 1);
- OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
- r = object_removed_append_all_prefix(bus, m, s, prefix, path, true);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- return 0;
-}
-
-_public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) {
- BUS_DONT_DESTROY(bus);
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct node *object_manager;
- int r;
-
- /*
- * This is like sd_bus_emit_object_added(), but emits an
- * InterfacesRemoved signal on the given path. This only includes any
- * registered interfaces but skips the properties. Note that this will
- * call into the find() callbacks of any registered vtable. Therefore,
- * you must call this function before destroying/unlinking your object.
- * Otherwise, the list of interfaces will be incomplete. However, note
- * that this will *NOT* call into any property callback. Therefore, the
- * object might be in an "destructed" state, as long as we can find it.
- */
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- r = bus_find_parent_object_manager(bus, &object_manager, path);
- if (r < 0)
- return r;
- if (r == 0)
- return -ESRCH;
-
- do {
- bus->nodes_modified = false;
- m = sd_bus_message_unref(m);
-
- r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_basic(m, 'o', path);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "s");
- if (r < 0)
- return r;
-
- r = object_removed_append_all(bus, m, path);
- if (r < 0)
- return r;
-
- if (bus->nodes_modified)
- continue;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- } while (bus->nodes_modified);
-
- return sd_bus_send(bus, m, NULL);
-}
-
-static int interfaces_added_append_one_prefix(
- sd_bus *bus,
- sd_bus_message *m,
- const char *prefix,
- const char *path,
- const char *interface,
- bool require_fallback) {
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- bool found_interface = false;
- struct node_vtable *c;
- struct node *n;
- void *u = NULL;
- int r;
-
- assert(bus);
- assert(m);
- assert(prefix);
- assert(path);
- assert(interface);
-
- n = hashmap_get(bus->nodes, prefix);
- if (!n)
- return 0;
-
- LIST_FOREACH(vtables, c, n->vtables) {
- if (require_fallback && !c->is_fallback)
- continue;
-
- if (!streq(c->interface, interface))
- continue;
-
- r = node_vtable_get_userdata(bus, path, c, &u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- if (r == 0)
- continue;
-
- if (!found_interface) {
- r = sd_bus_message_append_basic(m, 's', interface);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "{sv}");
- if (r < 0)
- return r;
-
- found_interface = true;
- }
-
- r = vtable_append_all_properties(bus, m, path, c, u, &error);
- if (r < 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- if (found_interface) {
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
- }
-
- return found_interface;
-}
-
-static int interfaces_added_append_one(
- sd_bus *bus,
- sd_bus_message *m,
- const char *path,
- const char *interface) {
-
- char *prefix;
- int r;
-
- assert(bus);
- assert(m);
- assert(path);
- assert(interface);
-
- r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false);
- if (r != 0)
- return r;
- if (bus->nodes_modified)
- return 0;
-
- prefix = alloca(strlen(path) + 1);
- OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
- r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
- if (r != 0)
- return r;
- if (bus->nodes_modified)
- return 0;
- }
-
- return -ENOENT;
-}
-
-_public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) {
- BUS_DONT_DESTROY(bus);
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct node *object_manager;
- char **i;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (strv_isempty(interfaces))
- return 0;
-
- r = bus_find_parent_object_manager(bus, &object_manager, path);
- if (r < 0)
- return r;
- if (r == 0)
- return -ESRCH;
-
- do {
- bus->nodes_modified = false;
- m = sd_bus_message_unref(m);
-
- r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_basic(m, 'o', path);
- if (r < 0)
- return r;
-
- r = sd_bus_message_open_container(m, 'a', "{sa{sv}}");
- if (r < 0)
- return r;
-
- STRV_FOREACH(i, interfaces) {
- assert_return(interface_name_is_valid(*i), -EINVAL);
-
- r = sd_bus_message_open_container(m, 'e', "sa{sv}");
- if (r < 0)
- return r;
-
- r = interfaces_added_append_one(bus, m, path, *i);
- if (r < 0)
- return r;
-
- if (bus->nodes_modified)
- break;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
- }
-
- if (bus->nodes_modified)
- continue;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return r;
-
- } while (bus->nodes_modified);
-
- return sd_bus_send(bus, m, NULL);
-}
-
-_public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) {
- char **interfaces;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- interfaces = strv_from_stdarg_alloca(interface);
-
- return sd_bus_emit_interfaces_added_strv(bus, path, interfaces);
-}
-
-_public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct node *object_manager;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (strv_isempty(interfaces))
- return 0;
-
- r = bus_find_parent_object_manager(bus, &object_manager, path);
- if (r < 0)
- return r;
- if (r == 0)
- return -ESRCH;
-
- r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved");
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_basic(m, 'o', path);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_strv(m, interfaces);
- if (r < 0)
- return r;
-
- return sd_bus_send(bus, m, NULL);
-}
-
-_public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) {
- char **interfaces;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- interfaces = strv_from_stdarg_alloca(interface);
-
- return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
-}
-
-_public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) {
- sd_bus_slot *s;
- struct node *n;
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- n = bus_node_allocate(bus, path);
- if (!n)
- return -ENOMEM;
-
- s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
- s->node_object_manager.node = n;
- LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager);
- bus->nodes_modified = true;
-
- if (slot)
- *slot = s;
-
- return 0;
-
-fail:
- sd_bus_slot_unref(s);
- bus_node_gc(bus, n);
-
- return r;
-}
diff --git a/src/libsystemd/sd-bus/bus-objects.h b/src/libsystemd/sd-bus/bus-objects.h
deleted file mode 100644
index e0b8c534ed..0000000000
--- a/src/libsystemd/sd-bus/bus-objects.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-internal.h"
-
-int bus_process_object(sd_bus *bus, sd_bus_message *m);
-void bus_node_gc(sd_bus *b, struct node *n);
diff --git a/src/libsystemd/sd-bus/bus-protocol.h b/src/libsystemd/sd-bus/bus-protocol.h
deleted file mode 100644
index 9d180cb284..0000000000
--- a/src/libsystemd/sd-bus/bus-protocol.h
+++ /dev/null
@@ -1,180 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <endian.h>
-
-#include "macro.h"
-
-/* 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! */
- };
-};
-
-/* Endianness */
-
-enum {
- _BUS_INVALID_ENDIAN = 0,
- BUS_LITTLE_ENDIAN = 'l',
- BUS_BIG_ENDIAN = 'B',
-#if __BYTE_ORDER == __BIG_ENDIAN
- BUS_NATIVE_ENDIAN = BUS_BIG_ENDIAN,
- BUS_REVERSE_ENDIAN = BUS_LITTLE_ENDIAN
-#else
- BUS_NATIVE_ENDIAN = BUS_LITTLE_ENDIAN,
- BUS_REVERSE_ENDIAN = BUS_BIG_ENDIAN
-#endif
-};
-
-/* Flags */
-
-enum {
- BUS_MESSAGE_NO_REPLY_EXPECTED = 1,
- BUS_MESSAGE_NO_AUTO_START = 2,
- BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION = 4,
-};
-
-/* Header fields */
-
-enum {
- _BUS_MESSAGE_HEADER_INVALID = 0,
- BUS_MESSAGE_HEADER_PATH,
- BUS_MESSAGE_HEADER_INTERFACE,
- BUS_MESSAGE_HEADER_MEMBER,
- BUS_MESSAGE_HEADER_ERROR_NAME,
- BUS_MESSAGE_HEADER_REPLY_SERIAL,
- BUS_MESSAGE_HEADER_DESTINATION,
- BUS_MESSAGE_HEADER_SENDER,
- BUS_MESSAGE_HEADER_SIGNATURE,
- BUS_MESSAGE_HEADER_UNIX_FDS,
- _BUS_MESSAGE_HEADER_MAX
-};
-
-/* RequestName parameters */
-
-enum {
- BUS_NAME_ALLOW_REPLACEMENT = 1,
- BUS_NAME_REPLACE_EXISTING = 2,
- BUS_NAME_DO_NOT_QUEUE = 4
-};
-
-/* RequestName returns */
-enum {
- BUS_NAME_PRIMARY_OWNER = 1,
- BUS_NAME_IN_QUEUE = 2,
- BUS_NAME_EXISTS = 3,
- BUS_NAME_ALREADY_OWNER = 4
-};
-
-/* ReleaseName returns */
-enum {
- BUS_NAME_RELEASED = 1,
- BUS_NAME_NON_EXISTENT = 2,
- BUS_NAME_NOT_OWNER = 3,
-};
-
-/* StartServiceByName returns */
-enum {
- BUS_START_REPLY_SUCCESS = 1,
- BUS_START_REPLY_ALREADY_RUNNING = 2,
-};
-
-#define BUS_INTROSPECT_DOCTYPE \
- "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \
- "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
-
-#define BUS_INTROSPECT_INTERFACE_PEER \
- " <interface name=\"org.freedesktop.DBus.Peer\">\n" \
- " <method name=\"Ping\"/>\n" \
- " <method name=\"GetMachineId\">\n" \
- " <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
- " </method>\n" \
- " </interface>\n"
-
-#define BUS_INTROSPECT_INTERFACE_INTROSPECTABLE \
- " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
- " <method name=\"Introspect\">\n" \
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
- " </method>\n" \
- " </interface>\n"
-
-#define BUS_INTROSPECT_INTERFACE_PROPERTIES \
- " <interface name=\"org.freedesktop.DBus.Properties\">\n" \
- " <method name=\"Get\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"value\" direction=\"out\" type=\"v\"/>\n" \
- " </method>\n" \
- " <method name=\"GetAll\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
- " </method>\n" \
- " <method name=\"Set\">\n" \
- " <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
- " <arg name=\"value\" direction=\"in\" type=\"v\"/>\n" \
- " </method>\n" \
- " <signal name=\"PropertiesChanged\">\n" \
- " <arg type=\"s\" name=\"interface\"/>\n" \
- " <arg type=\"a{sv}\" name=\"changed_properties\"/>\n" \
- " <arg type=\"as\" name=\"invalidated_properties\"/>\n" \
- " </signal>\n" \
- " </interface>\n"
-
-#define BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER \
- " <interface name=\"org.freedesktop.DBus.ObjectManager\">\n" \
- " <method name=\"GetManagedObjects\">\n" \
- " <arg type=\"a{oa{sa{sv}}}\" name=\"object_paths_interfaces_and_properties\" direction=\"out\"/>\n" \
- " </method>\n" \
- " <signal name=\"InterfacesAdded\">\n" \
- " <arg type=\"o\" name=\"object_path\"/>\n" \
- " <arg type=\"a{sa{sv}}\" name=\"interfaces_and_properties\"/>\n" \
- " </signal>\n" \
- " <signal name=\"InterfacesRemoved\">\n" \
- " <arg type=\"o\" name=\"object_path\"/>\n" \
- " <arg type=\"as\" name=\"interfaces\"/>\n" \
- " </signal>\n" \
- " </interface>\n"
diff --git a/src/libsystemd/sd-bus/bus-signature.c b/src/libsystemd/sd-bus/bus-signature.c
deleted file mode 100644
index 7bc243494a..0000000000
--- a/src/libsystemd/sd-bus/bus-signature.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <util.h>
-
-#include "bus-signature.h"
-#include "bus-type.h"
-
-static int signature_element_length_internal(
- const char *s,
- bool allow_dict_entry,
- unsigned array_depth,
- unsigned struct_depth,
- size_t *l) {
-
- int r;
-
- if (!s)
- return -EINVAL;
-
- assert(l);
-
- if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
- *l = 1;
- return 0;
- }
-
- if (*s == SD_BUS_TYPE_ARRAY) {
- size_t t;
-
- if (array_depth >= 32)
- return -EINVAL;
-
- r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
- if (r < 0)
- return r;
-
- *l = t + 1;
- return 0;
- }
-
- if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
- const char *p = s + 1;
-
- if (struct_depth >= 32)
- return -EINVAL;
-
- while (*p != SD_BUS_TYPE_STRUCT_END) {
- size_t t;
-
- r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
- if (r < 0)
- return r;
-
- p += t;
- }
-
- *l = p - s + 1;
- return 0;
- }
-
- if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
- const char *p = s + 1;
- unsigned n = 0;
-
- if (struct_depth >= 32)
- return -EINVAL;
-
- while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
- size_t t;
-
- if (n == 0 && !bus_type_is_basic(*p))
- return -EINVAL;
-
- r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
- if (r < 0)
- return r;
-
- p += t;
- n++;
- }
-
- if (n != 2)
- return -EINVAL;
-
- *l = p - s + 1;
- return 0;
- }
-
- return -EINVAL;
-}
-
-
-int signature_element_length(const char *s, size_t *l) {
- return signature_element_length_internal(s, true, 0, 0, l);
-}
-
-bool signature_is_single(const char *s, bool allow_dict_entry) {
- int r;
- size_t t;
-
- if (!s)
- return false;
-
- r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
- if (r < 0)
- return false;
-
- return s[t] == 0;
-}
-
-bool signature_is_pair(const char *s) {
-
- if (!s)
- return false;
-
- if (!bus_type_is_basic(*s))
- return false;
-
- return signature_is_single(s + 1, false);
-}
-
-bool signature_is_valid(const char *s, bool allow_dict_entry) {
- const char *p;
- int r;
-
- if (!s)
- return false;
-
- p = s;
- while (*p) {
- size_t t;
-
- r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
- if (r < 0)
- return false;
-
- p += t;
- }
-
- return p - s <= 255;
-}
diff --git a/src/libsystemd/sd-bus/bus-signature.h b/src/libsystemd/sd-bus/bus-signature.h
deleted file mode 100644
index 1e0cd7f587..0000000000
--- a/src/libsystemd/sd-bus/bus-signature.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-bool signature_is_single(const char *s, bool allow_dict_entry);
-bool signature_is_pair(const char *s);
-bool signature_is_valid(const char *s, bool allow_dict_entry);
-
-int signature_element_length(const char *s, size_t *l);
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
deleted file mode 100644
index 33590c31ac..0000000000
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-control.h"
-#include "bus-objects.h"
-#include "bus-slot.h"
-#include "string-util.h"
-
-sd_bus_slot *bus_slot_allocate(
- sd_bus *bus,
- bool floating,
- BusSlotType type,
- size_t extra,
- void *userdata) {
-
- sd_bus_slot *slot;
-
- assert(bus);
-
- slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
- if (!slot)
- return NULL;
-
- slot->n_ref = 1;
- slot->type = type;
- slot->bus = bus;
- slot->floating = floating;
- slot->userdata = userdata;
-
- if (!floating)
- sd_bus_ref(bus);
-
- LIST_PREPEND(slots, bus->slots, slot);
-
- return slot;
-}
-
-_public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
-
- if (!slot)
- return NULL;
-
- assert(slot->n_ref > 0);
-
- slot->n_ref++;
- return slot;
-}
-
-void bus_slot_disconnect(sd_bus_slot *slot) {
- sd_bus *bus;
-
- assert(slot);
-
- if (!slot->bus)
- return;
-
- switch (slot->type) {
-
- case BUS_REPLY_CALLBACK:
-
- if (slot->reply_callback.cookie != 0)
- ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
-
- if (slot->reply_callback.timeout != 0)
- prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
-
- break;
-
- case BUS_FILTER_CALLBACK:
- slot->bus->filter_callbacks_modified = true;
- LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
- break;
-
- case BUS_MATCH_CALLBACK:
-
- if (slot->match_added)
- bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
-
- slot->bus->match_callbacks_modified = true;
- bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
-
- free(slot->match_callback.match_string);
-
- break;
-
- case BUS_NODE_CALLBACK:
-
- if (slot->node_callback.node) {
- LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
- slot->bus->nodes_modified = true;
-
- bus_node_gc(slot->bus, slot->node_callback.node);
- }
-
- break;
-
- case BUS_NODE_ENUMERATOR:
-
- if (slot->node_enumerator.node) {
- LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
- slot->bus->nodes_modified = true;
-
- bus_node_gc(slot->bus, slot->node_enumerator.node);
- }
-
- break;
-
- case BUS_NODE_OBJECT_MANAGER:
-
- if (slot->node_object_manager.node) {
- LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager);
- slot->bus->nodes_modified = true;
-
- bus_node_gc(slot->bus, slot->node_object_manager.node);
- }
-
- break;
-
- case BUS_NODE_VTABLE:
-
- if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
- const sd_bus_vtable *v;
-
- for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) {
- struct vtable_member *x = NULL;
-
- switch (v->type) {
-
- case _SD_BUS_VTABLE_METHOD: {
- struct vtable_member key;
-
- key.path = slot->node_vtable.node->path;
- key.interface = slot->node_vtable.interface;
- key.member = v->x.method.member;
-
- x = hashmap_remove(slot->bus->vtable_methods, &key);
- break;
- }
-
- case _SD_BUS_VTABLE_PROPERTY:
- case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
- struct vtable_member key;
-
- key.path = slot->node_vtable.node->path;
- key.interface = slot->node_vtable.interface;
- key.member = v->x.method.member;
-
-
- x = hashmap_remove(slot->bus->vtable_properties, &key);
- break;
- }}
-
- free(x);
- }
- }
-
- free(slot->node_vtable.interface);
-
- if (slot->node_vtable.node) {
- LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
- slot->bus->nodes_modified = true;
-
- bus_node_gc(slot->bus, slot->node_vtable.node);
- }
-
- break;
-
- default:
- assert_not_reached("Wut? Unknown slot type?");
- }
-
- bus = slot->bus;
-
- slot->type = _BUS_SLOT_INVALID;
- slot->bus = NULL;
- LIST_REMOVE(slots, bus->slots, slot);
-
- if (!slot->floating)
- sd_bus_unref(bus);
-}
-
-_public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
-
- if (!slot)
- return NULL;
-
- assert(slot->n_ref > 0);
-
- if (slot->n_ref > 1) {
- slot->n_ref--;
- return NULL;
- }
-
- bus_slot_disconnect(slot);
- free(slot->description);
- return mfree(slot);
-}
-
-_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
- assert_return(slot, NULL);
-
- return slot->bus;
-}
-
-_public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
- assert_return(slot, NULL);
-
- return slot->userdata;
-}
-
-_public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
- void *ret;
-
- assert_return(slot, NULL);
-
- ret = slot->userdata;
- slot->userdata = userdata;
-
- return ret;
-}
-
-_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
- assert_return(slot, NULL);
- assert_return(slot->type >= 0, NULL);
-
- if (slot->bus->current_slot != slot)
- return NULL;
-
- return slot->bus->current_message;
-}
-
-_public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot) {
- assert_return(slot, NULL);
- assert_return(slot->type >= 0, NULL);
-
- if (slot->bus->current_slot != slot)
- return NULL;
-
- return slot->bus->current_handler;
-}
-
-_public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) {
- assert_return(slot, NULL);
- assert_return(slot->type >= 0, NULL);
-
- if (slot->bus->current_slot != slot)
- return NULL;
-
- return slot->bus->current_userdata;
-}
-
-_public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) {
- assert_return(slot, -EINVAL);
-
- return free_and_strdup(&slot->description, description);
-}
-
-_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) {
- assert_return(slot, -EINVAL);
- assert_return(description, -EINVAL);
- assert_return(slot->description, -ENXIO);
-
- *description = slot->description;
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/bus-slot.h b/src/libsystemd/sd-bus/bus-slot.h
deleted file mode 100644
index 3b8b94dc6b..0000000000
--- a/src/libsystemd/sd-bus/bus-slot.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "bus-internal.h"
-
-sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata);
-
-void bus_slot_disconnect(sd_bus_slot *slot);
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
deleted file mode 100644
index cfd7753139..0000000000
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ /dev/null
@@ -1,1064 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <endian.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "sd-bus.h"
-#include "sd-daemon.h"
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-socket.h"
-#include "fd-util.h"
-#include "formats-util.h"
-#include "hexdecoct.h"
-#include "macro.h"
-#include "missing.h"
-#include "selinux-util.h"
-#include "signal-util.h"
-#include "stdio-util.h"
-#include "string-util.h"
-#include "user-util.h"
-#include "utf8.h"
-#include "util.h"
-
-#define SNDBUF_SIZE (8*1024*1024)
-
-static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
-
- while (size > 0) {
- struct iovec *i = iov + *idx;
-
- if (i->iov_len > size) {
- i->iov_base = (uint8_t*) i->iov_base + size;
- i->iov_len -= size;
- return;
- }
-
- size -= i->iov_len;
-
- i->iov_base = NULL;
- i->iov_len = 0;
-
- (*idx)++;
- }
-}
-
-static int append_iovec(sd_bus_message *m, const void *p, size_t sz) {
- assert(m);
- assert(p);
- assert(sz > 0);
-
- m->iovec[m->n_iovec].iov_base = (void*) p;
- m->iovec[m->n_iovec].iov_len = sz;
- m->n_iovec++;
-
- return 0;
-}
-
-static int bus_message_setup_iovec(sd_bus_message *m) {
- struct bus_body_part *part;
- unsigned n, i;
- int r;
-
- assert(m);
- assert(m->sealed);
-
- if (m->n_iovec > 0)
- return 0;
-
- assert(!m->iovec);
-
- n = 1 + m->n_body_parts;
- if (n < ELEMENTSOF(m->iovec_fixed))
- m->iovec = m->iovec_fixed;
- else {
- m->iovec = new(struct iovec, n);
- if (!m->iovec) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m));
- if (r < 0)
- goto fail;
-
- MESSAGE_FOREACH_PART(part, i, m) {
- r = bus_body_part_map(part);
- if (r < 0)
- goto fail;
-
- r = append_iovec(m, part->data, part->size);
- if (r < 0)
- goto fail;
- }
-
- assert(n == m->n_iovec);
-
- return 0;
-
-fail:
- m->poisoned = true;
- return r;
-}
-
-bool bus_socket_auth_needs_write(sd_bus *b) {
-
- unsigned i;
-
- if (b->auth_index >= ELEMENTSOF(b->auth_iovec))
- return false;
-
- for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) {
- struct iovec *j = b->auth_iovec + i;
-
- if (j->iov_len > 0)
- return true;
- }
-
- return false;
-}
-
-static int bus_socket_write_auth(sd_bus *b) {
- ssize_t k;
-
- assert(b);
- assert(b->state == BUS_AUTHENTICATING);
-
- if (!bus_socket_auth_needs_write(b))
- return 0;
-
- if (b->prefer_writev)
- k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
- else {
- struct msghdr mh;
- zero(mh);
-
- mh.msg_iov = b->auth_iovec + b->auth_index;
- mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
-
- k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
- if (k < 0 && errno == ENOTSOCK) {
- b->prefer_writev = true;
- k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
- }
- }
-
- if (k < 0)
- return errno == EAGAIN ? 0 : -errno;
-
- iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
- return 1;
-}
-
-static int bus_socket_auth_verify_client(sd_bus *b) {
- char *e, *f, *start;
- sd_id128_t peer;
- unsigned i;
- int r;
-
- assert(b);
-
- /* We expect two response lines: "OK" and possibly
- * "AGREE_UNIX_FD" */
-
- e = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2);
- if (!e)
- return 0;
-
- if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) {
- f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
- if (!f)
- return 0;
-
- start = f + 2;
- } else {
- f = NULL;
- start = e + 2;
- }
-
- /* Nice! We got all the lines we need. First check the OK
- * line */
-
- if (e - (char*) b->rbuffer != 3 + 32)
- return -EPERM;
-
- if (memcmp(b->rbuffer, "OK ", 3))
- return -EPERM;
-
- b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
-
- for (i = 0; i < 32; i += 2) {
- int x, y;
-
- x = unhexchar(((char*) b->rbuffer)[3 + i]);
- y = unhexchar(((char*) b->rbuffer)[3 + i + 1]);
-
- if (x < 0 || y < 0)
- return -EINVAL;
-
- peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
- }
-
- if (!sd_id128_is_null(b->server_id) &&
- !sd_id128_equal(b->server_id, peer))
- return -EPERM;
-
- b->server_id = peer;
-
- /* And possibly check the second line, too */
-
- if (f)
- b->can_fds =
- (f - e == strlen("\r\nAGREE_UNIX_FD")) &&
- memcmp(e + 2, "AGREE_UNIX_FD", strlen("AGREE_UNIX_FD")) == 0;
-
- b->rbuffer_size -= (start - (char*) b->rbuffer);
- memmove(b->rbuffer, start, b->rbuffer_size);
-
- r = bus_start_running(b);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static bool line_equals(const char *s, size_t m, const char *line) {
- size_t l;
-
- l = strlen(line);
- if (l != m)
- return false;
-
- return memcmp(s, line, l) == 0;
-}
-
-static bool line_begins(const char *s, size_t m, const char *word) {
- size_t l;
-
- l = strlen(word);
- if (m < l)
- return false;
-
- if (memcmp(s, word, l) != 0)
- return false;
-
- return m == l || (m > l && s[l] == ' ');
-}
-
-static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
- _cleanup_free_ char *token = NULL;
- size_t len;
- int r;
-
- if (!b->anonymous_auth)
- return 0;
-
- if (l <= 0)
- return 1;
-
- assert(p[0] == ' ');
- p++; l--;
-
- if (l % 2 != 0)
- return 0;
-
- r = unhexmem(p, l, (void **) &token, &len);
- if (r < 0)
- return 0;
-
- if (memchr(token, 0, len))
- return 0;
-
- return !!utf8_is_valid(token);
-}
-
-static int verify_external_token(sd_bus *b, const char *p, size_t l) {
- _cleanup_free_ char *token = NULL;
- size_t len;
- uid_t u;
- int r;
-
- /* We don't do any real authentication here. Instead, we if
- * the owner of this bus wanted authentication he should have
- * checked SO_PEERCRED before even creating the bus object. */
-
- if (!b->anonymous_auth && !b->ucred_valid)
- return 0;
-
- if (l <= 0)
- return 1;
-
- assert(p[0] == ' ');
- p++; l--;
-
- if (l % 2 != 0)
- return 0;
-
- r = unhexmem(p, l, (void**) &token, &len);
- if (r < 0)
- return 0;
-
- if (memchr(token, 0, len))
- return 0;
-
- r = parse_uid(token, &u);
- if (r < 0)
- return 0;
-
- /* We ignore the passed value if anonymous authentication is
- * on anyway. */
- if (!b->anonymous_auth && u != b->ucred.uid)
- return 0;
-
- return 1;
-}
-
-static int bus_socket_auth_write(sd_bus *b, const char *t) {
- char *p;
- size_t l;
-
- assert(b);
- assert(t);
-
- /* We only make use of the first iovec */
- assert(b->auth_index == 0 || b->auth_index == 1);
-
- l = strlen(t);
- p = malloc(b->auth_iovec[0].iov_len + l);
- if (!p)
- return -ENOMEM;
-
- memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
- memcpy(p + b->auth_iovec[0].iov_len, t, l);
-
- b->auth_iovec[0].iov_base = p;
- b->auth_iovec[0].iov_len += l;
-
- free(b->auth_buffer);
- b->auth_buffer = p;
- b->auth_index = 0;
- return 0;
-}
-
-static int bus_socket_auth_write_ok(sd_bus *b) {
- char t[3 + 32 + 2 + 1];
-
- assert(b);
-
- xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
-
- return bus_socket_auth_write(b, t);
-}
-
-static int bus_socket_auth_verify_server(sd_bus *b) {
- char *e;
- const char *line;
- size_t l;
- bool processed = false;
- int r;
-
- assert(b);
-
- if (b->rbuffer_size < 1)
- return 0;
-
- /* First char must be a NUL byte */
- if (*(char*) b->rbuffer != 0)
- return -EIO;
-
- if (b->rbuffer_size < 3)
- return 0;
-
- /* Begin with the first line */
- if (b->auth_rbegin <= 0)
- b->auth_rbegin = 1;
-
- for (;;) {
- /* Check if line is complete */
- line = (char*) b->rbuffer + b->auth_rbegin;
- e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2);
- if (!e)
- return processed;
-
- l = e - line;
-
- if (line_begins(line, l, "AUTH ANONYMOUS")) {
-
- r = verify_anonymous_token(b, line + 14, l - 14);
- if (r < 0)
- return r;
- if (r == 0)
- r = bus_socket_auth_write(b, "REJECTED\r\n");
- else {
- b->auth = BUS_AUTH_ANONYMOUS;
- r = bus_socket_auth_write_ok(b);
- }
-
- } else if (line_begins(line, l, "AUTH EXTERNAL")) {
-
- r = verify_external_token(b, line + 13, l - 13);
- if (r < 0)
- return r;
- if (r == 0)
- r = bus_socket_auth_write(b, "REJECTED\r\n");
- else {
- b->auth = BUS_AUTH_EXTERNAL;
- r = bus_socket_auth_write_ok(b);
- }
-
- } else if (line_begins(line, l, "AUTH"))
- r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n");
- else if (line_equals(line, l, "CANCEL") ||
- line_begins(line, l, "ERROR")) {
-
- b->auth = _BUS_AUTH_INVALID;
- r = bus_socket_auth_write(b, "REJECTED\r\n");
-
- } else if (line_equals(line, l, "BEGIN")) {
-
- if (b->auth == _BUS_AUTH_INVALID)
- r = bus_socket_auth_write(b, "ERROR\r\n");
- else {
- /* We can't leave from the auth phase
- * before we haven't written
- * everything queued, so let's check
- * that */
-
- if (bus_socket_auth_needs_write(b))
- return 1;
-
- b->rbuffer_size -= (e + 2 - (char*) b->rbuffer);
- memmove(b->rbuffer, e + 2, b->rbuffer_size);
- return bus_start_running(b);
- }
-
- } else if (line_begins(line, l, "DATA")) {
-
- if (b->auth == _BUS_AUTH_INVALID)
- r = bus_socket_auth_write(b, "ERROR\r\n");
- else {
- if (b->auth == BUS_AUTH_ANONYMOUS)
- r = verify_anonymous_token(b, line + 4, l - 4);
- else
- r = verify_external_token(b, line + 4, l - 4);
-
- if (r < 0)
- return r;
- if (r == 0) {
- b->auth = _BUS_AUTH_INVALID;
- r = bus_socket_auth_write(b, "REJECTED\r\n");
- } else
- r = bus_socket_auth_write_ok(b);
- }
- } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
- if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD))
- r = bus_socket_auth_write(b, "ERROR\r\n");
- else {
- b->can_fds = true;
- r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n");
- }
- } else
- r = bus_socket_auth_write(b, "ERROR\r\n");
-
- if (r < 0)
- return r;
-
- b->auth_rbegin = e + 2 - (char*) b->rbuffer;
-
- processed = true;
- }
-}
-
-static int bus_socket_auth_verify(sd_bus *b) {
- assert(b);
-
- if (b->is_server)
- return bus_socket_auth_verify_server(b);
- else
- return bus_socket_auth_verify_client(b);
-}
-
-static int bus_socket_read_auth(sd_bus *b) {
- struct msghdr mh;
- struct iovec iov = {};
- size_t n;
- ssize_t k;
- int r;
- void *p;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
- } control;
- bool handle_cmsg = false;
-
- assert(b);
- assert(b->state == BUS_AUTHENTICATING);
-
- r = bus_socket_auth_verify(b);
- if (r != 0)
- return r;
-
- n = MAX(256u, b->rbuffer_size * 2);
-
- if (n > BUS_AUTH_SIZE_MAX)
- n = BUS_AUTH_SIZE_MAX;
-
- if (b->rbuffer_size >= n)
- return -ENOBUFS;
-
- p = realloc(b->rbuffer, n);
- if (!p)
- return -ENOMEM;
-
- b->rbuffer = p;
-
- iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size;
- iov.iov_len = n - b->rbuffer_size;
-
- if (b->prefer_readv)
- k = readv(b->input_fd, &iov, 1);
- else {
- zero(mh);
- mh.msg_iov = &iov;
- mh.msg_iovlen = 1;
- mh.msg_control = &control;
- mh.msg_controllen = sizeof(control);
-
- k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
- if (k < 0 && errno == ENOTSOCK) {
- b->prefer_readv = true;
- k = readv(b->input_fd, &iov, 1);
- } else
- handle_cmsg = true;
- }
- if (k < 0)
- return errno == EAGAIN ? 0 : -errno;
- if (k == 0)
- return -ECONNRESET;
-
- b->rbuffer_size += k;
-
- if (handle_cmsg) {
- struct cmsghdr *cmsg;
-
- CMSG_FOREACH(cmsg, &mh)
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- int j;
-
- /* Whut? We received fds during the auth
- * protocol? Somebody is playing games with
- * us. Close them all, and fail */
- j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
- close_many((int*) CMSG_DATA(cmsg), j);
- return -EIO;
- } else
- log_debug("Got unexpected auxiliary data with level=%d and type=%d",
- cmsg->cmsg_level, cmsg->cmsg_type);
- }
-
- r = bus_socket_auth_verify(b);
- if (r != 0)
- return r;
-
- return 1;
-}
-
-void bus_socket_setup(sd_bus *b) {
- assert(b);
-
- /* Increase the buffers to 8 MB */
- fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
- fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
-
- b->is_kernel = false;
- b->message_version = 1;
- b->message_endian = 0;
-}
-
-static void bus_get_peercred(sd_bus *b) {
- int r;
-
- assert(b);
-
- /* Get the peer for socketpair() sockets */
- b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
-
- /* Get the SELinux context of the peer */
- if (mac_selinux_have()) {
- r = getpeersec(b->input_fd, &b->label);
- if (r < 0 && r != -EOPNOTSUPP)
- log_debug_errno(r, "Failed to determine peer security context: %m");
- }
-}
-
-static int bus_socket_start_auth_client(sd_bus *b) {
- size_t l;
- const char *auth_suffix, *auth_prefix;
-
- assert(b);
-
- if (b->anonymous_auth) {
- auth_prefix = "\0AUTH ANONYMOUS ";
-
- /* For ANONYMOUS auth we send some arbitrary "trace" string */
- l = 9;
- b->auth_buffer = hexmem("anonymous", l);
- } else {
- char text[DECIMAL_STR_MAX(uid_t) + 1];
-
- auth_prefix = "\0AUTH EXTERNAL ";
-
- xsprintf(text, UID_FMT, geteuid());
-
- l = strlen(text);
- b->auth_buffer = hexmem(text, l);
- }
-
- if (!b->auth_buffer)
- return -ENOMEM;
-
- if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD)
- auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
- else
- auth_suffix = "\r\nBEGIN\r\n";
-
- b->auth_iovec[0].iov_base = (void*) auth_prefix;
- b->auth_iovec[0].iov_len = 1 + strlen(auth_prefix + 1);
- b->auth_iovec[1].iov_base = (void*) b->auth_buffer;
- b->auth_iovec[1].iov_len = l * 2;
- b->auth_iovec[2].iov_base = (void*) auth_suffix;
- b->auth_iovec[2].iov_len = strlen(auth_suffix);
-
- return bus_socket_write_auth(b);
-}
-
-int bus_socket_start_auth(sd_bus *b) {
- assert(b);
-
- bus_get_peercred(b);
-
- b->state = BUS_AUTHENTICATING;
- b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
-
- if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
- b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
-
- if (b->output_fd != b->input_fd)
- if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
- b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
-
- if (b->is_server)
- return bus_socket_read_auth(b);
- else
- return bus_socket_start_auth_client(b);
-}
-
-int bus_socket_connect(sd_bus *b) {
- int r;
-
- assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
-
- b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (b->input_fd < 0)
- return -errno;
-
- b->output_fd = b->input_fd;
-
- bus_socket_setup(b);
-
- r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
- if (r < 0) {
- if (errno == EINPROGRESS)
- return 1;
-
- return -errno;
- }
-
- return bus_socket_start_auth(b);
-}
-
-int bus_socket_exec(sd_bus *b) {
- int s[2], r;
- pid_t pid;
-
- assert(b);
- assert(b->input_fd < 0);
- assert(b->output_fd < 0);
- assert(b->exec_path);
-
- r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
- if (r < 0)
- return -errno;
-
- pid = fork();
- if (pid < 0) {
- safe_close_pair(s);
- return -errno;
- }
- if (pid == 0) {
- /* Child */
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- close_all_fds(s+1, 1);
-
- assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO);
- assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
-
- if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO)
- safe_close(s[1]);
-
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_nonblock(STDIN_FILENO, false);
- fd_nonblock(STDOUT_FILENO, false);
-
- if (b->exec_argv)
- execvp(b->exec_path, b->exec_argv);
- else {
- const char *argv[] = { b->exec_path, NULL };
- execvp(b->exec_path, (char**) argv);
- }
-
- _exit(EXIT_FAILURE);
- }
-
- safe_close(s[1]);
- b->output_fd = b->input_fd = s[0];
-
- bus_socket_setup(b);
-
- return bus_socket_start_auth(b);
-}
-
-int bus_socket_take_fd(sd_bus *b) {
- assert(b);
-
- bus_socket_setup(b);
-
- return bus_socket_start_auth(b);
-}
-
-int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
- struct iovec *iov;
- ssize_t k;
- size_t n;
- unsigned j;
- int r;
-
- assert(bus);
- assert(m);
- assert(idx);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- if (*idx >= BUS_MESSAGE_SIZE(m))
- return 0;
-
- r = bus_message_setup_iovec(m);
- if (r < 0)
- return r;
-
- n = m->n_iovec * sizeof(struct iovec);
- iov = alloca(n);
- memcpy_safe(iov, m->iovec, n);
-
- j = 0;
- iovec_advance(iov, &j, *idx);
-
- if (bus->prefer_writev)
- k = writev(bus->output_fd, iov, m->n_iovec);
- else {
- struct msghdr mh = {
- .msg_iov = iov,
- .msg_iovlen = m->n_iovec,
- };
-
- if (m->n_fds > 0) {
- struct cmsghdr *control;
-
- mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
- mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
- control->cmsg_level = SOL_SOCKET;
- control->cmsg_type = SCM_RIGHTS;
- memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
- }
-
- k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
- if (k < 0 && errno == ENOTSOCK) {
- bus->prefer_writev = true;
- k = writev(bus->output_fd, iov, m->n_iovec);
- }
- }
-
- if (k < 0)
- return errno == EAGAIN ? 0 : -errno;
-
- *idx += (size_t) k;
- return 1;
-}
-
-static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
- uint32_t a, b;
- uint8_t e;
- uint64_t sum;
-
- assert(bus);
- assert(need);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- if (bus->rbuffer_size < sizeof(struct bus_header)) {
- *need = sizeof(struct bus_header) + 8;
-
- /* Minimum message size:
- *
- * Header +
- *
- * Method Call: +2 string headers
- * Signal: +3 string headers
- * Method Error: +1 string headers
- * +1 uint32 headers
- * Method Reply: +1 uint32 headers
- *
- * A string header is at least 9 bytes
- * A uint32 header is at least 8 bytes
- *
- * Hence the minimum message size of a valid message
- * is header + 8 bytes */
-
- return 0;
- }
-
- a = ((const uint32_t*) bus->rbuffer)[1];
- b = ((const uint32_t*) bus->rbuffer)[3];
-
- e = ((const uint8_t*) bus->rbuffer)[0];
- if (e == BUS_LITTLE_ENDIAN) {
- a = le32toh(a);
- b = le32toh(b);
- } else if (e == BUS_BIG_ENDIAN) {
- a = be32toh(a);
- b = be32toh(b);
- } else
- return -EBADMSG;
-
- sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
- if (sum >= BUS_MESSAGE_SIZE_MAX)
- return -ENOBUFS;
-
- *need = (size_t) sum;
- return 0;
-}
-
-static int bus_socket_make_message(sd_bus *bus, size_t size) {
- sd_bus_message *t;
- void *b;
- int r;
-
- assert(bus);
- assert(bus->rbuffer_size >= size);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- r = bus_rqueue_make_room(bus);
- if (r < 0)
- return r;
-
- if (bus->rbuffer_size > size) {
- b = memdup((const uint8_t*) bus->rbuffer + size,
- bus->rbuffer_size - size);
- if (!b)
- return -ENOMEM;
- } else
- b = NULL;
-
- r = bus_message_from_malloc(bus,
- bus->rbuffer, size,
- bus->fds, bus->n_fds,
- NULL,
- &t);
- if (r < 0) {
- free(b);
- return r;
- }
-
- bus->rbuffer = b;
- bus->rbuffer_size -= size;
-
- bus->fds = NULL;
- bus->n_fds = 0;
-
- bus->rqueue[bus->rqueue_size++] = t;
-
- return 1;
-}
-
-int bus_socket_read_message(sd_bus *bus) {
- struct msghdr mh;
- struct iovec iov = {};
- ssize_t k;
- size_t need;
- int r;
- void *b;
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
- } control;
- bool handle_cmsg = false;
-
- assert(bus);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- r = bus_socket_read_message_need(bus, &need);
- if (r < 0)
- return r;
-
- if (bus->rbuffer_size >= need)
- return bus_socket_make_message(bus, need);
-
- b = realloc(bus->rbuffer, need);
- if (!b)
- return -ENOMEM;
-
- bus->rbuffer = b;
-
- iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size;
- iov.iov_len = need - bus->rbuffer_size;
-
- if (bus->prefer_readv)
- k = readv(bus->input_fd, &iov, 1);
- else {
- zero(mh);
- mh.msg_iov = &iov;
- mh.msg_iovlen = 1;
- mh.msg_control = &control;
- mh.msg_controllen = sizeof(control);
-
- k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
- if (k < 0 && errno == ENOTSOCK) {
- bus->prefer_readv = true;
- k = readv(bus->input_fd, &iov, 1);
- } else
- handle_cmsg = true;
- }
- if (k < 0)
- return errno == EAGAIN ? 0 : -errno;
- if (k == 0)
- return -ECONNRESET;
-
- bus->rbuffer_size += k;
-
- if (handle_cmsg) {
- struct cmsghdr *cmsg;
-
- CMSG_FOREACH(cmsg, &mh)
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- int n, *f;
-
- n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
-
- if (!bus->can_fds) {
- /* Whut? We received fds but this
- * isn't actually enabled? Close them,
- * and fail */
-
- close_many((int*) CMSG_DATA(cmsg), n);
- return -EIO;
- }
-
- f = realloc(bus->fds, sizeof(int) * (bus->n_fds + n));
- if (!f) {
- close_many((int*) CMSG_DATA(cmsg), n);
- return -ENOMEM;
- }
-
- memcpy_safe(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
- bus->fds = f;
- bus->n_fds += n;
- } else
- log_debug("Got unexpected auxiliary data with level=%d and type=%d",
- cmsg->cmsg_level, cmsg->cmsg_type);
- }
-
- r = bus_socket_read_message_need(bus, &need);
- if (r < 0)
- return r;
-
- if (bus->rbuffer_size >= need)
- return bus_socket_make_message(bus, need);
-
- return 1;
-}
-
-int bus_socket_process_opening(sd_bus *b) {
- int error = 0;
- socklen_t slen = sizeof(error);
- struct pollfd p = {
- .fd = b->output_fd,
- .events = POLLOUT,
- };
- int r;
-
- assert(b->state == BUS_OPENING);
-
- r = poll(&p, 1, 0);
- if (r < 0)
- return -errno;
-
- if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
- return 0;
-
- r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
- if (r < 0)
- b->last_connect_error = errno;
- else if (error != 0)
- b->last_connect_error = error;
- else if (p.revents & (POLLERR|POLLHUP))
- b->last_connect_error = ECONNREFUSED;
- else
- return bus_socket_start_auth(b);
-
- return bus_next_address(b);
-}
-
-int bus_socket_process_authenticating(sd_bus *b) {
- int r;
-
- assert(b);
- assert(b->state == BUS_AUTHENTICATING);
-
- if (now(CLOCK_MONOTONIC) >= b->auth_timeout)
- return -ETIMEDOUT;
-
- r = bus_socket_write_auth(b);
- if (r != 0)
- return r;
-
- return bus_socket_read_auth(b);
-}
diff --git a/src/libsystemd/sd-bus/bus-socket.h b/src/libsystemd/sd-bus/bus-socket.h
deleted file mode 100644
index 684feead74..0000000000
--- a/src/libsystemd/sd-bus/bus-socket.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-void bus_socket_setup(sd_bus *b);
-
-int bus_socket_connect(sd_bus *b);
-int bus_socket_exec(sd_bus *b);
-int bus_socket_take_fd(sd_bus *b);
-int bus_socket_start_auth(sd_bus *b);
-
-int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx);
-int bus_socket_read_message(sd_bus *bus);
-
-int bus_socket_process_opening(sd_bus *b);
-int bus_socket_process_authenticating(sd_bus *b);
-
-bool bus_socket_auth_needs_write(sd_bus *b);
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
deleted file mode 100644
index 4acaf24793..0000000000
--- a/src/libsystemd/sd-bus/bus-track.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-track.h"
-#include "bus-util.h"
-
-struct track_item {
- unsigned n_ref;
- char *name;
- sd_bus_slot *slot;
-};
-
-struct sd_bus_track {
- unsigned n_ref;
- unsigned n_adding; /* are we in the process of adding a new name? */
- sd_bus *bus;
- sd_bus_track_handler_t handler;
- void *userdata;
- Hashmap *names;
- LIST_FIELDS(sd_bus_track, queue);
- Iterator iterator;
- bool in_list:1; /* In bus->tracks? */
- bool in_queue:1; /* In bus->track_queue? */
- bool modified:1;
- bool recursive:1;
-
- LIST_FIELDS(sd_bus_track, tracks);
-};
-
-#define MATCH_PREFIX \
- "type='signal'," \
- "sender='org.freedesktop.DBus'," \
- "path='/org/freedesktop/DBus'," \
- "interface='org.freedesktop.DBus'," \
- "member='NameOwnerChanged'," \
- "arg0='"
-
-#define MATCH_SUFFIX \
- "'"
-
-#define MATCH_FOR_NAME(name) \
- ({ \
- char *_x; \
- size_t _l = strlen(name); \
- _x = alloca(strlen(MATCH_PREFIX)+_l+strlen(MATCH_SUFFIX)+1); \
- strcpy(stpcpy(stpcpy(_x, MATCH_PREFIX), name), MATCH_SUFFIX); \
- _x; \
- })
-
-static struct track_item* track_item_free(struct track_item *i) {
-
- if (!i)
- return NULL;
-
- sd_bus_slot_unref(i->slot);
- free(i->name);
- return mfree(i);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free);
-
-static void bus_track_add_to_queue(sd_bus_track *track) {
- assert(track);
-
- /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of
- * conditions. */
-
- /* Already in the queue? */
- if (track->in_queue)
- return;
-
- /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait
- * until the addition is complete. */
- if (track->n_adding > 0)
- return;
-
- /* still referenced? */
- if (hashmap_size(track->names) > 0)
- return;
-
- /* Nothing to call? */
- if (!track->handler)
- return;
-
- /* Already closed? */
- if (!track->in_list)
- return;
-
- LIST_PREPEND(queue, track->bus->track_queue, track);
- track->in_queue = true;
-}
-
-static void bus_track_remove_from_queue(sd_bus_track *track) {
- assert(track);
-
- if (!track->in_queue)
- return;
-
- LIST_REMOVE(queue, track->bus->track_queue, track);
- track->in_queue = false;
-}
-
-static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) {
- struct track_item *i;
-
- assert(track);
- assert(name);
-
- i = hashmap_remove(track->names, name);
- if (!i)
- return 0;
-
- track_item_free(i);
-
- bus_track_add_to_queue(track);
-
- track->modified = true;
- return 1;
-}
-
-_public_ int sd_bus_track_new(
- sd_bus *bus,
- sd_bus_track **track,
- sd_bus_track_handler_t handler,
- void *userdata) {
-
- sd_bus_track *t;
-
- assert_return(bus, -EINVAL);
- assert_return(track, -EINVAL);
-
- if (!bus->bus_client)
- return -EINVAL;
-
- t = new0(sd_bus_track, 1);
- if (!t)
- return -ENOMEM;
-
- t->n_ref = 1;
- t->handler = handler;
- t->userdata = userdata;
- t->bus = sd_bus_ref(bus);
-
- LIST_PREPEND(tracks, bus->tracks, t);
- t->in_list = true;
-
- bus_track_add_to_queue(t);
-
- *track = t;
- return 0;
-}
-
-_public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
-
- if (!track)
- return NULL;
-
- assert(track->n_ref > 0);
-
- track->n_ref++;
-
- return track;
-}
-
-_public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
- struct track_item *i;
-
- if (!track)
- return NULL;
-
- assert(track->n_ref > 0);
-
- if (track->n_ref > 1) {
- track->n_ref--;
- return NULL;
- }
-
- while ((i = hashmap_steal_first(track->names)))
- track_item_free(i);
-
- if (track->in_list)
- LIST_REMOVE(tracks, track->bus->tracks, track);
-
- bus_track_remove_from_queue(track);
- hashmap_free(track->names);
- sd_bus_unref(track->bus);
- return mfree(track);
-}
-
-static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- sd_bus_track *track = userdata;
- const char *name, *old, *new;
- int r;
-
- assert(message);
- assert(track);
-
- r = sd_bus_message_read(message, "sss", &name, &old, &new);
- if (r < 0)
- return 0;
-
- bus_track_remove_name_fully(track, name);
- return 0;
-}
-
-_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
- _cleanup_(track_item_freep) struct track_item *n = NULL;
- struct track_item *i;
- const char *match;
- int r;
-
- assert_return(track, -EINVAL);
- assert_return(service_name_is_valid(name), -EINVAL);
-
- i = hashmap_get(track->names, name);
- if (i) {
- if (track->recursive) {
- unsigned k = track->n_ref + 1;
-
- if (k < track->n_ref) /* Check for overflow */
- return -EOVERFLOW;
-
- track->n_ref = k;
- }
-
- bus_track_remove_from_queue(track);
- return 0;
- }
-
- r = hashmap_ensure_allocated(&track->names, &string_hash_ops);
- if (r < 0)
- return r;
-
- n = new0(struct track_item, 1);
- if (!n)
- return -ENOMEM;
- n->name = strdup(name);
- if (!n->name)
- return -ENOMEM;
-
- /* First, subscribe to this name */
- match = MATCH_FOR_NAME(name);
-
- bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
-
- track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
- r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
- track->n_adding--;
- if (r < 0) {
- bus_track_add_to_queue(track);
- return r;
- }
-
- r = hashmap_put(track->names, n->name, n);
- if (r < 0) {
- bus_track_add_to_queue(track);
- return r;
- }
-
- /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */
- track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */
- r = sd_bus_get_name_creds(track->bus, name, 0, NULL);
- track->n_adding--;
- if (r < 0) {
- hashmap_remove(track->names, name);
- bus_track_add_to_queue(track);
- return r;
- }
-
- n->n_ref = 1;
- n = NULL;
-
- bus_track_remove_from_queue(track);
- track->modified = true;
-
- return 1;
-}
-
-_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
- struct track_item *i;
-
- assert_return(name, -EINVAL);
-
- if (!track) /* Treat a NULL track object as an empty track object */
- return 0;
-
- if (!track->recursive)
- return bus_track_remove_name_fully(track, name);
-
- i = hashmap_get(track->names, name);
- if (!i)
- return -EUNATCH;
- if (i->n_ref <= 0)
- return -EUNATCH;
-
- i->n_ref--;
-
- if (i->n_ref <= 0)
- return bus_track_remove_name_fully(track, name);
-
- return 1;
-}
-
-_public_ unsigned sd_bus_track_count(sd_bus_track *track) {
-
- if (!track) /* Let's consider a NULL object equivalent to an empty object */
- return 0;
-
- /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note
- * that this returns the number of names being watched, and multiple references to the same name are not
- * counted. */
-
- return hashmap_size(track->names);
-}
-
-_public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) {
- assert_return(name, NULL);
-
- if (!track) /* Let's consider a NULL object equivalent to an empty object */
- return NULL;
-
- return hashmap_get(track->names, (void*) name) ? name : NULL;
-}
-
-_public_ const char* sd_bus_track_first(sd_bus_track *track) {
- const char *n = NULL;
-
- if (!track)
- return NULL;
-
- track->modified = false;
- track->iterator = ITERATOR_FIRST;
-
- hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n);
- return n;
-}
-
-_public_ const char* sd_bus_track_next(sd_bus_track *track) {
- const char *n = NULL;
-
- if (!track)
- return NULL;
-
- if (track->modified)
- return NULL;
-
- hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n);
- return n;
-}
-
-_public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
- const char *sender;
-
- assert_return(track, -EINVAL);
- assert_return(m, -EINVAL);
-
- if (sd_bus_message_get_bus(m) != track->bus)
- return -EINVAL;
-
- sender = sd_bus_message_get_sender(m);
- if (!sender)
- return -EINVAL;
-
- return sd_bus_track_add_name(track, sender);
-}
-
-_public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) {
- const char *sender;
-
- assert_return(m, -EINVAL);
-
- if (!track) /* Treat a NULL track object as an empty track object */
- return 0;
-
- if (sd_bus_message_get_bus(m) != track->bus)
- return -EINVAL;
-
- sender = sd_bus_message_get_sender(m);
- if (!sender)
- return -EINVAL;
-
- return sd_bus_track_remove_name(track, sender);
-}
-
-_public_ sd_bus* sd_bus_track_get_bus(sd_bus_track *track) {
- assert_return(track, NULL);
-
- return track->bus;
-}
-
-void bus_track_dispatch(sd_bus_track *track) {
- int r;
-
- assert(track);
- assert(track->handler);
-
- bus_track_remove_from_queue(track);
-
- sd_bus_track_ref(track);
-
- r = track->handler(track, track->userdata);
- if (r < 0)
- log_debug_errno(r, "Failed to process track handler: %m");
- else if (r == 0)
- bus_track_add_to_queue(track);
-
- sd_bus_track_unref(track);
-}
-
-void bus_track_close(sd_bus_track *track) {
- struct track_item *i;
-
- assert(track);
-
- /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
- * immediately, as we are closing now, but first flush out all names. */
-
- if (!track->in_list)
- return; /* We already closed this one, don't close it again. */
-
- /* Remember that this one is closed now */
- LIST_REMOVE(tracks, track->bus->tracks, track);
- track->in_list = false;
-
- /* If there's no name in this one anyway, we don't have to dispatch */
- if (hashmap_isempty(track->names))
- return;
-
- /* Let's flush out all names */
- while ((i = hashmap_steal_first(track->names)))
- track_item_free(i);
-
- /* Invoke handler */
- if (track->handler)
- bus_track_dispatch(track);
-}
-
-_public_ void *sd_bus_track_get_userdata(sd_bus_track *track) {
- assert_return(track, NULL);
-
- return track->userdata;
-}
-
-_public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) {
- void *ret;
-
- assert_return(track, NULL);
-
- ret = track->userdata;
- track->userdata = userdata;
-
- return ret;
-}
-
-_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
- assert_return(track, -EINVAL);
-
- if (track->recursive == !!b)
- return 0;
-
- if (!hashmap_isempty(track->names))
- return -EBUSY;
-
- track->recursive = b;
- return 0;
-}
-
-_public_ int sd_bus_track_get_recursive(sd_bus_track *track) {
- assert_return(track, -EINVAL);
-
- return track->recursive;
-}
-
-_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) {
- const char *sender;
-
- assert_return(m, -EINVAL);
-
- if (!track) /* Let's consider a NULL object equivalent to an empty object */
- return 0;
-
- if (sd_bus_message_get_bus(m) != track->bus)
- return -EINVAL;
-
- sender = sd_bus_message_get_sender(m);
- if (!sender)
- return -EINVAL;
-
- return sd_bus_track_count_name(track, sender);
-}
-
-_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) {
- struct track_item *i;
-
- assert_return(service_name_is_valid(name), -EINVAL);
-
- if (!track) /* Let's consider a NULL object equivalent to an empty object */
- return 0;
-
- i = hashmap_get(track->names, name);
- if (!i)
- return 0;
-
- return i->n_ref;
-}
diff --git a/src/libsystemd/sd-bus/bus-track.h b/src/libsystemd/sd-bus/bus-track.h
deleted file mode 100644
index 26bd05f5c7..0000000000
--- a/src/libsystemd/sd-bus/bus-track.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-void bus_track_dispatch(sd_bus_track *track);
-void bus_track_close(sd_bus_track *track);
diff --git a/src/libsystemd/sd-bus/bus-type.c b/src/libsystemd/sd-bus/bus-type.c
deleted file mode 100644
index c692afc580..0000000000
--- a/src/libsystemd/sd-bus/bus-type.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-type.h"
-
-bool bus_type_is_valid(char c) {
- static const char valid[] = {
- SD_BUS_TYPE_BYTE,
- SD_BUS_TYPE_BOOLEAN,
- SD_BUS_TYPE_INT16,
- SD_BUS_TYPE_UINT16,
- SD_BUS_TYPE_INT32,
- SD_BUS_TYPE_UINT32,
- SD_BUS_TYPE_INT64,
- SD_BUS_TYPE_UINT64,
- SD_BUS_TYPE_DOUBLE,
- SD_BUS_TYPE_STRING,
- SD_BUS_TYPE_OBJECT_PATH,
- SD_BUS_TYPE_SIGNATURE,
- SD_BUS_TYPE_ARRAY,
- SD_BUS_TYPE_VARIANT,
- SD_BUS_TYPE_STRUCT,
- SD_BUS_TYPE_DICT_ENTRY,
- SD_BUS_TYPE_UNIX_FD
- };
-
- return !!memchr(valid, c, sizeof(valid));
-}
-
-bool bus_type_is_valid_in_signature(char c) {
- static const char valid[] = {
- SD_BUS_TYPE_BYTE,
- SD_BUS_TYPE_BOOLEAN,
- SD_BUS_TYPE_INT16,
- SD_BUS_TYPE_UINT16,
- SD_BUS_TYPE_INT32,
- SD_BUS_TYPE_UINT32,
- SD_BUS_TYPE_INT64,
- SD_BUS_TYPE_UINT64,
- SD_BUS_TYPE_DOUBLE,
- SD_BUS_TYPE_STRING,
- SD_BUS_TYPE_OBJECT_PATH,
- SD_BUS_TYPE_SIGNATURE,
- SD_BUS_TYPE_ARRAY,
- SD_BUS_TYPE_VARIANT,
- SD_BUS_TYPE_STRUCT_BEGIN,
- SD_BUS_TYPE_STRUCT_END,
- SD_BUS_TYPE_DICT_ENTRY_BEGIN,
- SD_BUS_TYPE_DICT_ENTRY_END,
- SD_BUS_TYPE_UNIX_FD
- };
-
- return !!memchr(valid, c, sizeof(valid));
-}
-
-bool bus_type_is_basic(char c) {
- static const char valid[] = {
- SD_BUS_TYPE_BYTE,
- SD_BUS_TYPE_BOOLEAN,
- SD_BUS_TYPE_INT16,
- SD_BUS_TYPE_UINT16,
- SD_BUS_TYPE_INT32,
- SD_BUS_TYPE_UINT32,
- SD_BUS_TYPE_INT64,
- SD_BUS_TYPE_UINT64,
- SD_BUS_TYPE_DOUBLE,
- SD_BUS_TYPE_STRING,
- SD_BUS_TYPE_OBJECT_PATH,
- SD_BUS_TYPE_SIGNATURE,
- SD_BUS_TYPE_UNIX_FD
- };
-
- return !!memchr(valid, c, sizeof(valid));
-}
-
-bool bus_type_is_trivial(char c) {
- static const char valid[] = {
- SD_BUS_TYPE_BYTE,
- SD_BUS_TYPE_BOOLEAN,
- SD_BUS_TYPE_INT16,
- SD_BUS_TYPE_UINT16,
- SD_BUS_TYPE_INT32,
- SD_BUS_TYPE_UINT32,
- SD_BUS_TYPE_INT64,
- SD_BUS_TYPE_UINT64,
- SD_BUS_TYPE_DOUBLE
- };
-
- return !!memchr(valid, c, sizeof(valid));
-}
-
-bool bus_type_is_container(char c) {
- static const char valid[] = {
- SD_BUS_TYPE_ARRAY,
- SD_BUS_TYPE_VARIANT,
- SD_BUS_TYPE_STRUCT,
- SD_BUS_TYPE_DICT_ENTRY
- };
-
- return !!memchr(valid, c, sizeof(valid));
-}
-
-int bus_type_get_alignment(char c) {
-
- switch (c) {
- case SD_BUS_TYPE_BYTE:
- case SD_BUS_TYPE_SIGNATURE:
- case SD_BUS_TYPE_VARIANT:
- return 1;
-
- case SD_BUS_TYPE_INT16:
- case SD_BUS_TYPE_UINT16:
- return 2;
-
- case SD_BUS_TYPE_BOOLEAN:
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_UINT32:
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_ARRAY:
- case SD_BUS_TYPE_UNIX_FD:
- return 4;
-
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- case SD_BUS_TYPE_STRUCT:
- case SD_BUS_TYPE_STRUCT_BEGIN:
- case SD_BUS_TYPE_DICT_ENTRY:
- case SD_BUS_TYPE_DICT_ENTRY_BEGIN:
- return 8;
- }
-
- return -EINVAL;
-}
-
-int bus_type_get_size(char c) {
-
- switch (c) {
- case SD_BUS_TYPE_BYTE:
- return 1;
-
- case SD_BUS_TYPE_INT16:
- case SD_BUS_TYPE_UINT16:
- return 2;
-
- case SD_BUS_TYPE_BOOLEAN:
- case SD_BUS_TYPE_INT32:
- case SD_BUS_TYPE_UINT32:
- case SD_BUS_TYPE_UNIX_FD:
- return 4;
-
- case SD_BUS_TYPE_INT64:
- case SD_BUS_TYPE_UINT64:
- case SD_BUS_TYPE_DOUBLE:
- return 8;
- }
-
- return -EINVAL;
-}
diff --git a/src/libsystemd/sd-bus/bus-type.h b/src/libsystemd/sd-bus/bus-type.h
deleted file mode 100644
index 5c87eb5f08..0000000000
--- a/src/libsystemd/sd-bus/bus-type.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-#include "sd-bus.h"
-
-#include "macro.h"
-
-bool bus_type_is_valid(char c) _const_;
-bool bus_type_is_valid_in_signature(char c) _const_;
-bool bus_type_is_basic(char c) _const_;
-/* "trivial" is systemd's term for what the D-Bus Specification calls
- * a "fixed type": that is, a basic type of fixed length */
-bool bus_type_is_trivial(char c) _const_;
-bool bus_type_is_container(char c) _const_;
-
-int bus_type_get_alignment(char c) _const_;
-int bus_type_get_size(char c) _const_;
diff --git a/src/libsystemd/sd-bus/busctl-introspect.c b/src/libsystemd/sd-bus/busctl-introspect.c
deleted file mode 100644
index b09509f8e1..0000000000
--- a/src/libsystemd/sd-bus/busctl-introspect.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "busctl-introspect.h"
-#include "string-util.h"
-#include "util.h"
-#include "xml.h"
-
-#define NODE_DEPTH_MAX 16
-
-typedef struct Context {
- const XMLIntrospectOps *ops;
- void *userdata;
-
- char *interface_name;
- uint64_t interface_flags;
-
- char *member_name;
- char *member_signature;
- char *member_result;
- uint64_t member_flags;
- bool member_writable;
-
- const char *current;
- void *xml_state;
-} Context;
-
-static void context_reset_member(Context *c) {
- free(c->member_name);
- free(c->member_signature);
- free(c->member_result);
-
- c->member_name = c->member_signature = c->member_result = NULL;
- c->member_flags = 0;
- c->member_writable = false;
-}
-
-static void context_reset_interface(Context *c) {
- c->interface_name = mfree(c->interface_name);
- c->interface_flags = 0;
-
- context_reset_member(c);
-}
-
-static int parse_xml_annotation(Context *context, uint64_t *flags) {
-
- enum {
- STATE_ANNOTATION,
- STATE_NAME,
- STATE_VALUE
- } state = STATE_ANNOTATION;
-
- _cleanup_free_ char *field = NULL, *value = NULL;
-
- assert(context);
-
- for (;;) {
- _cleanup_free_ char *name = NULL;
-
- int t;
-
- t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
- if (t < 0) {
- log_error("XML parse error.");
- return t;
- }
-
- if (t == XML_END) {
- log_error("Premature end of XML data.");
- return -EBADMSG;
- }
-
- switch (state) {
-
- case STATE_ANNOTATION:
-
- if (t == XML_ATTRIBUTE_NAME) {
-
- if (streq_ptr(name, "name"))
- state = STATE_NAME;
-
- else if (streq_ptr(name, "value"))
- state = STATE_VALUE;
-
- else {
- log_error("Unexpected <annotation> attribute %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "annotation"))) {
-
- if (flags) {
- if (streq_ptr(field, "org.freedesktop.DBus.Deprecated")) {
-
- if (streq_ptr(value, "true"))
- *flags |= SD_BUS_VTABLE_DEPRECATED;
-
- } else if (streq_ptr(field, "org.freedesktop.DBus.Method.NoReply")) {
-
- if (streq_ptr(value, "true"))
- *flags |= SD_BUS_VTABLE_METHOD_NO_REPLY;
-
- } else if (streq_ptr(field, "org.freedesktop.DBus.Property.EmitsChangedSignal")) {
-
- if (streq_ptr(value, "const"))
- *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) | SD_BUS_VTABLE_PROPERTY_CONST;
- else if (streq_ptr(value, "invalidates"))
- *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST)) | SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION;
- else if (streq_ptr(value, "false"))
- *flags = *flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION);
- }
- }
-
- return 0;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <annotation>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free(field);
- field = name;
- name = NULL;
-
- state = STATE_ANNOTATION;
- } else {
- log_error("Unexpected token in <annotation>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_VALUE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free(value);
- value = name;
- name = NULL;
-
- state = STATE_ANNOTATION;
- } else {
- log_error("Unexpected token in <annotation>. (3)");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Bad state");
- }
- }
-}
-
-static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth) {
-
- enum {
- STATE_NODE,
- STATE_NODE_NAME,
- STATE_INTERFACE,
- STATE_INTERFACE_NAME,
- STATE_METHOD,
- STATE_METHOD_NAME,
- STATE_METHOD_ARG,
- STATE_METHOD_ARG_NAME,
- STATE_METHOD_ARG_TYPE,
- STATE_METHOD_ARG_DIRECTION,
- STATE_SIGNAL,
- STATE_SIGNAL_NAME,
- STATE_SIGNAL_ARG,
- STATE_SIGNAL_ARG_NAME,
- STATE_SIGNAL_ARG_TYPE,
- STATE_PROPERTY,
- STATE_PROPERTY_NAME,
- STATE_PROPERTY_TYPE,
- STATE_PROPERTY_ACCESS,
- } state = STATE_NODE;
-
- _cleanup_free_ char *node_path = NULL, *argument_type = NULL, *argument_direction = NULL;
- const char *np = prefix;
- int r;
-
- assert(context);
- assert(prefix);
-
- if (n_depth > NODE_DEPTH_MAX) {
- log_error("<node> depth too high.");
- return -EINVAL;
- }
-
- for (;;) {
- _cleanup_free_ char *name = NULL;
- int t;
-
- t = xml_tokenize(&context->current, &name, &context->xml_state, NULL);
- if (t < 0) {
- log_error("XML parse error.");
- return t;
- }
-
- if (t == XML_END) {
- log_error("Premature end of XML data.");
- return -EBADMSG;
- }
-
- switch (state) {
-
- case STATE_NODE:
- if (t == XML_ATTRIBUTE_NAME) {
-
- if (streq_ptr(name, "name"))
- state = STATE_NODE_NAME;
- else {
- log_error("Unexpected <node> attribute %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_OPEN) {
-
- if (streq_ptr(name, "interface"))
- state = STATE_INTERFACE;
- else if (streq_ptr(name, "node")) {
-
- r = parse_xml_node(context, np, n_depth+1);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <node> tag %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) {
-
- if (context->ops->on_path) {
- r = context->ops->on_path(node_path ? node_path : np, context->userdata);
- if (r < 0)
- return r;
- }
-
- return 0;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <node>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_NODE_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- free(node_path);
-
- if (name[0] == '/') {
- node_path = name;
- name = NULL;
- } else {
-
- if (endswith(prefix, "/"))
- node_path = strappend(prefix, name);
- else
- node_path = strjoin(prefix, "/", name, NULL);
- if (!node_path)
- return log_oom();
- }
-
- np = node_path;
- state = STATE_NODE;
- } else {
- log_error("Unexpected token in <node>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_INTERFACE:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_INTERFACE_NAME;
- else {
- log_error("Unexpected <interface> attribute %s.", name);
- return -EBADMSG;
- }
-
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "method"))
- state = STATE_METHOD;
- else if (streq_ptr(name, "signal"))
- state = STATE_SIGNAL;
- else if (streq_ptr(name, "property")) {
- context->member_flags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE;
- state = STATE_PROPERTY;
- } else if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->interface_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <interface> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "interface"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_interface) {
- r = context->ops->on_interface(context->interface_name, context->interface_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_interface(context);
- }
-
- state = STATE_NODE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <interface>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_INTERFACE_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- if (n_depth == 0) {
- free(context->interface_name);
- context->interface_name = name;
- name = NULL;
- }
-
- state = STATE_INTERFACE;
- } else {
- log_error("Unexpected token in <interface>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_METHOD_NAME;
- else {
- log_error("Unexpected <method> attribute %s", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "arg"))
- state = STATE_METHOD_ARG;
- else if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->member_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <method> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "method"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_method) {
- r = context->ops->on_method(context->interface_name, context->member_name, context->member_signature, context->member_result, context->member_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_member(context);
- }
-
- state = STATE_INTERFACE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <method> (1).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- if (n_depth == 0) {
- free(context->member_name);
- context->member_name = name;
- name = NULL;
- }
-
- state = STATE_METHOD;
- } else {
- log_error("Unexpected token in <method> (2).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_METHOD_ARG_NAME;
- else if (streq_ptr(name, "type"))
- state = STATE_METHOD_ARG_TYPE;
- else if (streq_ptr(name, "direction"))
- state = STATE_METHOD_ARG_DIRECTION;
- else {
- log_error("Unexpected method <arg> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, NULL);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected method <arg> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
-
- if (n_depth == 0) {
-
- if (argument_type) {
- if (!argument_direction || streq(argument_direction, "in")) {
- if (!strextend(&context->member_signature, argument_type, NULL))
- return log_oom();
- } else if (streq(argument_direction, "out")) {
- if (!strextend(&context->member_result, argument_type, NULL))
- return log_oom();
- }
- }
-
- argument_type = mfree(argument_type);
- argument_direction = mfree(argument_direction);
- }
-
- state = STATE_METHOD;
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in method <arg>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE)
- state = STATE_METHOD_ARG;
- else {
- log_error("Unexpected token in method <arg>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG_TYPE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free(argument_type);
- argument_type = name;
- name = NULL;
-
- state = STATE_METHOD_ARG;
- } else {
- log_error("Unexpected token in method <arg>. (3)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_METHOD_ARG_DIRECTION:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free(argument_direction);
- argument_direction = name;
- name = NULL;
-
- state = STATE_METHOD_ARG;
- } else {
- log_error("Unexpected token in method <arg>. (4)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_SIGNAL_NAME;
- else {
- log_error("Unexpected <signal> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "arg"))
- state = STATE_SIGNAL_ARG;
- else if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->member_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <signal> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "signal"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_signal) {
- r = context->ops->on_signal(context->interface_name, context->member_name, context->member_signature, context->member_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_member(context);
- }
-
- state = STATE_INTERFACE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <signal>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- if (n_depth == 0) {
- free(context->member_name);
- context->member_name = name;
- name = NULL;
- }
-
- state = STATE_SIGNAL;
- } else {
- log_error("Unexpected token in <signal>. (2)");
- return -EINVAL;
- }
-
- break;
-
-
- case STATE_SIGNAL_ARG:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_SIGNAL_ARG_NAME;
- else if (streq_ptr(name, "type"))
- state = STATE_SIGNAL_ARG_TYPE;
- else {
- log_error("Unexpected signal <arg> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
- if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, NULL);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected signal <arg> tag %s.", name);
- return -EINVAL;
- }
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) {
-
- if (argument_type) {
- if (!strextend(&context->member_signature, argument_type, NULL))
- return log_oom();
-
- argument_type = mfree(argument_type);
- }
-
- state = STATE_SIGNAL;
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in signal <arg> (1).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL_ARG_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE)
- state = STATE_SIGNAL_ARG;
- else {
- log_error("Unexpected token in signal <arg> (2).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_SIGNAL_ARG_TYPE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
- free(argument_type);
- argument_type = name;
- name = NULL;
-
- state = STATE_SIGNAL_ARG;
- } else {
- log_error("Unexpected token in signal <arg> (3).");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY:
-
- if (t == XML_ATTRIBUTE_NAME) {
- if (streq_ptr(name, "name"))
- state = STATE_PROPERTY_NAME;
- else if (streq_ptr(name, "type"))
- state = STATE_PROPERTY_TYPE;
- else if (streq_ptr(name, "access"))
- state = STATE_PROPERTY_ACCESS;
- else {
- log_error("Unexpected <property> attribute %s.", name);
- return -EBADMSG;
- }
- } else if (t == XML_TAG_OPEN) {
-
- if (streq_ptr(name, "annotation")) {
- r = parse_xml_annotation(context, &context->member_flags);
- if (r < 0)
- return r;
- } else {
- log_error("Unexpected <property> tag %s.", name);
- return -EINVAL;
- }
-
- } else if (t == XML_TAG_CLOSE_EMPTY ||
- (t == XML_TAG_CLOSE && streq_ptr(name, "property"))) {
-
- if (n_depth == 0) {
- if (context->ops->on_property) {
- r = context->ops->on_property(context->interface_name, context->member_name, context->member_signature, context->member_writable, context->member_flags, context->userdata);
- if (r < 0)
- return r;
- }
-
- context_reset_member(context);
- }
-
- state = STATE_INTERFACE;
-
- } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token in <property>. (1)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY_NAME:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- if (n_depth == 0) {
- free(context->member_name);
- context->member_name = name;
- name = NULL;
- }
- state = STATE_PROPERTY;
- } else {
- log_error("Unexpected token in <property>. (2)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY_TYPE:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- if (n_depth == 0) {
- free(context->member_signature);
- context->member_signature = name;
- name = NULL;
- }
-
- state = STATE_PROPERTY;
- } else {
- log_error("Unexpected token in <property>. (3)");
- return -EINVAL;
- }
-
- break;
-
- case STATE_PROPERTY_ACCESS:
-
- if (t == XML_ATTRIBUTE_VALUE) {
-
- if (streq(name, "readwrite") || streq(name, "write"))
- context->member_writable = true;
-
- state = STATE_PROPERTY;
- } else {
- log_error("Unexpected token in <property>. (4)");
- return -EINVAL;
- }
-
- break;
- }
- }
-}
-
-int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata) {
- Context context = {
- .ops = ops,
- .userdata = userdata,
- .current = xml,
- };
-
- int r;
-
- assert(prefix);
- assert(xml);
- assert(ops);
-
- for (;;) {
- _cleanup_free_ char *name = NULL;
-
- r = xml_tokenize(&context.current, &name, &context.xml_state, NULL);
- if (r < 0) {
- log_error("XML parse error");
- goto finish;
- }
-
- if (r == XML_END) {
- r = 0;
- break;
- }
-
- if (r == XML_TAG_OPEN) {
-
- if (streq(name, "node")) {
- r = parse_xml_node(&context, prefix, 0);
- if (r < 0)
- goto finish;
- } else {
- log_error("Unexpected tag '%s' in introspection data.", name);
- r = -EBADMSG;
- goto finish;
- }
- } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) {
- log_error("Unexpected token.");
- r = -EBADMSG;
- goto finish;
- }
- }
-
-finish:
- context_reset_interface(&context);
-
- return r;
-}
diff --git a/src/libsystemd/sd-bus/busctl-introspect.h b/src/libsystemd/sd-bus/busctl-introspect.h
deleted file mode 100644
index d922e352db..0000000000
--- a/src/libsystemd/sd-bus/busctl-introspect.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-
-typedef struct XMLIntrospectOps {
- int (*on_path)(const char *path, void *userdata);
- int (*on_interface)(const char *name, uint64_t flags, void *userdata);
- int (*on_method)(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata);
- int (*on_signal)(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata);
- int (*on_property)(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata);
-} XMLIntrospectOps;
-
-int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata);
diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c
deleted file mode 100644
index 2c3f591053..0000000000
--- a/src/libsystemd/sd-bus/busctl.c
+++ /dev/null
@@ -1,2086 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <getopt.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-dump.h"
-#include "bus-internal.h"
-#include "bus-signature.h"
-#include "bus-type.h"
-#include "bus-util.h"
-#include "busctl-introspect.h"
-#include "escape.h"
-#include "fd-util.h"
-#include "locale-util.h"
-#include "log.h"
-#include "pager.h"
-#include "parse-util.h"
-#include "path-util.h"
-#include "set.h"
-#include "strv.h"
-#include "terminal-util.h"
-#include "user-util.h"
-#include "util.h"
-
-static bool arg_no_pager = false;
-static bool arg_legend = true;
-static char *arg_address = NULL;
-static bool arg_unique = false;
-static bool arg_acquired = false;
-static bool arg_activatable = false;
-static bool arg_show_machine = false;
-static char **arg_matches = NULL;
-static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static char *arg_host = NULL;
-static bool arg_user = false;
-static size_t arg_snaplen = 4096;
-static bool arg_list = false;
-static bool arg_quiet = false;
-static bool arg_verbose = false;
-static bool arg_expect_reply = true;
-static bool arg_auto_start = true;
-static bool arg_allow_interactive_authorization = true;
-static bool arg_augment_creds = true;
-static usec_t arg_timeout = 0;
-
-#define NAME_IS_ACQUIRED INT_TO_PTR(1)
-#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
-
-static int list_bus_names(sd_bus *bus, char **argv) {
- _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL;
- _cleanup_free_ char **merged = NULL;
- _cleanup_hashmap_free_ Hashmap *names = NULL;
- char **i;
- int r;
- size_t max_i = 0;
- unsigned n = 0;
- void *v;
- char *k;
- Iterator iterator;
-
- assert(bus);
-
- if (!arg_unique && !arg_acquired && !arg_activatable)
- arg_unique = arg_acquired = arg_activatable = true;
-
- r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to list names: %m");
-
- pager_open(arg_no_pager, false);
-
- names = hashmap_new(&string_hash_ops);
- if (!names)
- return log_oom();
-
- STRV_FOREACH(i, acquired) {
- max_i = MAX(max_i, strlen(*i));
-
- r = hashmap_put(names, *i, NAME_IS_ACQUIRED);
- if (r < 0)
- return log_error_errno(r, "Failed to add to hashmap: %m");
- }
-
- STRV_FOREACH(i, activatable) {
- max_i = MAX(max_i, strlen(*i));
-
- r = hashmap_put(names, *i, NAME_IS_ACTIVATABLE);
- if (r < 0 && r != -EEXIST)
- return log_error_errno(r, "Failed to add to hashmap: %m");
- }
-
- merged = new(char*, hashmap_size(names) + 1);
- HASHMAP_FOREACH_KEY(v, k, names, iterator)
- merged[n++] = k;
-
- merged[n] = NULL;
- strv_sort(merged);
-
- if (arg_legend) {
- printf("%-*s %*s %-*s %-*s %-*s %-*s %-*s %-*s",
- (int) max_i, "NAME", 10, "PID", 15, "PROCESS", 16, "USER", 13, "CONNECTION", 25, "UNIT", 10, "SESSION", 19, "DESCRIPTION");
-
- if (arg_show_machine)
- puts(" MACHINE");
- else
- putchar('\n');
- }
-
- STRV_FOREACH(i, merged) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- sd_id128_t mid;
-
- if (hashmap_get(names, *i) == NAME_IS_ACTIVATABLE) {
- /* Activatable */
-
- printf("%-*s", (int) max_i, *i);
- printf(" - - - (activatable) - - ");
- if (arg_show_machine)
- puts(" -");
- else
- putchar('\n');
- continue;
-
- }
-
- if (!arg_unique && (*i)[0] == ':')
- continue;
-
- if (!arg_acquired && (*i)[0] != ':')
- continue;
-
- printf("%-*s", (int) max_i, *i);
-
- r = sd_bus_get_name_creds(
- bus, *i,
- (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) |
- SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|
- SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION|
- SD_BUS_CREDS_DESCRIPTION, &creds);
- if (r >= 0) {
- const char *unique, *session, *unit, *cn;
- pid_t pid;
- uid_t uid;
-
- r = sd_bus_creds_get_pid(creds, &pid);
- if (r >= 0) {
- const char *comm = NULL;
-
- sd_bus_creds_get_comm(creds, &comm);
-
- printf(" %10lu %-15s", (unsigned long) pid, strna(comm));
- } else
- fputs(" - - ", stdout);
-
- r = sd_bus_creds_get_euid(creds, &uid);
- if (r >= 0) {
- _cleanup_free_ char *u = NULL;
-
- u = uid_to_name(uid);
- if (!u)
- return log_oom();
-
- if (strlen(u) > 16)
- u[16] = 0;
-
- printf(" %-16s", u);
- } else
- fputs(" - ", stdout);
-
- r = sd_bus_creds_get_unique_name(creds, &unique);
- if (r >= 0)
- printf(" %-13s", unique);
- else
- fputs(" - ", stdout);
-
- r = sd_bus_creds_get_unit(creds, &unit);
- if (r >= 0) {
- _cleanup_free_ char *e;
-
- e = ellipsize(unit, 25, 100);
- if (!e)
- return log_oom();
-
- printf(" %-25s", e);
- } else
- fputs(" - ", stdout);
-
- r = sd_bus_creds_get_session(creds, &session);
- if (r >= 0)
- printf(" %-10s", session);
- else
- fputs(" - ", stdout);
-
- r = sd_bus_creds_get_description(creds, &cn);
- if (r >= 0)
- printf(" %-19s", cn);
- else
- fputs(" - ", stdout);
-
- } else
- printf(" - - - - - - - ");
-
- if (arg_show_machine) {
- r = sd_bus_get_name_machine_id(bus, *i, &mid);
- if (r >= 0) {
- char m[SD_ID128_STRING_MAX];
- printf(" %s\n", sd_id128_to_string(mid, m));
- } else
- puts(" -");
- } else
- putchar('\n');
- }
-
- return 0;
-}
-
-static void print_subtree(const char *prefix, const char *path, char **l) {
- const char *vertical, *space;
- char **n;
-
- /* We assume the list is sorted. Let's first skip over the
- * entry we are looking at. */
- for (;;) {
- if (!*l)
- return;
-
- if (!streq(*l, path))
- break;
-
- l++;
- }
-
- vertical = strjoina(prefix, special_glyph(TREE_VERTICAL));
- space = strjoina(prefix, special_glyph(TREE_SPACE));
-
- for (;;) {
- bool has_more = false;
-
- if (!*l || !path_startswith(*l, path))
- break;
-
- n = l + 1;
- for (;;) {
- if (!*n || !path_startswith(*n, path))
- break;
-
- if (!path_startswith(*n, *l)) {
- has_more = true;
- break;
- }
-
- n++;
- }
-
- printf("%s%s%s\n", prefix, special_glyph(has_more ? TREE_BRANCH : TREE_RIGHT), *l);
-
- print_subtree(has_more ? vertical : space, *l, l);
- l = n;
- }
-}
-
-static void print_tree(const char *prefix, char **l) {
-
- pager_open(arg_no_pager, false);
-
- prefix = strempty(prefix);
-
- if (arg_list) {
- char **i;
-
- STRV_FOREACH(i, l)
- printf("%s%s\n", prefix, *i);
- return;
- }
-
- if (strv_isempty(l)) {
- printf("No objects discovered.\n");
- return;
- }
-
- if (streq(l[0], "/") && !l[1]) {
- printf("Only root object discovered.\n");
- return;
- }
-
- print_subtree(prefix, "/", l);
-}
-
-static int on_path(const char *path, void *userdata) {
- Set *paths = userdata;
- int r;
-
- assert(paths);
-
- r = set_put_strdup(paths, path);
- if (r < 0)
- return log_oom();
-
- return 0;
-}
-
-static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) {
- static const XMLIntrospectOps ops = {
- .on_path = on_path,
- };
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *xml;
- int r;
-
- r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
- if (r < 0) {
- if (many)
- printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r));
- else
- log_error("Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r));
- return r;
- }
-
- r = sd_bus_message_read(reply, "s", &xml);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return parse_xml_introspect(path, xml, &ops, paths);
-}
-
-static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) {
- _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
- _cleanup_free_ char **l = NULL;
- char *m;
- int r;
-
- paths = set_new(&string_hash_ops);
- if (!paths)
- return log_oom();
-
- done = set_new(&string_hash_ops);
- if (!done)
- return log_oom();
-
- failed = set_new(&string_hash_ops);
- if (!failed)
- return log_oom();
-
- m = strdup("/");
- if (!m)
- return log_oom();
-
- r = set_put(paths, m);
- if (r < 0) {
- free(m);
- return log_oom();
- }
-
- for (;;) {
- _cleanup_free_ char *p = NULL;
- int q;
-
- p = set_steal_first(paths);
- if (!p)
- break;
-
- if (set_contains(done, p) ||
- set_contains(failed, p))
- continue;
-
- q = find_nodes(bus, service, p, paths, many);
- if (q < 0) {
- if (r >= 0)
- r = q;
-
- q = set_put(failed, p);
- } else
- q = set_put(done, p);
-
- if (q < 0)
- return log_oom();
-
- assert(q != 0);
- p = NULL;
- }
-
- pager_open(arg_no_pager, false);
-
- l = set_get_strv(done);
- if (!l)
- return log_oom();
-
- strv_sort(l);
- print_tree(prefix, l);
-
- fflush(stdout);
-
- return r;
-}
-
-static int tree(sd_bus *bus, char **argv) {
- char **i;
- int r = 0;
-
- if (!arg_unique && !arg_acquired)
- arg_acquired = true;
-
- if (strv_length(argv) <= 1) {
- _cleanup_strv_free_ char **names = NULL;
- bool not_first = false;
-
- r = sd_bus_list_names(bus, &names, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to get name list: %m");
-
- pager_open(arg_no_pager, false);
-
- STRV_FOREACH(i, names) {
- int q;
-
- if (!arg_unique && (*i)[0] == ':')
- continue;
-
- if (!arg_acquired && (*i)[0] == ':')
- continue;
-
- if (not_first)
- printf("\n");
-
- printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
-
- q = tree_one(bus, *i, NULL, true);
- if (q < 0 && r >= 0)
- r = q;
-
- not_first = true;
- }
- } else {
- STRV_FOREACH(i, argv+1) {
- int q;
-
- if (i > argv+1)
- printf("\n");
-
- if (argv[2]) {
- pager_open(arg_no_pager, false);
- printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
- }
-
- q = tree_one(bus, *i, NULL, !!argv[2]);
- if (q < 0 && r >= 0)
- r = q;
- }
- }
-
- return r;
-}
-
-static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) {
- int r;
-
- for (;;) {
- const char *contents = NULL;
- char type;
- union {
- uint8_t u8;
- uint16_t u16;
- int16_t s16;
- uint32_t u32;
- int32_t s32;
- uint64_t u64;
- int64_t s64;
- double d64;
- const char *string;
- int i;
- } basic;
-
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r < 0)
- return r;
- if (r == 0)
- return needs_space;
-
- if (bus_type_is_container(type) > 0) {
-
- r = sd_bus_message_enter_container(m, type, contents);
- if (r < 0)
- return r;
-
- if (type == SD_BUS_TYPE_ARRAY) {
- unsigned n = 0;
-
- /* count array entries */
- for (;;) {
-
- r = sd_bus_message_skip(m, contents);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- n++;
- }
-
- r = sd_bus_message_rewind(m, false);
- if (r < 0)
- return r;
-
- if (needs_space)
- fputc(' ', f);
-
- fprintf(f, "%u", n);
- needs_space = true;
-
- } else if (type == SD_BUS_TYPE_VARIANT) {
-
- if (needs_space)
- fputc(' ', f);
-
- fprintf(f, "%s", contents);
- needs_space = true;
- }
-
- r = format_cmdline(m, f, needs_space);
- if (r < 0)
- return r;
-
- needs_space = r > 0;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return r;
-
- continue;
- }
-
- r = sd_bus_message_read_basic(m, type, &basic);
- if (r < 0)
- return r;
-
- if (needs_space)
- fputc(' ', f);
-
- switch (type) {
- case SD_BUS_TYPE_BYTE:
- fprintf(f, "%u", basic.u8);
- break;
-
- case SD_BUS_TYPE_BOOLEAN:
- fputs(true_false(basic.i), f);
- break;
-
- case SD_BUS_TYPE_INT16:
- fprintf(f, "%i", basic.s16);
- break;
-
- case SD_BUS_TYPE_UINT16:
- fprintf(f, "%u", basic.u16);
- break;
-
- case SD_BUS_TYPE_INT32:
- fprintf(f, "%i", basic.s32);
- break;
-
- case SD_BUS_TYPE_UINT32:
- fprintf(f, "%u", basic.u32);
- break;
-
- case SD_BUS_TYPE_INT64:
- fprintf(f, "%" PRIi64, basic.s64);
- break;
-
- case SD_BUS_TYPE_UINT64:
- fprintf(f, "%" PRIu64, basic.u64);
- break;
-
- case SD_BUS_TYPE_DOUBLE:
- fprintf(f, "%g", basic.d64);
- break;
-
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_SIGNATURE: {
- _cleanup_free_ char *b = NULL;
-
- b = cescape(basic.string);
- if (!b)
- return -ENOMEM;
-
- fprintf(f, "\"%s\"", b);
- break;
- }
-
- case SD_BUS_TYPE_UNIX_FD:
- fprintf(f, "%i", basic.i);
- break;
-
- default:
- assert_not_reached("Unknown basic type.");
- }
-
- needs_space = true;
- }
-}
-
-typedef struct Member {
- const char *type;
- char *interface;
- char *name;
- char *signature;
- char *result;
- char *value;
- bool writable;
- uint64_t flags;
-} Member;
-
-static void member_hash_func(const void *p, struct siphash *state) {
- const Member *m = p;
- uint64_t arity = 1;
-
- assert(m);
- assert(m->type);
-
- string_hash_func(m->type, state);
-
- arity += !!m->name + !!m->interface;
-
- uint64_hash_func(&arity, state);
-
- if (m->name)
- string_hash_func(m->name, state);
-
- if (m->interface)
- string_hash_func(m->interface, state);
-}
-
-static int member_compare_func(const void *a, const void *b) {
- const Member *x = a, *y = b;
- int d;
-
- assert(x);
- assert(y);
- assert(x->type);
- assert(y->type);
-
- d = strcmp_ptr(x->interface, y->interface);
- if (d != 0)
- return d;
-
- d = strcmp(x->type, y->type);
- if (d != 0)
- return d;
-
- return strcmp_ptr(x->name, y->name);
-}
-
-static int member_compare_funcp(const void *a, const void *b) {
- const Member *const * x = (const Member *const *) a, * const *y = (const Member *const *) b;
-
- return member_compare_func(*x, *y);
-}
-
-static void member_free(Member *m) {
- if (!m)
- return;
-
- free(m->interface);
- free(m->name);
- free(m->signature);
- free(m->result);
- free(m->value);
- free(m);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free);
-
-static void member_set_free(Set *s) {
- Member *m;
-
- while ((m = set_steal_first(s)))
- member_free(m);
-
- set_free(s);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
-
-static int on_interface(const char *interface, uint64_t flags, void *userdata) {
- _cleanup_(member_freep) Member *m;
- Set *members = userdata;
- int r;
-
- assert(interface);
- assert(members);
-
- m = new0(Member, 1);
- if (!m)
- return log_oom();
-
- m->type = "interface";
- m->flags = flags;
-
- r = free_and_strdup(&m->interface, interface);
- if (r < 0)
- return log_oom();
-
- r = set_put(members, m);
- if (r <= 0) {
- log_error("Duplicate interface");
- return -EINVAL;
- }
-
- m = NULL;
- return 0;
-}
-
-static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) {
- _cleanup_(member_freep) Member *m;
- Set *members = userdata;
- int r;
-
- assert(interface);
- assert(name);
-
- m = new0(Member, 1);
- if (!m)
- return log_oom();
-
- m->type = "method";
- m->flags = flags;
-
- r = free_and_strdup(&m->interface, interface);
- if (r < 0)
- return log_oom();
-
- r = free_and_strdup(&m->name, name);
- if (r < 0)
- return log_oom();
-
- r = free_and_strdup(&m->signature, signature);
- if (r < 0)
- return log_oom();
-
- r = free_and_strdup(&m->result, result);
- if (r < 0)
- return log_oom();
-
- r = set_put(members, m);
- if (r <= 0) {
- log_error("Duplicate method");
- return -EINVAL;
- }
-
- m = NULL;
- return 0;
-}
-
-static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) {
- _cleanup_(member_freep) Member *m;
- Set *members = userdata;
- int r;
-
- assert(interface);
- assert(name);
-
- m = new0(Member, 1);
- if (!m)
- return log_oom();
-
- m->type = "signal";
- m->flags = flags;
-
- r = free_and_strdup(&m->interface, interface);
- if (r < 0)
- return log_oom();
-
- r = free_and_strdup(&m->name, name);
- if (r < 0)
- return log_oom();
-
- r = free_and_strdup(&m->signature, signature);
- if (r < 0)
- return log_oom();
-
- r = set_put(members, m);
- if (r <= 0) {
- log_error("Duplicate signal");
- return -EINVAL;
- }
-
- m = NULL;
- return 0;
-}
-
-static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) {
- _cleanup_(member_freep) Member *m;
- Set *members = userdata;
- int r;
-
- assert(interface);
- assert(name);
-
- m = new0(Member, 1);
- if (!m)
- return log_oom();
-
- m->type = "property";
- m->flags = flags;
- m->writable = writable;
-
- r = free_and_strdup(&m->interface, interface);
- if (r < 0)
- return log_oom();
-
- r = free_and_strdup(&m->name, name);
- if (r < 0)
- return log_oom();
-
- r = free_and_strdup(&m->signature, signature);
- if (r < 0)
- return log_oom();
-
- r = set_put(members, m);
- if (r <= 0) {
- log_error("Duplicate property");
- return -EINVAL;
- }
-
- m = NULL;
- return 0;
-}
-
-static const char *strdash(const char *x) {
- return isempty(x) ? "-" : x;
-}
-
-static int introspect(sd_bus *bus, char **argv) {
- static const struct hash_ops member_hash_ops = {
- .hash = member_hash_func,
- .compare = member_compare_func,
- };
-
- static const XMLIntrospectOps ops = {
- .on_interface = on_interface,
- .on_method = on_method,
- .on_signal = on_signal,
- .on_property = on_property,
- };
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(member_set_freep) Set *members = NULL;
- Iterator i;
- Member *m;
- const char *xml;
- int r;
- unsigned name_width, type_width, signature_width, result_width;
- Member **sorted = NULL;
- unsigned k = 0, j, n_args;
-
- n_args = strv_length(argv);
- if (n_args < 3) {
- log_error("Requires service and object path argument.");
- return -EINVAL;
- }
-
- if (n_args > 4) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- members = set_new(&member_hash_ops);
- if (!members)
- return log_oom();
-
- r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
- if (r < 0) {
- log_error("Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r));
- return r;
- }
-
- r = sd_bus_message_read(reply, "s", &xml);
- if (r < 0)
- return bus_log_parse_error(r);
-
- /* First, get list of all properties */
- r = parse_xml_introspect(argv[2], xml, &ops, members);
- if (r < 0)
- return r;
-
- /* Second, find the current values for them */
- SET_FOREACH(m, members, i) {
-
- if (!streq(m->type, "property"))
- continue;
-
- if (m->value)
- continue;
-
- if (argv[3] && !streq(argv[3], m->interface))
- continue;
-
- r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
-
- r = sd_bus_message_enter_container(reply, 'a', "{sv}");
- if (r < 0)
- return bus_log_parse_error(r);
-
- for (;;) {
- Member *z;
- _cleanup_free_ char *buf = NULL;
- _cleanup_fclose_ FILE *mf = NULL;
- size_t sz = 0;
- const char *name;
-
- r = sd_bus_message_enter_container(reply, 'e', "sv");
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (r == 0)
- break;
-
- r = sd_bus_message_read(reply, "s", &name);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, 'v', NULL);
- if (r < 0)
- return bus_log_parse_error(r);
-
- mf = open_memstream(&buf, &sz);
- if (!mf)
- return log_oom();
-
- r = format_cmdline(reply, mf, false);
- if (r < 0)
- return bus_log_parse_error(r);
-
- fclose(mf);
- mf = NULL;
-
- z = set_get(members, &((Member) {
- .type = "property",
- .interface = m->interface,
- .name = (char*) name }));
- if (z) {
- free(z->value);
- z->value = buf;
- buf = NULL;
- }
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- pager_open(arg_no_pager, false);
-
- name_width = strlen("NAME");
- type_width = strlen("TYPE");
- signature_width = strlen("SIGNATURE");
- result_width = strlen("RESULT/VALUE");
-
- sorted = newa(Member*, set_size(members));
-
- SET_FOREACH(m, members, i) {
-
- if (argv[3] && !streq(argv[3], m->interface))
- continue;
-
- if (m->interface)
- name_width = MAX(name_width, strlen(m->interface));
- if (m->name)
- name_width = MAX(name_width, strlen(m->name) + 1);
- if (m->type)
- type_width = MAX(type_width, strlen(m->type));
- if (m->signature)
- signature_width = MAX(signature_width, strlen(m->signature));
- if (m->result)
- result_width = MAX(result_width, strlen(m->result));
- if (m->value)
- result_width = MAX(result_width, strlen(m->value));
-
- sorted[k++] = m;
- }
-
- if (result_width > 40)
- result_width = 40;
-
- qsort(sorted, k, sizeof(Member*), member_compare_funcp);
-
- if (arg_legend) {
- printf("%-*s %-*s %-*s %-*s %s\n",
- (int) name_width, "NAME",
- (int) type_width, "TYPE",
- (int) signature_width, "SIGNATURE",
- (int) result_width, "RESULT/VALUE",
- "FLAGS");
- }
-
- for (j = 0; j < k; j++) {
- _cleanup_free_ char *ellipsized = NULL;
- const char *rv;
- bool is_interface;
-
- m = sorted[j];
-
- if (argv[3] && !streq(argv[3], m->interface))
- continue;
-
- is_interface = streq(m->type, "interface");
-
- if (argv[3] && is_interface)
- continue;
-
- if (m->value) {
- ellipsized = ellipsize(m->value, result_width, 100);
- if (!ellipsized)
- return log_oom();
-
- rv = ellipsized;
- } else
- rv = strdash(m->result);
-
- printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
- is_interface ? ansi_highlight() : "",
- is_interface ? "" : ".",
- - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name),
- is_interface ? ansi_normal() : "",
- (int) type_width, strdash(m->type),
- (int) signature_width, strdash(m->signature),
- (int) result_width, rv,
- (m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"),
- (m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "",
- (m->flags & SD_BUS_VTABLE_PROPERTY_CONST) ? " const" : "",
- (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) ? " emits-change" : "",
- (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) ? " emits-invalidation" : "",
- m->writable ? " writable" : "");
- }
-
- return 0;
-}
-
-static int message_dump(sd_bus_message *m, FILE *f) {
- return bus_message_dump(m, f, BUS_MESSAGE_DUMP_WITH_HEADER);
-}
-
-static int message_pcap(sd_bus_message *m, FILE *f) {
- return bus_message_pcap_frame(m, arg_snaplen, f);
-}
-
-static int monitor(sd_bus *bus, char *argv[], int (*dump)(sd_bus_message *m, FILE *f)) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char **i;
- uint32_t flags = 0;
- int r;
-
- /* upgrade connection; it's not used for anything else after this call */
- r = sd_bus_message_new_method_call(bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_open_container(message, 'a', "s");
- if (r < 0)
- return bus_log_create_error(r);
-
- STRV_FOREACH(i, argv+1) {
- _cleanup_free_ char *m = NULL;
-
- if (!service_name_is_valid(*i)) {
- log_error("Invalid service name '%s'", *i);
- return -EINVAL;
- }
-
- m = strjoin("sender='", *i, "'", NULL);
- if (!m)
- return log_oom();
-
- r = sd_bus_message_append_basic(message, 's', m);
- if (r < 0)
- return bus_log_create_error(r);
-
- free(m);
- m = strjoin("destination='", *i, "'", NULL);
- if (!m)
- return log_oom();
-
- r = sd_bus_message_append_basic(message, 's', m);
- if (r < 0)
- return bus_log_create_error(r);
- }
-
- STRV_FOREACH(i, arg_matches) {
- r = sd_bus_message_append_basic(message, 's', *i);
- if (r < 0)
- return bus_log_create_error(r);
- }
-
- r = sd_bus_message_close_container(message);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_basic(message, 'u', &flags);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_call(bus, message, arg_timeout, &error, NULL);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
-
- log_info("Monitoring bus message stream.");
-
- for (;;) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-
- r = sd_bus_process(bus, &m);
- if (r < 0)
- return log_error_errno(r, "Failed to process bus: %m");
-
- if (m) {
- dump(m, stdout);
- fflush(stdout);
-
- if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected") > 0) {
- log_info("Connection terminated, exiting.");
- return 0;
- }
-
- continue;
- }
-
- if (r > 0)
- continue;
-
- r = sd_bus_wait(bus, (uint64_t) -1);
- if (r < 0)
- return log_error_errno(r, "Failed to wait for bus: %m");
- }
-}
-
-static int capture(sd_bus *bus, char *argv[]) {
- int r;
-
- if (isatty(fileno(stdout)) > 0) {
- log_error("Refusing to write message data to console, please redirect output to a file.");
- return -EINVAL;
- }
-
- bus_pcap_header(arg_snaplen, stdout);
-
- r = monitor(bus, argv, message_pcap);
- if (r < 0)
- return r;
-
- if (ferror(stdout)) {
- log_error("Couldn't write capture file.");
- return -EIO;
- }
-
- return r;
-}
-
-static int status(sd_bus *bus, char *argv[]) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- pid_t pid;
- int r;
-
- assert(bus);
-
- if (strv_length(argv) > 2) {
- log_error("Expects no or one argument.");
- return -EINVAL;
- }
-
- if (argv[1]) {
- r = parse_pid(argv[1], &pid);
- if (r < 0)
- r = sd_bus_get_name_creds(
- bus,
- argv[1],
- (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL,
- &creds);
- else
- r = sd_bus_creds_new_from_pid(
- &creds,
- pid,
- _SD_BUS_CREDS_ALL);
- } else {
- const char *scope, *address;
- sd_id128_t bus_id;
-
- r = sd_bus_get_address(bus, &address);
- if (r >= 0)
- printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_normal());
-
- r = sd_bus_get_scope(bus, &scope);
- if (r >= 0)
- printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_normal());
-
- r = sd_bus_get_bus_id(bus, &bus_id);
- if (r >= 0)
- printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal());
-
- r = sd_bus_get_owner_creds(
- bus,
- (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL,
- &creds);
- }
-
- if (r < 0)
- return log_error_errno(r, "Failed to get credentials: %m");
-
- bus_creds_dump(creds, NULL, false);
- return 0;
-}
-
-static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) {
- char **p;
- int r;
-
- assert(m);
- assert(signature);
- assert(x);
-
- p = *x;
-
- for (;;) {
- const char *v;
- char t;
-
- t = *signature;
- v = *p;
-
- if (t == 0)
- break;
- if (!v) {
- log_error("Too few parameters for signature.");
- return -EINVAL;
- }
-
- signature++;
- p++;
-
- switch (t) {
-
- case SD_BUS_TYPE_BOOLEAN:
-
- r = parse_boolean(v);
- if (r < 0) {
- log_error("Failed to parse as boolean: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &r);
- break;
-
- case SD_BUS_TYPE_BYTE: {
- uint8_t z;
-
- r = safe_atou8(v, &z);
- if (r < 0) {
- log_error("Failed to parse as byte (unsigned 8bit integer): %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
- case SD_BUS_TYPE_INT16: {
- int16_t z;
-
- r = safe_atoi16(v, &z);
- if (r < 0) {
- log_error("Failed to parse as signed 16bit integer: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
- case SD_BUS_TYPE_UINT16: {
- uint16_t z;
-
- r = safe_atou16(v, &z);
- if (r < 0) {
- log_error("Failed to parse as unsigned 16bit integer: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
- case SD_BUS_TYPE_INT32: {
- int32_t z;
-
- r = safe_atoi32(v, &z);
- if (r < 0) {
- log_error("Failed to parse as signed 32bit integer: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
- case SD_BUS_TYPE_UINT32: {
- uint32_t z;
-
- r = safe_atou32(v, &z);
- if (r < 0) {
- log_error("Failed to parse as unsigned 32bit integer: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
- case SD_BUS_TYPE_INT64: {
- int64_t z;
-
- r = safe_atoi64(v, &z);
- if (r < 0) {
- log_error("Failed to parse as signed 64bit integer: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
- case SD_BUS_TYPE_UINT64: {
- uint64_t z;
-
- r = safe_atou64(v, &z);
- if (r < 0) {
- log_error("Failed to parse as unsigned 64bit integer: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
-
- case SD_BUS_TYPE_DOUBLE: {
- double z;
-
- r = safe_atod(v, &z);
- if (r < 0) {
- log_error("Failed to parse as double precision floating point: %s", v);
- return r;
- }
-
- r = sd_bus_message_append_basic(m, t, &z);
- break;
- }
-
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_SIGNATURE:
-
- r = sd_bus_message_append_basic(m, t, v);
- break;
-
- case SD_BUS_TYPE_ARRAY: {
- uint32_t n;
- size_t k;
-
- r = safe_atou32(v, &n);
- if (r < 0) {
- log_error("Failed to parse number of array entries: %s", v);
- return r;
- }
-
- r = signature_element_length(signature, &k);
- if (r < 0) {
- log_error("Invalid array signature.");
- return r;
- }
-
- {
- unsigned i;
- char s[k + 1];
- memcpy(s, signature, k);
- s[k] = 0;
-
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s);
- if (r < 0)
- return bus_log_create_error(r);
-
- for (i = 0; i < n; i++) {
- r = message_append_cmdline(m, s, &p);
- if (r < 0)
- return r;
- }
- }
-
- signature += k;
-
- r = sd_bus_message_close_container(m);
- break;
- }
-
- case SD_BUS_TYPE_VARIANT:
- r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = message_append_cmdline(m, v, &p);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(m);
- break;
-
- case SD_BUS_TYPE_STRUCT_BEGIN:
- case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
- size_t k;
-
- signature--;
- p--;
-
- r = signature_element_length(signature, &k);
- if (r < 0) {
- log_error("Invalid struct/dict entry signature.");
- return r;
- }
-
- {
- char s[k-1];
- memcpy(s, signature + 1, k - 2);
- s[k - 2] = 0;
-
- r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = message_append_cmdline(m, s, &p);
- if (r < 0)
- return r;
- }
-
- signature += k;
-
- r = sd_bus_message_close_container(m);
- break;
- }
-
- case SD_BUS_TYPE_UNIX_FD:
- log_error("UNIX file descriptor not supported as type.");
- return -EINVAL;
-
- default:
- log_error("Unknown signature type %c.", t);
- return -EINVAL;
- }
-
- if (r < 0)
- return bus_log_create_error(r);
- }
-
- *x = p;
- return 0;
-}
-
-static int call(sd_bus *bus, char *argv[]) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
- int r;
-
- assert(bus);
-
- if (strv_length(argv) < 5) {
- log_error("Expects at least four arguments.");
- return -EINVAL;
- }
-
- r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_set_expect_reply(m, arg_expect_reply);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_set_auto_start(m, arg_auto_start);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_set_allow_interactive_authorization(m, arg_allow_interactive_authorization);
- if (r < 0)
- return bus_log_create_error(r);
-
- if (!isempty(argv[5])) {
- char **p;
-
- p = argv+6;
-
- r = message_append_cmdline(m, argv[5], &p);
- if (r < 0)
- return r;
-
- if (*p) {
- log_error("Too many parameters for signature.");
- return -EINVAL;
- }
- }
-
- if (!arg_expect_reply) {
- r = sd_bus_send(bus, m, NULL);
- if (r < 0) {
- log_error("Failed to send message.");
- return r;
- }
-
- return 0;
- }
-
- r = sd_bus_call(bus, m, arg_timeout, &error, &reply);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
-
- r = sd_bus_message_is_empty(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (r == 0 && !arg_quiet) {
-
- if (arg_verbose) {
- pager_open(arg_no_pager, false);
-
- r = bus_message_dump(reply, stdout, 0);
- if (r < 0)
- return r;
- } else {
-
- fputs(sd_bus_message_get_signature(reply, true), stdout);
- fputc(' ', stdout);
-
- r = format_cmdline(reply, stdout, false);
- if (r < 0)
- return bus_log_parse_error(r);
-
- fputc('\n', stdout);
- }
- }
-
- return 0;
-}
-
-static int get_property(sd_bus *bus, char *argv[]) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned n;
- char **i;
- int r;
-
- assert(bus);
-
- n = strv_length(argv);
- if (n < 5) {
- log_error("Expects at least four arguments.");
- return -EINVAL;
- }
-
- STRV_FOREACH(i, argv + 4) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- const char *contents = NULL;
- char type;
-
- r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
-
- r = sd_bus_message_peek_type(reply, &type, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, 'v', contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (arg_verbose) {
- pager_open(arg_no_pager, false);
-
- r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY);
- if (r < 0)
- return r;
- } else {
- fputs(contents, stdout);
- fputc(' ', stdout);
-
- r = format_cmdline(reply, stdout, false);
- if (r < 0)
- return bus_log_parse_error(r);
-
- fputc('\n', stdout);
- }
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- return 0;
-}
-
-static int set_property(sd_bus *bus, char *argv[]) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned n;
- char **p;
- int r;
-
- assert(bus);
-
- n = strv_length(argv);
- if (n < 6) {
- log_error("Expects at least five arguments.");
- return -EINVAL;
- }
-
- r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(m, "ss", argv[3], argv[4]);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_open_container(m, 'v', argv[5]);
- if (r < 0)
- return bus_log_create_error(r);
-
- p = argv+6;
- r = message_append_cmdline(m, argv[5], &p);
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(m);
- if (r < 0)
- return bus_log_create_error(r);
-
- if (*p) {
- log_error("Too many parameters for signature.");
- return -EINVAL;
- }
-
- r = sd_bus_call(bus, m, arg_timeout, &error, NULL);
- if (r < 0) {
- log_error("%s", bus_error_message(&error, r));
- return r;
- }
-
- return 0;
-}
-
-static int help(void) {
- printf("%s [OPTIONS...] {COMMAND} ...\n\n"
- "Introspect the bus.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-pager Do not pipe output into a pager\n"
- " --no-legend Do not show the headers and footers\n"
- " --system Connect to system bus\n"
- " --user Connect to user bus\n"
- " -H --host=[USER@]HOST Operate on remote host\n"
- " -M --machine=CONTAINER Operate on local container\n"
- " --address=ADDRESS Connect to bus specified by address\n"
- " --show-machine Show machine ID column in list\n"
- " --unique Only show unique names\n"
- " --acquired Only show acquired names\n"
- " --activatable Only show activatable names\n"
- " --match=MATCH Only show matching messages\n"
- " --size=SIZE Maximum length of captured packet\n"
- " --list Don't show tree, but simple object path list\n"
- " --quiet Don't show method call reply\n"
- " --verbose Show result values in long format\n"
- " --expect-reply=BOOL Expect a method call reply\n"
- " --auto-start=BOOL Auto-start destination service\n"
- " --allow-interactive-authorization=BOOL\n"
- " Allow interactive authorization for operation\n"
- " --timeout=SECS Maximum time to wait for method call completion\n"
- " --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n\n"
- "Commands:\n"
- " list List bus names\n"
- " status [SERVICE] Show bus service, process or bus owner credentials\n"
- " monitor [SERVICE...] Show bus traffic\n"
- " capture [SERVICE...] Capture bus traffic as pcap\n"
- " tree [SERVICE...] Show object tree of service\n"
- " introspect SERVICE OBJECT [INTERFACE]\n"
- " call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n"
- " Call a method\n"
- " get-property SERVICE OBJECT INTERFACE PROPERTY...\n"
- " Get property value\n"
- " set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n"
- " Set property value\n"
- " help Show this help\n"
- , program_invocation_short_name);
-
- return 0;
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_NO_PAGER,
- ARG_NO_LEGEND,
- ARG_SYSTEM,
- ARG_USER,
- ARG_ADDRESS,
- ARG_MATCH,
- ARG_SHOW_MACHINE,
- ARG_UNIQUE,
- ARG_ACQUIRED,
- ARG_ACTIVATABLE,
- ARG_SIZE,
- ARG_LIST,
- ARG_VERBOSE,
- ARG_EXPECT_REPLY,
- ARG_AUTO_START,
- ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
- ARG_TIMEOUT,
- ARG_AUGMENT_CREDS,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
- { "system", no_argument, NULL, ARG_SYSTEM },
- { "user", no_argument, NULL, ARG_USER },
- { "address", required_argument, NULL, ARG_ADDRESS },
- { "show-machine", no_argument, NULL, ARG_SHOW_MACHINE },
- { "unique", no_argument, NULL, ARG_UNIQUE },
- { "acquired", no_argument, NULL, ARG_ACQUIRED },
- { "activatable", no_argument, NULL, ARG_ACTIVATABLE },
- { "match", required_argument, NULL, ARG_MATCH },
- { "host", required_argument, NULL, 'H' },
- { "machine", required_argument, NULL, 'M' },
- { "size", required_argument, NULL, ARG_SIZE },
- { "list", no_argument, NULL, ARG_LIST },
- { "quiet", no_argument, NULL, 'q' },
- { "verbose", no_argument, NULL, ARG_VERBOSE },
- { "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY },
- { "auto-start", required_argument, NULL, ARG_AUTO_START },
- { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
- { "timeout", required_argument, NULL, ARG_TIMEOUT },
- { "augment-creds",required_argument, NULL, ARG_AUGMENT_CREDS},
- {},
- };
-
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hH:M:q", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- return help();
-
- case ARG_VERSION:
- return version();
-
- case ARG_NO_PAGER:
- arg_no_pager = true;
- break;
-
- case ARG_NO_LEGEND:
- arg_legend = false;
- break;
-
- case ARG_USER:
- arg_user = true;
- break;
-
- case ARG_SYSTEM:
- arg_user = false;
- break;
-
- case ARG_ADDRESS:
- arg_address = optarg;
- break;
-
- case ARG_SHOW_MACHINE:
- arg_show_machine = true;
- break;
-
- case ARG_UNIQUE:
- arg_unique = true;
- break;
-
- case ARG_ACQUIRED:
- arg_acquired = true;
- break;
-
- case ARG_ACTIVATABLE:
- arg_activatable = true;
- break;
-
- case ARG_MATCH:
- if (strv_extend(&arg_matches, optarg) < 0)
- return log_oom();
- break;
-
- case ARG_SIZE: {
- uint64_t sz;
-
- r = parse_size(optarg, 1024, &sz);
- if (r < 0) {
- log_error("Failed to parse size: %s", optarg);
- return r;
- }
-
- if ((uint64_t) (size_t) sz != sz) {
- log_error("Size out of range.");
- return -E2BIG;
- }
-
- arg_snaplen = (size_t) sz;
- break;
- }
-
- case ARG_LIST:
- arg_list = true;
- break;
-
- case 'H':
- arg_transport = BUS_TRANSPORT_REMOTE;
- arg_host = optarg;
- break;
-
- case 'M':
- arg_transport = BUS_TRANSPORT_MACHINE;
- arg_host = optarg;
- break;
-
- case 'q':
- arg_quiet = true;
- break;
-
- case ARG_VERBOSE:
- arg_verbose = true;
- break;
-
- case ARG_EXPECT_REPLY:
- r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --expect-reply= parameter.");
- return r;
- }
-
- arg_expect_reply = !!r;
- break;
-
-
- case ARG_AUTO_START:
- r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --auto-start= parameter.");
- return r;
- }
-
- arg_auto_start = !!r;
- break;
-
-
- case ARG_ALLOW_INTERACTIVE_AUTHORIZATION:
- r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --allow-interactive-authorization= parameter.");
- return r;
- }
-
- arg_allow_interactive_authorization = !!r;
- break;
-
- case ARG_TIMEOUT:
- r = parse_sec(optarg, &arg_timeout);
- if (r < 0) {
- log_error("Failed to parse --timeout= parameter.");
- return r;
- }
-
- break;
-
- case ARG_AUGMENT_CREDS:
- r = parse_boolean(optarg);
- if (r < 0) {
- log_error("Failed to parse --augment-creds= parameter.");
- return r;
- }
-
- arg_augment_creds = !!r;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- return 1;
-}
-
-static int busctl_main(sd_bus *bus, int argc, char *argv[]) {
- assert(bus);
-
- if (optind >= argc ||
- streq(argv[optind], "list"))
- return list_bus_names(bus, argv + optind);
-
- if (streq(argv[optind], "monitor"))
- return monitor(bus, argv + optind, message_dump);
-
- if (streq(argv[optind], "capture"))
- return capture(bus, argv + optind);
-
- if (streq(argv[optind], "status"))
- return status(bus, argv + optind);
-
- if (streq(argv[optind], "tree"))
- return tree(bus, argv + optind);
-
- if (streq(argv[optind], "introspect"))
- return introspect(bus, argv + optind);
-
- if (streq(argv[optind], "call"))
- return call(bus, argv + optind);
-
- if (streq(argv[optind], "get-property"))
- return get_property(bus, argv + optind);
-
- if (streq(argv[optind], "set-property"))
- return set_property(bus, argv + optind);
-
- if (streq(argv[optind], "help"))
- return help();
-
- log_error("Unknown command '%s'", argv[optind]);
- return -EINVAL;
-}
-
-int main(int argc, char *argv[]) {
- sd_bus *bus = NULL;
- int r;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- r = sd_bus_new(&bus);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate bus: %m");
- goto finish;
- }
-
- if (STRPTR_IN_SET(argv[optind], "monitor", "capture")) {
-
- r = sd_bus_set_monitor(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to set monitor mode: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL);
- if (r < 0) {
- log_error_errno(r, "Failed to enable credentials: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_timestamp(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to enable timestamps: %m");
- goto finish;
- }
-
- r = sd_bus_negotiate_fds(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to enable fds: %m");
- goto finish;
- }
- }
-
- r = sd_bus_set_bus_client(bus, true);
- if (r < 0) {
- log_error_errno(r, "Failed to set bus client: %m");
- goto finish;
- }
-
- if (arg_address)
- r = sd_bus_set_address(bus, arg_address);
- else {
- switch (arg_transport) {
-
- case BUS_TRANSPORT_LOCAL:
- if (arg_user) {
- bus->is_user = true;
- r = bus_set_address_user(bus);
- } else {
- bus->is_system = true;
- r = bus_set_address_system(bus);
- }
- break;
-
- case BUS_TRANSPORT_REMOTE:
- r = bus_set_address_system_remote(bus, arg_host);
- break;
-
- case BUS_TRANSPORT_MACHINE:
- r = bus_set_address_system_machine(bus, arg_host);
- break;
-
- default:
- assert_not_reached("Hmm, unknown transport type.");
- }
- }
- if (r < 0) {
- log_error_errno(r, "Failed to set address: %m");
- goto finish;
- }
-
- r = sd_bus_start(bus);
- if (r < 0) {
- log_error_errno(r, "Failed to connect to bus: %m");
- goto finish;
- }
-
- r = busctl_main(bus, argc, argv);
-
-finish:
- sd_bus_flush_close_unref(bus);
- pager_close();
-
- strv_free(arg_matches);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h
deleted file mode 100644
index ecffc6b13c..0000000000
--- a/src/libsystemd/sd-bus/kdbus.h
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef _UAPI_KDBUS_H_
-#define _UAPI_KDBUS_H_
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-#define KDBUS_IOCTL_MAGIC 0x95
-#define KDBUS_SRC_ID_KERNEL (0)
-#define KDBUS_DST_ID_NAME (0)
-#define KDBUS_MATCH_ID_ANY (~0ULL)
-#define KDBUS_DST_ID_BROADCAST (~0ULL)
-#define KDBUS_FLAG_NEGOTIATE (1ULL << 63)
-
-/**
- * struct kdbus_notify_id_change - name registry change message
- * @id: New or former owner of the name
- * @flags: flags field from KDBUS_HELLO_*
- *
- * Sent from kernel to userspace when the owner or activator of
- * a well-known name changes.
- *
- * Attached to:
- * KDBUS_ITEM_ID_ADD
- * KDBUS_ITEM_ID_REMOVE
- */
-struct kdbus_notify_id_change {
- __u64 id;
- __u64 flags;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_notify_name_change - name registry change message
- * @old_id: ID and flags of former owner of a name
- * @new_id: ID and flags of new owner of a name
- * @name: Well-known name
- *
- * Sent from kernel to userspace when the owner or activator of
- * a well-known name changes.
- *
- * Attached to:
- * KDBUS_ITEM_NAME_ADD
- * KDBUS_ITEM_NAME_REMOVE
- * KDBUS_ITEM_NAME_CHANGE
- */
-struct kdbus_notify_name_change {
- struct kdbus_notify_id_change old_id;
- struct kdbus_notify_id_change new_id;
- char name[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_creds - process credentials
- * @uid: User ID
- * @euid: Effective UID
- * @suid: Saved UID
- * @fsuid: Filesystem UID
- * @gid: Group ID
- * @egid: Effective GID
- * @sgid: Saved GID
- * @fsgid: Filesystem GID
- *
- * Attached to:
- * KDBUS_ITEM_CREDS
- */
-struct kdbus_creds {
- __u64 uid;
- __u64 euid;
- __u64 suid;
- __u64 fsuid;
- __u64 gid;
- __u64 egid;
- __u64 sgid;
- __u64 fsgid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_pids - process identifiers
- * @pid: Process ID
- * @tid: Thread ID
- * @ppid: Parent process ID
- *
- * The PID and TID of a process.
- *
- * Attached to:
- * KDBUS_ITEM_PIDS
- */
-struct kdbus_pids {
- __u64 pid;
- __u64 tid;
- __u64 ppid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_caps - process capabilities
- * @last_cap: Highest currently known capability bit
- * @caps: Variable number of 32-bit capabilities flags
- *
- * Contains a variable number of 32-bit capabilities flags.
- *
- * Attached to:
- * KDBUS_ITEM_CAPS
- */
-struct kdbus_caps {
- __u32 last_cap;
- __u32 caps[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_audit - audit information
- * @sessionid: The audit session ID
- * @loginuid: The audit login uid
- *
- * Attached to:
- * KDBUS_ITEM_AUDIT
- */
-struct kdbus_audit {
- __u32 sessionid;
- __u32 loginuid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_timestamp
- * @seqnum: Global per-domain message sequence number
- * @monotonic_ns: Monotonic timestamp, in nanoseconds
- * @realtime_ns: Realtime timestamp, in nanoseconds
- *
- * Attached to:
- * KDBUS_ITEM_TIMESTAMP
- */
-struct kdbus_timestamp {
- __u64 seqnum;
- __u64 monotonic_ns;
- __u64 realtime_ns;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_vec - I/O vector for kdbus payload items
- * @size: The size of the vector
- * @address: Memory address of data buffer
- * @offset: Offset in the in-message payload memory,
- * relative to the message head
- *
- * Attached to:
- * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF
- */
-struct kdbus_vec {
- __u64 size;
- union {
- __u64 address;
- __u64 offset;
- };
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_bloom_parameter - bus-wide bloom parameters
- * @size: Size of the bit field in bytes (m / 8)
- * @n_hash: Number of hash functions used (k)
- */
-struct kdbus_bloom_parameter {
- __u64 size;
- __u64 n_hash;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_bloom_filter - bloom filter containing n elements
- * @generation: Generation of the element set in the filter
- * @data: Bit field, multiple of 8 bytes
- */
-struct kdbus_bloom_filter {
- __u64 generation;
- __u64 data[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_memfd - a kdbus memfd
- * @start: The offset into the memfd where the segment starts
- * @size: The size of the memfd segment
- * @fd: The file descriptor number
- * @__pad: Padding to ensure proper alignment and size
- *
- * Attached to:
- * KDBUS_ITEM_PAYLOAD_MEMFD
- */
-struct kdbus_memfd {
- __u64 start;
- __u64 size;
- int fd;
- __u32 __pad;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_name - a registered well-known name with its flags
- * @flags: Flags from KDBUS_NAME_*
- * @name: Well-known name
- *
- * Attached to:
- * KDBUS_ITEM_OWNED_NAME
- */
-struct kdbus_name {
- __u64 flags;
- char name[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_policy_access_type - permissions of a policy record
- * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid
- * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid
- * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid
- * @KDBUS_POLICY_ACCESS_WORLD: World-accessible
- */
-enum kdbus_policy_access_type {
- _KDBUS_POLICY_ACCESS_NULL,
- KDBUS_POLICY_ACCESS_USER,
- KDBUS_POLICY_ACCESS_GROUP,
- KDBUS_POLICY_ACCESS_WORLD,
-};
-
-/**
- * enum kdbus_policy_access_flags - mode flags
- * @KDBUS_POLICY_OWN: Allow to own a well-known name
- * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE
- * @KDBUS_POLICY_TALK: Allow communication to a well-known name
- * Implies KDBUS_POLICY_SEE
- * @KDBUS_POLICY_SEE: Allow to see a well-known name
- */
-enum kdbus_policy_type {
- KDBUS_POLICY_SEE = 0,
- KDBUS_POLICY_TALK,
- KDBUS_POLICY_OWN,
-};
-
-/**
- * struct kdbus_policy_access - policy access item
- * @type: One of KDBUS_POLICY_ACCESS_* types
- * @access: Access to grant
- * @id: For KDBUS_POLICY_ACCESS_USER, the uid
- * For KDBUS_POLICY_ACCESS_GROUP, the gid
- */
-struct kdbus_policy_access {
- __u64 type; /* USER, GROUP, WORLD */
- __u64 access; /* OWN, TALK, SEE */
- __u64 id; /* uid, gid, 0 */
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_attach_flags - flags for metadata attachments
- * @KDBUS_ATTACH_TIMESTAMP: Timestamp
- * @KDBUS_ATTACH_CREDS: Credentials
- * @KDBUS_ATTACH_PIDS: PIDs
- * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups
- * @KDBUS_ATTACH_NAMES: Well-known names
- * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID
- * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID
- * @KDBUS_ATTACH_EXE: The path of the executable
- * @KDBUS_ATTACH_CMDLINE: The process command line
- * @KDBUS_ATTACH_CGROUP: The croup membership
- * @KDBUS_ATTACH_CAPS: The process capabilities
- * @KDBUS_ATTACH_SECLABEL: The security label
- * @KDBUS_ATTACH_AUDIT: The audit IDs
- * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name
- * @_KDBUS_ATTACH_ALL: All of the above
- * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of
- * metatdata.
- */
-enum kdbus_attach_flags {
- KDBUS_ATTACH_TIMESTAMP = 1ULL << 0,
- KDBUS_ATTACH_CREDS = 1ULL << 1,
- KDBUS_ATTACH_PIDS = 1ULL << 2,
- KDBUS_ATTACH_AUXGROUPS = 1ULL << 3,
- KDBUS_ATTACH_NAMES = 1ULL << 4,
- KDBUS_ATTACH_TID_COMM = 1ULL << 5,
- KDBUS_ATTACH_PID_COMM = 1ULL << 6,
- KDBUS_ATTACH_EXE = 1ULL << 7,
- KDBUS_ATTACH_CMDLINE = 1ULL << 8,
- KDBUS_ATTACH_CGROUP = 1ULL << 9,
- KDBUS_ATTACH_CAPS = 1ULL << 10,
- KDBUS_ATTACH_SECLABEL = 1ULL << 11,
- KDBUS_ATTACH_AUDIT = 1ULL << 12,
- KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13,
- _KDBUS_ATTACH_ALL = (1ULL << 14) - 1,
- _KDBUS_ATTACH_ANY = ~0ULL
-};
-
-/**
- * enum kdbus_item_type - item types to chain data in a list
- * @_KDBUS_ITEM_NULL: Uninitialized/invalid
- * @_KDBUS_ITEM_USER_BASE: Start of user items
- * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items
- * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data
- * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head
- * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd
- * @KDBUS_ITEM_FDS: Attached file descriptors
- * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous
- * operation by writing to it from
- * userspace
- * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with
- * KDBUS_CMD_BUS_MAKE, carries a
- * struct kdbus_bloom_parameter
- * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message,
- * used to match against a bloom mask of a
- * connection, carries a struct
- * kdbus_bloom_filter
- * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a
- * message'sbloom filter
- * @KDBUS_ITEM_DST_NAME: Destination's well-known name
- * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint
- * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which
- * metadata a connection opts in to send
- * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which
- * metadata a connection requests to
- * receive for each reeceived message
- * @KDBUS_ITEM_ID: Connection ID
- * @KDBUS_ITEM_NAME: Well-know name with flags
- * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items
- * @KDBUS_ITEM_TIMESTAMP: Timestamp
- * @KDBUS_ITEM_CREDS: Process credentials
- * @KDBUS_ITEM_PIDS: Process identifiers
- * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups
- * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated
- * connection
- * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_EXE: The path of the executable
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_CMDLINE: The process command line
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_CGROUP: The croup membership
- * @KDBUS_ITEM_CAPS: The process capabilities
- * @KDBUS_ITEM_SECLABEL: The security label
- * @KDBUS_ITEM_AUDIT: The audit IDs
- * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name
- * (debugging)
- * @_KDBUS_ITEM_POLICY_BASE: Start of policy items
- * @KDBUS_ITEM_POLICY_ACCESS: Policy access block
- * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items
- * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change
- * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change
- * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached
- * @KDBUS_ITEM_REPLY_DEAD: Destination died
- *
- * N.B: The process and thread COMM fields, as well as the CMDLINE and
- * EXE fields may be altered by unprivileged processes und should
- * hence *not* used for security decisions. Peers should make use of
- * these items only for informational purposes, such as generating log
- * records.
- */
-enum kdbus_item_type {
- _KDBUS_ITEM_NULL,
- _KDBUS_ITEM_USER_BASE,
- KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE,
- KDBUS_ITEM_PAYLOAD_VEC,
- KDBUS_ITEM_PAYLOAD_OFF,
- KDBUS_ITEM_PAYLOAD_MEMFD,
- KDBUS_ITEM_FDS,
- KDBUS_ITEM_CANCEL_FD,
- KDBUS_ITEM_BLOOM_PARAMETER,
- KDBUS_ITEM_BLOOM_FILTER,
- KDBUS_ITEM_BLOOM_MASK,
- KDBUS_ITEM_DST_NAME,
- KDBUS_ITEM_MAKE_NAME,
- KDBUS_ITEM_ATTACH_FLAGS_SEND,
- KDBUS_ITEM_ATTACH_FLAGS_RECV,
- KDBUS_ITEM_ID,
- KDBUS_ITEM_NAME,
- KDBUS_ITEM_DST_ID,
-
- /* keep these item types in sync with KDBUS_ATTACH_* flags */
- _KDBUS_ITEM_ATTACH_BASE = 0x1000,
- KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE,
- KDBUS_ITEM_CREDS,
- KDBUS_ITEM_PIDS,
- KDBUS_ITEM_AUXGROUPS,
- KDBUS_ITEM_OWNED_NAME,
- KDBUS_ITEM_TID_COMM,
- KDBUS_ITEM_PID_COMM,
- KDBUS_ITEM_EXE,
- KDBUS_ITEM_CMDLINE,
- KDBUS_ITEM_CGROUP,
- KDBUS_ITEM_CAPS,
- KDBUS_ITEM_SECLABEL,
- KDBUS_ITEM_AUDIT,
- KDBUS_ITEM_CONN_DESCRIPTION,
-
- _KDBUS_ITEM_POLICY_BASE = 0x2000,
- KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE,
-
- _KDBUS_ITEM_KERNEL_BASE = 0x8000,
- KDBUS_ITEM_NAME_ADD = _KDBUS_ITEM_KERNEL_BASE,
- KDBUS_ITEM_NAME_REMOVE,
- KDBUS_ITEM_NAME_CHANGE,
- KDBUS_ITEM_ID_ADD,
- KDBUS_ITEM_ID_REMOVE,
- KDBUS_ITEM_REPLY_TIMEOUT,
- KDBUS_ITEM_REPLY_DEAD,
-};
-
-/**
- * struct kdbus_item - chain of data blocks
- * @size: Overall data record size
- * @type: Kdbus_item type of data
- * @data: Generic bytes
- * @data32: Generic 32 bit array
- * @data64: Generic 64 bit array
- * @str: Generic string
- * @id: Connection ID
- * @vec: KDBUS_ITEM_PAYLOAD_VEC
- * @creds: KDBUS_ITEM_CREDS
- * @audit: KDBUS_ITEM_AUDIT
- * @timestamp: KDBUS_ITEM_TIMESTAMP
- * @name: KDBUS_ITEM_NAME
- * @bloom_parameter: KDBUS_ITEM_BLOOM_PARAMETER
- * @bloom_filter: KDBUS_ITEM_BLOOM_FILTER
- * @memfd: KDBUS_ITEM_PAYLOAD_MEMFD
- * @name_change: KDBUS_ITEM_NAME_ADD
- * KDBUS_ITEM_NAME_REMOVE
- * KDBUS_ITEM_NAME_CHANGE
- * @id_change: KDBUS_ITEM_ID_ADD
- * KDBUS_ITEM_ID_REMOVE
- * @policy: KDBUS_ITEM_POLICY_ACCESS
- */
-struct kdbus_item {
- __u64 size;
- __u64 type;
- union {
- __u8 data[0];
- __u32 data32[0];
- __u64 data64[0];
- char str[0];
-
- __u64 id;
- struct kdbus_vec vec;
- struct kdbus_creds creds;
- struct kdbus_pids pids;
- struct kdbus_audit audit;
- struct kdbus_caps caps;
- struct kdbus_timestamp timestamp;
- struct kdbus_name name;
- struct kdbus_bloom_parameter bloom_parameter;
- struct kdbus_bloom_filter bloom_filter;
- struct kdbus_memfd memfd;
- int fds[0];
- struct kdbus_notify_name_change name_change;
- struct kdbus_notify_id_change id_change;
- struct kdbus_policy_access policy_access;
- };
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_msg_flags - type of message
- * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for
- * method calls. The userspace-supplied
- * cookie identifies the message and the
- * respective reply carries the cookie
- * in cookie_reply
- * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed
- * name is not currently active. This flag is
- * not looked at by the kernel but only
- * serves as hint for userspace implementations.
- * @KDBUS_MSG_SIGNAL: Treat this message as signal
- */
-enum kdbus_msg_flags {
- KDBUS_MSG_EXPECT_REPLY = 1ULL << 0,
- KDBUS_MSG_NO_AUTO_START = 1ULL << 1,
- KDBUS_MSG_SIGNAL = 1ULL << 2,
-};
-
-/**
- * enum kdbus_payload_type - type of payload carried by message
- * @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message
- * @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus"
- *
- * Any payload-type is accepted. Common types will get added here once
- * established.
- */
-enum kdbus_payload_type {
- KDBUS_PAYLOAD_KERNEL,
- KDBUS_PAYLOAD_DBUS = 0x4442757344427573ULL,
-};
-
-/**
- * struct kdbus_msg - the representation of a kdbus message
- * @size: Total size of the message
- * @flags: Message flags (KDBUS_MSG_*), userspace → kernel
- * @priority: Message queue priority value
- * @dst_id: 64-bit ID of the destination connection
- * @src_id: 64-bit ID of the source connection
- * @payload_type: Payload type (KDBUS_PAYLOAD_*)
- * @cookie: Userspace-supplied cookie, for the connection
- * to identify its messages
- * @timeout_ns: The time to wait for a message reply from the peer.
- * If there is no reply, and the send command is
- * executed asynchronously, a kernel-generated message
- * with an attached KDBUS_ITEM_REPLY_TIMEOUT item
- * is sent to @src_id. For synchronously executed send
- * command, the value denotes the maximum time the call
- * blocks to wait for a reply. The timeout is expected in
- * nanoseconds and as absolute CLOCK_MONOTONIC value.
- * @cookie_reply: A reply to the requesting message with the same
- * cookie. The requesting connection can match its
- * request and the reply with this value
- * @items: A list of kdbus_items containing the message payload
- */
-struct kdbus_msg {
- __u64 size;
- __u64 flags;
- __s64 priority;
- __u64 dst_id;
- __u64 src_id;
- __u64 payload_type;
- __u64 cookie;
- union {
- __u64 timeout_ns;
- __u64 cookie_reply;
- };
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_msg_info - returned message container
- * @offset: Offset of kdbus_msg slice in pool
- * @msg_size: Copy of the kdbus_msg.size field
- * @return_flags: Command return flags, kernel → userspace
- */
-struct kdbus_msg_info {
- __u64 offset;
- __u64 msg_size;
- __u64 return_flags;
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_send_flags - flags for sending messages
- * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to
- * reply to this message. The
- * KDBUS_CMD_SEND ioctl() will block
- * until the reply is received, and
- * reply in struct kdbus_cmd_send will
- * yield the offset in the sender's pool
- * where the reply can be found.
- * This flag is only valid if
- * @KDBUS_MSG_EXPECT_REPLY is set as well.
- */
-enum kdbus_send_flags {
- KDBUS_SEND_SYNC_REPLY = 1ULL << 0,
-};
-
-/**
- * struct kdbus_cmd_send - send message
- * @size: Overall size of this structure
- * @flags: Flags to change send behavior (KDBUS_SEND_*)
- * @return_flags: Command return flags, kernel → userspace
- * @msg_address: Storage address of the kdbus_msg to send
- * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY
- * was given
- * @items: Additional items for this command
- */
-struct kdbus_cmd_send {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 msg_address;
- struct kdbus_msg_info reply;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_recv_flags - flags for de-queuing messages
- * @KDBUS_RECV_PEEK: Return the next queued message without
- * actually de-queuing it, and without installing
- * any file descriptors or other resources. It is
- * usually used to determine the activating
- * connection of a bus name.
- * @KDBUS_RECV_DROP: Drop and free the next queued message and all
- * its resources without actually receiving it.
- * @KDBUS_RECV_USE_PRIORITY: Only de-queue messages with the specified or
- * higher priority (lowest values); if not set,
- * the priority value is ignored.
- */
-enum kdbus_recv_flags {
- KDBUS_RECV_PEEK = 1ULL << 0,
- KDBUS_RECV_DROP = 1ULL << 1,
- KDBUS_RECV_USE_PRIORITY = 1ULL << 2,
-};
-
-/**
- * enum kdbus_recv_return_flags - return flags for message receive commands
- * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not
- * be installed. These descriptors in
- * KDBUS_ITEM_FDS will carry the value -1.
- * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since
- * the last time a message was received.
- * The 'dropped_msgs' counter contains the
- * number of messages dropped pool
- * overflows or other missed broadcasts.
- */
-enum kdbus_recv_return_flags {
- KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0,
- KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1,
-};
-
-/**
- * struct kdbus_cmd_recv - struct to de-queue a buffered message
- * @size: Overall size of this object
- * @flags: KDBUS_RECV_* flags, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @priority: Minimum priority of the messages to de-queue. Lowest
- * values have the highest priority.
- * @dropped_msgs: In case there were any dropped messages since the last
- * time a message was received, this will be set to the
- * number of lost messages and
- * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in
- * 'return_flags'. This can only happen if the ioctl
- * returns 0 or EAGAIN.
- * @msg: Return storage for received message.
- * @items: Additional items for this command.
- *
- * This struct is used with the KDBUS_CMD_RECV ioctl.
- */
-struct kdbus_cmd_recv {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __s64 priority;
- __u64 dropped_msgs;
- struct kdbus_msg_info msg;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_cmd_free - struct to free a slice of memory in the pool
- * @size: Overall size of this structure
- * @flags: Flags for the free command, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @offset: The offset of the memory slice, as returned by other
- * ioctls
- * @items: Additional items to modify the behavior
- *
- * This struct is used with the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_cmd_free {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_hello_flags - flags for struct kdbus_cmd_hello
- * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of
- * any passed file descriptors
- * @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers
- * a well-know name for a process to be started
- * when traffic arrives
- * @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers
- * policy entries for a name. The provided name
- * is not activated and not registered with the
- * name database, it only allows unprivileged
- * connections to acquire a name, talk or discover
- * a service
- * @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor
- * bus traffic
- */
-enum kdbus_hello_flags {
- KDBUS_HELLO_ACCEPT_FD = 1ULL << 0,
- KDBUS_HELLO_ACTIVATOR = 1ULL << 1,
- KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2,
- KDBUS_HELLO_MONITOR = 1ULL << 3,
-};
-
-/**
- * struct kdbus_cmd_hello - struct to say hello to kdbus
- * @size: The total size of the structure
- * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @attach_flags_send: Mask of metadata to attach to each message sent
- * off by this connection (KDBUS_ATTACH_*)
- * @attach_flags_recv: Mask of metadata to attach to each message receieved
- * by the new connection (KDBUS_ATTACH_*)
- * @bus_flags: The flags field copied verbatim from the original
- * KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful
- * to do negotiation of features of the payload that is
- * transferred (kernel → userspace)
- * @id: The ID of this connection (kernel → userspace)
- * @pool_size: Size of the connection's buffer where the received
- * messages are placed
- * @offset: Pool offset where items are returned to report
- * additional information about the bus and the newly
- * created connection.
- * @items_size: Size of buffer returned in the pool slice at @offset.
- * @id128: Unique 128-bit ID of the bus (kernel → userspace)
- * @items: A list of items
- *
- * This struct is used with the KDBUS_CMD_HELLO ioctl.
- */
-struct kdbus_cmd_hello {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 attach_flags_send;
- __u64 attach_flags_recv;
- __u64 bus_flags;
- __u64 id;
- __u64 pool_size;
- __u64 offset;
- __u64 items_size;
- __u8 id128[16];
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_info - connection information
- * @size: total size of the struct
- * @id: 64bit object ID
- * @flags: object creation flags
- * @items: list of items
- *
- * Note that the user is responsible for freeing the allocated memory with
- * the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_info {
- __u64 size;
- __u64 id;
- __u64 flags;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_list_flags - what to include into the returned list
- * @KDBUS_LIST_UNIQUE: active connections
- * @KDBUS_LIST_ACTIVATORS: activator connections
- * @KDBUS_LIST_NAMES: known well-known names
- * @KDBUS_LIST_QUEUED: queued-up names
- */
-enum kdbus_list_flags {
- KDBUS_LIST_UNIQUE = 1ULL << 0,
- KDBUS_LIST_NAMES = 1ULL << 1,
- KDBUS_LIST_ACTIVATORS = 1ULL << 2,
- KDBUS_LIST_QUEUED = 1ULL << 3,
-};
-
-/**
- * struct kdbus_cmd_list - list connections
- * @size: overall size of this object
- * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel
- * @return_flags: command return flags, kernel → userspace
- * @offset: Offset in the caller's pool buffer where an array of
- * kdbus_info objects is stored.
- * The user must use KDBUS_CMD_FREE to free the
- * allocated memory.
- * @list_size: size of returned list in bytes
- * @items: Items for the command. Reserved for future use.
- *
- * This structure is used with the KDBUS_CMD_LIST ioctl.
- */
-struct kdbus_cmd_list {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
- __u64 list_size;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl
- * @size: The total size of the struct
- * @flags: Flags for this ioctl, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @id: The 64-bit ID of the connection. If set to zero, passing
- * @name is required. kdbus will look up the name to
- * determine the ID in this case.
- * @attach_flags: Set of attach flags to specify the set of information
- * to receive, userspace → kernel
- * @offset: Returned offset in the caller's pool buffer where the
- * kdbus_info struct result is stored. The user must
- * use KDBUS_CMD_FREE to free the allocated memory.
- * @info_size: Output buffer to report size of data at @offset.
- * @items: The optional item list, containing the
- * well-known name to look up as a KDBUS_ITEM_NAME.
- * Only needed in case @id is zero.
- *
- * On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will
- * tell the user the offset in the connection pool buffer at which to find the
- * result in a struct kdbus_info.
- */
-struct kdbus_cmd_info {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 id;
- __u64 attach_flags;
- __u64 offset;
- __u64 info_size;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl
- * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already
- * exists, remove them before installing the new
- * matches.
- */
-enum kdbus_cmd_match_flags {
- KDBUS_MATCH_REPLACE = 1ULL << 0,
-};
-
-/**
- * struct kdbus_cmd_match - struct to add or remove matches
- * @size: The total size of the struct
- * @flags: Flags for match command (KDBUS_MATCH_*),
- * userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @cookie: Userspace supplied cookie. When removing, the cookie
- * identifies the match to remove
- * @items: A list of items for additional information
- *
- * This structure is used with the KDBUS_CMD_MATCH_ADD and
- * KDBUS_CMD_MATCH_REMOVE ioctl.
- */
-struct kdbus_cmd_match {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 cookie;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE
- * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible
- * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible
- */
-enum kdbus_make_flags {
- KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0,
- KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1,
-};
-
-/**
- * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE
- * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections
- * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name
- * @KDBUS_NAME_QUEUE: Name should be queued if busy
- * @KDBUS_NAME_IN_QUEUE: Name is queued
- * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection
- */
-enum kdbus_name_flags {
- KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0,
- KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
- KDBUS_NAME_QUEUE = 1ULL << 2,
- KDBUS_NAME_IN_QUEUE = 1ULL << 3,
- KDBUS_NAME_ACTIVATOR = 1ULL << 4,
-};
-
-/**
- * struct kdbus_cmd - generic ioctl payload
- * @size: Overall size of this structure
- * @flags: Flags for this ioctl, userspace → kernel
- * @return_flags: Ioctl return flags, kernel → userspace
- * @items: Additional items to modify the behavior
- *
- * This is a generic ioctl payload object. It's used by all ioctls that only
- * take flags and items as input.
- */
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * Ioctl API
- *
- * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command
- * creates a new bus with the specified
- * name. The bus is immediately shut down and
- * cleaned up when the opened file descriptor is
- * closed.
- *
- * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to
- * the bus. Such endpoints usually carry a more
- * restrictive policy and grant restricted access
- * to specific applications.
- * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used
- * to update the policy.
- *
- * KDBUS_CMD_HELLO: By opening the bus node, a connection is
- * created. After a HELLO the opened connection
- * becomes an active peer on the bus.
- * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to
- * update the metadata subscription mask and
- * policy.
- * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no
- * messages queued up in the connection's pool,
- * the call succeeds, and the handle is rendered
- * unusable. Otherwise, -EBUSY is returned without
- * any further side-effects.
- * KDBUS_CMD_FREE: Release the allocated memory in the receiver's
- * pool.
- * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the
- * initial creator of the connection. The data was
- * stored at registration time and does not
- * necessarily represent the connected process or
- * the actual state of the process.
- * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus
- * a connection is attached to.
- *
- * KDBUS_CMD_SEND: Send a message and pass data from userspace to
- * the kernel.
- * KDBUS_CMD_RECV: Receive a message from the kernel which is
- * placed in the receiver's pool.
- *
- * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with
- * the connection. Well-known names are used to
- * address a peer on the bus.
- * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection
- * currently owns.
- * KDBUS_CMD_LIST: Retrieve the list of all currently registered
- * well-known and unique names.
- *
- * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should
- * be delivered to the connection.
- * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages.
- */
-enum kdbus_ioctl_type {
- /* bus owner (00-0f) */
- KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00,
- struct kdbus_cmd),
-
- /* endpoint owner (10-1f) */
- KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10,
- struct kdbus_cmd),
- KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11,
- struct kdbus_cmd),
-
- /* connection owner (80-ff) */
- KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80,
- struct kdbus_cmd_hello),
- KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81,
- struct kdbus_cmd),
- KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82,
- struct kdbus_cmd),
- KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83,
- struct kdbus_cmd_free),
- KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84,
- struct kdbus_cmd_info),
- KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85,
- struct kdbus_cmd_info),
- KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86,
- struct kdbus_cmd_list),
-
- KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90,
- struct kdbus_cmd_send),
- KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91,
- struct kdbus_cmd_recv),
-
- KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0,
- struct kdbus_cmd),
- KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1,
- struct kdbus_cmd),
-
- KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0,
- struct kdbus_cmd_match),
- KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1,
- struct kdbus_cmd_match),
-};
-
-#endif /* _UAPI_KDBUS_H_ */
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
deleted file mode 100644
index d746348544..0000000000
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ /dev/null
@@ -1,3853 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <endian.h>
-#include <netdb.h>
-#include <poll.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-container.h"
-#include "bus-control.h"
-#include "bus-internal.h"
-#include "bus-kernel.h"
-#include "bus-label.h"
-#include "bus-message.h"
-#include "bus-objects.h"
-#include "bus-protocol.h"
-#include "bus-slot.h"
-#include "bus-socket.h"
-#include "bus-track.h"
-#include "bus-type.h"
-#include "bus-util.h"
-#include "cgroup-util.h"
-#include "def.h"
-#include "fd-util.h"
-#include "hexdecoct.h"
-#include "hostname-util.h"
-#include "macro.h"
-#include "missing.h"
-#include "parse-util.h"
-#include "string-util.h"
-#include "strv.h"
-#include "util.h"
-
-#define log_debug_bus_message(m) \
- do { \
- sd_bus_message *_mm = (m); \
- log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", \
- bus_message_type_to_string(_mm->header->type), \
- strna(sd_bus_message_get_sender(_mm)), \
- strna(sd_bus_message_get_destination(_mm)), \
- strna(sd_bus_message_get_path(_mm)), \
- strna(sd_bus_message_get_interface(_mm)), \
- strna(sd_bus_message_get_member(_mm)), \
- BUS_MESSAGE_COOKIE(_mm), \
- _mm->reply_cookie, \
- strna(_mm->error.message)); \
- } while (false)
-
-static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
-static int attach_io_events(sd_bus *b);
-static void detach_io_events(sd_bus *b);
-
-static thread_local sd_bus *default_system_bus = NULL;
-static thread_local sd_bus *default_user_bus = NULL;
-static thread_local sd_bus *default_starter_bus = NULL;
-
-static void bus_close_fds(sd_bus *b) {
- assert(b);
-
- detach_io_events(b);
-
- if (b->input_fd != b->output_fd)
- safe_close(b->output_fd);
- b->output_fd = b->input_fd = safe_close(b->input_fd);
-}
-
-static void bus_reset_queues(sd_bus *b) {
- assert(b);
-
- while (b->rqueue_size > 0)
- sd_bus_message_unref(b->rqueue[--b->rqueue_size]);
-
- b->rqueue = mfree(b->rqueue);
- b->rqueue_allocated = 0;
-
- while (b->wqueue_size > 0)
- sd_bus_message_unref(b->wqueue[--b->wqueue_size]);
-
- b->wqueue = mfree(b->wqueue);
- b->wqueue_allocated = 0;
-}
-
-static void bus_free(sd_bus *b) {
- sd_bus_slot *s;
-
- assert(b);
- assert(!b->track_queue);
- assert(!b->tracks);
-
- b->state = BUS_CLOSED;
-
- sd_bus_detach_event(b);
-
- while ((s = b->slots)) {
- /* At this point only floating slots can still be
- * around, because the non-floating ones keep a
- * reference to the bus, and we thus couldn't be
- * destructing right now... We forcibly disconnect the
- * slots here, so that they still can be referenced by
- * apps, but are dead. */
-
- assert(s->floating);
- bus_slot_disconnect(s);
- sd_bus_slot_unref(s);
- }
-
- if (b->default_bus_ptr)
- *b->default_bus_ptr = NULL;
-
- bus_close_fds(b);
-
- if (b->kdbus_buffer)
- munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
-
- free(b->label);
- free(b->rbuffer);
- free(b->unique_name);
- free(b->auth_buffer);
- free(b->address);
- free(b->kernel);
- free(b->machine);
- free(b->fake_label);
- free(b->cgroup_root);
- free(b->description);
-
- free(b->exec_path);
- strv_free(b->exec_argv);
-
- close_many(b->fds, b->n_fds);
- free(b->fds);
-
- bus_reset_queues(b);
-
- ordered_hashmap_free_free(b->reply_callbacks);
- prioq_free(b->reply_callbacks_prioq);
-
- assert(b->match_callbacks.type == BUS_MATCH_ROOT);
- bus_match_free(&b->match_callbacks);
-
- hashmap_free_free(b->vtable_methods);
- hashmap_free_free(b->vtable_properties);
-
- assert(hashmap_isempty(b->nodes));
- hashmap_free(b->nodes);
-
- bus_kernel_flush_memfd(b);
-
- assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
-
- free(b);
-}
-
-_public_ int sd_bus_new(sd_bus **ret) {
- sd_bus *r;
-
- assert_return(ret, -EINVAL);
-
- r = new0(sd_bus, 1);
- if (!r)
- return -ENOMEM;
-
- r->n_ref = REFCNT_INIT;
- r->input_fd = r->output_fd = -1;
- r->message_version = 1;
- r->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
- r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
- r->attach_flags |= KDBUS_ATTACH_NAMES;
- r->original_pid = getpid();
-
- assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
-
- /* We guarantee that wqueue always has space for at least one
- * entry */
- if (!GREEDY_REALLOC(r->wqueue, r->wqueue_allocated, 1)) {
- free(r);
- return -ENOMEM;
- }
-
- *ret = r;
- return 0;
-}
-
-_public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
- char *a;
-
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(address, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- a = strdup(address);
- if (!a)
- return -ENOMEM;
-
- free(bus->address);
- bus->address = a;
-
- return 0;
-}
-
-_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(input_fd >= 0, -EBADF);
- assert_return(output_fd >= 0, -EBADF);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- bus->input_fd = input_fd;
- bus->output_fd = output_fd;
- return 0;
-}
-
-_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
- char *p, **a;
-
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(path, -EINVAL);
- assert_return(!strv_isempty(argv), -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- p = strdup(path);
- if (!p)
- return -ENOMEM;
-
- a = strv_copy(argv);
- if (!a) {
- free(p);
- return -ENOMEM;
- }
-
- free(bus->exec_path);
- strv_free(bus->exec_argv);
-
- bus->exec_path = p;
- bus->exec_argv = a;
-
- return 0;
-}
-
-_public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- bus->bus_client = !!b;
- return 0;
-}
-
-_public_ int sd_bus_set_monitor(sd_bus *bus, int b) {
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- SET_FLAG(bus->hello_flags, KDBUS_HELLO_MONITOR, b);
- return 0;
-}
-
-_public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) {
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b);
- return 0;
-}
-
-_public_ int sd_bus_negotiate_timestamp(sd_bus *bus, int b) {
- uint64_t new_flags;
- assert_return(bus, -EINVAL);
- assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- new_flags = bus->attach_flags;
- SET_FLAG(new_flags, KDBUS_ATTACH_TIMESTAMP, b);
-
- if (bus->attach_flags == new_flags)
- return 0;
-
- bus->attach_flags = new_flags;
- if (bus->state != BUS_UNSET && bus->is_kernel)
- bus_kernel_realize_attach_flags(bus);
-
- return 0;
-}
-
-_public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) {
- uint64_t new_flags;
-
- assert_return(bus, -EINVAL);
- assert_return(mask <= _SD_BUS_CREDS_ALL, -EINVAL);
- assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- SET_FLAG(bus->creds_mask, mask, b);
-
- /* The well knowns we need unconditionally, so that matches can work */
- bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
-
- /* Make sure we don't lose the timestamp flag */
- new_flags = (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) | attach_flags_to_kdbus(bus->creds_mask);
- if (bus->attach_flags == new_flags)
- return 0;
-
- bus->attach_flags = new_flags;
- if (bus->state != BUS_UNSET && bus->is_kernel)
- bus_kernel_realize_attach_flags(bus);
-
- return 0;
-}
-
-_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
- assert_return(bus, -EINVAL);
- assert_return(b || sd_id128_equal(server_id, SD_ID128_NULL), -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- bus->is_server = !!b;
- bus->server_id = server_id;
- return 0;
-}
-
-_public_ int sd_bus_set_anonymous(sd_bus *bus, int b) {
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- bus->anonymous_auth = !!b;
- return 0;
-}
-
-_public_ int sd_bus_set_trusted(sd_bus *bus, int b) {
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- bus->trusted = !!b;
- return 0;
-}
-
-_public_ int sd_bus_set_description(sd_bus *bus, const char *description) {
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return free_and_strdup(&bus->description, description);
-}
-
-_public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) {
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- bus->allow_interactive_authorization = !!b;
- return 0;
-}
-
-_public_ int sd_bus_get_allow_interactive_authorization(sd_bus *bus) {
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return bus->allow_interactive_authorization;
-}
-
-static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- const char *s;
- sd_bus *bus;
- int r;
-
- assert(reply);
- bus = reply->bus;
- assert(bus);
- assert(bus->state == BUS_HELLO || bus->state == BUS_CLOSING);
-
- r = sd_bus_message_get_errno(reply);
- if (r > 0)
- return -r;
-
- r = sd_bus_message_read(reply, "s", &s);
- if (r < 0)
- return r;
-
- if (!service_name_is_valid(s) || s[0] != ':')
- return -EBADMSG;
-
- bus->unique_name = strdup(s);
- if (!bus->unique_name)
- return -ENOMEM;
-
- if (bus->state == BUS_HELLO)
- bus->state = BUS_RUNNING;
-
- return 1;
-}
-
-static int bus_send_hello(sd_bus *bus) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(bus);
-
- if (!bus->bus_client || bus->is_kernel)
- return 0;
-
- r = sd_bus_message_new_method_call(
- bus,
- &m,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "Hello");
- if (r < 0)
- return r;
-
- return sd_bus_call_async(bus, NULL, m, hello_callback, NULL, 0);
-}
-
-int bus_start_running(sd_bus *bus) {
- assert(bus);
-
- if (bus->bus_client && !bus->is_kernel) {
- bus->state = BUS_HELLO;
- return 1;
- }
-
- bus->state = BUS_RUNNING;
- return 1;
-}
-
-static int parse_address_key(const char **p, const char *key, char **value) {
- size_t l, n = 0, allocated = 0;
- const char *a;
- char *r = NULL;
-
- assert(p);
- assert(*p);
- assert(value);
-
- if (key) {
- l = strlen(key);
- if (strncmp(*p, key, l) != 0)
- return 0;
-
- if ((*p)[l] != '=')
- return 0;
-
- if (*value)
- return -EINVAL;
-
- a = *p + l + 1;
- } else
- a = *p;
-
- while (*a != ';' && *a != ',' && *a != 0) {
- char c;
-
- if (*a == '%') {
- int x, y;
-
- x = unhexchar(a[1]);
- if (x < 0) {
- free(r);
- return x;
- }
-
- y = unhexchar(a[2]);
- if (y < 0) {
- free(r);
- return y;
- }
-
- c = (char) ((x << 4) | y);
- a += 3;
- } else {
- c = *a;
- a++;
- }
-
- if (!GREEDY_REALLOC(r, allocated, n + 2))
- return -ENOMEM;
-
- r[n++] = c;
- }
-
- if (!r) {
- r = strdup("");
- if (!r)
- return -ENOMEM;
- } else
- r[n] = 0;
-
- if (*a == ',')
- a++;
-
- *p = a;
-
- free(*value);
- *value = r;
-
- return 1;
-}
-
-static void skip_address_key(const char **p) {
- assert(p);
- assert(*p);
-
- *p += strcspn(*p, ",");
-
- if (**p == ',')
- (*p)++;
-}
-
-static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
- _cleanup_free_ char *path = NULL, *abstract = NULL;
- size_t l;
- int r;
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "path", &path);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "abstract", &abstract);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- skip_address_key(p);
- }
-
- if (!path && !abstract)
- return -EINVAL;
-
- if (path && abstract)
- return -EINVAL;
-
- if (path) {
- l = strlen(path);
- if (l > sizeof(b->sockaddr.un.sun_path))
- return -E2BIG;
-
- b->sockaddr.un.sun_family = AF_UNIX;
- strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
- b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
- } else if (abstract) {
- l = strlen(abstract);
- if (l > sizeof(b->sockaddr.un.sun_path) - 1)
- return -E2BIG;
-
- b->sockaddr.un.sun_family = AF_UNIX;
- b->sockaddr.un.sun_path[0] = 0;
- strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
- b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
- }
-
- return 0;
-}
-
-static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
- _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
- int r;
- struct addrinfo *result, hints = {
- .ai_socktype = SOCK_STREAM,
- .ai_flags = AI_ADDRCONFIG,
- };
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "host", &host);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "port", &port);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "family", &family);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- skip_address_key(p);
- }
-
- if (!host || !port)
- return -EINVAL;
-
- if (family) {
- if (streq(family, "ipv4"))
- hints.ai_family = AF_INET;
- else if (streq(family, "ipv6"))
- hints.ai_family = AF_INET6;
- else
- return -EINVAL;
- }
-
- r = getaddrinfo(host, port, &hints, &result);
- if (r == EAI_SYSTEM)
- return -errno;
- else if (r != 0)
- return -EADDRNOTAVAIL;
-
- memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
- b->sockaddr_size = result->ai_addrlen;
-
- freeaddrinfo(result);
-
- return 0;
-}
-
-static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
- char *path = NULL;
- unsigned n_argv = 0, j;
- char **argv = NULL;
- size_t allocated = 0;
- int r;
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- goto fail;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "path", &path);
- if (r < 0)
- goto fail;
- else if (r > 0)
- continue;
-
- if (startswith(*p, "argv")) {
- unsigned ul;
-
- errno = 0;
- ul = strtoul(*p + 4, (char**) p, 10);
- if (errno > 0 || **p != '=' || ul > 256) {
- r = -EINVAL;
- goto fail;
- }
-
- (*p)++;
-
- if (ul >= n_argv) {
- if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) {
- r = -ENOMEM;
- goto fail;
- }
-
- n_argv = ul + 1;
- }
-
- r = parse_address_key(p, NULL, argv + ul);
- if (r < 0)
- goto fail;
-
- continue;
- }
-
- skip_address_key(p);
- }
-
- if (!path) {
- r = -EINVAL;
- goto fail;
- }
-
- /* Make sure there are no holes in the array, with the
- * exception of argv[0] */
- for (j = 1; j < n_argv; j++)
- if (!argv[j]) {
- r = -EINVAL;
- goto fail;
- }
-
- if (argv && argv[0] == NULL) {
- argv[0] = strdup(path);
- if (!argv[0]) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- b->exec_path = path;
- b->exec_argv = argv;
- return 0;
-
-fail:
- for (j = 0; j < n_argv; j++)
- free(argv[j]);
-
- free(argv);
- free(path);
- return r;
-}
-
-static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
- _cleanup_free_ char *path = NULL;
- int r;
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "path", &path);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- skip_address_key(p);
- }
-
- if (!path)
- return -EINVAL;
-
- free(b->kernel);
- b->kernel = path;
- path = NULL;
-
- return 0;
-}
-
-static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) {
- _cleanup_free_ char *machine = NULL, *pid = NULL;
- int r;
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "machine", &machine);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "pid", &pid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- skip_address_key(p);
- }
-
- if (!machine == !pid)
- return -EINVAL;
-
- if (machine) {
- if (!machine_name_is_valid(machine))
- return -EINVAL;
-
- free(b->machine);
- b->machine = machine;
- machine = NULL;
- } else {
- b->machine = mfree(b->machine);
- }
-
- if (pid) {
- r = parse_pid(pid, &b->nspid);
- if (r < 0)
- return r;
- } else
- b->nspid = 0;
-
- b->sockaddr.un.sun_family = AF_UNIX;
- strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
- b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un);
-
- return 0;
-}
-
-static int parse_container_kernel_address(sd_bus *b, const char **p, char **guid) {
- _cleanup_free_ char *machine = NULL, *pid = NULL;
- int r;
-
- assert(b);
- assert(p);
- assert(*p);
- assert(guid);
-
- while (**p != 0 && **p != ';') {
- r = parse_address_key(p, "guid", guid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "machine", &machine);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- r = parse_address_key(p, "pid", &pid);
- if (r < 0)
- return r;
- else if (r > 0)
- continue;
-
- skip_address_key(p);
- }
-
- if (!machine == !pid)
- return -EINVAL;
-
- if (machine) {
- if (!machine_name_is_valid(machine))
- return -EINVAL;
-
- free(b->machine);
- b->machine = machine;
- machine = NULL;
- } else {
- b->machine = mfree(b->machine);
- }
-
- if (pid) {
- r = parse_pid(pid, &b->nspid);
- if (r < 0)
- return r;
- } else
- b->nspid = 0;
-
- r = free_and_strdup(&b->kernel, "/sys/fs/kdbus/0-system/bus");
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static void bus_reset_parsed_address(sd_bus *b) {
- assert(b);
-
- zero(b->sockaddr);
- b->sockaddr_size = 0;
- b->exec_argv = strv_free(b->exec_argv);
- b->exec_path = mfree(b->exec_path);
- b->server_id = SD_ID128_NULL;
- b->kernel = mfree(b->kernel);
- b->machine = mfree(b->machine);
- b->nspid = 0;
-}
-
-static int bus_parse_next_address(sd_bus *b) {
- _cleanup_free_ char *guid = NULL;
- const char *a;
- int r;
-
- assert(b);
-
- if (!b->address)
- return 0;
- if (b->address[b->address_index] == 0)
- return 0;
-
- bus_reset_parsed_address(b);
-
- a = b->address + b->address_index;
-
- while (*a != 0) {
-
- if (*a == ';') {
- a++;
- continue;
- }
-
- if (startswith(a, "unix:")) {
- a += 5;
-
- r = parse_unix_address(b, &a, &guid);
- if (r < 0)
- return r;
- break;
-
- } else if (startswith(a, "tcp:")) {
-
- a += 4;
- r = parse_tcp_address(b, &a, &guid);
- if (r < 0)
- return r;
-
- break;
-
- } else if (startswith(a, "unixexec:")) {
-
- a += 9;
- r = parse_exec_address(b, &a, &guid);
- if (r < 0)
- return r;
-
- break;
-
- } else if (startswith(a, "kernel:")) {
-
- a += 7;
- r = parse_kernel_address(b, &a, &guid);
- if (r < 0)
- return r;
-
- break;
- } else if (startswith(a, "x-machine-unix:")) {
-
- a += 15;
- r = parse_container_unix_address(b, &a, &guid);
- if (r < 0)
- return r;
-
- break;
- } else if (startswith(a, "x-machine-kernel:")) {
-
- a += 17;
- r = parse_container_kernel_address(b, &a, &guid);
- if (r < 0)
- return r;
-
- break;
- }
-
- a = strchr(a, ';');
- if (!a)
- return 0;
- }
-
- if (guid) {
- r = sd_id128_from_string(guid, &b->server_id);
- if (r < 0)
- return r;
- }
-
- b->address_index = a - b->address;
- return 1;
-}
-
-static int bus_start_address(sd_bus *b) {
- bool container_kdbus_available = false;
- bool kdbus_available = false;
- int r;
-
- assert(b);
-
- for (;;) {
- bool skipped = false;
-
- bus_close_fds(b);
-
- /*
- * Usually, if you provide multiple different bus-addresses, we
- * try all of them in order. We use the first one that
- * succeeds. However, if you mix kernel and unix addresses, we
- * never try unix-addresses if a previous kernel address was
- * tried and kdbus was available. This is required to prevent
- * clients to fallback to the bus-proxy if kdbus is available
- * but failed (eg., too many connections).
- */
-
- if (b->exec_path)
- r = bus_socket_exec(b);
- else if ((b->nspid > 0 || b->machine) && b->kernel) {
- r = bus_container_connect_kernel(b);
- if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
- container_kdbus_available = true;
-
- } else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) {
- if (!container_kdbus_available)
- r = bus_container_connect_socket(b);
- else
- skipped = true;
-
- } else if (b->kernel) {
- r = bus_kernel_connect(b);
- if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
- kdbus_available = true;
-
- } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
- if (!kdbus_available)
- r = bus_socket_connect(b);
- else
- skipped = true;
- } else
- skipped = true;
-
- if (!skipped) {
- if (r >= 0) {
- r = attach_io_events(b);
- if (r >= 0)
- return r;
- }
-
- b->last_connect_error = -r;
- }
-
- r = bus_parse_next_address(b);
- if (r < 0)
- return r;
- if (r == 0)
- return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
- }
-}
-
-int bus_next_address(sd_bus *b) {
- assert(b);
-
- bus_reset_parsed_address(b);
- return bus_start_address(b);
-}
-
-static int bus_start_fd(sd_bus *b) {
- struct stat st;
- int r;
-
- assert(b);
- assert(b->input_fd >= 0);
- assert(b->output_fd >= 0);
-
- r = fd_nonblock(b->input_fd, true);
- if (r < 0)
- return r;
-
- r = fd_cloexec(b->input_fd, true);
- if (r < 0)
- return r;
-
- if (b->input_fd != b->output_fd) {
- r = fd_nonblock(b->output_fd, true);
- if (r < 0)
- return r;
-
- r = fd_cloexec(b->output_fd, true);
- if (r < 0)
- return r;
- }
-
- if (fstat(b->input_fd, &st) < 0)
- return -errno;
-
- if (S_ISCHR(b->input_fd))
- return bus_kernel_take_fd(b);
- else
- return bus_socket_take_fd(b);
-}
-
-_public_ int sd_bus_start(sd_bus *bus) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(bus->state == BUS_UNSET, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- bus->state = BUS_OPENING;
-
- if (bus->is_server && bus->bus_client)
- return -EINVAL;
-
- if (bus->input_fd >= 0)
- r = bus_start_fd(bus);
- else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine)
- r = bus_start_address(bus);
- else
- return -EINVAL;
-
- if (r < 0) {
- sd_bus_close(bus);
- return r;
- }
-
- return bus_send_hello(bus);
-}
-
-_public_ int sd_bus_open(sd_bus **ret) {
- const char *e;
- sd_bus *b;
- int r;
-
- assert_return(ret, -EINVAL);
-
- /* Let's connect to the starter bus if it is set, and
- * otherwise to the bus that is appropropriate for the scope
- * we are running in */
-
- e = secure_getenv("DBUS_STARTER_BUS_TYPE");
- if (e) {
- if (streq(e, "system"))
- return sd_bus_open_system(ret);
- else if (STR_IN_SET(e, "session", "user"))
- return sd_bus_open_user(ret);
- }
-
- e = secure_getenv("DBUS_STARTER_ADDRESS");
- if (!e) {
- if (cg_pid_get_owner_uid(0, NULL) >= 0)
- return sd_bus_open_user(ret);
- else
- return sd_bus_open_system(ret);
- }
-
- r = sd_bus_new(&b);
- if (r < 0)
- return r;
-
- r = sd_bus_set_address(b, e);
- if (r < 0)
- goto fail;
-
- b->bus_client = true;
-
- /* We don't know whether the bus is trusted or not, so better
- * be safe, and authenticate everything */
- b->trusted = false;
- b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
- b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
-
- r = sd_bus_start(b);
- if (r < 0)
- goto fail;
-
- *ret = b;
- return 0;
-
-fail:
- bus_free(b);
- return r;
-}
-
-int bus_set_address_system(sd_bus *b) {
- const char *e;
- assert(b);
-
- e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
- if (e)
- return sd_bus_set_address(b, e);
-
- return sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_ADDRESS);
-}
-
-_public_ int sd_bus_open_system(sd_bus **ret) {
- sd_bus *b;
- int r;
-
- assert_return(ret, -EINVAL);
-
- r = sd_bus_new(&b);
- if (r < 0)
- return r;
-
- r = bus_set_address_system(b);
- if (r < 0)
- goto fail;
-
- b->bus_client = true;
- b->is_system = true;
-
- /* Let's do per-method access control on the system bus. We
- * need the caller's UID and capability set for that. */
- b->trusted = false;
- b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
- b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS;
-
- r = sd_bus_start(b);
- if (r < 0)
- goto fail;
-
- *ret = b;
- return 0;
-
-fail:
- bus_free(b);
- return r;
-}
-
-int bus_set_address_user(sd_bus *b) {
- const char *e;
- uid_t uid;
- int r;
-
- assert(b);
-
- e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
- if (e)
- return sd_bus_set_address(b, e);
-
- r = cg_pid_get_owner_uid(0, &uid);
- if (r < 0)
- uid = getuid();
-
- e = secure_getenv("XDG_RUNTIME_DIR");
- if (e) {
- _cleanup_free_ char *ee = NULL;
-
- ee = bus_address_escape(e);
- if (!ee)
- return -ENOMEM;
-
- (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, ee);
- } else
- (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, uid);
-
- if (!b->address)
- return -ENOMEM;
-
- return 0;
-}
-
-_public_ int sd_bus_open_user(sd_bus **ret) {
- sd_bus *b;
- int r;
-
- assert_return(ret, -EINVAL);
-
- r = sd_bus_new(&b);
- if (r < 0)
- return r;
-
- r = bus_set_address_user(b);
- if (r < 0)
- return r;
-
- b->bus_client = true;
- b->is_user = true;
-
- /* We don't do any per-method access control on the user
- * bus. */
- b->trusted = true;
-
- r = sd_bus_start(b);
- if (r < 0)
- goto fail;
-
- *ret = b;
- return 0;
-
-fail:
- bus_free(b);
- return r;
-}
-
-int bus_set_address_system_remote(sd_bus *b, const char *host) {
- _cleanup_free_ char *e = NULL;
- char *m = NULL, *c = NULL;
-
- assert(b);
- assert(host);
-
- /* Let's see if we shall enter some container */
- m = strchr(host, ':');
- if (m) {
- m++;
-
- /* Let's make sure this is not a port of some kind,
- * and is a valid machine name. */
- if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) {
- char *t;
-
- /* Cut out the host part */
- t = strndupa(host, m - host - 1);
- e = bus_address_escape(t);
- if (!e)
- return -ENOMEM;
-
- c = strjoina(",argv4=--machine=", m);
- }
- }
-
- if (!e) {
- e = bus_address_escape(host);
- if (!e)
- return -ENOMEM;
- }
-
- b->address = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", c, NULL);
- if (!b->address)
- return -ENOMEM;
-
- return 0;
- }
-
-_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
- sd_bus *bus;
- int r;
-
- assert_return(host, -EINVAL);
- assert_return(ret, -EINVAL);
-
- r = sd_bus_new(&bus);
- if (r < 0)
- return r;
-
- r = bus_set_address_system_remote(bus, host);
- if (r < 0)
- goto fail;
-
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
-
- r = sd_bus_start(bus);
- if (r < 0)
- goto fail;
-
- *ret = bus;
- return 0;
-
-fail:
- bus_free(bus);
- return r;
-}
-
-int bus_set_address_system_machine(sd_bus *b, const char *machine) {
- _cleanup_free_ char *e = NULL;
-
- assert(b);
- assert(machine);
-
- e = bus_address_escape(machine);
- if (!e)
- return -ENOMEM;
-
- b->address = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
- if (!b->address)
- return -ENOMEM;
-
- return 0;
-}
-
-_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
- sd_bus *bus;
- int r;
-
- assert_return(machine, -EINVAL);
- assert_return(ret, -EINVAL);
- assert_return(machine_name_is_valid(machine), -EINVAL);
-
- r = sd_bus_new(&bus);
- if (r < 0)
- return r;
-
- r = bus_set_address_system_machine(bus, machine);
- if (r < 0)
- goto fail;
-
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
-
- r = sd_bus_start(bus);
- if (r < 0)
- goto fail;
-
- *ret = bus;
- return 0;
-
-fail:
- bus_free(bus);
- return r;
-}
-
-_public_ void sd_bus_close(sd_bus *bus) {
-
- if (!bus)
- return;
- if (bus->state == BUS_CLOSED)
- return;
- if (bus_pid_changed(bus))
- return;
-
- bus->state = BUS_CLOSED;
-
- sd_bus_detach_event(bus);
-
- /* Drop all queued messages so that they drop references to
- * the bus object and the bus may be freed */
- bus_reset_queues(bus);
-
- if (!bus->is_kernel)
- bus_close_fds(bus);
-
- /* We'll leave the fd open in case this is a kernel bus, since
- * there might still be memblocks around that reference this
- * bus, and they might need to invoke the KDBUS_CMD_FREE
- * ioctl on the fd when they are freed. */
-}
-
-_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
-
- if (!bus)
- return NULL;
-
- sd_bus_flush(bus);
- sd_bus_close(bus);
-
- return sd_bus_unref(bus);
-}
-
-static void bus_enter_closing(sd_bus *bus) {
- assert(bus);
-
- if (bus->state != BUS_OPENING &&
- bus->state != BUS_AUTHENTICATING &&
- bus->state != BUS_HELLO &&
- bus->state != BUS_RUNNING)
- return;
-
- bus->state = BUS_CLOSING;
-}
-
-_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
-
- if (!bus)
- return NULL;
-
- assert_se(REFCNT_INC(bus->n_ref) >= 2);
-
- return bus;
-}
-
-_public_ sd_bus *sd_bus_unref(sd_bus *bus) {
- unsigned i;
-
- if (!bus)
- return NULL;
-
- i = REFCNT_DEC(bus->n_ref);
- if (i > 0)
- return NULL;
-
- bus_free(bus);
- return NULL;
-}
-
-_public_ int sd_bus_is_open(sd_bus *bus) {
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return BUS_IS_OPEN(bus->state);
-}
-
-_public_ int sd_bus_can_send(sd_bus *bus, char type) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(bus->state != BUS_UNSET, -ENOTCONN);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- if (type == SD_BUS_TYPE_UNIX_FD) {
- if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
- return 0;
-
- r = bus_ensure_running(bus);
- if (r < 0)
- return r;
-
- return bus->can_fds;
- }
-
- return bus_type_is_valid(type);
-}
-
-_public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(id, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- r = bus_ensure_running(bus);
- if (r < 0)
- return r;
-
- *id = bus->server_id;
- return 0;
-}
-
-static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
- assert(b);
- assert(m);
-
- if (m->sealed) {
- /* If we copy the same message to multiple
- * destinations, avoid using the same cookie
- * numbers. */
- b->cookie = MAX(b->cookie, BUS_MESSAGE_COOKIE(m));
- return 0;
- }
-
- if (timeout == 0)
- timeout = BUS_DEFAULT_TIMEOUT;
-
- return bus_message_seal(m, ++b->cookie, timeout);
-}
-
-static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
- bool remarshal = false;
-
- assert(b);
-
- /* wrong packet version */
- if (b->message_version != 0 && b->message_version != (*m)->header->version)
- remarshal = true;
-
- /* wrong packet endianness */
- if (b->message_endian != 0 && b->message_endian != (*m)->header->endian)
- remarshal = true;
-
- /* TODO: kdbus-messages received from the kernel contain data which is
- * not allowed to be passed to KDBUS_CMD_SEND. Therefore, we have to
- * force remarshaling of the message. Technically, we could just
- * recreate the kdbus message, but that is non-trivial as other parts of
- * the message refer to m->kdbus already. This should be fixed! */
- if ((*m)->kdbus && (*m)->release_kdbus)
- remarshal = true;
-
- return remarshal ? bus_message_remarshal(b, m) : 0;
-}
-
-int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) {
- assert(b);
- assert(m);
-
- /* Fake some timestamps, if they were requested, and not
- * already initialized */
- if (b->attach_flags & KDBUS_ATTACH_TIMESTAMP) {
- if (m->realtime <= 0)
- m->realtime = now(CLOCK_REALTIME);
-
- if (m->monotonic <= 0)
- m->monotonic = now(CLOCK_MONOTONIC);
- }
-
- /* The bus specification says the serial number cannot be 0,
- * 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_t) -1 rather
- * than (uint64_t) -1 since dbus1 only had 32bit identifiers,
- * even though kdbus can do 64bit. */
- return bus_message_seal(m, 0xFFFFFFFFULL, 0);
-}
-
-static int bus_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call, size_t *idx) {
- int r;
-
- assert(bus);
- assert(m);
-
- if (bus->is_kernel)
- r = bus_kernel_write_message(bus, m, hint_sync_call);
- else
- r = bus_socket_write_message(bus, m, idx);
-
- if (r <= 0)
- return r;
-
- if (bus->is_kernel || *idx >= BUS_MESSAGE_SIZE(m))
- log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s",
- bus_message_type_to_string(m->header->type),
- strna(sd_bus_message_get_sender(m)),
- strna(sd_bus_message_get_destination(m)),
- strna(sd_bus_message_get_path(m)),
- strna(sd_bus_message_get_interface(m)),
- strna(sd_bus_message_get_member(m)),
- BUS_MESSAGE_COOKIE(m),
- m->reply_cookie,
- strna(m->error.message));
-
- return r;
-}
-
-static int dispatch_wqueue(sd_bus *bus) {
- int r, ret = 0;
-
- assert(bus);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- while (bus->wqueue_size > 0) {
-
- r = bus_write_message(bus, bus->wqueue[0], false, &bus->windex);
- if (r < 0)
- return r;
- else if (r == 0)
- /* Didn't do anything this time */
- return ret;
- else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
- /* Fully written. Let's drop the entry from
- * the queue.
- *
- * This isn't particularly optimized, but
- * well, this is supposed to be our worst-case
- * buffer only, and the socket buffer is
- * supposed to be our primary buffer, and if
- * it got full, then all bets are off
- * anyway. */
-
- bus->wqueue_size--;
- sd_bus_message_unref(bus->wqueue[0]);
- memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
- bus->windex = 0;
-
- ret = 1;
- }
- }
-
- return ret;
-}
-
-static int bus_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
- assert(bus);
-
- if (bus->is_kernel)
- return bus_kernel_read_message(bus, hint_priority, priority);
- else
- return bus_socket_read_message(bus);
-}
-
-int bus_rqueue_make_room(sd_bus *bus) {
- assert(bus);
-
- if (bus->rqueue_size >= BUS_RQUEUE_MAX)
- return -ENOBUFS;
-
- if (!GREEDY_REALLOC(bus->rqueue, bus->rqueue_allocated, bus->rqueue_size + 1))
- return -ENOMEM;
-
- return 0;
-}
-
-static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) {
- int r, ret = 0;
-
- assert(bus);
- assert(m);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- /* Note that the priority logic is only available on kdbus,
- * where the rqueue is unused. We check the rqueue here
- * anyway, because it's simple... */
-
- for (;;) {
- if (bus->rqueue_size > 0) {
- /* Dispatch a queued message */
-
- *m = bus->rqueue[0];
- bus->rqueue_size--;
- memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
- return 1;
- }
-
- /* Try to read a new message */
- r = bus_read_message(bus, hint_priority, priority);
- if (r < 0)
- return r;
- if (r == 0)
- return ret;
-
- ret = 1;
- }
-}
-
-static int bus_send_internal(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie, bool hint_sync_call) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
- int r;
-
- assert_return(m, -EINVAL);
-
- if (!bus)
- bus = m->bus;
-
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (m->n_fds > 0) {
- r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
- if (r < 0)
- return r;
- if (r == 0)
- return -EOPNOTSUPP;
- }
-
- /* If the cookie number isn't kept, then we know that no reply
- * is expected */
- if (!cookie && !m->sealed)
- m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED;
-
- r = bus_seal_message(bus, m, 0);
- if (r < 0)
- return r;
-
- /* Remarshall if we have to. This will possibly unref the
- * message and place a replacement in m */
- r = bus_remarshal_message(bus, &m);
- if (r < 0)
- return r;
-
- /* If this is a reply and no reply was requested, then let's
- * suppress this, if we can */
- if (m->dont_send)
- goto finish;
-
- if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
- size_t idx = 0;
-
- r = bus_write_message(bus, m, hint_sync_call, &idx);
- if (r < 0) {
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- return -ECONNRESET;
- }
-
- return r;
- }
-
- if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
- /* Wasn't fully written. So let's remember how
- * much was written. Note that the first entry
- * of the wqueue array is always allocated so
- * that we always can remember how much was
- * written. */
- bus->wqueue[0] = sd_bus_message_ref(m);
- bus->wqueue_size = 1;
- bus->windex = idx;
- }
-
- } else {
- /* Just append it to the queue. */
-
- if (bus->wqueue_size >= BUS_WQUEUE_MAX)
- return -ENOBUFS;
-
- if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
- return -ENOMEM;
-
- bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m);
- }
-
-finish:
- if (cookie)
- *cookie = BUS_MESSAGE_COOKIE(m);
-
- return 1;
-}
-
-_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) {
- return bus_send_internal(bus, m, cookie, false);
-}
-
-_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) {
- int r;
-
- assert_return(m, -EINVAL);
-
- if (!bus)
- bus = m->bus;
-
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (!streq_ptr(m->destination, destination)) {
-
- if (!destination)
- return -EEXIST;
-
- r = sd_bus_message_set_destination(m, destination);
- if (r < 0)
- return r;
- }
-
- return sd_bus_send(bus, m, cookie);
-}
-
-static usec_t calc_elapse(uint64_t usec) {
- if (usec == (uint64_t) -1)
- return 0;
-
- return now(CLOCK_MONOTONIC) + usec;
-}
-
-static int timeout_compare(const void *a, const void *b) {
- const struct reply_callback *x = a, *y = b;
-
- if (x->timeout != 0 && y->timeout == 0)
- return -1;
-
- if (x->timeout == 0 && y->timeout != 0)
- return 1;
-
- if (x->timeout < y->timeout)
- return -1;
-
- if (x->timeout > y->timeout)
- return 1;
-
- return 0;
-}
-
-_public_ int sd_bus_call_async(
- sd_bus *bus,
- sd_bus_slot **slot,
- sd_bus_message *_m,
- sd_bus_message_handler_t callback,
- void *userdata,
- uint64_t usec) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
- _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL;
- int r;
-
- assert_return(m, -EINVAL);
- assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
- assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
- assert_return(callback, -EINVAL);
-
- if (!bus)
- bus = m->bus;
-
- assert_return(!bus_pid_changed(bus), -ECHILD);
- assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- r = ordered_hashmap_ensure_allocated(&bus->reply_callbacks, &uint64_hash_ops);
- if (r < 0)
- return r;
-
- r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
- if (r < 0)
- return r;
-
- r = bus_seal_message(bus, m, usec);
- if (r < 0)
- return r;
-
- r = bus_remarshal_message(bus, &m);
- if (r < 0)
- return r;
-
- s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata);
- if (!s)
- return -ENOMEM;
-
- s->reply_callback.callback = callback;
-
- s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m);
- r = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback);
- if (r < 0) {
- s->reply_callback.cookie = 0;
- return r;
- }
-
- s->reply_callback.timeout = calc_elapse(m->timeout);
- if (s->reply_callback.timeout != 0) {
- r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx);
- if (r < 0) {
- s->reply_callback.timeout = 0;
- return r;
- }
- }
-
- r = sd_bus_send(bus, m, &s->reply_callback.cookie);
- if (r < 0)
- return r;
-
- if (slot)
- *slot = s;
- s = NULL;
-
- return r;
-}
-
-int bus_ensure_running(sd_bus *bus) {
- int r;
-
- assert(bus);
-
- if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING)
- return -ENOTCONN;
- if (bus->state == BUS_RUNNING)
- return 1;
-
- for (;;) {
- r = sd_bus_process(bus, NULL);
- if (r < 0)
- return r;
- if (bus->state == BUS_RUNNING)
- return 1;
- if (r > 0)
- continue;
-
- r = sd_bus_wait(bus, (uint64_t) -1);
- if (r < 0)
- return r;
- }
-}
-
-_public_ int sd_bus_call(
- sd_bus *bus,
- sd_bus_message *_m,
- uint64_t usec,
- sd_bus_error *error,
- sd_bus_message **reply) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m);
- usec_t timeout;
- uint64_t cookie;
- unsigned i;
- int r;
-
- bus_assert_return(m, -EINVAL, error);
- bus_assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL, error);
- bus_assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL, error);
- bus_assert_return(!bus_error_is_dirty(error), -EINVAL, error);
-
- if (!bus)
- bus = m->bus;
-
- bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
- bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error);
-
- if (!BUS_IS_OPEN(bus->state)) {
- r = -ENOTCONN;
- goto fail;
- }
-
- r = bus_ensure_running(bus);
- if (r < 0)
- goto fail;
-
- i = bus->rqueue_size;
-
- r = bus_seal_message(bus, m, usec);
- if (r < 0)
- goto fail;
-
- r = bus_remarshal_message(bus, &m);
- if (r < 0)
- goto fail;
-
- r = bus_send_internal(bus, m, &cookie, true);
- if (r < 0)
- goto fail;
-
- timeout = calc_elapse(m->timeout);
-
- for (;;) {
- usec_t left;
-
- while (i < bus->rqueue_size) {
- sd_bus_message *incoming = NULL;
-
- incoming = bus->rqueue[i];
-
- if (incoming->reply_cookie == cookie) {
- /* Found a match! */
-
- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
- bus->rqueue_size--;
- log_debug_bus_message(incoming);
-
- if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
-
- if (incoming->n_fds <= 0 || (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
- if (reply)
- *reply = incoming;
- else
- sd_bus_message_unref(incoming);
-
- return 1;
- }
-
- r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
- sd_bus_message_unref(incoming);
- return r;
-
- } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
- r = sd_bus_error_copy(error, &incoming->error);
- sd_bus_message_unref(incoming);
- return r;
- } else {
- r = -EIO;
- goto fail;
- }
-
- } else if (BUS_MESSAGE_COOKIE(incoming) == cookie &&
- bus->unique_name &&
- incoming->sender &&
- streq(bus->unique_name, incoming->sender)) {
-
- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
- bus->rqueue_size--;
-
- /* Our own message? Somebody is trying
- * to send its own client a message,
- * let's not dead-lock, let's fail
- * immediately. */
-
- sd_bus_message_unref(incoming);
- r = -ELOOP;
- goto fail;
- }
-
- /* Try to read more, right-away */
- i++;
- }
-
- r = bus_read_message(bus, false, 0);
- if (r < 0) {
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = -ECONNRESET;
- }
-
- goto fail;
- }
- if (r > 0)
- continue;
-
- if (timeout > 0) {
- usec_t n;
-
- n = now(CLOCK_MONOTONIC);
- if (n >= timeout) {
- r = -ETIMEDOUT;
- goto fail;
- }
-
- left = timeout - n;
- } else
- left = (uint64_t) -1;
-
- r = bus_poll(bus, true, left);
- if (r < 0)
- goto fail;
- if (r == 0) {
- r = -ETIMEDOUT;
- goto fail;
- }
-
- r = dispatch_wqueue(bus);
- if (r < 0) {
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = -ECONNRESET;
- }
-
- goto fail;
- }
- }
-
-fail:
- return sd_bus_error_set_errno(error, r);
-}
-
-_public_ int sd_bus_get_fd(sd_bus *bus) {
-
- assert_return(bus, -EINVAL);
- assert_return(bus->input_fd == bus->output_fd, -EPERM);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return bus->input_fd;
-}
-
-_public_ int sd_bus_get_events(sd_bus *bus) {
- int flags = 0;
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state) && bus->state != BUS_CLOSING)
- return -ENOTCONN;
-
- if (bus->state == BUS_OPENING)
- flags |= POLLOUT;
- else if (bus->state == BUS_AUTHENTICATING) {
-
- if (bus_socket_auth_needs_write(bus))
- flags |= POLLOUT;
-
- flags |= POLLIN;
-
- } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
- if (bus->rqueue_size <= 0)
- flags |= POLLIN;
- if (bus->wqueue_size > 0)
- flags |= POLLOUT;
- }
-
- return flags;
-}
-
-_public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
- struct reply_callback *c;
-
- assert_return(bus, -EINVAL);
- assert_return(timeout_usec, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!BUS_IS_OPEN(bus->state) && bus->state != BUS_CLOSING)
- return -ENOTCONN;
-
- if (bus->track_queue) {
- *timeout_usec = 0;
- return 1;
- }
-
- if (bus->state == BUS_CLOSING) {
- *timeout_usec = 0;
- return 1;
- }
-
- if (bus->state == BUS_AUTHENTICATING) {
- *timeout_usec = bus->auth_timeout;
- return 1;
- }
-
- if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
- *timeout_usec = (uint64_t) -1;
- return 0;
- }
-
- if (bus->rqueue_size > 0) {
- *timeout_usec = 0;
- return 1;
- }
-
- c = prioq_peek(bus->reply_callbacks_prioq);
- if (!c) {
- *timeout_usec = (uint64_t) -1;
- return 0;
- }
-
- if (c->timeout == 0) {
- *timeout_usec = (uint64_t) -1;
- return 0;
- }
-
- *timeout_usec = c->timeout;
- return 1;
-}
-
-static int process_timeout(sd_bus *bus) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL;
- struct reply_callback *c;
- sd_bus_slot *slot;
- usec_t n;
- int r;
-
- assert(bus);
-
- c = prioq_peek(bus->reply_callbacks_prioq);
- if (!c)
- return 0;
-
- n = now(CLOCK_MONOTONIC);
- if (c->timeout > n)
- return 0;
-
- r = bus_message_new_synthetic_error(
- bus,
- c->cookie,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out"),
- &m);
- if (r < 0)
- return r;
-
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
-
- assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
- c->timeout = 0;
-
- ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
- c->cookie = 0;
-
- slot = container_of(c, sd_bus_slot, reply_callback);
-
- bus->iteration_counter++;
-
- bus->current_message = m;
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = NULL;
- bus->current_message = NULL;
-
- if (slot->floating) {
- bus_slot_disconnect(slot);
- sd_bus_slot_unref(slot);
- }
-
- sd_bus_slot_unref(slot);
-
- return bus_maybe_reply_error(m, r, &error_buffer);
-}
-
-static int process_hello(sd_bus *bus, sd_bus_message *m) {
- assert(bus);
- assert(m);
-
- if (bus->state != BUS_HELLO)
- return 0;
-
- /* Let's make sure the first message on the bus is the HELLO
- * reply. But note that we don't actually parse the message
- * here (we leave that to the usual handling), we just verify
- * we don't let any earlier msg through. */
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
- m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
- return -EIO;
-
- if (m->reply_cookie != 1)
- return -EIO;
-
- return 0;
-}
-
-static int process_reply(sd_bus *bus, sd_bus_message *m) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *synthetic_reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- struct reply_callback *c;
- sd_bus_slot *slot;
- int r;
-
- assert(bus);
- assert(m);
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
- m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
- return 0;
-
- if (bus->is_kernel && (bus->hello_flags & KDBUS_HELLO_MONITOR))
- return 0;
-
- if (m->destination && bus->unique_name && !streq_ptr(m->destination, bus->unique_name))
- return 0;
-
- c = ordered_hashmap_remove(bus->reply_callbacks, &m->reply_cookie);
- if (!c)
- return 0;
-
- c->cookie = 0;
-
- slot = container_of(c, sd_bus_slot, reply_callback);
-
- if (m->n_fds > 0 && !(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
-
- /* If the reply contained a file descriptor which we
- * didn't want we pass an error instead. */
-
- r = bus_message_new_synthetic_error(
- bus,
- m->reply_cookie,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"),
- &synthetic_reply);
- if (r < 0)
- return r;
-
- /* Copy over original timestamp */
- synthetic_reply->realtime = m->realtime;
- synthetic_reply->monotonic = m->monotonic;
- synthetic_reply->seqnum = m->seqnum;
-
- r = bus_seal_synthetic_message(bus, synthetic_reply);
- if (r < 0)
- return r;
-
- m = synthetic_reply;
- } else {
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
- }
-
- if (c->timeout != 0) {
- prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
- }
-
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = NULL;
-
- if (slot->floating) {
- bus_slot_disconnect(slot);
- sd_bus_slot_unref(slot);
- }
-
- sd_bus_slot_unref(slot);
-
- return bus_maybe_reply_error(m, r, &error_buffer);
-}
-
-static int process_filter(sd_bus *bus, sd_bus_message *m) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- struct filter_callback *l;
- int r;
-
- assert(bus);
- assert(m);
-
- do {
- bus->filter_callbacks_modified = false;
-
- LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
- sd_bus_slot *slot;
-
- if (bus->filter_callbacks_modified)
- break;
-
- /* Don't run this more than once per iteration */
- if (l->last_iteration == bus->iteration_counter)
- continue;
-
- l->last_iteration = bus->iteration_counter;
-
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- slot = container_of(l, sd_bus_slot, filter_callback);
-
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = l->callback;
- bus->current_userdata = slot->userdata;
- r = l->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = sd_bus_slot_unref(slot);
-
- r = bus_maybe_reply_error(m, r, &error_buffer);
- if (r != 0)
- return r;
-
- }
-
- } while (bus->filter_callbacks_modified);
-
- return 0;
-}
-
-static int process_match(sd_bus *bus, sd_bus_message *m) {
- int r;
-
- assert(bus);
- assert(m);
-
- do {
- bus->match_callbacks_modified = false;
-
- r = bus_match_run(bus, &bus->match_callbacks, m);
- if (r != 0)
- return r;
-
- } while (bus->match_callbacks_modified);
-
- return 0;
-}
-
-static int process_builtin(sd_bus *bus, sd_bus_message *m) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- int r;
-
- assert(bus);
- assert(m);
-
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- if (bus->manual_peer_interface)
- return 0;
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
- return 0;
-
- if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
- return 0;
-
- if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
- return 1;
-
- if (streq_ptr(m->member, "Ping"))
- r = sd_bus_message_new_method_return(m, &reply);
- else if (streq_ptr(m->member, "GetMachineId")) {
- sd_id128_t id;
- char sid[33];
-
- r = sd_id128_get_machine(&id);
- if (r < 0)
- return r;
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
- } else {
- r = sd_bus_message_new_method_errorf(
- m, &reply,
- SD_BUS_ERROR_UNKNOWN_METHOD,
- "Unknown method '%s' on interface '%s'.", m->member, m->interface);
- }
-
- if (r < 0)
- return r;
-
- r = sd_bus_send(bus, reply, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int process_fd_check(sd_bus *bus, sd_bus_message *m) {
- assert(bus);
- assert(m);
-
- /* If we got a message with a file descriptor which we didn't
- * want to accept, then let's drop it. How can this even
- * happen? For example, when the kernel queues a message into
- * an activatable names's queue which allows fds, and then is
- * delivered to us later even though we ourselves did not
- * negotiate it. */
-
- if (bus->hello_flags & KDBUS_HELLO_MONITOR)
- return 0;
-
- if (m->n_fds <= 0)
- return 0;
-
- if (bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)
- return 0;
-
- if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
- return 1; /* just eat it up */
-
- return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Message contains file descriptors, which I cannot accept. Sorry.");
-}
-
-static int process_message(sd_bus *bus, sd_bus_message *m) {
- int r;
-
- assert(bus);
- assert(m);
-
- bus->current_message = m;
- bus->iteration_counter++;
-
- log_debug_bus_message(m);
-
- r = process_hello(bus, m);
- if (r != 0)
- goto finish;
-
- r = process_reply(bus, m);
- if (r != 0)
- goto finish;
-
- r = process_fd_check(bus, m);
- if (r != 0)
- goto finish;
-
- r = process_filter(bus, m);
- if (r != 0)
- goto finish;
-
- r = process_match(bus, m);
- if (r != 0)
- goto finish;
-
- r = process_builtin(bus, m);
- if (r != 0)
- goto finish;
-
- r = bus_process_object(bus, m);
-
-finish:
- bus->current_message = NULL;
- return r;
-}
-
-static int dispatch_track(sd_bus *bus) {
- assert(bus);
-
- if (!bus->track_queue)
- return 0;
-
- bus_track_dispatch(bus->track_queue);
- return 1;
-}
-
-static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- int r;
-
- assert(bus);
- assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
-
- r = process_timeout(bus);
- if (r != 0)
- goto null_message;
-
- r = dispatch_wqueue(bus);
- if (r != 0)
- goto null_message;
-
- r = dispatch_track(bus);
- if (r != 0)
- goto null_message;
-
- r = dispatch_rqueue(bus, hint_priority, priority, &m);
- if (r < 0)
- return r;
- if (!m)
- goto null_message;
-
- r = process_message(bus, m);
- if (r != 0)
- goto null_message;
-
- if (ret) {
- r = sd_bus_message_rewind(m, true);
- if (r < 0)
- return r;
-
- *ret = m;
- m = NULL;
- return 1;
- }
-
- if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) {
-
- log_debug("Unprocessed message call sender=%s object=%s interface=%s member=%s",
- strna(sd_bus_message_get_sender(m)),
- strna(sd_bus_message_get_path(m)),
- strna(sd_bus_message_get_interface(m)),
- strna(sd_bus_message_get_member(m)));
-
- r = sd_bus_reply_method_errorf(
- m,
- SD_BUS_ERROR_UNKNOWN_OBJECT,
- "Unknown object '%s'.", m->path);
- if (r < 0)
- return r;
- }
-
- return 1;
-
-null_message:
- if (r >= 0 && ret)
- *ret = NULL;
-
- return r;
-}
-
-static int bus_exit_now(sd_bus *bus) {
- assert(bus);
-
- /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
- * sd_event_exit(), otherwise invokes libc exit(). */
-
- if (bus->exited) /* did we already exit? */
- return 0;
- if (!bus->exit_triggered) /* was the exit condition triggered? */
- return 0;
- if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */
- return 0;
-
- bus->exited = true; /* never exit more than once */
-
- log_debug("Bus connection disconnected, exiting.");
-
- if (bus->event)
- return sd_event_exit(bus->event, EXIT_FAILURE);
- else
- exit(EXIT_FAILURE);
-
- assert_not_reached("exit() didn't exit?");
-}
-
-static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- sd_bus_slot *slot;
- int r;
-
- assert(bus);
- assert(c);
-
- r = bus_message_new_synthetic_error(
- bus,
- c->cookie,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
- &m);
- if (r < 0)
- return r;
-
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
-
- if (c->timeout != 0) {
- prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
- }
-
- ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
- c->cookie = 0;
-
- slot = container_of(c, sd_bus_slot, reply_callback);
-
- bus->iteration_counter++;
-
- bus->current_message = m;
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = NULL;
- bus->current_message = NULL;
-
- if (slot->floating) {
- bus_slot_disconnect(slot);
- sd_bus_slot_unref(slot);
- }
-
- sd_bus_slot_unref(slot);
-
- return bus_maybe_reply_error(m, r, &error_buffer);
-}
-
-static int process_closing(sd_bus *bus, sd_bus_message **ret) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct reply_callback *c;
- int r;
-
- assert(bus);
- assert(bus->state == BUS_CLOSING);
-
- /* First, fail all outstanding method calls */
- c = ordered_hashmap_first(bus->reply_callbacks);
- if (c)
- return process_closing_reply_callback(bus, c);
-
- /* Then, fake-drop all remaining bus tracking references */
- if (bus->tracks) {
- bus_track_close(bus->tracks);
- return 1;
- }
-
- /* Then, synthesize a Disconnected message */
- r = sd_bus_message_new_signal(
- bus,
- &m,
- "/org/freedesktop/DBus/Local",
- "org.freedesktop.DBus.Local",
- "Disconnected");
- if (r < 0)
- return r;
-
- bus_message_set_sender_local(bus, m);
-
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
-
- sd_bus_close(bus);
-
- bus->current_message = m;
- bus->iteration_counter++;
-
- r = process_filter(bus, m);
- if (r != 0)
- goto finish;
-
- r = process_match(bus, m);
- if (r != 0)
- goto finish;
-
- /* Nothing else to do, exit now, if the condition holds */
- bus->exit_triggered = true;
- (void) bus_exit_now(bus);
-
- if (ret) {
- *ret = m;
- m = NULL;
- }
-
- r = 1;
-
-finish:
- bus->current_message = NULL;
-
- return r;
-}
-
-static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) {
- BUS_DONT_DESTROY(bus);
- int r;
-
- /* Returns 0 when we didn't do anything. This should cause the
- * caller to invoke sd_bus_wait() before returning the next
- * time. Returns > 0 when we did something, which possibly
- * means *ret is filled in with an unprocessed message. */
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- /* We don't allow recursively invoking sd_bus_process(). */
- assert_return(!bus->current_message, -EBUSY);
- assert(!bus->current_slot);
-
- switch (bus->state) {
-
- case BUS_UNSET:
- return -ENOTCONN;
-
- case BUS_CLOSED:
- return -ECONNRESET;
-
- case BUS_OPENING:
- r = bus_socket_process_opening(bus);
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = 1;
- } else if (r < 0)
- return r;
- if (ret)
- *ret = NULL;
- return r;
-
- case BUS_AUTHENTICATING:
- r = bus_socket_process_authenticating(bus);
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = 1;
- } else if (r < 0)
- return r;
-
- if (ret)
- *ret = NULL;
-
- return r;
-
- case BUS_RUNNING:
- case BUS_HELLO:
- r = process_running(bus, hint_priority, priority, ret);
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- r = 1;
-
- if (ret)
- *ret = NULL;
- }
-
- return r;
-
- case BUS_CLOSING:
- return process_closing(bus, ret);
- }
-
- assert_not_reached("Unknown state");
-}
-
-_public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
- return bus_process_internal(bus, false, 0, ret);
-}
-
-_public_ int sd_bus_process_priority(sd_bus *bus, int64_t priority, sd_bus_message **ret) {
- return bus_process_internal(bus, true, priority, ret);
-}
-
-static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
- struct pollfd p[2] = {};
- int r, e, n;
- struct timespec ts;
- usec_t m = USEC_INFINITY;
-
- assert(bus);
-
- if (bus->state == BUS_CLOSING)
- return 1;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- e = sd_bus_get_events(bus);
- if (e < 0)
- return e;
-
- if (need_more)
- /* The caller really needs some more data, he doesn't
- * care about what's already read, or any timeouts
- * except its own. */
- e |= POLLIN;
- else {
- usec_t until;
- /* The caller wants to process if there's something to
- * process, but doesn't care otherwise */
-
- r = sd_bus_get_timeout(bus, &until);
- if (r < 0)
- return r;
- if (r > 0) {
- usec_t nw;
- nw = now(CLOCK_MONOTONIC);
- m = until > nw ? until - nw : 0;
- }
- }
-
- if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
- m = timeout_usec;
-
- p[0].fd = bus->input_fd;
- if (bus->output_fd == bus->input_fd) {
- p[0].events = e;
- n = 1;
- } else {
- p[0].events = e & POLLIN;
- p[1].fd = bus->output_fd;
- p[1].events = e & POLLOUT;
- n = 2;
- }
-
- r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
- if (r < 0)
- return -errno;
-
- return r > 0 ? 1 : 0;
-}
-
-_public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (bus->state == BUS_CLOSING)
- return 0;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->rqueue_size > 0)
- return 0;
-
- return bus_poll(bus, false, timeout_usec);
-}
-
-_public_ int sd_bus_flush(sd_bus *bus) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (bus->state == BUS_CLOSING)
- return 0;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- r = bus_ensure_running(bus);
- if (r < 0)
- return r;
-
- if (bus->wqueue_size <= 0)
- return 0;
-
- for (;;) {
- r = dispatch_wqueue(bus);
- if (r < 0) {
- if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) {
- bus_enter_closing(bus);
- return -ECONNRESET;
- }
-
- return r;
- }
-
- if (bus->wqueue_size <= 0)
- return 0;
-
- r = bus_poll(bus, false, (uint64_t) -1);
- if (r < 0)
- return r;
- }
-}
-
-_public_ int sd_bus_add_filter(
- sd_bus *bus,
- sd_bus_slot **slot,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- sd_bus_slot *s;
-
- assert_return(bus, -EINVAL);
- assert_return(callback, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- s = bus_slot_allocate(bus, !slot, BUS_FILTER_CALLBACK, sizeof(struct filter_callback), userdata);
- if (!s)
- return -ENOMEM;
-
- s->filter_callback.callback = callback;
-
- bus->filter_callbacks_modified = true;
- LIST_PREPEND(callbacks, bus->filter_callbacks, &s->filter_callback);
-
- if (slot)
- *slot = s;
-
- return 0;
-}
-
-_public_ int sd_bus_add_match(
- sd_bus *bus,
- sd_bus_slot **slot,
- const char *match,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- struct bus_match_component *components = NULL;
- unsigned n_components = 0;
- sd_bus_slot *s = NULL;
- int r = 0;
-
- assert_return(bus, -EINVAL);
- assert_return(match, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- r = bus_match_parse(match, &components, &n_components);
- if (r < 0)
- goto finish;
-
- s = bus_slot_allocate(bus, !slot, BUS_MATCH_CALLBACK, sizeof(struct match_callback), userdata);
- if (!s) {
- r = -ENOMEM;
- goto finish;
- }
-
- s->match_callback.callback = callback;
- s->match_callback.cookie = ++bus->match_cookie;
-
- if (bus->bus_client) {
- enum bus_match_scope scope;
-
- scope = bus_match_get_scope(components, n_components);
-
- /* Do not install server-side matches for matches
- * against the local service, interface or bus
- * path. */
- if (scope != BUS_MATCH_LOCAL) {
-
- if (!bus->is_kernel) {
- /* When this is not a kernel transport, we
- * store the original match string, so that we
- * can use it to remove the match again */
-
- s->match_callback.match_string = strdup(match);
- if (!s->match_callback.match_string) {
- r = -ENOMEM;
- goto finish;
- }
- }
-
- r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie);
- if (r < 0)
- goto finish;
-
- s->match_added = true;
- }
- }
-
- bus->match_callbacks_modified = true;
- r = bus_match_add(&bus->match_callbacks, components, n_components, &s->match_callback);
- if (r < 0)
- goto finish;
-
- if (slot)
- *slot = s;
- s = NULL;
-
-finish:
- bus_match_parse_free(components, n_components);
- sd_bus_slot_unref(s);
-
- return r;
-}
-
-int bus_remove_match_by_string(
- sd_bus *bus,
- const char *match,
- sd_bus_message_handler_t callback,
- void *userdata) {
-
- struct bus_match_component *components = NULL;
- unsigned n_components = 0;
- struct match_callback *c;
- int r = 0;
-
- assert_return(bus, -EINVAL);
- assert_return(match, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- r = bus_match_parse(match, &components, &n_components);
- if (r < 0)
- goto finish;
-
- r = bus_match_find(&bus->match_callbacks, components, n_components, NULL, NULL, &c);
- if (r <= 0)
- goto finish;
-
- sd_bus_slot_unref(container_of(c, sd_bus_slot, match_callback));
-
-finish:
- bus_match_parse_free(components, n_components);
-
- return r;
-}
-
-bool bus_pid_changed(sd_bus *bus) {
- assert(bus);
-
- /* We don't support people creating a bus connection and
- * keeping it around over a fork(). Let's complain. */
-
- return bus->original_pid != getpid();
-}
-
-static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- sd_bus *bus = userdata;
- int r;
-
- assert(bus);
-
- r = sd_bus_process(bus, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
- sd_bus *bus = userdata;
- int r;
-
- assert(bus);
-
- r = sd_bus_process(bus, NULL);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int prepare_callback(sd_event_source *s, void *userdata) {
- sd_bus *bus = userdata;
- int r, e;
- usec_t until;
-
- assert(s);
- assert(bus);
-
- e = sd_bus_get_events(bus);
- if (e < 0)
- return e;
-
- if (bus->output_fd != bus->input_fd) {
-
- r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT);
- if (r < 0)
- return r;
- } else {
- r = sd_event_source_set_io_events(bus->input_io_event_source, e);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_get_timeout(bus, &until);
- if (r < 0)
- return r;
- if (r > 0) {
- int j;
-
- j = sd_event_source_set_time(bus->time_event_source, until);
- if (j < 0)
- return j;
- }
-
- r = sd_event_source_set_enabled(bus->time_event_source, r > 0);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-static int quit_callback(sd_event_source *event, void *userdata) {
- sd_bus *bus = userdata;
-
- assert(event);
-
- sd_bus_flush(bus);
- sd_bus_close(bus);
-
- return 1;
-}
-
-static int attach_io_events(sd_bus *bus) {
- int r;
-
- assert(bus);
-
- if (bus->input_fd < 0)
- return 0;
-
- if (!bus->event)
- return 0;
-
- if (!bus->input_io_event_source) {
- r = sd_event_add_io(bus->event, &bus->input_io_event_source, bus->input_fd, 0, io_callback, bus);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_prepare(bus->input_io_event_source, prepare_callback);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(bus->input_io_event_source, bus->event_priority);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_description(bus->input_io_event_source, "bus-input");
- } else
- r = sd_event_source_set_io_fd(bus->input_io_event_source, bus->input_fd);
-
- if (r < 0)
- return r;
-
- if (bus->output_fd != bus->input_fd) {
- assert(bus->output_fd >= 0);
-
- if (!bus->output_io_event_source) {
- r = sd_event_add_io(bus->event, &bus->output_io_event_source, bus->output_fd, 0, io_callback, bus);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(bus->output_io_event_source, bus->event_priority);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_description(bus->input_io_event_source, "bus-output");
- } else
- r = sd_event_source_set_io_fd(bus->output_io_event_source, bus->output_fd);
-
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static void detach_io_events(sd_bus *bus) {
- assert(bus);
-
- if (bus->input_io_event_source) {
- sd_event_source_set_enabled(bus->input_io_event_source, SD_EVENT_OFF);
- bus->input_io_event_source = sd_event_source_unref(bus->input_io_event_source);
- }
-
- if (bus->output_io_event_source) {
- sd_event_source_set_enabled(bus->output_io_event_source, SD_EVENT_OFF);
- bus->output_io_event_source = sd_event_source_unref(bus->output_io_event_source);
- }
-}
-
-_public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(!bus->event, -EBUSY);
-
- assert(!bus->input_io_event_source);
- assert(!bus->output_io_event_source);
- assert(!bus->time_event_source);
-
- if (event)
- bus->event = sd_event_ref(event);
- else {
- r = sd_event_default(&bus->event);
- if (r < 0)
- return r;
- }
-
- bus->event_priority = priority;
-
- r = sd_event_add_time(bus->event, &bus->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, bus);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_priority(bus->time_event_source, priority);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_description(bus->time_event_source, "bus-time");
- if (r < 0)
- goto fail;
-
- r = sd_event_add_exit(bus->event, &bus->quit_event_source, quit_callback, bus);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_description(bus->quit_event_source, "bus-exit");
- if (r < 0)
- goto fail;
-
- r = attach_io_events(bus);
- if (r < 0)
- goto fail;
-
- return 0;
-
-fail:
- sd_bus_detach_event(bus);
- return r;
-}
-
-_public_ int sd_bus_detach_event(sd_bus *bus) {
- assert_return(bus, -EINVAL);
-
- if (!bus->event)
- return 0;
-
- detach_io_events(bus);
-
- if (bus->time_event_source) {
- sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF);
- bus->time_event_source = sd_event_source_unref(bus->time_event_source);
- }
-
- if (bus->quit_event_source) {
- sd_event_source_set_enabled(bus->quit_event_source, SD_EVENT_OFF);
- bus->quit_event_source = sd_event_source_unref(bus->quit_event_source);
- }
-
- bus->event = sd_event_unref(bus->event);
- return 1;
-}
-
-_public_ sd_event* sd_bus_get_event(sd_bus *bus) {
- assert_return(bus, NULL);
-
- return bus->event;
-}
-
-_public_ sd_bus_message* sd_bus_get_current_message(sd_bus *bus) {
- assert_return(bus, NULL);
-
- return bus->current_message;
-}
-
-_public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) {
- assert_return(bus, NULL);
-
- return bus->current_slot;
-}
-
-_public_ sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus) {
- assert_return(bus, NULL);
-
- return bus->current_handler;
-}
-
-_public_ void* sd_bus_get_current_userdata(sd_bus *bus) {
- assert_return(bus, NULL);
-
- return bus->current_userdata;
-}
-
-static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) {
- sd_bus *b = NULL;
- int r;
-
- assert(bus_open);
- assert(default_bus);
-
- if (!ret)
- return !!*default_bus;
-
- if (*default_bus) {
- *ret = sd_bus_ref(*default_bus);
- return 0;
- }
-
- r = bus_open(&b);
- if (r < 0)
- return r;
-
- b->default_bus_ptr = default_bus;
- b->tid = gettid();
- *default_bus = b;
-
- *ret = b;
- return 1;
-}
-
-_public_ int sd_bus_default_system(sd_bus **ret) {
- return bus_default(sd_bus_open_system, &default_system_bus, ret);
-}
-
-
-_public_ int sd_bus_default_user(sd_bus **ret) {
- return bus_default(sd_bus_open_user, &default_user_bus, ret);
-}
-
-_public_ int sd_bus_default(sd_bus **ret) {
-
- const char *e;
-
- /* Let's try our best to reuse another cached connection. If
- * the starter bus type is set, connect via our normal
- * connection logic, ignoring $DBUS_STARTER_ADDRESS, so that
- * we can share the connection with the user/system default
- * bus. */
-
- e = secure_getenv("DBUS_STARTER_BUS_TYPE");
- if (e) {
- if (streq(e, "system"))
- return sd_bus_default_system(ret);
- else if (STR_IN_SET(e, "user", "session"))
- return sd_bus_default_user(ret);
- }
-
- /* No type is specified, so we have not other option than to
- * use the starter address if it is set. */
-
- e = secure_getenv("DBUS_STARTER_ADDRESS");
- if (e) {
-
- return bus_default(sd_bus_open, &default_starter_bus, ret);
- }
-
- /* Finally, if nothing is set use the cached connection for
- * the right scope */
-
- if (cg_pid_get_owner_uid(0, NULL) >= 0)
- return sd_bus_default_user(ret);
- else
- return sd_bus_default_system(ret);
-}
-
-_public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) {
- assert_return(b, -EINVAL);
- assert_return(tid, -EINVAL);
- assert_return(!bus_pid_changed(b), -ECHILD);
-
- if (b->tid != 0) {
- *tid = b->tid;
- return 0;
- }
-
- if (b->event)
- return sd_event_get_tid(b->event, tid);
-
- return -ENXIO;
-}
-
-_public_ int sd_bus_path_encode(const char *prefix, const char *external_id, char **ret_path) {
- _cleanup_free_ char *e = NULL;
- char *ret;
-
- assert_return(object_path_is_valid(prefix), -EINVAL);
- assert_return(external_id, -EINVAL);
- assert_return(ret_path, -EINVAL);
-
- e = bus_label_escape(external_id);
- if (!e)
- return -ENOMEM;
-
- ret = strjoin(prefix, "/", e, NULL);
- if (!ret)
- return -ENOMEM;
-
- *ret_path = ret;
- return 0;
-}
-
-_public_ int sd_bus_path_decode(const char *path, const char *prefix, char **external_id) {
- const char *e;
- char *ret;
-
- assert_return(object_path_is_valid(path), -EINVAL);
- assert_return(object_path_is_valid(prefix), -EINVAL);
- assert_return(external_id, -EINVAL);
-
- e = object_path_startswith(path, prefix);
- if (!e) {
- *external_id = NULL;
- return 0;
- }
-
- ret = bus_label_unescape(e);
- if (!ret)
- return -ENOMEM;
-
- *external_id = ret;
- return 1;
-}
-
-_public_ int sd_bus_path_encode_many(char **out, const char *path_template, ...) {
- _cleanup_strv_free_ char **labels = NULL;
- char *path, *path_pos, **label_pos;
- const char *sep, *template_pos;
- size_t path_length;
- va_list list;
- int r;
-
- assert_return(out, -EINVAL);
- assert_return(path_template, -EINVAL);
-
- path_length = strlen(path_template);
-
- va_start(list, path_template);
- for (sep = strchr(path_template, '%'); sep; sep = strchr(sep + 1, '%')) {
- const char *arg;
- char *label;
-
- arg = va_arg(list, const char *);
- if (!arg) {
- va_end(list);
- return -EINVAL;
- }
-
- label = bus_label_escape(arg);
- if (!label) {
- va_end(list);
- return -ENOMEM;
- }
-
- r = strv_consume(&labels, label);
- if (r < 0) {
- va_end(list);
- return r;
- }
-
- /* add label length, but account for the format character */
- path_length += strlen(label) - 1;
- }
- va_end(list);
-
- path = malloc(path_length + 1);
- if (!path)
- return -ENOMEM;
-
- path_pos = path;
- label_pos = labels;
-
- for (template_pos = path_template; *template_pos; ) {
- sep = strchrnul(template_pos, '%');
- path_pos = mempcpy(path_pos, template_pos, sep - template_pos);
- if (!*sep)
- break;
-
- path_pos = stpcpy(path_pos, *label_pos++);
- template_pos = sep + 1;
- }
-
- *path_pos = 0;
- *out = path;
- return 0;
-}
-
-_public_ int sd_bus_path_decode_many(const char *path, const char *path_template, ...) {
- _cleanup_strv_free_ char **labels = NULL;
- const char *template_pos, *path_pos;
- char **label_pos;
- va_list list;
- int r;
-
- /*
- * This decodes an object-path based on a template argument. The
- * template consists of a verbatim path, optionally including special
- * directives:
- *
- * - Each occurrence of '%' in the template matches an arbitrary
- * substring of a label in the given path. At most one such
- * directive is allowed per label. For each such directive, the
- * caller must provide an output parameter (char **) via va_arg. If
- * NULL is passed, the given label is verified, but not returned.
- * For each matched label, the *decoded* label is stored in the
- * passed output argument, and the caller is responsible to free
- * it. Note that the output arguments are only modified if the
- * actualy path matched the template. Otherwise, they're left
- * untouched.
- *
- * This function returns <0 on error, 0 if the path does not match the
- * template, 1 if it matched.
- */
-
- assert_return(path, -EINVAL);
- assert_return(path_template, -EINVAL);
-
- path_pos = path;
-
- for (template_pos = path_template; *template_pos; ) {
- const char *sep;
- size_t length;
- char *label;
-
- /* verify everything until the next '%' matches verbatim */
- sep = strchrnul(template_pos, '%');
- length = sep - template_pos;
- if (strncmp(path_pos, template_pos, length))
- return 0;
-
- path_pos += length;
- template_pos += length;
-
- if (!*template_pos)
- break;
-
- /* We found the next '%' character. Everything up until here
- * matched. We now skip ahead to the end of this label and make
- * sure it matches the tail of the label in the path. Then we
- * decode the string in-between and save it for later use. */
-
- ++template_pos; /* skip over '%' */
-
- sep = strchrnul(template_pos, '/');
- length = sep - template_pos; /* length of suffix to match verbatim */
-
- /* verify the suffixes match */
- sep = strchrnul(path_pos, '/');
- if (sep - path_pos < (ssize_t)length ||
- strncmp(sep - length, template_pos, length))
- return 0;
-
- template_pos += length; /* skip over matched label */
- length = sep - path_pos - length; /* length of sub-label to decode */
-
- /* store unescaped label for later use */
- label = bus_label_unescape_n(path_pos, length);
- if (!label)
- return -ENOMEM;
-
- r = strv_consume(&labels, label);
- if (r < 0)
- return r;
-
- path_pos = sep; /* skip decoded label and suffix */
- }
-
- /* end of template must match end of path */
- if (*path_pos)
- return 0;
-
- /* copy the labels over to the caller */
- va_start(list, path_template);
- for (label_pos = labels; label_pos && *label_pos; ++label_pos) {
- char **arg;
-
- arg = va_arg(list, char **);
- if (arg)
- *arg = *label_pos;
- else
- free(*label_pos);
- }
- va_end(list);
-
- free(labels);
- labels = NULL;
- return 1;
-}
-
-_public_ int sd_bus_try_close(sd_bus *bus) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (!bus->is_kernel)
- return -EOPNOTSUPP;
-
- if (!BUS_IS_OPEN(bus->state))
- return -ENOTCONN;
-
- if (bus->rqueue_size > 0)
- return -EBUSY;
-
- if (bus->wqueue_size > 0)
- return -EBUSY;
-
- r = bus_kernel_try_close(bus);
- if (r < 0)
- return r;
-
- sd_bus_close(bus);
- return 0;
-}
-
-_public_ int sd_bus_get_description(sd_bus *bus, const char **description) {
- assert_return(bus, -EINVAL);
- assert_return(description, -EINVAL);
- assert_return(bus->description, -ENXIO);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- *description = bus->description;
- return 0;
-}
-
-int bus_get_root_path(sd_bus *bus) {
- int r;
-
- if (bus->cgroup_root)
- return 0;
-
- r = cg_get_root_path(&bus->cgroup_root);
- if (r == -ENOENT) {
- bus->cgroup_root = strdup("/");
- if (!bus->cgroup_root)
- return -ENOMEM;
-
- r = 0;
- }
-
- return r;
-}
-
-_public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) {
- int r;
-
- assert_return(bus, -EINVAL);
- assert_return(scope, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (bus->is_kernel) {
- _cleanup_free_ char *n = NULL;
- const char *dash;
-
- r = bus_kernel_get_bus_name(bus, &n);
- if (r < 0)
- return r;
-
- if (streq(n, "0-system")) {
- *scope = "system";
- return 0;
- }
-
- dash = strchr(n, '-');
- if (streq_ptr(dash, "-user")) {
- *scope = "user";
- return 0;
- }
- }
-
- if (bus->is_user) {
- *scope = "user";
- return 0;
- }
-
- if (bus->is_system) {
- *scope = "system";
- return 0;
- }
-
- return -ENODATA;
-}
-
-_public_ int sd_bus_get_address(sd_bus *bus, const char **address) {
-
- assert_return(bus, -EINVAL);
- assert_return(address, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- if (bus->address) {
- *address = bus->address;
- return 0;
- }
-
- return -ENODATA;
-}
-
-_public_ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) {
- assert_return(bus, -EINVAL);
- assert_return(mask, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- *mask = bus->creds_mask;
- return 0;
-}
-
-_public_ int sd_bus_is_bus_client(sd_bus *bus) {
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return bus->bus_client;
-}
-
-_public_ int sd_bus_is_server(sd_bus *bus) {
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return bus->is_server;
-}
-
-_public_ int sd_bus_is_anonymous(sd_bus *bus) {
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return bus->anonymous_auth;
-}
-
-_public_ int sd_bus_is_trusted(sd_bus *bus) {
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return bus->trusted;
-}
-
-_public_ int sd_bus_is_monitor(sd_bus *bus) {
- assert_return(bus, -EINVAL);
- assert_return(!bus_pid_changed(bus), -ECHILD);
-
- return !!(bus->hello_flags & KDBUS_HELLO_MONITOR);
-}
-
-static void flush_close(sd_bus *bus) {
- if (!bus)
- return;
-
- /* Flushes and closes the specified bus. We take a ref before,
- * to ensure the flushing does not cause the bus to be
- * unreferenced. */
-
- sd_bus_flush_close_unref(sd_bus_ref(bus));
-}
-
-_public_ void sd_bus_default_flush_close(void) {
- flush_close(default_starter_bus);
- flush_close(default_user_bus);
- flush_close(default_system_bus);
-}
-
-_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
- assert_return(bus, -EINVAL);
-
- /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already
- * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never
- * from the client side. */
- bus->exit_on_disconnect = b;
-
- /* If the exit condition was triggered already, exit immediately. */
- return bus_exit_now(bus);
-}
-
-_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
- assert_return(bus, -EINVAL);
-
- return bus->exit_on_disconnect;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-benchmark.c b/src/libsystemd/sd-bus/test-bus-benchmark.c
deleted file mode 100644
index 56ac2ab3dd..0000000000
--- a/src/libsystemd/sd-bus/test-bus-benchmark.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/wait.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-internal.h"
-#include "bus-kernel.h"
-#include "bus-util.h"
-#include "def.h"
-#include "fd-util.h"
-#include "time-util.h"
-#include "util.h"
-
-#define MAX_SIZE (2*1024*1024)
-
-static usec_t arg_loop_usec = 100 * USEC_PER_MSEC;
-
-typedef enum Type {
- TYPE_KDBUS,
- TYPE_LEGACY,
- TYPE_DIRECT,
-} Type;
-
-static void server(sd_bus *b, size_t *result) {
- int r;
-
- for (;;) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-
- r = sd_bus_process(b, &m);
- assert_se(r >= 0);
-
- if (r == 0)
- assert_se(sd_bus_wait(b, USEC_INFINITY) >= 0);
- if (!m)
- continue;
-
- if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping"))
- assert_se(sd_bus_reply_method_return(m, NULL) >= 0);
- else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) {
- const void *p;
- size_t sz;
-
- /* Make sure the mmap is mapped */
- assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0);
-
- r = sd_bus_reply_method_return(m, NULL);
- assert_se(r >= 0);
- } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) {
- uint64_t res;
- assert_se(sd_bus_message_read(m, "t", &res) > 0);
-
- *result = res;
- return;
-
- } else if (!sd_bus_message_is_signal(m, NULL, NULL))
- assert_not_reached("Unknown method");
- }
-}
-
-static void transaction(sd_bus *b, size_t sz, const char *server_name) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
- uint8_t *p;
-
- assert_se(sd_bus_message_new_method_call(b, &m, server_name, "/", "benchmark.server", "Work") >= 0);
- assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0);
-
- memset(p, 0x80, sz);
-
- assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0);
-}
-
-static void client_bisect(const char *address, const char *server_name) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
- size_t lsize, rsize, csize;
- sd_bus *b;
- int r;
-
- r = sd_bus_new(&b);
- assert_se(r >= 0);
-
- r = sd_bus_set_address(b, address);
- assert_se(r >= 0);
-
- r = sd_bus_start(b);
- assert_se(r >= 0);
-
- r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL);
- assert_se(r >= 0);
-
- lsize = 1;
- rsize = MAX_SIZE;
-
- printf("SIZE\tCOPY\tMEMFD\n");
-
- for (;;) {
- usec_t t;
- unsigned n_copying, n_memfd;
-
- csize = (lsize + rsize) / 2;
-
- if (csize <= lsize)
- break;
-
- if (csize <= 0)
- break;
-
- printf("%zu\t", csize);
-
- b->use_memfd = 0;
-
- t = now(CLOCK_MONOTONIC);
- for (n_copying = 0;; n_copying++) {
- transaction(b, csize, server_name);
- if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
- break;
- }
- printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
-
- b->use_memfd = -1;
-
- t = now(CLOCK_MONOTONIC);
- for (n_memfd = 0;; n_memfd++) {
- transaction(b, csize, server_name);
- if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
- break;
- }
- printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
-
- if (n_copying == n_memfd)
- break;
-
- if (n_copying > n_memfd)
- lsize = csize;
- else
- rsize = csize;
- }
-
- b->use_memfd = 1;
- assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0);
- assert_se(sd_bus_message_append(x, "t", csize) >= 0);
- assert_se(sd_bus_send(b, x, NULL) >= 0);
-
- sd_bus_unref(b);
-}
-
-static void client_chart(Type type, const char *address, const char *server_name, int fd) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL;
- size_t csize;
- sd_bus *b;
- int r;
-
- r = sd_bus_new(&b);
- assert_se(r >= 0);
-
- if (type == TYPE_DIRECT) {
- r = sd_bus_set_fd(b, fd, fd);
- assert_se(r >= 0);
- } else {
- r = sd_bus_set_address(b, address);
- assert_se(r >= 0);
-
- r = sd_bus_set_bus_client(b, true);
- assert_se(r >= 0);
- }
-
- r = sd_bus_start(b);
- assert_se(r >= 0);
-
- r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL);
- assert_se(r >= 0);
-
- switch (type) {
- case TYPE_KDBUS:
- printf("SIZE\tCOPY\tMEMFD\n");
- break;
- case TYPE_LEGACY:
- printf("SIZE\tLEGACY\n");
- break;
- case TYPE_DIRECT:
- printf("SIZE\tDIRECT\n");
- break;
- }
-
- for (csize = 1; csize <= MAX_SIZE; csize *= 2) {
- usec_t t;
- unsigned n_copying, n_memfd;
-
- printf("%zu\t", csize);
-
- if (type == TYPE_KDBUS) {
- b->use_memfd = 0;
-
- t = now(CLOCK_MONOTONIC);
- for (n_copying = 0;; n_copying++) {
- transaction(b, csize, server_name);
- if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
- break;
- }
-
- printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec));
-
- b->use_memfd = -1;
- }
-
- t = now(CLOCK_MONOTONIC);
- for (n_memfd = 0;; n_memfd++) {
- transaction(b, csize, server_name);
- if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec)
- break;
- }
-
- printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec));
- }
-
- b->use_memfd = 1;
- assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0);
- assert_se(sd_bus_message_append(x, "t", csize) >= 0);
- assert_se(sd_bus_send(b, x, NULL) >= 0);
-
- sd_bus_unref(b);
-}
-
-int main(int argc, char *argv[]) {
- enum {
- MODE_BISECT,
- MODE_CHART,
- } mode = MODE_BISECT;
- Type type = TYPE_KDBUS;
- int i, pair[2] = { -1, -1 };
- _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *server_name = NULL;
- _cleanup_close_ int bus_ref = -1;
- const char *unique;
- cpu_set_t cpuset;
- size_t result;
- sd_bus *b;
- pid_t pid;
- int r;
-
- for (i = 1; i < argc; i++) {
- if (streq(argv[i], "chart")) {
- mode = MODE_CHART;
- continue;
- } else if (streq(argv[i], "legacy")) {
- type = TYPE_LEGACY;
- continue;
- } else if (streq(argv[i], "direct")) {
- type = TYPE_DIRECT;
- continue;
- }
-
- assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0);
- }
-
- assert_se(!MODE_BISECT || TYPE_KDBUS);
-
- assert_se(arg_loop_usec > 0);
-
- if (type == TYPE_KDBUS) {
- assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
-
- bus_ref = bus_kernel_create_bus(name, false, &bus_name);
- if (bus_ref == -ENOENT)
- exit(EXIT_TEST_SKIP);
-
- assert_se(bus_ref >= 0);
-
- address = strappend("kernel:path=", bus_name);
- assert_se(address);
- } else if (type == TYPE_LEGACY) {
- const char *e;
-
- e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
- assert_se(e);
-
- address = strdup(e);
- assert_se(address);
- }
-
- r = sd_bus_new(&b);
- assert_se(r >= 0);
-
- if (type == TYPE_DIRECT) {
- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0);
-
- r = sd_bus_set_fd(b, pair[0], pair[0]);
- assert_se(r >= 0);
-
- r = sd_bus_set_server(b, true, SD_ID128_NULL);
- assert_se(r >= 0);
- } else {
- r = sd_bus_set_address(b, address);
- assert_se(r >= 0);
-
- r = sd_bus_set_bus_client(b, true);
- assert_se(r >= 0);
- }
-
- r = sd_bus_start(b);
- assert_se(r >= 0);
-
- if (type != TYPE_DIRECT) {
- r = sd_bus_get_unique_name(b, &unique);
- assert_se(r >= 0);
-
- server_name = strdup(unique);
- assert_se(server_name);
- }
-
- sync();
- setpriority(PRIO_PROCESS, 0, -19);
-
- pid = fork();
- assert_se(pid >= 0);
-
- if (pid == 0) {
- CPU_ZERO(&cpuset);
- CPU_SET(0, &cpuset);
- pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-
- safe_close(bus_ref);
- sd_bus_unref(b);
-
- switch (mode) {
- case MODE_BISECT:
- client_bisect(address, server_name);
- break;
-
- case MODE_CHART:
- client_chart(type, address, server_name, pair[1]);
- break;
- }
-
- _exit(0);
- }
-
- CPU_ZERO(&cpuset);
- CPU_SET(1, &cpuset);
- pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-
- server(b, &result);
-
- if (mode == MODE_BISECT)
- printf("Copying/memfd are equally fast at %zu bytes\n", result);
-
- assert_se(waitpid(pid, NULL, 0) == pid);
-
- safe_close(pair[1]);
- sd_bus_unref(b);
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c
deleted file mode 100644
index fc60830059..0000000000
--- a/src/libsystemd/sd-bus/test-bus-chat.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-error.h"
-#include "bus-internal.h"
-#include "bus-match.h"
-#include "bus-util.h"
-#include "fd-util.h"
-#include "formats-util.h"
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-
-static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)));
- return 0;
-}
-
-static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- int r;
-
- if (sd_bus_message_is_method_error(m, NULL))
- return 0;
-
- if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) {
- log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m));
-
- r = sd_bus_reply_method_return(m, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to send reply: %m");
-
- return 1;
- }
-
- return 0;
-}
-
-static int server_init(sd_bus **_bus) {
- sd_bus *bus = NULL;
- sd_id128_t id;
- int r;
- const char *unique;
-
- assert_se(_bus);
-
- r = sd_bus_open_user(&bus);
- if (r < 0) {
- log_error_errno(r, "Failed to connect to user bus: %m");
- goto fail;
- }
-
- r = sd_bus_get_bus_id(bus, &id);
- if (r < 0) {
- log_error_errno(r, "Failed to get server ID: %m");
- goto fail;
- }
-
- r = sd_bus_get_unique_name(bus, &unique);
- if (r < 0) {
- log_error_errno(r, "Failed to get unique name: %m");
- goto fail;
- }
-
- log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id));
- log_info("Unique ID: %s", unique);
- log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h'));
-
- r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0);
- if (r < 0) {
- log_error_errno(r, "Failed to acquire name: %m");
- goto fail;
- }
-
- r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to add object: %m");
- goto fail;
- }
-
- r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to add match: %m");
- goto fail;
- }
-
- r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to add match: %m");
- goto fail;
- }
-
- bus_match_dump(&bus->match_callbacks, 0);
-
- *_bus = bus;
- return 0;
-
-fail:
- sd_bus_unref(bus);
- return r;
-}
-
-static int server(sd_bus *bus) {
- int r;
- bool client1_gone = false, client2_gone = false;
-
- while (!client1_gone || !client2_gone) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- pid_t pid = 0;
- const char *label = NULL;
-
- r = sd_bus_process(bus, &m);
- if (r < 0) {
- log_error_errno(r, "Failed to process requests: %m");
- goto fail;
- }
-
- if (r == 0) {
- r = sd_bus_wait(bus, (uint64_t) -1);
- if (r < 0) {
- log_error_errno(r, "Failed to wait: %m");
- goto fail;
- }
-
- continue;
- }
-
- if (!m)
- continue;
-
- sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid);
- sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label);
- log_info("Got message! member=%s pid="PID_FMT" label=%s",
- strna(sd_bus_message_get_member(m)),
- pid,
- strna(label));
- /* bus_message_dump(m); */
- /* sd_bus_message_rewind(m, true); */
-
- if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) {
- const char *hello;
- _cleanup_free_ char *lowercase = NULL;
-
- r = sd_bus_message_read(m, "s", &hello);
- if (r < 0) {
- log_error_errno(r, "Failed to get parameter: %m");
- goto fail;
- }
-
- lowercase = strdup(hello);
- if (!lowercase) {
- r = log_oom();
- goto fail;
- }
-
- ascii_strlower(lowercase);
-
- r = sd_bus_reply_method_return(m, "s", lowercase);
- if (r < 0) {
- log_error_errno(r, "Failed to send reply: %m");
- goto fail;
- }
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) {
-
- r = sd_bus_reply_method_return(m, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to send reply: %m");
- goto fail;
- }
-
- client1_gone = true;
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) {
-
- r = sd_bus_reply_method_return(m, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to send reply: %m");
- goto fail;
- }
-
- client2_gone = true;
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) {
-
- sleep(1);
-
- r = sd_bus_reply_method_return(m, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to send reply: %m");
- goto fail;
- }
-
- } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) {
- int fd;
- static const char x = 'X';
-
- r = sd_bus_message_read(m, "h", &fd);
- if (r < 0) {
- log_error_errno(r, "Failed to get parameter: %m");
- goto fail;
- }
-
- log_info("Received fd=%d", fd);
-
- if (write(fd, &x, 1) < 0) {
- log_error_errno(errno, "Failed to write to fd: %m");
- safe_close(fd);
- goto fail;
- }
-
- r = sd_bus_reply_method_return(m, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to send reply: %m");
- goto fail;
- }
-
- } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
-
- r = sd_bus_reply_method_error(
- m,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
- if (r < 0) {
- log_error_errno(r, "Failed to send reply: %m");
- goto fail;
- }
- }
- }
-
- r = 0;
-
-fail:
- if (bus) {
- sd_bus_flush(bus);
- sd_bus_unref(bus);
- }
-
- return r;
-}
-
-static void* client1(void*p) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *hello;
- int r;
- _cleanup_close_pair_ int pp[2] = { -1, -1 };
- char x;
-
- r = sd_bus_open_user(&bus);
- if (r < 0) {
- log_error_errno(r, "Failed to connect to user bus: %m");
- goto finish;
- }
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.systemd.test",
- "LowerCase",
- &error,
- &reply,
- "s",
- "HELLO");
- if (r < 0) {
- log_error_errno(r, "Failed to issue method call: %m");
- goto finish;
- }
-
- r = sd_bus_message_read(reply, "s", &hello);
- if (r < 0) {
- log_error_errno(r, "Failed to get string: %m");
- goto finish;
- }
-
- assert_se(streq(hello, "hello"));
-
- if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) {
- log_error_errno(errno, "Failed to allocate pipe: %m");
- r = -errno;
- goto finish;
- }
-
- log_info("Sending fd=%d", pp[1]);
-
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.systemd.test",
- "FileDescriptor",
- &error,
- NULL,
- "h",
- pp[1]);
- if (r < 0) {
- log_error_errno(r, "Failed to issue method call: %m");
- goto finish;
- }
-
- errno = 0;
- if (read(pp[0], &x, 1) <= 0) {
- log_error("Failed to read from pipe: %s", errno ? strerror(errno) : "early read");
- goto finish;
- }
-
- r = 0;
-
-finish:
- if (bus) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
-
- r = sd_bus_message_new_method_call(
- bus,
- &q,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.systemd.test",
- "ExitClient1");
- if (r < 0)
- log_error_errno(r, "Failed to allocate method call: %m");
- else
- sd_bus_send(bus, q, NULL);
-
- }
-
- return INT_TO_PTR(r);
-}
-
-static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- bool *x = userdata;
-
- log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m");
-
- *x = 1;
- return 1;
-}
-
-static void* client2(void*p) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- bool quit = false;
- const char *mid;
- int r;
-
- r = sd_bus_open_user(&bus);
- if (r < 0) {
- log_error_errno(r, "Failed to connect to user bus: %m");
- goto finish;
- }
-
- r = sd_bus_message_new_method_call(
- bus,
- &m,
- "org.freedesktop.systemd.test",
- "/foo/bar/waldo/piep",
- "org.object.test",
- "Foobar");
- if (r < 0) {
- log_error_errno(r, "Failed to allocate method call: %m");
- goto finish;
- }
-
- r = sd_bus_send(bus, m, NULL);
- if (r < 0) {
- log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
- goto finish;
- }
-
- m = sd_bus_message_unref(m);
-
- r = sd_bus_message_new_signal(
- bus,
- &m,
- "/foobar",
- "foo.bar",
- "Notify");
- if (r < 0) {
- log_error_errno(r, "Failed to allocate signal: %m");
- goto finish;
- }
-
- r = sd_bus_send(bus, m, NULL);
- if (r < 0) {
- log_error("Failed to issue signal: %s", bus_error_message(&error, -r));
- goto finish;
- }
-
- m = sd_bus_message_unref(m);
-
- r = sd_bus_message_new_method_call(
- bus,
- &m,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.DBus.Peer",
- "GetMachineId");
- if (r < 0) {
- log_error_errno(r, "Failed to allocate method call: %m");
- goto finish;
- }
-
- r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0) {
- log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
- goto finish;
- }
-
- r = sd_bus_message_read(reply, "s", &mid);
- if (r < 0) {
- log_error_errno(r, "Failed to parse machine ID: %m");
- goto finish;
- }
-
- log_info("Machine ID is %s.", mid);
-
- m = sd_bus_message_unref(m);
-
- r = sd_bus_message_new_method_call(
- bus,
- &m,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.systemd.test",
- "Slow");
- if (r < 0) {
- log_error_errno(r, "Failed to allocate method call: %m");
- goto finish;
- }
-
- reply = sd_bus_message_unref(reply);
-
- r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply);
- if (r < 0)
- log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
- else
- log_info("Slow call succeed.");
-
- m = sd_bus_message_unref(m);
-
- r = sd_bus_message_new_method_call(
- bus,
- &m,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.systemd.test",
- "Slow");
- if (r < 0) {
- log_error_errno(r, "Failed to allocate method call: %m");
- goto finish;
- }
-
- r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
- if (r < 0) {
- log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
- goto finish;
- }
-
- while (!quit) {
- r = sd_bus_process(bus, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to process requests: %m");
- goto finish;
- }
- if (r == 0) {
- r = sd_bus_wait(bus, (uint64_t) -1);
- if (r < 0) {
- log_error_errno(r, "Failed to wait: %m");
- goto finish;
- }
- }
- }
-
- r = 0;
-
-finish:
- if (bus) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
-
- r = sd_bus_message_new_method_call(
- bus,
- &q,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.systemd.test",
- "ExitClient2");
- if (r < 0) {
- log_error_errno(r, "Failed to allocate method call: %m");
- goto finish;
- }
-
- (void) sd_bus_send(bus, q, NULL);
- }
-
- return INT_TO_PTR(r);
-}
-
-int main(int argc, char *argv[]) {
- pthread_t c1, c2;
- sd_bus *bus;
- void *p;
- int q, r;
-
- r = server_init(&bus);
- if (r < 0) {
- log_info("Failed to connect to bus, skipping tests.");
- return EXIT_TEST_SKIP;
- }
-
- log_info("Initialized...");
-
- r = pthread_create(&c1, NULL, client1, bus);
- if (r != 0)
- return EXIT_FAILURE;
-
- r = pthread_create(&c2, NULL, client2, bus);
- if (r != 0)
- return EXIT_FAILURE;
-
- r = server(bus);
-
- q = pthread_join(c1, &p);
- if (q != 0)
- return EXIT_FAILURE;
- if (PTR_TO_INT(p) < 0)
- return EXIT_FAILURE;
-
- q = pthread_join(c2, &p);
- if (q != 0)
- return EXIT_FAILURE;
- if (PTR_TO_INT(p) < 0)
- return EXIT_FAILURE;
-
- if (r < 0)
- return EXIT_FAILURE;
-
- return EXIT_SUCCESS;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-cleanup.c b/src/libsystemd/sd-bus/test-bus-cleanup.c
deleted file mode 100644
index 250a5b2908..0000000000
--- a/src/libsystemd/sd-bus/test-bus-cleanup.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdio.h>
-
-#include "sd-bus.h"
-
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "refcnt.h"
-
-static void test_bus_new(void) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
-
- assert_se(sd_bus_new(&bus) == 0);
- printf("after new: refcount %u\n", REFCNT_GET(bus->n_ref));
-}
-
-static int test_bus_open(void) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- int r;
-
- r = sd_bus_open_system(&bus);
- if (r == -ECONNREFUSED || r == -ENOENT)
- return r;
-
- assert_se(r >= 0);
- printf("after open: refcount %u\n", REFCNT_GET(bus->n_ref));
-
- return 0;
-}
-
-static void test_bus_new_method_call(void) {
- sd_bus *bus = NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-
- assert_se(sd_bus_open_system(&bus) >= 0);
-
- assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path", "an.interface.name", "AMethodName") >= 0);
-
- printf("after message_new_method_call: refcount %u\n", REFCNT_GET(bus->n_ref));
-
- sd_bus_flush_close_unref(bus);
- printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
-}
-
-static void test_bus_new_signal(void) {
- sd_bus *bus = NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
-
- assert_se(sd_bus_open_system(&bus) >= 0);
-
- assert_se(sd_bus_message_new_signal(bus, &m, "/an/object/path", "an.interface.name", "Name") >= 0);
-
- printf("after message_new_signal: refcount %u\n", REFCNT_GET(bus->n_ref));
-
- sd_bus_flush_close_unref(bus);
- printf("after bus_flush_close_unref: refcount %u\n", m->n_ref);
-}
-
-int main(int argc, char **argv) {
- int r;
-
- log_parse_environment();
- log_open();
-
- test_bus_new();
- r = test_bus_open();
- if (r < 0) {
- log_info("Failed to connect to bus, skipping tests.");
- return EXIT_TEST_SKIP;
- }
-
- test_bus_new_method_call();
- test_bus_new_signal();
-
- return EXIT_SUCCESS;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c
deleted file mode 100644
index 6fdcfa4128..0000000000
--- a/src/libsystemd/sd-bus/test-bus-creds.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "bus-dump.h"
-#include "bus-util.h"
-#include "cgroup-util.h"
-
-int main(int argc, char *argv[]) {
- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- int r;
-
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
-
- if (cg_all_unified() == -ENOMEDIUM) {
- log_info("Skipping test: /sys/fs/cgroup/ not available");
- return EXIT_TEST_SKIP;
- }
-
- r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL);
- log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m");
- assert_se(r >= 0);
-
- bus_creds_dump(creds, NULL, true);
-
- creds = sd_bus_creds_unref(creds);
-
- r = sd_bus_creds_new_from_pid(&creds, 1, _SD_BUS_CREDS_ALL);
- if (r != -EACCES) {
- assert_se(r >= 0);
- putchar('\n');
- bus_creds_dump(creds, NULL, true);
- }
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c
deleted file mode 100644
index 66a3874f10..0000000000
--- a/src/libsystemd/sd-bus/test-bus-error.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "bus-common-errors.h"
-#include "bus-error.h"
-#include "bus-util.h"
-#include "errno-list.h"
-
-static void test_error(void) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
- const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
- const sd_bus_error temporarily_const_error = {
- .name = SD_BUS_ERROR_ACCESS_DENIED,
- .message = "oh! no",
- ._need_free = -1
- };
-
- assert_se(!sd_bus_error_is_set(&error));
- assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -EOPNOTSUPP);
- assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED));
- assert_se(streq(error.message, "xxx"));
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED));
- assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP);
- assert_se(sd_bus_error_is_set(&error));
- sd_bus_error_free(&error);
-
- /* Check with no error */
- assert_se(!sd_bus_error_is_set(&error));
- assert_se(sd_bus_error_setf(&error, NULL, "yyy %i", -1) == 0);
- assert_se(error.name == NULL);
- assert_se(error.message == NULL);
- assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
- assert_se(sd_bus_error_get_errno(&error) == 0);
- assert_se(!sd_bus_error_is_set(&error));
-
- assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
- assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
- assert_se(streq(error.message, "yyy -1"));
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
- assert_se(sd_bus_error_get_errno(&error) == ENOENT);
- assert_se(sd_bus_error_is_set(&error));
-
- assert_se(!sd_bus_error_is_set(&second));
- assert_se(second._need_free == 0);
- assert_se(error._need_free > 0);
- assert_se(sd_bus_error_copy(&second, &error) == -ENOENT);
- assert_se(second._need_free > 0);
- assert_se(streq(error.name, second.name));
- assert_se(streq(error.message, second.message));
- assert_se(sd_bus_error_get_errno(&second) == ENOENT);
- assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND));
- assert_se(sd_bus_error_is_set(&second));
-
- sd_bus_error_free(&error);
- sd_bus_error_free(&second);
-
- assert_se(!sd_bus_error_is_set(&second));
- assert_se(const_error._need_free == 0);
- assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST);
- assert_se(second._need_free == 0);
- assert_se(streq(const_error.name, second.name));
- assert_se(streq(const_error.message, second.message));
- assert_se(sd_bus_error_get_errno(&second) == EEXIST);
- assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS));
- assert_se(sd_bus_error_is_set(&second));
- sd_bus_error_free(&second);
-
- assert_se(!sd_bus_error_is_set(&second));
- assert_se(temporarily_const_error._need_free < 0);
- assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES);
- assert_se(second._need_free > 0);
- assert_se(streq(temporarily_const_error.name, second.name));
- assert_se(streq(temporarily_const_error.message, second.message));
- assert_se(sd_bus_error_get_errno(&second) == EACCES);
- assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED));
- assert_se(sd_bus_error_is_set(&second));
-
- assert_se(!sd_bus_error_is_set(&error));
- assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN);
- assert_se(streq(error.name, "System.Error.EUCLEAN"));
- assert_se(streq(error.message, "Hallo"));
- assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN"));
- assert_se(sd_bus_error_get_errno(&error) == EUCLEAN);
- assert_se(sd_bus_error_is_set(&error));
- sd_bus_error_free(&error);
-
- assert_se(!sd_bus_error_is_set(&error));
- assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
- assert_se(streq(error.name, "System.Error.EBUSY"));
- assert_se(streq(error.message, strerror(EBUSY)));
- assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
- assert_se(sd_bus_error_get_errno(&error) == EBUSY);
- assert_se(sd_bus_error_is_set(&error));
- sd_bus_error_free(&error);
-
- assert_se(!sd_bus_error_is_set(&error));
- assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO);
- assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR));
- assert_se(streq(error.message, "Waldi X"));
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
- assert_se(sd_bus_error_get_errno(&error) == EIO);
- assert_se(sd_bus_error_is_set(&error));
- sd_bus_error_free(&error);
-
- /* Check with no error */
- assert_se(!sd_bus_error_is_set(&error));
- assert_se(sd_bus_error_set_errnof(&error, 0, "Waldi %c", 'X') == 0);
- assert_se(error.name == NULL);
- assert_se(error.message == NULL);
- assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
- assert_se(sd_bus_error_get_errno(&error) == 0);
- assert_se(!sd_bus_error_is_set(&error));
-}
-
-extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
-extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];
-
-static void dump_mapping_table(void) {
- const sd_bus_error_map *m;
-
- printf("----- errno mappings ------\n");
- m = __start_BUS_ERROR_MAP;
- while (m < __stop_BUS_ERROR_MAP) {
-
- if (m->code == BUS_ERROR_MAP_END_MARKER) {
- m = ALIGN8_PTR(m+1);
- continue;
- }
-
- printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code)));
- m++;
- }
- printf("---------------------------\n");
-}
-
-static void test_errno_mapping_standard(void) {
- assert_se(sd_bus_error_set(NULL, "System.Error.EUCLEAN", NULL) == -EUCLEAN);
- assert_se(sd_bus_error_set(NULL, "System.Error.EBUSY", NULL) == -EBUSY);
- assert_se(sd_bus_error_set(NULL, "System.Error.EINVAL", NULL) == -EINVAL);
- assert_se(sd_bus_error_set(NULL, "System.Error.WHATSIT", NULL) == -EIO);
-}
-
-BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error", 5),
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-2", 52),
- SD_BUS_ERROR_MAP_END
-};
-
-BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors2[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-3", 33),
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-4", 44),
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-33", 333),
- SD_BUS_ERROR_MAP_END
-};
-
-static const sd_bus_error_map test_errors3[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-88", 888),
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-99", 999),
- SD_BUS_ERROR_MAP_END
-};
-
-static const sd_bus_error_map test_errors4[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-77", 777),
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-78", 778),
- SD_BUS_ERROR_MAP_END
-};
-
-static const sd_bus_error_map test_errors_bad1[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", 0),
- SD_BUS_ERROR_MAP_END
-};
-
-static const sd_bus_error_map test_errors_bad2[] = {
- SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", -1),
- SD_BUS_ERROR_MAP_END
-};
-
-static void test_errno_mapping_custom(void) {
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-x", NULL) == -EIO);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-33", NULL) == -333);
-
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -EIO);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -EIO);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -EIO);
-
- assert_se(sd_bus_error_add_map(test_errors3) > 0);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -888);
- assert_se(sd_bus_error_add_map(test_errors4) > 0);
- assert_se(sd_bus_error_add_map(test_errors4) == 0);
- assert_se(sd_bus_error_add_map(test_errors3) == 0);
-
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -999);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -777);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-78", NULL) == -778);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52);
- assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-y", NULL) == -EIO);
-
- assert_se(sd_bus_error_set(NULL, BUS_ERROR_NO_SUCH_UNIT, NULL) == -ENOENT);
-
- assert_se(sd_bus_error_add_map(test_errors_bad1) == -EINVAL);
- assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL);
-}
-
-int main(int argc, char *argv[]) {
- dump_mapping_table();
-
- test_error();
- test_errno_mapping_standard();
- test_errno_mapping_custom();
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c
deleted file mode 100644
index 83f114a0fe..0000000000
--- a/src/libsystemd/sd-bus/test-bus-gvariant.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#ifdef 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 "bus-util.h"
-#include "macro.h"
-#include "util.h"
-
-static void test_bus_gvariant_is_fixed_size(void) {
- assert_se(bus_gvariant_is_fixed_size("") > 0);
- assert_se(bus_gvariant_is_fixed_size("()") > 0);
- 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);
-}
-
-static void test_bus_gvariant_get_size(void) {
- assert_se(bus_gvariant_get_size("") == 0);
- assert_se(bus_gvariant_get_size("()") == 1);
- 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);
-}
-
-static void test_bus_gvariant_get_alignment(void) {
- assert_se(bus_gvariant_get_alignment("") == 1);
- assert_se(bus_gvariant_get_alignment("()") == 1);
- 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);
-}
-
-static void test_marshal(void) {
- _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;
- size_t sz;
- int r;
-
- r = sd_bus_open_system(&bus);
- if (r < 0)
- exit(EXIT_TEST_SKIP);
-
- bus->message_version = 2; /* dirty hack to enable gvariant */
-
- assert_se(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") >= 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(bus_message_seal(m, 4711, 0) >= 0);
-
-#ifdef 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(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0);
-
- assert_se(bus_message_get_blob(m, &blob, &sz) >= 0);
-
-#ifdef 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(bus_message_dump(n, NULL, 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(bus_message_seal(m, 4712, 0) >= 0);
- assert_se(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0);
-}
-
-int main(int argc, char *argv[]) {
-
- test_bus_gvariant_is_fixed_size();
- test_bus_gvariant_get_size();
- test_bus_gvariant_get_alignment();
- test_marshal();
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c
deleted file mode 100644
index 4425cfae26..0000000000
--- a/src/libsystemd/sd-bus/test-bus-introspect.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-introspect.h"
-#include "log.h"
-
-static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- return -EINVAL;
-}
-
-static int prop_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- return -EINVAL;
-}
-
-static const sd_bus_vtable vtable[] = {
- SD_BUS_VTABLE_START(0),
- SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0),
- SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED),
- SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY),
- SD_BUS_SIGNAL("Wowza", "sss", 0),
- SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED),
- SD_BUS_WRITABLE_PROPERTY("AProperty", "s", prop_get, prop_set, 0, 0),
- SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", prop_get, 0, SD_BUS_VTABLE_DEPRECATED),
- SD_BUS_PROPERTY("ChangingProperty", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("Invalidating", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
- SD_BUS_PROPERTY("Constant", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT),
- SD_BUS_VTABLE_END
-};
-
-int main(int argc, char *argv[]) {
- struct introspect intro;
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(introspect_begin(&intro, false) >= 0);
-
- fprintf(intro.f, " <interface name=\"org.foo\">\n");
- assert_se(introspect_write_interface(&intro, vtable) >= 0);
- fputs(" </interface>\n", intro.f);
-
- fflush(intro.f);
- fputs(intro.introspection, stdout);
-
- introspect_free(&intro);
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c b/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
deleted file mode 100644
index eb6179d7d2..0000000000
--- a/src/libsystemd/sd-bus/test-bus-kernel-bloom.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-kernel.h"
-#include "bus-util.h"
-#include "fd-util.h"
-#include "log.h"
-#include "util.h"
-
-static int test_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- int *found = userdata;
-
- *found = 1;
-
- return 0;
-}
-
-static void test_one(
- const char *path,
- const char *interface,
- const char *member,
- bool as_list,
- const char *arg0,
- const char *match,
- bool good) {
-
- _cleanup_close_ int bus_ref = -1;
- _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- sd_bus *a, *b;
- int r, found = 0;
-
- assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
-
- bus_ref = bus_kernel_create_bus(name, false, &bus_name);
- if (bus_ref == -ENOENT)
- exit(EXIT_TEST_SKIP);
-
- assert_se(bus_ref >= 0);
-
- address = strappend("kernel:path=", bus_name);
- assert_se(address);
-
- r = sd_bus_new(&a);
- assert_se(r >= 0);
-
- r = sd_bus_new(&b);
- assert_se(r >= 0);
-
- r = sd_bus_set_address(a, address);
- assert_se(r >= 0);
-
- r = sd_bus_set_address(b, address);
- assert_se(r >= 0);
-
- r = sd_bus_start(a);
- assert_se(r >= 0);
-
- r = sd_bus_start(b);
- assert_se(r >= 0);
-
- log_debug("match");
- r = sd_bus_add_match(b, NULL, match, test_match, &found);
- assert_se(r >= 0);
-
- log_debug("signal");
-
- if (as_list)
- r = sd_bus_emit_signal(a, path, interface, member, "as", 1, arg0);
- else
- r = sd_bus_emit_signal(a, path, interface, member, "s", arg0);
- assert_se(r >= 0);
-
- r = sd_bus_process(b, &m);
- assert_se(r >= 0 && good == !!found);
-
- sd_bus_unref(a);
- sd_bus_unref(b);
-}
-
-int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
-
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/tuut'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "interface='waldo.com'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Piep'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Pi_ep'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foobar'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foo_bar'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foobar'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foo_bar'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foobar'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foo_bar'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false);
-
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/quux'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false);
- test_one("/", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true);
-
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo/'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/'", true);
-
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/bar/waldo", "arg0path='/foo/'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo'", true);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo/bar/waldo'", false);
- test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/", "arg0path='/foo/bar/waldo'", true);
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-kernel.c b/src/libsystemd/sd-bus/test-bus-kernel.c
deleted file mode 100644
index 2214817312..0000000000
--- a/src/libsystemd/sd-bus/test-bus-kernel.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <fcntl.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-dump.h"
-#include "bus-kernel.h"
-#include "bus-util.h"
-#include "fd-util.h"
-#include "log.h"
-#include "util.h"
-
-int main(int argc, char *argv[]) {
- _cleanup_close_ int bus_ref = -1;
- _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *bname = NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *ua = NULL, *ub = NULL, *the_string = NULL;
- sd_bus *a, *b;
- int r, pipe_fds[2];
- const char *nn;
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
-
- bus_ref = bus_kernel_create_bus(name, false, &bus_name);
- if (bus_ref == -ENOENT)
- return EXIT_TEST_SKIP;
-
- assert_se(bus_ref >= 0);
-
- address = strappend("kernel:path=", bus_name);
- assert_se(address);
-
- r = sd_bus_new(&a);
- assert_se(r >= 0);
-
- r = sd_bus_new(&b);
- assert_se(r >= 0);
-
- r = sd_bus_set_description(a, "a");
- assert_se(r >= 0);
-
- r = sd_bus_set_address(a, address);
- assert_se(r >= 0);
-
- r = sd_bus_set_address(b, address);
- assert_se(r >= 0);
-
- assert_se(sd_bus_negotiate_timestamp(a, 1) >= 0);
- assert_se(sd_bus_negotiate_creds(a, true, _SD_BUS_CREDS_ALL) >= 0);
-
- assert_se(sd_bus_negotiate_timestamp(b, 0) >= 0);
- assert_se(sd_bus_negotiate_creds(b, true, 0) >= 0);
-
- r = sd_bus_start(a);
- assert_se(r >= 0);
-
- r = sd_bus_start(b);
- assert_se(r >= 0);
-
- assert_se(sd_bus_negotiate_timestamp(b, 1) >= 0);
- assert_se(sd_bus_negotiate_creds(b, true, _SD_BUS_CREDS_ALL) >= 0);
-
- r = sd_bus_get_unique_name(a, &ua);
- assert_se(r >= 0);
- printf("unique a: %s\n", ua);
-
- r = sd_bus_get_description(a, &nn);
- assert_se(r >= 0);
- printf("name of a: %s\n", nn);
-
- r = sd_bus_get_unique_name(b, &ub);
- assert_se(r >= 0);
- printf("unique b: %s\n", ub);
-
- r = sd_bus_get_description(b, &nn);
- assert_se(r >= 0);
- printf("name of b: %s\n", nn);
-
- assert_se(bus_kernel_get_bus_name(b, &bname) >= 0);
- assert_se(endswith(bname, name));
-
- r = sd_bus_call_method(a, "this.doesnt.exist", "/foo", "meh.mah", "muh", &error, NULL, "s", "yayayay");
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN));
- assert_se(r == -EHOSTUNREACH);
-
- r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL);
- assert_se(r >= 0);
-
- r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name");
- assert_se(r >= 0);
-
- r = sd_bus_try_close(b);
- assert_se(r == -EBUSY);
-
- r = sd_bus_process_priority(b, -10, &m);
- assert_se(r == 0);
-
- r = sd_bus_process(b, &m);
- assert_se(r > 0);
- assert_se(m);
-
- bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
- assert_se(sd_bus_message_rewind(m, true) >= 0);
-
- r = sd_bus_message_read(m, "s", &the_string);
- assert_se(r >= 0);
- assert_se(streq(the_string, "I am a string"));
-
- sd_bus_message_unref(m);
- m = NULL;
-
- r = sd_bus_request_name(a, "net.x0pointer.foobar", 0);
- assert_se(r >= 0);
-
- r = sd_bus_message_new_method_call(b, &m, "net.x0pointer.foobar", "/a/path", "an.inter.face", "AMethod");
- assert_se(r >= 0);
-
- assert_se(pipe2(pipe_fds, O_CLOEXEC) >= 0);
-
- assert_se(write(pipe_fds[1], "x", 1) == 1);
-
- pipe_fds[1] = safe_close(pipe_fds[1]);
-
- r = sd_bus_message_append(m, "h", pipe_fds[0]);
- assert_se(r >= 0);
-
- pipe_fds[0] = safe_close(pipe_fds[0]);
-
- r = sd_bus_send(b, m, NULL);
- assert_se(r >= 0);
-
- for (;;) {
- sd_bus_message_unref(m);
- m = NULL;
- r = sd_bus_process(a, &m);
- assert_se(r > 0);
- assert_se(m);
-
- bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
- assert_se(sd_bus_message_rewind(m, true) >= 0);
-
- if (sd_bus_message_is_method_call(m, "an.inter.face", "AMethod")) {
- int fd;
- char x;
-
- r = sd_bus_message_read(m, "h", &fd);
- assert_se(r >= 0);
-
- assert_se(read(fd, &x, 1) == 1);
- assert_se(x == 'x');
- break;
- }
- }
-
- r = sd_bus_release_name(a, "net.x0pointer.foobar");
- assert_se(r >= 0);
-
- r = sd_bus_release_name(a, "net.x0pointer.foobar");
- assert_se(r == -ESRCH);
-
- r = sd_bus_try_close(a);
- assert_se(r >= 0);
-
- sd_bus_unref(a);
- sd_bus_unref(b);
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c
deleted file mode 100644
index a28cc5b79e..0000000000
--- a/src/libsystemd/sd-bus/test-bus-marshal.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <math.h>
-#include <stdlib.h>
-
-#ifdef HAVE_GLIB
-#include <gio/gio.h>
-#endif
-
-#ifdef HAVE_DBUS
-#include <dbus/dbus.h>
-#endif
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-dump.h"
-#include "bus-label.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "fd-util.h"
-#include "hexdecoct.h"
-#include "log.h"
-#include "util.h"
-
-static void test_bus_path_encode_unique(void) {
- _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
-
- assert_se(bus_path_encode_unique(NULL, "/foo/bar", "some.sender", "a.suffix", &a) >= 0 && streq_ptr(a, "/foo/bar/some_2esender/a_2esuffix"));
- assert_se(bus_path_decode_unique(a, "/foo/bar", &b, &c) > 0 && streq_ptr(b, "some.sender") && streq_ptr(c, "a.suffix"));
- assert_se(bus_path_decode_unique(a, "/bar/foo", &d, &d) == 0 && !d);
- assert_se(bus_path_decode_unique("/foo/bar/onlyOneSuffix", "/foo/bar", &d, &d) == 0 && !d);
- assert_se(bus_path_decode_unique("/foo/bar/_/_", "/foo/bar", &d, &e) > 0 && streq_ptr(d, "") && streq_ptr(e, ""));
-}
-
-static void test_bus_path_encode(void) {
- _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
-
- assert_se(sd_bus_path_encode("/foo/bar", "waldo", &a) >= 0 && streq(a, "/foo/bar/waldo"));
- assert_se(sd_bus_path_decode(a, "/waldo", &b) == 0 && b == NULL);
- assert_se(sd_bus_path_decode(a, "/foo/bar", &b) > 0 && streq(b, "waldo"));
-
- assert_se(sd_bus_path_encode("xxxx", "waldo", &c) < 0);
- assert_se(sd_bus_path_encode("/foo/", "waldo", &c) < 0);
-
- assert_se(sd_bus_path_encode("/foo/bar", "", &c) >= 0 && streq(c, "/foo/bar/_"));
- assert_se(sd_bus_path_decode(c, "/foo/bar", &d) > 0 && streq(d, ""));
-
- assert_se(sd_bus_path_encode("/foo/bar", "foo.bar", &e) >= 0 && streq(e, "/foo/bar/foo_2ebar"));
- assert_se(sd_bus_path_decode(e, "/foo/bar", &f) > 0 && streq(f, "foo.bar"));
-}
-
-static void test_bus_path_encode_many(void) {
- _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
-
- assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/prefix/bar", "/prefix/%bar", NULL) == 1);
- assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%/suffix", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/prefix/foobar/suffix", "/prefix/%/suffix", &a) == 1 && streq_ptr(a, "foobar"));
- assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", &b, &c) == 1 && streq_ptr(b, "foo") && streq_ptr(c, "bar"));
- assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", NULL, &d) == 1 && streq_ptr(d, "bar"));
-
- assert_se(sd_bus_path_decode_many("/foo/bar", "/foo/bar/%", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar%", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/bar", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%bar", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar/suffix") == 1);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%%/suffix", NULL, NULL) == 0); /* multiple '%' are treated verbatim */
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffi", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffix", &e) == 1 && streq_ptr(e, "bar"));
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/%", NULL, NULL) == 1);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/%", NULL, NULL, NULL) == 1);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%/%/%", NULL, NULL, NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%", NULL, NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/", NULL, NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%", NULL) == 0);
- assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%", NULL) == 0);
-
- assert_se(sd_bus_path_encode_many(&f, "/prefix/one_%_two/mid/three_%_four/suffix", "foo", "bar") >= 0 && streq_ptr(f, "/prefix/one_foo_two/mid/three_bar_four/suffix"));
-}
-
-static void test_bus_label_escape_one(const char *a, const char *b) {
- _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL;
-
- assert_se(t = bus_label_escape(a));
- assert_se(streq(t, b));
-
- assert_se(x = bus_label_unescape(t));
- assert_se(streq(a, x));
-
- assert_se(y = bus_label_unescape(b));
- assert_se(streq(a, y));
-}
-
-static void test_bus_label_escape(void) {
- test_bus_label_escape_one("foo123bar", "foo123bar");
- test_bus_label_escape_one("foo.bar", "foo_2ebar");
- test_bus_label_escape_one("foo_2ebar", "foo_5f2ebar");
- test_bus_label_escape_one("", "_");
- test_bus_label_escape_one("_", "_5f");
- test_bus_label_escape_one("1", "_31");
- test_bus_label_escape_one(":1", "_3a1");
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL;
- int r, boolean;
- const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature;
- uint8_t u, v;
- void *buffer = NULL;
- size_t sz;
- char *h;
- const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array;
- char *s;
- _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL;
- _cleanup_fclose_ FILE *ms = NULL;
- size_t first_size = 0, second_size = 0, third_size = 0;
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
- double dbl;
- uint64_t u64;
-
- r = sd_bus_default_system(&bus);
- if (r < 0)
- return EXIT_TEST_SKIP;
-
- r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep");
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "");
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "s", "a string");
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "s", NULL);
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss");
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after");
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo");
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10);
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "()");
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3");
- assert_se(r >= 0);
-
- r = sd_bus_message_open_container(m, 'a', "s");
- assert_se(r >= 0);
-
- r = sd_bus_message_append_basic(m, 's', "foobar");
- assert_se(r >= 0);
-
- r = sd_bus_message_append_basic(m, 's', "waldo");
- assert_se(r >= 0);
-
- r = sd_bus_message_close_container(m);
- assert_se(r >= 0);
-
- r = sd_bus_message_append_string_space(m, 5, &s);
- assert_se(r >= 0);
- strcpy(s, "hallo");
-
- r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array));
- assert_se(r >= 0);
-
- r = sd_bus_message_append_array(m, 'u', NULL, 0);
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/");
- assert_se(r >= 0);
-
- r = bus_message_seal(m, 4711, 0);
- assert_se(r >= 0);
-
- bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- ms = open_memstream(&first, &first_size);
- bus_message_dump(m, ms, 0);
- fflush(ms);
- assert_se(!ferror(ms));
-
- r = bus_message_get_blob(m, &buffer, &sz);
- assert_se(r >= 0);
-
- h = hexmem(buffer, sz);
- assert_se(h);
-
- log_info("message size = %zu, contents =\n%s", sz, h);
- free(h);
-
-#ifdef HAVE_GLIB
- {
- GDBusMessage *g;
- char *p;
-
-#if !defined(GLIB_VERSION_2_36)
- g_type_init();
-#endif
-
- g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL);
- p = g_dbus_message_print(g, 0);
- log_info("%s", p);
- g_free(p);
- g_object_unref(g);
- }
-#endif
-
-#ifdef HAVE_DBUS
- {
- DBusMessage *w;
- DBusError error;
-
- dbus_error_init(&error);
-
- w = dbus_message_demarshal(buffer, sz, &error);
- if (!w)
- log_error("%s", error.message);
- else
- dbus_message_unref(w);
-
- dbus_error_free(&error);
- }
-#endif
-
- m = sd_bus_message_unref(m);
-
- r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m);
- assert_se(r >= 0);
-
- bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- fclose(ms);
- ms = open_memstream(&second, &second_size);
- bus_message_dump(m, ms, 0);
- fflush(ms);
- assert_se(!ferror(ms));
- assert_se(first_size == second_size);
- assert_se(memcmp(first, second, first_size) == 0);
-
- assert_se(sd_bus_message_rewind(m, true) >= 0);
-
- r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature);
- assert_se(r > 0);
- assert_se(streq(x, "a string"));
- assert_se(streq(x2, ""));
- assert_se(streq(y, "string #1"));
- assert_se(streq(z, "string #2"));
- assert_se(streq(a_signature, "sba(tt)ss"));
-
- r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d);
- assert_se(r > 0);
- assert_se(streq(x, "foobar"));
- assert_se(streq(y, "foo"));
- assert_se(streq(z, "bar"));
- assert_se(streq(a, "waldo"));
- assert_se(streq(b, "piep"));
- assert_se(streq(c, "pap"));
- assert_se(streq(d, "after"));
-
- r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y);
- assert_se(r > 0);
- assert_se(u == 3);
- assert_se(streq(x, "foo"));
- assert_se(v == 5);
- assert_se(streq(y, "waldo"));
-
- r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u);
- assert_se(r > 0);
- assert_se(v == 8);
- assert_se(u64 == 777);
- assert_se(u == 7);
-
- r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64);
- assert_se(r > 0);
- assert_se(v == 9);
- assert_se(u == 77);
- assert_se(u64 == 7777);
-
- r = sd_bus_message_read(m, "y", &v);
- assert_se(r > 0);
- assert_se(v == 10);
-
- r = sd_bus_message_read(m, "()");
- assert_se(r > 0);
-
- r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d);
- assert_se(r > 0);
- assert_se(boolean);
- assert_se(streq(x, "aaa"));
- assert_se(streq(y, "1"));
- assert_se(streq(a, "bbb"));
- assert_se(streq(b, "2"));
- assert_se(streq(c, "ccc"));
- assert_se(streq(d, "3"));
-
- assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0);
-
- r = sd_bus_message_read(m, "as", 2, &x, &y);
- assert_se(r > 0);
- assert_se(streq(x, "foobar"));
- assert_se(streq(y, "waldo"));
-
- r = sd_bus_message_read_basic(m, 's', &s);
- assert_se(r > 0);
- assert_se(streq(s, "hallo"));
-
- r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz);
- assert_se(r > 0);
- assert_se(sz == sizeof(integer_array));
- assert_se(memcmp(integer_array, return_array, sz) == 0);
-
- r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz);
- assert_se(r > 0);
- assert_se(sz == 0);
-
- r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y);
- assert_se(r > 0);
- assert_se(streq(x, "foo"));
- assert_se(u64 == 815ULL);
- assert_se(fabs(dbl - 47.0) < 0.1);
- assert_se(streq(y, "/"));
-
- r = sd_bus_message_peek_type(m, NULL, NULL);
- assert_se(r == 0);
-
- r = sd_bus_message_new_method_call(bus, &copy, "foobar.waldo", "/", "foobar.waldo", "Piep");
- assert_se(r >= 0);
-
- r = sd_bus_message_rewind(m, true);
- assert_se(r >= 0);
-
- r = sd_bus_message_copy(copy, m, true);
- assert_se(r >= 0);
-
- r = bus_message_seal(copy, 4712, 0);
- assert_se(r >= 0);
-
- fclose(ms);
- ms = open_memstream(&third, &third_size);
- bus_message_dump(copy, ms, 0);
- fflush(ms);
- assert_se(!ferror(ms));
-
- printf("<%.*s>\n", (int) first_size, first);
- printf("<%.*s>\n", (int) third_size, third);
-
- assert_se(first_size == third_size);
- assert_se(memcmp(first, third, third_size) == 0);
-
- r = sd_bus_message_rewind(m, true);
- assert_se(r >= 0);
-
- assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
-
- r = sd_bus_message_skip(m, "ssasg");
- assert_se(r > 0);
-
- assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0);
-
- r = sd_bus_message_skip(m, "sass");
- assert_se(r >= 0);
-
- assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0);
-
- r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y()");
- assert_se(r >= 0);
-
- assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0);
-
- r = sd_bus_message_read(m, "b", &boolean);
- assert_se(r > 0);
- assert_se(boolean);
-
- r = sd_bus_message_enter_container(m, 0, NULL);
- assert_se(r > 0);
-
- r = sd_bus_message_read(m, "(ss)", &x, &y);
- assert_se(r > 0);
-
- r = sd_bus_message_read(m, "(ss)", &a, &b);
- assert_se(r > 0);
-
- r = sd_bus_message_read(m, "(ss)", &c, &d);
- assert_se(r > 0);
-
- r = sd_bus_message_read(m, "(ss)", &x, &y);
- assert_se(r == 0);
-
- r = sd_bus_message_exit_container(m);
- assert_se(r >= 0);
-
- assert_se(streq(x, "aaa"));
- assert_se(streq(y, "1"));
- assert_se(streq(a, "bbb"));
- assert_se(streq(b, "2"));
- assert_se(streq(c, "ccc"));
- assert_se(streq(d, "3"));
-
- test_bus_label_escape();
- test_bus_path_encode();
- test_bus_path_encode_unique();
- test_bus_path_encode_many();
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c
deleted file mode 100644
index 29c4529f95..0000000000
--- a/src/libsystemd/sd-bus/test-bus-match.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-match.h"
-#include "bus-message.h"
-#include "bus-slot.h"
-#include "bus-util.h"
-#include "log.h"
-#include "macro.h"
-
-static bool mask[32];
-
-static int filter(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- log_info("Ran %u", PTR_TO_UINT(userdata));
- assert_se(PTR_TO_UINT(userdata) < ELEMENTSOF(mask));
- mask[PTR_TO_UINT(userdata)] = true;
- return 0;
-}
-
-static bool mask_contains(unsigned a[], unsigned n) {
- unsigned i, j;
-
- for (i = 0; i < ELEMENTSOF(mask); i++) {
- bool found = false;
-
- for (j = 0; j < n; j++)
- if (a[j] == i) {
- found = true;
- break;
- }
-
- if (found != mask[i])
- return false;
- }
-
- return true;
-}
-
-static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) {
- struct bus_match_component *components = NULL;
- unsigned n_components = 0;
- sd_bus_slot *s;
- int r;
-
- s = slots + value;
- zero(*s);
-
- r = bus_match_parse(match, &components, &n_components);
- if (r < 0)
- return r;
-
- s->userdata = INT_TO_PTR(value);
- s->match_callback.callback = filter;
-
- r = bus_match_add(root, components, n_components, &s->match_callback);
- bus_match_parse_free(components, n_components);
-
- return r;
-}
-
-static void test_match_scope(const char *match, enum bus_match_scope scope) {
- struct bus_match_component *components = NULL;
- unsigned n_components = 0;
-
- assert_se(bus_match_parse(match, &components, &n_components) >= 0);
- assert_se(bus_match_get_scope(components, n_components) == scope);
- bus_match_parse_free(components, n_components);
-}
-
-int main(int argc, char *argv[]) {
- struct bus_match_node root = {
- .type = BUS_MATCH_ROOT,
- };
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- enum bus_match_node_type i;
- sd_bus_slot slots[19];
- int r;
-
- r = sd_bus_open_system(&bus);
- if (r < 0)
- return EXIT_TEST_SKIP;
-
- assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0);
- assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0);
- assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0);
- assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0);
- assert_se(match_add(slots, &root, "", 5) >= 0);
- assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0);
- assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0);
- assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0);
- assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0);
- assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0);
- assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0);
- assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0);
- assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
- assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
- assert_se(match_add(slots, &root, "arg4has='pi'", 15) >= 0);
- assert_se(match_add(slots, &root, "arg4has='pa'", 16) >= 0);
- assert_se(match_add(slots, &root, "arg4has='po'", 17) >= 0);
- assert_se(match_add(slots, &root, "arg4='pi'", 18) >= 0);
-
- bus_match_dump(&root, 0);
-
- assert_se(sd_bus_message_new_signal(bus, &m, "/foo/bar", "bar.x", "waldo") >= 0);
- assert_se(sd_bus_message_append(m, "ssssas", "one", "two", "/prefix/three", "prefix.four", 3, "pi", "pa", "po") >= 0);
- assert_se(bus_message_seal(m, 1, 0) >= 0);
-
- zero(mask);
- assert_se(bus_match_run(NULL, &root, m) == 0);
- assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14, 15, 16, 17 }, 11));
-
- assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0);
- assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0);
-
- bus_match_dump(&root, 0);
-
- zero(mask);
- assert_se(bus_match_run(NULL, &root, m) == 0);
- assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7, 15, 16, 17 }, 9));
-
- for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) {
- char buf[32];
- const char *x;
-
- assert_se(x = bus_match_node_type_to_string(i, buf, sizeof(buf)));
-
- if (i >= BUS_MATCH_MESSAGE_TYPE)
- assert_se(bus_match_node_type_from_string(x, strlen(x)) == i);
- }
-
- bus_match_free(&root);
-
- test_match_scope("interface='foobar'", BUS_MATCH_GENERIC);
- test_match_scope("", BUS_MATCH_GENERIC);
- test_match_scope("interface='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL);
- test_match_scope("sender='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL);
- test_match_scope("member='gurke',path='/org/freedesktop/DBus/Local'", BUS_MATCH_LOCAL);
- test_match_scope("arg2='piep',sender='org.freedesktop.DBus',member='waldo'", BUS_MATCH_DRIVER);
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c
deleted file mode 100644
index f11cafd888..0000000000
--- a/src/libsystemd/sd-bus/test-bus-objects.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-dump.h"
-#include "bus-internal.h"
-#include "bus-message.h"
-#include "bus-util.h"
-#include "log.h"
-#include "macro.h"
-#include "strv.h"
-#include "util.h"
-
-struct context {
- int fds[2];
- bool quit;
- char *something;
- char *automatic_string_property;
- uint32_t automatic_integer_property;
-};
-
-static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- struct context *c = userdata;
- const char *s;
- char *n = NULL;
- int r;
-
- r = sd_bus_message_read(m, "s", &s);
- assert_se(r > 0);
-
- n = strjoin("<<<", s, ">>>", NULL);
- assert_se(n);
-
- free(c->something);
- c->something = n;
-
- log_info("AlterSomething() called, got %s, returning %s", s, n);
-
- /* This should fail, since the return type doesn't match */
- assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG);
-
- r = sd_bus_reply_method_return(m, "s", n);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- struct context *c = userdata;
- int r;
-
- c->quit = true;
-
- log_info("Exit called");
-
- r = sd_bus_reply_method_return(m, "");
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- struct context *c = userdata;
- int r;
-
- log_info("property get for %s called, returning \"%s\".", property, c->something);
-
- r = sd_bus_message_append(reply, "s", c->something);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
- struct context *c = userdata;
- const char *s;
- char *n;
- int r;
-
- log_info("property set for %s called", property);
-
- r = sd_bus_message_read(value, "s", &s);
- assert_se(r >= 0);
-
- n = strdup(s);
- assert_se(n);
-
- free(c->something);
- c->something = n;
-
- return 1;
-}
-
-static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
- _cleanup_free_ char *s = NULL;
- const char *x;
- int r;
-
- assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
- r = sd_bus_message_append(reply, "s", s);
- assert_se(r >= 0);
-
- assert_se(x = startswith(path, "/value/"));
-
- assert_se(PTR_TO_UINT(userdata) == 30);
-
- return 1;
-}
-
-static int notify_test(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int r;
-
- assert_se(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
-
- r = sd_bus_reply_method_return(m, NULL);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int r;
-
- assert_se(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0);
-
- r = sd_bus_reply_method_return(m, NULL);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int r;
-
- assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
-
- r = sd_bus_reply_method_return(m, NULL);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int r;
-
- assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0);
-
- r = sd_bus_reply_method_return(m, NULL);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int r;
-
- assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
-
- r = sd_bus_reply_method_return(m, NULL);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
- int r;
-
- assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0);
-
- r = sd_bus_reply_method_return(m, NULL);
- assert_se(r >= 0);
-
- return 1;
-}
-
-static const sd_bus_vtable vtable[] = {
- SD_BUS_VTABLE_START(0),
- SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
- SD_BUS_METHOD("Exit", "", "", exit_handler, 0),
- SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
- SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0),
- SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0),
- SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
- SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0),
- SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0),
- SD_BUS_METHOD("EmitObjectAdded", NULL, NULL, emit_object_added, 0),
- SD_BUS_METHOD("EmitObjectRemoved", NULL, NULL, emit_object_removed, 0),
- SD_BUS_VTABLE_END
-};
-
-static const sd_bus_vtable vtable2[] = {
- SD_BUS_VTABLE_START(0),
- SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0),
- SD_BUS_METHOD("NotifyTest2", "", "", notify_test2, 0),
- SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
- SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
- SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something), SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
- SD_BUS_VTABLE_END
-};
-
-static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
-
- if (object_path_startswith("/value", path))
- assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
-
- return 1;
-}
-
-static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
-
- if (object_path_startswith("/value/a", path))
- assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z", NULL));
-
- return 1;
-}
-
-static void *server(void *p) {
- struct context *c = p;
- sd_bus *bus = NULL;
- sd_id128_t id;
- int r;
-
- c->quit = false;
-
- assert_se(sd_id128_randomize(&id) >= 0);
-
- assert_se(sd_bus_new(&bus) >= 0);
- assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
- assert_se(sd_bus_set_server(bus, 1, id) >= 0);
-
- assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
- assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
- assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
- assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
- assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0);
- assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
- assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0);
-
- assert_se(sd_bus_start(bus) >= 0);
-
- log_error("Entering event loop on server");
-
- while (!c->quit) {
- log_error("Loop!");
-
- r = sd_bus_process(bus, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to process requests: %m");
- goto fail;
- }
-
- if (r == 0) {
- r = sd_bus_wait(bus, (uint64_t) -1);
- if (r < 0) {
- log_error_errno(r, "Failed to wait: %m");
- goto fail;
- }
-
- continue;
- }
- }
-
- r = 0;
-
-fail:
- if (bus) {
- sd_bus_flush(bus);
- sd_bus_unref(bus);
- }
-
- return INT_TO_PTR(r);
-}
-
-static int client(struct context *c) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *s;
- int r;
-
- assert_se(sd_bus_new(&bus) >= 0);
- assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
- assert_se(sd_bus_start(bus) >= 0);
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL);
- assert_se(r >= 0);
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- assert_se(streq(s, "<<<hallo>>>"));
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
- assert_se(r < 0);
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
-
- sd_bus_error_free(&error);
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
- assert_se(r < 0);
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
-
- sd_bus_error_free(&error);
-
- r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- assert_se(streq(s, "<<<hallo>>>"));
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
- assert_se(r >= 0);
-
- r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- assert_se(streq(s, "test"));
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
- assert_se(r >= 0);
-
- assert_se(c->automatic_integer_property == 815);
-
- r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
- assert_se(r >= 0);
-
- assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- fputs(s, stdout);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- log_info("read %s", s);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- fputs(s, stdout);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- fputs(s, stdout);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
- assert_se(r >= 0);
-
- r = sd_bus_message_read(reply, "s", &s);
- assert_se(r >= 0);
- fputs(s, stdout);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
- assert_se(r >= 0);
-
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
- assert_se(r < 0);
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
- sd_bus_error_free(&error);
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
- assert_se(r < 0);
- assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
- sd_bus_error_free(&error);
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
- assert_se(r >= 0);
-
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
- assert_se(r >= 0);
-
- r = sd_bus_process(bus, &reply);
- assert_se(r > 0);
-
- assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, "");
- assert_se(r >= 0);
-
- r = sd_bus_process(bus, &reply);
- assert_se(r > 0);
-
- assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, "");
- assert_se(r >= 0);
-
- r = sd_bus_process(bus, &reply);
- assert_se(r > 0);
-
- assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, "");
- assert_se(r >= 0);
-
- r = sd_bus_process(bus, &reply);
- assert_se(r > 0);
-
- assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, "");
- assert_se(r >= 0);
-
- r = sd_bus_process(bus, &reply);
- assert_se(r > 0);
-
- assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, "");
- assert_se(r >= 0);
-
- r = sd_bus_process(bus, &reply);
- assert_se(r > 0);
-
- assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
- bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- sd_bus_message_unref(reply);
- reply = NULL;
-
- r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
- assert_se(r >= 0);
-
- sd_bus_flush(bus);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- struct context c = {};
- pthread_t s;
- void *p;
- int r, q;
-
- zero(c);
-
- c.automatic_integer_property = 4711;
- assert_se(c.automatic_string_property = strdup("dudeldu"));
-
- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
-
- r = pthread_create(&s, NULL, server, &c);
- if (r != 0)
- return -r;
-
- r = client(&c);
-
- q = pthread_join(s, &p);
- if (q != 0)
- return -q;
-
- if (r < 0)
- return r;
-
- if (PTR_TO_INT(p) < 0)
- return PTR_TO_INT(p);
-
- free(c.something);
- free(c.automatic_string_property);
-
- return EXIT_SUCCESS;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c
deleted file mode 100644
index b6272efc30..0000000000
--- a/src/libsystemd/sd-bus/test-bus-server.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "sd-bus.h"
-
-#include "bus-internal.h"
-#include "bus-util.h"
-#include "log.h"
-#include "macro.h"
-#include "util.h"
-
-struct context {
- int fds[2];
-
- bool client_negotiate_unix_fds;
- bool server_negotiate_unix_fds;
-
- bool client_anonymous_auth;
- bool server_anonymous_auth;
-};
-
-static void *server(void *p) {
- struct context *c = p;
- sd_bus *bus = NULL;
- sd_id128_t id;
- bool quit = false;
- int r;
-
- assert_se(sd_id128_randomize(&id) >= 0);
-
- assert_se(sd_bus_new(&bus) >= 0);
- assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
- assert_se(sd_bus_set_server(bus, 1, id) >= 0);
- assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
- assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
- assert_se(sd_bus_start(bus) >= 0);
-
- while (!quit) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
-
- r = sd_bus_process(bus, &m);
- if (r < 0) {
- log_error_errno(r, "Failed to process requests: %m");
- goto fail;
- }
-
- if (r == 0) {
- r = sd_bus_wait(bus, (uint64_t) -1);
- if (r < 0) {
- log_error_errno(r, "Failed to wait: %m");
- goto fail;
- }
-
- continue;
- }
-
- if (!m)
- continue;
-
- log_info("Got message! member=%s", strna(sd_bus_message_get_member(m)));
-
- if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
-
- assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
-
- r = sd_bus_message_new_method_return(m, &reply);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate return: %m");
- goto fail;
- }
-
- quit = true;
-
- } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
- r = sd_bus_message_new_method_error(
- m,
- &reply,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
- if (r < 0) {
- log_error_errno(r, "Failed to allocate return: %m");
- goto fail;
- }
- }
-
- if (reply) {
- r = sd_bus_send(bus, reply, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to send reply: %m");
- goto fail;
- }
- }
- }
-
- r = 0;
-
-fail:
- if (bus) {
- sd_bus_flush(bus);
- sd_bus_unref(bus);
- }
-
- return INT_TO_PTR(r);
-}
-
-static int client(struct context *c) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
- sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
-
- assert_se(sd_bus_new(&bus) >= 0);
- assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
- assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
- assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
- assert_se(sd_bus_start(bus) >= 0);
-
- r = sd_bus_message_new_method_call(
- bus,
- &m,
- "org.freedesktop.systemd.test",
- "/",
- "org.freedesktop.systemd.test",
- "Exit");
- if (r < 0)
- return log_error_errno(r, "Failed to allocate method call: %m");
-
- r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0) {
- log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
- return r;
- }
-
- return 0;
-}
-
-static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds,
- bool client_anonymous_auth, bool server_anonymous_auth) {
-
- struct context c;
- pthread_t s;
- void *p;
- int r, q;
-
- zero(c);
-
- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
-
- c.client_negotiate_unix_fds = client_negotiate_unix_fds;
- c.server_negotiate_unix_fds = server_negotiate_unix_fds;
- c.client_anonymous_auth = client_anonymous_auth;
- c.server_anonymous_auth = server_anonymous_auth;
-
- r = pthread_create(&s, NULL, server, &c);
- if (r != 0)
- return -r;
-
- r = client(&c);
-
- q = pthread_join(s, &p);
- if (q != 0)
- return -q;
-
- if (r < 0)
- return r;
-
- if (PTR_TO_INT(p) < 0)
- return PTR_TO_INT(p);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- r = test_one(true, true, false, false);
- assert_se(r >= 0);
-
- r = test_one(true, false, false, false);
- assert_se(r >= 0);
-
- r = test_one(false, true, false, false);
- assert_se(r >= 0);
-
- r = test_one(false, false, false, false);
- assert_se(r >= 0);
-
- r = test_one(true, true, true, true);
- assert_se(r >= 0);
-
- r = test_one(true, true, false, true);
- assert_se(r >= 0);
-
- r = test_one(true, true, true, false);
- assert_se(r == -EPERM);
-
- return EXIT_SUCCESS;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c
deleted file mode 100644
index 4f4fd093bf..0000000000
--- a/src/libsystemd/sd-bus/test-bus-signature.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-internal.h"
-#include "bus-signature.h"
-#include "log.h"
-#include "string-util.h"
-
-int main(int argc, char *argv[]) {
- char prefix[256];
- int r;
-
- assert_se(signature_is_single("y", false));
- assert_se(signature_is_single("u", false));
- assert_se(signature_is_single("v", false));
- assert_se(signature_is_single("as", false));
- assert_se(signature_is_single("(ss)", false));
- assert_se(signature_is_single("()", false));
- assert_se(signature_is_single("(()()()()())", false));
- assert_se(signature_is_single("(((())))", false));
- assert_se(signature_is_single("((((s))))", false));
- assert_se(signature_is_single("{ss}", true));
- assert_se(signature_is_single("a{ss}", false));
- assert_se(!signature_is_single("uu", false));
- assert_se(!signature_is_single("", false));
- assert_se(!signature_is_single("(", false));
- assert_se(!signature_is_single(")", false));
- assert_se(!signature_is_single("())", false));
- assert_se(!signature_is_single("((())", false));
- assert_se(!signature_is_single("{)", false));
- assert_se(!signature_is_single("{}", true));
- assert_se(!signature_is_single("{sss}", true));
- assert_se(!signature_is_single("{s}", true));
- assert_se(!signature_is_single("{ss}", false));
- assert_se(!signature_is_single("{ass}", true));
- assert_se(!signature_is_single("a}", true));
-
- assert_se(signature_is_pair("yy"));
- assert_se(signature_is_pair("ss"));
- assert_se(signature_is_pair("sas"));
- assert_se(signature_is_pair("sv"));
- assert_se(signature_is_pair("sa(vs)"));
- assert_se(!signature_is_pair(""));
- assert_se(!signature_is_pair("va"));
- assert_se(!signature_is_pair("sss"));
- assert_se(!signature_is_pair("{s}ss"));
-
- assert_se(signature_is_valid("ssa{ss}sssub", true));
- assert_se(signature_is_valid("ssa{ss}sssub", false));
- assert_se(signature_is_valid("{ss}", true));
- assert_se(!signature_is_valid("{ss}", false));
- assert_se(signature_is_valid("", true));
- assert_se(signature_is_valid("", false));
-
- assert_se(signature_is_valid("sssusa(uuubbba(uu)uuuu)a{u(uuuvas)}", false));
-
- assert_se(!signature_is_valid("a", false));
- assert_se(signature_is_valid("as", false));
- assert_se(signature_is_valid("aas", false));
- assert_se(signature_is_valid("aaas", false));
- assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad", false));
- assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", false));
- assert_se(!signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau", false));
-
- assert_se(signature_is_valid("(((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))", false));
- assert_se(!signature_is_valid("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false));
-
- assert_se(namespace_complex_pattern("", ""));
- assert_se(namespace_complex_pattern("foobar", "foobar"));
- assert_se(namespace_complex_pattern("foobar.waldo", "foobar.waldo"));
- assert_se(namespace_complex_pattern("foobar.", "foobar.waldo"));
- assert_se(namespace_complex_pattern("foobar.waldo", "foobar."));
- assert_se(!namespace_complex_pattern("foobar.waldo", "foobar"));
- assert_se(!namespace_complex_pattern("foobar", "foobar.waldo"));
- assert_se(!namespace_complex_pattern("", "foo"));
- assert_se(!namespace_complex_pattern("foo", ""));
- assert_se(!namespace_complex_pattern("foo.", ""));
-
- assert_se(path_complex_pattern("", ""));
- assert_se(!path_complex_pattern("", "/"));
- assert_se(!path_complex_pattern("/", ""));
- assert_se(path_complex_pattern("/", "/"));
- assert_se(path_complex_pattern("/foobar/", "/"));
- assert_se(!path_complex_pattern("/foobar/", "/foobar"));
- assert_se(path_complex_pattern("/foobar", "/foobar"));
- assert_se(!path_complex_pattern("/foobar", "/foobar/"));
- assert_se(!path_complex_pattern("/foobar", "/foobar/waldo"));
- assert_se(path_complex_pattern("/foobar/", "/foobar/waldo"));
- assert_se(path_complex_pattern("/foobar/waldo", "/foobar/"));
-
- assert_se(path_simple_pattern("/foo/", "/foo/bar/waldo"));
-
- assert_se(namespace_simple_pattern("", ""));
- assert_se(namespace_simple_pattern("", ".foobar"));
- assert_se(namespace_simple_pattern("foobar", "foobar"));
- assert_se(namespace_simple_pattern("foobar.waldo", "foobar.waldo"));
- assert_se(namespace_simple_pattern("foobar", "foobar.waldo"));
- assert_se(!namespace_simple_pattern("foobar.waldo", "foobar"));
- assert_se(!namespace_simple_pattern("", "foo"));
- assert_se(!namespace_simple_pattern("foo", ""));
- assert_se(namespace_simple_pattern("foo.", "foo.bar.waldo"));
-
- assert_se(streq(object_path_startswith("/foo/bar", "/foo"), "bar"));
- assert_se(streq(object_path_startswith("/foo", "/foo"), ""));
- assert_se(streq(object_path_startswith("/foo", "/"), "foo"));
- assert_se(streq(object_path_startswith("/", "/"), ""));
- assert_se(!object_path_startswith("/foo", "/bar"));
- assert_se(!object_path_startswith("/", "/bar"));
- assert_se(!object_path_startswith("/foo", ""));
-
- assert_se(object_path_is_valid("/foo/bar"));
- assert_se(object_path_is_valid("/foo"));
- assert_se(object_path_is_valid("/"));
- assert_se(object_path_is_valid("/foo5"));
- assert_se(object_path_is_valid("/foo_5"));
- assert_se(!object_path_is_valid(""));
- assert_se(!object_path_is_valid("/foo/"));
- assert_se(!object_path_is_valid("//"));
- assert_se(!object_path_is_valid("//foo"));
- assert_se(!object_path_is_valid("/foo//bar"));
- assert_se(!object_path_is_valid("/foo/aaaäöä"));
-
- OBJECT_PATH_FOREACH_PREFIX(prefix, "/") {
- log_info("<%s>", prefix);
- assert_not_reached("???");
- }
-
- r = 0;
- OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx") {
- log_info("<%s>", prefix);
- assert_se(streq(prefix, "/"));
- assert_se(r == 0);
- r++;
- }
- assert_se(r == 1);
-
- r = 0;
- OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx/yyy/zzz") {
- log_info("<%s>", prefix);
- assert_se(r != 0 || streq(prefix, "/xxx/yyy"));
- assert_se(r != 1 || streq(prefix, "/xxx"));
- assert_se(r != 2 || streq(prefix, "/"));
- r++;
- }
- assert_se(r == 3);
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-track.c b/src/libsystemd/sd-bus/test-bus-track.c
deleted file mode 100644
index 4beb61f05a..0000000000
--- a/src/libsystemd/sd-bus/test-bus-track.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sd-bus.h>
-
-#include "macro.h"
-
-static bool track_cb_called_x = false;
-static bool track_cb_called_y = false;
-
-static int track_cb_x(sd_bus_track *t, void *userdata) {
-
- log_error("TRACK CB X");
-
- assert_se(!track_cb_called_x);
- track_cb_called_x = true;
-
- /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works
- * as it should. */
-
- assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0);
- return 1;
-}
-
-static int track_cb_y(sd_bus_track *t, void *userdata) {
- int r;
-
- log_error("TRACK CB Y");
-
- assert_se(!track_cb_called_y);
- track_cb_called_y = true;
-
- /* We got disconnected, let's close everything */
-
- r = sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS);
- assert_se(r >= 0);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_(sd_event_unrefp) sd_event *event = NULL;
- _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL;
- _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL;
- const char *unique;
- int r;
-
- r = sd_event_default(&event);
- assert_se(r >= 0);
-
- r = sd_bus_open_system(&a);
- if (IN_SET(r, -ECONNREFUSED, -ENOENT)) {
- log_info("Failed to connect to bus, skipping tests.");
- return EXIT_TEST_SKIP;
- }
- assert_se(r >= 0);
-
- r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL);
- assert_se(r >= 0);
-
- r = sd_bus_open_system(&b);
- assert_se(r >= 0);
-
- r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL);
- assert_se(r >= 0);
-
- /* Watch b's name from a */
- r = sd_bus_track_new(a, &x, track_cb_x, NULL);
- assert_se(r >= 0);
-
- r = sd_bus_get_unique_name(b, &unique);
- assert_se(r >= 0);
-
- r = sd_bus_track_add_name(x, unique);
- assert_se(r >= 0);
-
- /* Watch's a's own name from a */
- r = sd_bus_track_new(a, &y, track_cb_y, NULL);
- assert_se(r >= 0);
-
- r = sd_bus_get_unique_name(a, &unique);
- assert_se(r >= 0);
-
- r = sd_bus_track_add_name(y, unique);
- assert_se(r >= 0);
-
- /* Now make b's name disappear */
- sd_bus_close(b);
-
- r = sd_event_loop(event);
- assert_se(r >= 0);
-
- assert_se(track_cb_called_x);
- assert_se(track_cb_called_y);
-
- return 0;
-}
diff --git a/src/libsystemd/sd-bus/test-bus-zero-copy.c b/src/libsystemd/sd-bus/test-bus-zero-copy.c
deleted file mode 100644
index 3380e8500a..0000000000
--- a/src/libsystemd/sd-bus/test-bus-zero-copy.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/mman.h>
-
-#include "sd-bus.h"
-
-#include "alloc-util.h"
-#include "bus-dump.h"
-#include "bus-kernel.h"
-#include "bus-message.h"
-#include "fd-util.h"
-#include "log.h"
-#include "memfd-util.h"
-#include "string-util.h"
-#include "util.h"
-
-#define FIRST_ARRAY 17
-#define SECOND_ARRAY 33
-
-#define STRING_SIZE 123
-
-int main(int argc, char *argv[]) {
- _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
- const char *unique;
- uint8_t *p;
- sd_bus *a, *b;
- int r, bus_ref;
- sd_bus_message *m;
- int f;
- uint64_t sz;
- uint32_t u32;
- size_t i, l;
- char *s;
- _cleanup_close_ int sfd = -1;
-
- log_set_max_level(LOG_DEBUG);
-
- assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);
-
- bus_ref = bus_kernel_create_bus(name, false, &bus_name);
- if (bus_ref == -ENOENT)
- return EXIT_TEST_SKIP;
-
- assert_se(bus_ref >= 0);
-
- address = strappend("kernel:path=", bus_name);
- assert_se(address);
-
- r = sd_bus_new(&a);
- assert_se(r >= 0);
-
- r = sd_bus_new(&b);
- assert_se(r >= 0);
-
- r = sd_bus_set_address(a, address);
- assert_se(r >= 0);
-
- r = sd_bus_set_address(b, address);
- assert_se(r >= 0);
-
- r = sd_bus_start(a);
- assert_se(r >= 0);
-
- r = sd_bus_start(b);
- assert_se(r >= 0);
-
- r = sd_bus_get_unique_name(a, &unique);
- assert_se(r >= 0);
-
- r = sd_bus_message_new_method_call(b, &m, unique, "/a/path", "an.inter.face", "AMethod");
- assert_se(r >= 0);
-
- r = sd_bus_message_open_container(m, 'r', "aysay");
- assert_se(r >= 0);
-
- r = sd_bus_message_append_array_space(m, 'y', FIRST_ARRAY, (void**) &p);
- assert_se(r >= 0);
-
- p[0] = '<';
- memset(p+1, 'L', FIRST_ARRAY-2);
- p[FIRST_ARRAY-1] = '>';
-
- f = memfd_new_and_map(NULL, STRING_SIZE, (void**) &s);
- assert_se(f >= 0);
-
- s[0] = '<';
- for (i = 1; i < STRING_SIZE-2; i++)
- s[i] = '0' + (i % 10);
- s[STRING_SIZE-2] = '>';
- s[STRING_SIZE-1] = 0;
- munmap(s, STRING_SIZE);
-
- r = memfd_get_size(f, &sz);
- assert_se(r >= 0);
- assert_se(sz == STRING_SIZE);
-
- r = sd_bus_message_append_string_memfd(m, f, 0, (uint64_t) -1);
- assert_se(r >= 0);
-
- close(f);
-
- f = memfd_new_and_map(NULL, SECOND_ARRAY, (void**) &p);
- assert_se(f >= 0);
-
- p[0] = '<';
- memset(p+1, 'P', SECOND_ARRAY-2);
- p[SECOND_ARRAY-1] = '>';
- munmap(p, SECOND_ARRAY);
-
- r = memfd_get_size(f, &sz);
- assert_se(r >= 0);
- assert_se(sz == SECOND_ARRAY);
-
- r = sd_bus_message_append_array_memfd(m, 'y', f, 0, (uint64_t) -1);
- assert_se(r >= 0);
-
- close(f);
-
- r = sd_bus_message_close_container(m);
- assert_se(r >= 0);
-
- r = sd_bus_message_append(m, "u", 4711);
- assert_se(r >= 0);
-
- assert_se((sfd = memfd_new_and_map(NULL, 6, (void**) &p)) >= 0);
- memcpy(p, "abcd\0", 6);
- munmap(p, 6);
- assert_se(sd_bus_message_append_string_memfd(m, sfd, 1, 4) >= 0);
-
- r = bus_message_seal(m, 55, 99*USEC_PER_SEC);
- assert_se(r >= 0);
-
- bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
-
- r = sd_bus_send(b, m, NULL);
- assert_se(r >= 0);
-
- sd_bus_message_unref(m);
-
- r = sd_bus_process(a, &m);
- assert_se(r > 0);
-
- bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
- sd_bus_message_rewind(m, true);
-
- r = sd_bus_message_enter_container(m, 'r', "aysay");
- assert_se(r > 0);
-
- r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
- assert_se(r > 0);
- assert_se(l == FIRST_ARRAY);
-
- assert_se(p[0] == '<');
- for (i = 1; i < l-1; i++)
- assert_se(p[i] == 'L');
- assert_se(p[l-1] == '>');
-
- r = sd_bus_message_read(m, "s", &s);
- assert_se(r > 0);
-
- assert_se(s[0] == '<');
- for (i = 1; i < STRING_SIZE-2; i++)
- assert_se(s[i] == (char) ('0' + (i % 10)));
- assert_se(s[STRING_SIZE-2] == '>');
- assert_se(s[STRING_SIZE-1] == 0);
-
- r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
- assert_se(r > 0);
- assert_se(l == SECOND_ARRAY);
-
- assert_se(p[0] == '<');
- for (i = 1; i < l-1; i++)
- assert_se(p[i] == 'P');
- assert_se(p[l-1] == '>');
-
- r = sd_bus_message_exit_container(m);
- assert_se(r > 0);
-
- r = sd_bus_message_read(m, "u", &u32);
- assert_se(r > 0);
- assert_se(u32 == 4711);
-
- r = sd_bus_message_read(m, "s", &s);
- assert_se(r > 0);
- assert_se(streq_ptr(s, "bcd"));
-
- sd_bus_message_unref(m);
-
- sd_bus_unref(a);
- sd_bus_unref(b);
-
- return 0;
-}