['sd_bus_message_append_strv', '3', [], ''],
['sd_bus_message_at_end', '3', [], ''],
['sd_bus_message_copy', '3', [], ''],
- ['sd_bus_message_dump', '3', [], ''],
+ ['sd_bus_message_dump', '3', ['sd_bus_message_dump_json'], ''],
['sd_bus_message_get_cookie', '3', ['sd_bus_message_get_reply_cookie'], ''],
['sd_bus_message_get_monotonic_usec',
'3',
<refnamediv>
<refname>sd_bus_message_dump</refname>
+ <refname>sd_bus_message_dump_json</refname>
<refpurpose>Produce a string representation of a message for debugging purposes</refpurpose>
</refnamediv>
<paramdef>FILE *<parameter>f</parameter></paramdef>
<paramdef>uint64_t <parameter>flags</parameter></paramdef>
</funcprototype>
- </funcsynopsis>
- <para>
- <constant>SD_BUS_MESSAGE_DUMP_WITH_HEADER</constant>,
- <constant>SD_BUS_MESSAGE_DUMP_SUBTREE_ONLY</constant>
- </para>
+ <funcprototype>
+ <funcdef>int sd_bus_message_dump_json</funcdef>
+ <paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
+ <paramdef>uint64_t <parameter>flags</parameter></paramdef>
+ <paramdef>sd_json_variant **<parameter>ret</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
</refsynopsisdiv>
<refsect1>
intended to be used for debugging purposes, and the output is neither stable nor designed to be machine
readable.</para>
- <para>The <parameter>flags</parameter> parameter may be used to modify the output. With
- <constant>SD_BUS_MESSAGE_DUMP_WITH_HEADER</constant>, a header that specifies the message type and flags
- and some additional metadata is printed. When <constant>SD_BUS_MESSAGE_DUMP_SUBTREE_ONLY</constant> is
- not passed, the contents of the whole message are printed. When it <emphasis>is</emphasis> passed,
- only the current container in printed.</para>
+ <para>The <function>sd_bus_message_dump_json()</function> function converts the DBus message
+ <parameter>m</parameter> to a JSON variant and stores it in <parameter>ret</parameter>. The caller should
+ call <function>sd_json_variant_unref()</function> for the acquired JSON variant after use. Unlike
+ <function>sd_bus_message_dump()</function>, the function itself does not print anything. To print the
+ DBus message in the JSON format, please pass the returned JSON variant to
+ <function>sd_json_variant_dump()</function>.</para>
- <para>Note that this function moves the read pointer of the message. It may be necessary to reset the
+ <para>The <parameter>flags</parameter> parameter may be used to modify the output, and is a combination
+ of zero or more of the following flags:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>SD_BUS_MESSAGE_DUMP_WITH_HEADER</constant></term>
+
+ <listitem><para>The header of the message that specifies the message type, flags, and several more
+ additional metadata will be printed or included in the resulting JSON object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>SD_BUS_MESSAGE_DUMP_SUBTREE_ONLY</constant></term>
+
+ <listitem><para>Only the current container will be printed or converted. When the flag is
+ <emphasis>not</emphasis> specified, the contents of the whole message will be printed or converted.
+ </para></listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>Note that these functions move the read pointer of the message. It may be necessary to reset the
position afterwards, for example with
<citerefentry><refentrytitle>sd_bus_message_rewind</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
+
</refsect1>
<refsect1>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
+ <member><citerefentry><refentrytitle>sd-json</refentrytitle><manvolnum>3</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
#define NAME_IS_ACQUIRED INT_TO_PTR(1)
#define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
-static int json_transform_message(sd_bus_message *m, sd_json_variant **ret);
-
static int acquire_bus(bool set_monitor, sd_bus **ret) {
_cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
_cleanup_close_ int pin_fd = -EBADF;
}
static int message_json(sd_bus_message *m, FILE *f) {
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL, *w = NULL;
- char e[2];
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
int r;
- usec_t ts;
- r = json_transform_message(m, &v);
+ assert(m);
+
+ r = sd_bus_message_dump_json(m, SD_BUS_MESSAGE_DUMP_WITH_HEADER, &v);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to build JSON object from DBus message: %m");
+
+ r = sd_json_variant_dump(v, arg_json_format_flags, f, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to show JSON object: %m");
- e[0] = m->header->endian;
- e[1] = 0;
-
- ts = m->realtime;
- if (ts == 0)
- ts = now(CLOCK_REALTIME);
-
- r = sd_json_buildo(&w,
- SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(bus_message_type_to_string(m->header->type))),
- SD_JSON_BUILD_PAIR("endian", SD_JSON_BUILD_STRING(e)),
- SD_JSON_BUILD_PAIR("flags", SD_JSON_BUILD_INTEGER(m->header->flags)),
- SD_JSON_BUILD_PAIR("version", SD_JSON_BUILD_INTEGER(m->header->version)),
- SD_JSON_BUILD_PAIR("cookie", SD_JSON_BUILD_INTEGER(BUS_MESSAGE_COOKIE(m))),
- SD_JSON_BUILD_PAIR_CONDITION(m->reply_cookie != 0, "reply_cookie", SD_JSON_BUILD_INTEGER(m->reply_cookie)),
- SD_JSON_BUILD_PAIR("timestamp-realtime", SD_JSON_BUILD_UNSIGNED(ts)),
- SD_JSON_BUILD_PAIR_CONDITION(!!m->sender, "sender", SD_JSON_BUILD_STRING(m->sender)),
- SD_JSON_BUILD_PAIR_CONDITION(!!m->destination, "destination", SD_JSON_BUILD_STRING(m->destination)),
- SD_JSON_BUILD_PAIR_CONDITION(!!m->path, "path", SD_JSON_BUILD_STRING(m->path)),
- SD_JSON_BUILD_PAIR_CONDITION(!!m->interface, "interface", SD_JSON_BUILD_STRING(m->interface)),
- SD_JSON_BUILD_PAIR_CONDITION(!!m->member, "member", SD_JSON_BUILD_STRING(m->member)),
- SD_JSON_BUILD_PAIR_CONDITION(m->monotonic != 0, "monotonic", SD_JSON_BUILD_INTEGER(m->monotonic)),
- SD_JSON_BUILD_PAIR_CONDITION(m->realtime != 0, "realtime", SD_JSON_BUILD_INTEGER(m->realtime)),
- SD_JSON_BUILD_PAIR_CONDITION(m->seqnum != 0, "seqnum", SD_JSON_BUILD_INTEGER(m->seqnum)),
- SD_JSON_BUILD_PAIR_CONDITION(!!m->error.name, "error_name", SD_JSON_BUILD_STRING(m->error.name)),
- SD_JSON_BUILD_PAIR("payload", SD_JSON_BUILD_VARIANT(v)));
- if (r < 0)
- return log_error_errno(r, "Failed to build JSON object: %m");
-
- sd_json_variant_dump(w, arg_json_format_flags, f, NULL);
return 0;
}
return 0;
}
-static int json_transform_one(sd_bus_message *m, sd_json_variant **ret);
-
-static int json_transform_and_append(sd_bus_message *m, sd_json_variant **array) {
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *element = NULL;
- int r;
-
- assert(m);
- assert(array);
-
- r = json_transform_one(m, &element);
- if (r < 0)
- return r;
-
- r = sd_json_variant_append_array(array, element);
- if (r < 0)
- return log_error_errno(r, "Failed to append json element to array: %m");
-
- return 0;
-}
-
-static int json_transform_array_or_struct(sd_bus_message *m, sd_json_variant **ret) {
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
- int r;
-
- assert(m);
- assert(ret);
-
- r = sd_json_variant_new_array(&array, NULL, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate json empty array: %m");
-
- for (;;) {
- r = sd_bus_message_at_end(m, false);
- if (r < 0)
- return bus_log_parse_error(r);
- if (r > 0)
- break;
-
- r = json_transform_and_append(m, &array);
- if (r < 0)
- return r;
- }
-
- *ret = TAKE_PTR(array);
- return 0;
-}
-
-static int json_transform_variant(sd_bus_message *m, const char *contents, sd_json_variant **ret) {
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *value = NULL;
- int r;
-
- assert(m);
- assert(contents);
- assert(ret);
-
- r = json_transform_one(m, &value);
- if (r < 0)
- return r;
-
- r = sd_json_buildo(ret,
- SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(contents)),
- SD_JSON_BUILD_PAIR("data", SD_JSON_BUILD_VARIANT(value)));
- if (r < 0)
- return log_error_errno(r, "Failed to build json object: %m");
-
- return r;
-}
-
-static int json_transform_dict_array(sd_bus_message *m, sd_json_variant **ret) {
- sd_json_variant **elements = NULL;
- size_t n_elements = 0;
- int r;
-
- assert(m);
- assert(ret);
-
- CLEANUP_ARRAY(elements, n_elements, sd_json_variant_unref_many);
-
- for (;;) {
- const char *contents;
- char type;
-
- r = sd_bus_message_at_end(m, false);
- if (r < 0)
- return bus_log_parse_error(r);
- if (r > 0)
- break;
-
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- assert(type == 'e');
-
- if (!GREEDY_REALLOC(elements, n_elements + 2))
- return log_oom();
-
- r = sd_bus_message_enter_container(m, type, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = json_transform_one(m, elements + n_elements);
- if (r < 0)
- return r;
-
- n_elements++;
-
- r = json_transform_one(m, elements + n_elements);
- if (r < 0)
- return r;
-
- n_elements++;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
- }
-
- r = sd_json_variant_new_object(ret, elements, n_elements);
- if (r < 0)
- return log_error_errno(r, "Failed to create new json object: %m");
-
- return 0;
-}
-
-static int json_transform_one(sd_bus_message *m, sd_json_variant **ret) {
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
- const char *contents;
- char type;
- int r;
-
- assert(m);
- assert(ret);
-
- r = sd_bus_message_peek_type(m, &type, &contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- switch (type) {
-
- case SD_BUS_TYPE_BYTE: {
- uint8_t b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_unsigned(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform byte: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_BOOLEAN: {
- int b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_boolean(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform boolean: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_INT16: {
- int16_t b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_integer(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform int16: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_UINT16: {
- uint16_t b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_unsigned(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform uint16: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_INT32: {
- int32_t b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_integer(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform int32: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_UINT32: {
- uint32_t b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_unsigned(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform uint32: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_INT64: {
- int64_t b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_integer(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform int64: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_UINT64: {
- uint64_t b;
-
- r = sd_bus_message_read_basic(m, type, &b);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_unsigned(&v, b);
- if (r < 0)
- return log_error_errno(r, "Failed to transform uint64: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_DOUBLE: {
- double d;
-
- r = sd_bus_message_read_basic(m, type, &d);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_real(&v, d);
- if (r < 0)
- return log_error_errno(r, "Failed to transform double: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_STRING:
- case SD_BUS_TYPE_OBJECT_PATH:
- case SD_BUS_TYPE_SIGNATURE: {
- const char *s;
-
- r = sd_bus_message_read_basic(m, type, &s);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_json_variant_new_string(&v, s);
- if (r < 0)
- return log_error_errno(r, "Failed to transform double: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_UNIX_FD: {
- int fd;
-
- r = sd_bus_message_read_basic(m, type, &fd);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = json_variant_new_fd_info(&v, fd);
- if (r < 0)
- return log_error_errno(r, "Failed to transform fd: %m");
-
- break;
- }
-
- case SD_BUS_TYPE_ARRAY:
- case SD_BUS_TYPE_VARIANT:
- case SD_BUS_TYPE_STRUCT:
- r = sd_bus_message_enter_container(m, type, contents);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (type == SD_BUS_TYPE_VARIANT)
- r = json_transform_variant(m, contents, &v);
- else if (type == SD_BUS_TYPE_ARRAY && contents[0] == '{')
- r = json_transform_dict_array(m, &v);
- else
- r = json_transform_array_or_struct(m, &v);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- break;
-
- default:
- assert_not_reached();
- }
-
- *ret = TAKE_PTR(v);
- return 0;
-}
-
-static int json_transform_message(sd_bus_message *m, sd_json_variant **ret) {
- _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
- const char *type;
- int r;
-
- assert(m);
- assert(ret);
-
- assert_se(type = sd_bus_message_get_signature(m, false));
-
- r = json_transform_array_or_struct(m, &v);
- if (r < 0)
- return r;
-
- r = sd_json_buildo(ret,
- SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(type)),
- SD_JSON_BUILD_PAIR("data", SD_JSON_BUILD_VARIANT(v)));
- if (r < 0)
- return log_error_errno(r, "Failed to build json object: %m");
-
- return 0;
-}
-
static int call(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (arg_json_format_flags & (SD_JSON_FORMAT_PRETTY|SD_JSON_FORMAT_PRETTY_AUTO))
pager_open(arg_pager_flags);
- r = json_transform_message(reply, &v);
+ r = sd_bus_message_dump_json(reply, /* flags = */ 0, &v);
if (r < 0)
return r;
if (arg_json_format_flags & (SD_JSON_FORMAT_PRETTY|SD_JSON_FORMAT_PRETTY_AUTO))
pager_open(arg_pager_flags);
- r = json_transform_variant(reply, contents, &v);
+ r = sd_bus_message_dump_json(reply, SD_BUS_MESSAGE_DUMP_SUBTREE_ONLY, &v);
if (r < 0)
return r;
if (arg_json_format_flags & (SD_JSON_FORMAT_PRETTY|SD_JSON_FORMAT_PRETTY_AUTO))
pager_open(arg_pager_flags);
- r = json_transform_message(msg, &v);
+ r = sd_bus_message_dump_json(msg, /* flags = */ 0, &v);
if (r < 0)
return r;
LIBSYSTEMD_258 {
global:
+ sd_bus_message_dump_json;
sd_device_enumerator_add_all_parents;
sd_json_variant_type_from_string;
sd_json_variant_type_to_string;
'sd-bus/bus-convenience.c',
'sd-bus/bus-creds.c',
'sd-bus/bus-dump.c',
+ 'sd-bus/bus-dump-json.c',
'sd-bus/bus-error.c',
'sd-bus/bus-internal.c',
'sd-bus/bus-introspect.c',
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-bus.h"
+
+#include "alloc-util.h"
+#include "bus-internal.h"
+#include "bus-message.h"
+#include "json-util.h"
+#include "macro.h"
+#include "memory-util.h"
+#include "time-util.h"
+
+static int json_transform_one(sd_bus_message *m, sd_json_variant **ret);
+
+static int json_transform_array_or_struct(sd_bus_message *m, sd_json_variant **ret) {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
+ int r;
+
+ assert(m);
+ assert(ret);
+
+ r = sd_json_variant_new_array(&array, NULL, 0);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ r = sd_bus_message_at_end(m, false);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ break;
+
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ r = json_transform_one(m, &v);
+ if (r < 0)
+ return r;
+
+ r = sd_json_variant_append_array(&array, v);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = TAKE_PTR(array);
+ return 0;
+}
+
+static int json_transform_variant(sd_bus_message *m, const char *contents, sd_json_variant **ret) {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *value = NULL;
+ int r;
+
+ assert(m);
+ assert(contents);
+ assert(ret);
+
+ r = json_transform_one(m, &value);
+ if (r < 0)
+ return r;
+
+ return sd_json_buildo(
+ ret,
+ SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(contents)),
+ SD_JSON_BUILD_PAIR("data", SD_JSON_BUILD_VARIANT(value)));
+}
+
+static int json_transform_dict_array(sd_bus_message *m, sd_json_variant **ret) {
+ sd_json_variant **elements = NULL;
+ size_t n_elements = 0;
+ int r;
+
+ assert(m);
+ assert(ret);
+
+ CLEANUP_ARRAY(elements, n_elements, sd_json_variant_unref_many);
+
+ for (;;) {
+ const char *contents;
+ char type;
+
+ r = sd_bus_message_at_end(m, false);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ break;
+
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
+
+ assert(type == 'e');
+
+ if (!GREEDY_REALLOC(elements, n_elements + 2))
+ return -ENOMEM;
+
+ r = sd_bus_message_enter_container(m, type, contents);
+ if (r < 0)
+ return r;
+
+ r = json_transform_one(m, elements + n_elements);
+ if (r < 0)
+ return r;
+
+ n_elements++;
+
+ r = json_transform_one(m, elements + n_elements);
+ if (r < 0)
+ return r;
+
+ n_elements++;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+ }
+
+ return sd_json_variant_new_object(ret, elements, n_elements);
+}
+
+static int json_transform_one(sd_bus_message *m, sd_json_variant **ret) {
+ const char *contents;
+ char type;
+ int r;
+
+ assert(m);
+ assert(ret);
+
+ r = sd_bus_message_peek_type(m, &type, &contents);
+ if (r < 0)
+ return r;
+
+ switch (type) {
+
+ case SD_BUS_TYPE_BYTE: {
+ uint8_t b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_unsigned(ret, b);
+ }
+
+ case SD_BUS_TYPE_BOOLEAN: {
+ int b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_boolean(ret, b);
+ }
+
+ case SD_BUS_TYPE_INT16: {
+ int16_t b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_integer(ret, b);
+ }
+
+ case SD_BUS_TYPE_UINT16: {
+ uint16_t b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_unsigned(ret, b);
+ }
+
+ case SD_BUS_TYPE_INT32: {
+ int32_t b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_integer(ret, b);
+ }
+
+ case SD_BUS_TYPE_UINT32: {
+ uint32_t b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_unsigned(ret, b);
+ }
+
+ case SD_BUS_TYPE_INT64: {
+ int64_t b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_integer(ret, b);
+ }
+
+ case SD_BUS_TYPE_UINT64: {
+ uint64_t b;
+
+ r = sd_bus_message_read_basic(m, type, &b);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_unsigned(ret, b);
+ }
+
+ case SD_BUS_TYPE_DOUBLE: {
+ double d;
+
+ r = sd_bus_message_read_basic(m, type, &d);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_real(ret, d);
+ }
+
+ case SD_BUS_TYPE_STRING:
+ case SD_BUS_TYPE_OBJECT_PATH:
+ case SD_BUS_TYPE_SIGNATURE: {
+ const char *s;
+
+ r = sd_bus_message_read_basic(m, type, &s);
+ if (r < 0)
+ return r;
+
+ return sd_json_variant_new_string(ret, s);
+ }
+
+ case SD_BUS_TYPE_UNIX_FD: {
+ int fd;
+
+ r = sd_bus_message_read_basic(m, type, &fd);
+ if (r < 0)
+ return r;
+
+ return json_variant_new_fd_info(ret, fd);
+ }
+
+ case SD_BUS_TYPE_ARRAY:
+ case SD_BUS_TYPE_VARIANT:
+ case SD_BUS_TYPE_STRUCT: {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+
+ r = sd_bus_message_enter_container(m, type, contents);
+ if (r < 0)
+ return r;
+
+ if (type == SD_BUS_TYPE_VARIANT)
+ r = json_transform_variant(m, contents, &v);
+ else if (type == SD_BUS_TYPE_ARRAY && contents[0] == '{')
+ r = json_transform_dict_array(m, &v);
+ else
+ r = json_transform_array_or_struct(m, &v);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(m);
+ if (r < 0)
+ return r;
+
+ *ret = TAKE_PTR(v);
+ return 0;
+ }
+
+ default:
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "sd-bus: an invalid message type (signature=%s, type=%c, contents=%s).",
+ sd_bus_message_get_signature(m, /* complete = */ false), type, strna(contents));
+ }
+}
+
+static int json_transform_message(sd_bus_message *m, const char *type, sd_json_variant **ret) {
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ int r;
+
+ assert(m);
+ assert(type);
+ assert(ret);
+
+ r = json_transform_array_or_struct(m, &v);
+ if (r < 0)
+ return r;
+
+ return sd_json_buildo(
+ ret,
+ SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(type)),
+ SD_JSON_BUILD_PAIR("data", SD_JSON_BUILD_VARIANT(v)));
+}
+
+_public_ int sd_bus_message_dump_json(sd_bus_message *m, uint64_t flags, sd_json_variant **ret) {
+ int r;
+
+ assert_return(m, -EINVAL);
+ assert_return((flags & ~_SD_BUS_MESSAGE_DUMP_KNOWN_FLAGS) == 0, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ r = sd_bus_message_rewind(m, !FLAGS_SET(flags, SD_BUS_MESSAGE_DUMP_SUBTREE_ONLY));
+ if (r < 0)
+ return r;
+
+ const char *type = sd_bus_message_get_signature(m, !FLAGS_SET(flags, SD_BUS_MESSAGE_DUMP_SUBTREE_ONLY));
+ if (!type)
+ return -EINVAL;
+
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ if (FLAGS_SET(flags, SD_BUS_MESSAGE_DUMP_SUBTREE_ONLY))
+ r = json_transform_variant(m, type, &v);
+ else
+ r = json_transform_message(m, type, &v);
+ if (r < 0)
+ return r;
+
+ if (!FLAGS_SET(flags, SD_BUS_MESSAGE_DUMP_WITH_HEADER)) {
+ *ret = TAKE_PTR(v);
+ return 0;
+ }
+
+ usec_t ts = m->realtime;
+ if (ts == 0)
+ ts = now(CLOCK_REALTIME);
+
+ return sd_json_buildo(
+ ret,
+ SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(bus_message_type_to_string(m->header->type))),
+ SD_JSON_BUILD_PAIR("endian", SD_JSON_BUILD_STRING(CHAR_TO_STR(m->header->endian))),
+ SD_JSON_BUILD_PAIR("flags", SD_JSON_BUILD_INTEGER(m->header->flags)),
+ SD_JSON_BUILD_PAIR("version", SD_JSON_BUILD_INTEGER(m->header->version)),
+ SD_JSON_BUILD_PAIR("cookie", SD_JSON_BUILD_INTEGER(BUS_MESSAGE_COOKIE(m))),
+ SD_JSON_BUILD_PAIR_CONDITION(m->reply_cookie != 0, "reply_cookie", SD_JSON_BUILD_INTEGER(m->reply_cookie)),
+ SD_JSON_BUILD_PAIR("timestamp-realtime", SD_JSON_BUILD_UNSIGNED(ts)),
+ SD_JSON_BUILD_PAIR_CONDITION(!!m->sender, "sender", SD_JSON_BUILD_STRING(m->sender)),
+ SD_JSON_BUILD_PAIR_CONDITION(!!m->destination, "destination", SD_JSON_BUILD_STRING(m->destination)),
+ SD_JSON_BUILD_PAIR_CONDITION(!!m->path, "path", SD_JSON_BUILD_STRING(m->path)),
+ SD_JSON_BUILD_PAIR_CONDITION(!!m->interface, "interface", SD_JSON_BUILD_STRING(m->interface)),
+ SD_JSON_BUILD_PAIR_CONDITION(!!m->member, "member", SD_JSON_BUILD_STRING(m->member)),
+ SD_JSON_BUILD_PAIR_CONDITION(m->monotonic != 0, "monotonic", SD_JSON_BUILD_INTEGER(m->monotonic)),
+ SD_JSON_BUILD_PAIR_CONDITION(m->realtime != 0, "realtime", SD_JSON_BUILD_INTEGER(m->realtime)),
+ SD_JSON_BUILD_PAIR_CONDITION(m->seqnum != 0, "seqnum", SD_JSON_BUILD_INTEGER(m->seqnum)),
+ SD_JSON_BUILD_PAIR_CONDITION(!!m->error.name, "error_name", SD_JSON_BUILD_STRING(m->error.name)),
+ SD_JSON_BUILD_PAIR("payload", SD_JSON_BUILD_VARIANT(v)));
+}
if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0)
assert_se(g = memstream_init(&ms));
- sd_bus_message_dump(m, g ?: stdout, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
+ (void) sd_bus_message_dump(m, g, SD_BUS_MESSAGE_DUMP_WITH_HEADER);
+
+ _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+ if (sd_bus_message_dump_json(m, SD_BUS_MESSAGE_DUMP_WITH_HEADER, &v) >= 0)
+ (void) sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY | SD_JSON_FORMAT_COLOR_AUTO, g, NULL);
r = sd_bus_message_rewind(m, true);
assert_se(r >= 0);
#include "sd-bus-vtable.h"
#include "sd-event.h"
#include "sd-id128.h"
+#include "sd-json.h"
_SD_BEGIN_DECLARATIONS;
int sd_bus_message_sensitive(sd_bus_message *m);
int sd_bus_message_dump(sd_bus_message *m, FILE *f, uint64_t flags);
+int sd_bus_message_dump_json(sd_bus_message *m, uint64_t flags, sd_json_variant **ret);
/* Bus management */