diff options
author | Lennart Poettering <lennart@poettering.net> | 2024-10-15 14:38:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-15 14:38:18 +0200 |
commit | 34599ddfc650585a2c254278e813c162f17d52e0 (patch) | |
tree | aa31c95d6dc5490864cd202e294fd76d3d3db643 | |
parent | network: add AF_TO_ADDRESS_FAMILY() helper (diff) | |
parent | busctl: show information of passed file descriptor (diff) | |
download | systemd-34599ddfc650585a2c254278e813c162f17d52e0.tar.xz systemd-34599ddfc650585a2c254278e813c162f17d52e0.zip |
Merge pull request #34747 from yuwata/busctl-json-fd
busctl: dump passed fd info
-rw-r--r-- | src/basic/fs-util.c | 4 | ||||
-rw-r--r-- | src/basic/fs-util.h | 6 | ||||
-rw-r--r-- | src/busctl/busctl.c | 87 | ||||
-rw-r--r-- | src/libsystemd/sd-json/json-util.c | 124 | ||||
-rw-r--r-- | src/libsystemd/sd-json/json-util.h | 7 | ||||
-rw-r--r-- | src/libsystemd/sd-json/sd-json.c | 28 | ||||
-rw-r--r-- | src/test/test-json.c | 94 | ||||
-rwxr-xr-x | test/units/TEST-74-AUX-UTILS.busctl.sh | 4 |
8 files changed, 310 insertions, 44 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index a6b53e7067..9292e567c8 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -153,10 +153,6 @@ int readlinkat_malloc(int fd, const char *p, char **ret) { } } -int readlink_malloc(const char *p, char **ret) { - return readlinkat_malloc(AT_FDCWD, p, ret); -} - int readlink_value(const char *p, char **ret) { _cleanup_free_ char *link = NULL, *name = NULL; int r; diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 82e865180b..702b6010e2 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -28,9 +28,11 @@ int rmdir_parents(const char *path, const char *stop); int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); int readlinkat_malloc(int fd, const char *p, char **ret); -int readlink_malloc(const char *p, char **r); +static inline int readlink_malloc(const char *p, char **ret) { + return readlinkat_malloc(AT_FDCWD, p, ret); +} int readlink_value(const char *p, char **ret); -int readlink_and_make_absolute(const char *p, char **r); +int readlink_and_make_absolute(const char *p, char **ret); int chmod_and_chown_at(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid); static inline int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index c3e0a3a633..1e352a3729 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -21,6 +21,7 @@ #include "fileio.h" #include "format-table.h" #include "glyph-util.h" +#include "json-util.h" #include "log.h" #include "main-func.h" #include "memstream-util.h" @@ -1728,18 +1729,22 @@ static int message_append_cmdline(sd_bus_message *m, const char *signature, FDSe 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 **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(ret); + assert(array); r = json_transform_one(m, &element); if (r < 0) return r; - return sd_json_variant_append_array(ret, element); + 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) { @@ -1749,6 +1754,10 @@ static int json_transform_array_or_struct(sd_bus_message *m, sd_json_variant **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) @@ -1761,9 +1770,6 @@ static int json_transform_array_or_struct(sd_bus_message *m, sd_json_variant **r return r; } - if (!array) - return sd_json_variant_new_array(ret, NULL, 0); - *ret = TAKE_PTR(array); return 0; } @@ -1784,7 +1790,7 @@ static int json_transform_variant(sd_bus_message *m, const char *contents, sd_js 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_oom(); + return log_error_errno(r, "Failed to build json object: %m"); return r; } @@ -1811,7 +1817,7 @@ static int json_transform_dict_array(sd_bus_message *m, sd_json_variant **ret) { r = sd_bus_message_peek_type(m, &type, &contents); if (r < 0) - return r; + return bus_log_parse_error(r); assert(type == 'e'); @@ -1839,7 +1845,11 @@ static int json_transform_dict_array(sd_bus_message *m, sd_json_variant **ret) { return bus_log_parse_error(r); } - return sd_json_variant_new_object(ret, elements, n_elements); + 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) { @@ -1999,16 +2009,19 @@ static int json_transform_one(sd_bus_message *m, sd_json_variant **ret) { break; } - case SD_BUS_TYPE_UNIX_FD: - r = sd_bus_message_read_basic(m, type, NULL); + 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 = sd_json_variant_new_null(&v); + 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: @@ -2055,10 +2068,10 @@ static int json_transform_message(sd_bus_message *m, sd_json_variant **ret) { return r; r = sd_json_buildo(ret, - SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(type)), + 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_oom(); + return log_error_errno(r, "Failed to build json object: %m"); return 0; } @@ -2130,38 +2143,37 @@ static int call(int argc, char **argv, void *userdata) { r = sd_bus_message_is_empty(reply); if (r < 0) return bus_log_parse_error(r); + if (r > 0 || arg_quiet) + return 0; - if (r == 0 && !arg_quiet) { - - if (!FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) { - _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + if (!FLAGS_SET(arg_json_format_flags, SD_JSON_FORMAT_OFF)) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; - if (arg_json_format_flags & (SD_JSON_FORMAT_PRETTY|SD_JSON_FORMAT_PRETTY_AUTO)) - pager_open(arg_pager_flags); + 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); - if (r < 0) - return r; + r = json_transform_message(reply, &v); + if (r < 0) + return r; - sd_json_variant_dump(v, arg_json_format_flags, NULL, NULL); + sd_json_variant_dump(v, arg_json_format_flags, NULL, NULL); - } else if (arg_verbose) { - pager_open(arg_pager_flags); + } else if (arg_verbose) { + pager_open(arg_pager_flags); - r = sd_bus_message_dump(reply, stdout, 0); - if (r < 0) - return r; - } else { + r = sd_bus_message_dump(reply, stdout, 0); + if (r < 0) + return log_error_errno(r, "Failed to dump dbus message: %m"); + } else { - fputs(sd_bus_message_get_signature(reply, true), stdout); - fputc(' ', stdout); + 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); + r = format_cmdline(reply, stdout, false); + if (r < 0) + return bus_log_parse_error(r); - fputc('\n', stdout); - } + fputc('\n', stdout); } return 0; @@ -2289,7 +2301,6 @@ static int on_bus_signal_impl(sd_bus_message *msg) { r = sd_bus_message_is_empty(msg); if (r < 0) return bus_log_parse_error(r); - if (r > 0 || arg_quiet) return 0; diff --git a/src/libsystemd/sd-json/json-util.c b/src/libsystemd/sd-json/json-util.c index 0c1dea566a..4c978850c4 100644 --- a/src/libsystemd/sd-json/json-util.c +++ b/src/libsystemd/sd-json/json-util.c @@ -1,10 +1,13 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "alloc-util.h" +#include "devnum-util.h" +#include "fd-util.h" #include "glyph-util.h" #include "in-addr-util.h" #include "iovec-util.h" #include "json-util.h" +#include "mountpoint-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" @@ -294,3 +297,124 @@ int json_dispatch_pidref(const char *name, sd_json_variant *variant, sd_json_dis return 0; } + +int json_variant_new_devnum(sd_json_variant **ret, dev_t devnum) { + if (devnum == 0) + return sd_json_variant_new_null(ret); + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_UNSIGNED("major", major(devnum)), + SD_JSON_BUILD_PAIR_UNSIGNED("minor", minor(devnum))); +} + +int json_dispatch_devnum(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) { + dev_t *ret = ASSERT_PTR(userdata); + int r; + + assert(variant); + + if (sd_json_variant_is_null(variant)) { + *ret = 0; + return 0; + } + + struct { + uint32_t major; + uint32_t minor; + } data; + + static const sd_json_dispatch_field dispatch_table[] = { + { "major", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32, voffsetof(data, major), SD_JSON_MANDATORY }, + { "minor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint32, voffsetof(data, minor), SD_JSON_MANDATORY }, + {} + }; + + r = sd_json_dispatch(variant, dispatch_table, flags, &data); + if (r < 0) + return r; + + if (!DEVICE_MAJOR_VALID(data.major) || !DEVICE_MINOR_VALID(data.minor)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid device number.", strna(name)); + + *ret = makedev(data.major, data.minor); + return 0; +} + +static int json_variant_new_stat(sd_json_variant **ret, const struct stat *st) { + char mode[STRLEN("0755")+1]; + + assert(st); + + if (!stat_is_set(st)) + return sd_json_variant_new_null(ret); + + xsprintf(mode, "%04o", st->st_mode & ~S_IFMT); + + return sd_json_buildo( + ret, + JSON_BUILD_PAIR_DEVNUM("dev", st->st_dev), + SD_JSON_BUILD_PAIR_UNSIGNED("inode", st->st_ino), + JSON_BUILD_PAIR_STRING_NON_EMPTY("type", inode_type_to_string(st->st_mode)), + SD_JSON_BUILD_PAIR_STRING("mode", mode), + SD_JSON_BUILD_PAIR_UNSIGNED("linkCount", st->st_nlink), + SD_JSON_BUILD_PAIR_UNSIGNED("uid", st->st_uid), + SD_JSON_BUILD_PAIR_UNSIGNED("gid", st->st_gid), + SD_JSON_BUILD_PAIR_CONDITION( + S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode), + "rdev", + JSON_BUILD_DEVNUM(st->st_rdev)), + SD_JSON_BUILD_PAIR_UNSIGNED("size", st->st_size), + SD_JSON_BUILD_PAIR_UNSIGNED("blockSize", st->st_blksize), + SD_JSON_BUILD_PAIR_UNSIGNED("blocks", st->st_blocks)); +} + +static int json_variant_new_file_handle(sd_json_variant **ret, const struct file_handle *fid) { + assert(ret); + + if (!fid) + return sd_json_variant_new_null(ret); + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_INTEGER("type", fid->handle_type), + SD_JSON_BUILD_PAIR_BASE64("handle", fid->f_handle, fid->handle_bytes)); +} + +int json_variant_new_fd_info(sd_json_variant **ret, int fd) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL, *w = NULL; + _cleanup_free_ char *path = NULL; + _cleanup_free_ struct file_handle *fid = NULL; + struct stat st; + int mntid = -1, r; + + assert(fd >= 0 || fd == AT_FDCWD); + + r = fd_get_path(fd, &path); + if (r < 0) + return r; + + /* If AT_FDCWD is specified, show information about the current working directory. */ + if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0) + return -errno; + + r = json_variant_new_stat(&v, &st); + if (r < 0) + return r; + + r = name_to_handle_at_try_fid(fd, "", &fid, &mntid, AT_EMPTY_PATH); + if (r < 0 && is_name_to_handle_at_fatal_error(r)) + return r; + + r = json_variant_new_file_handle(&w, fid); + if (r < 0) + return r; + + return sd_json_buildo( + ret, + JSON_BUILD_PAIR_INTEGER_NON_NEGATIVE("fd", fd), + SD_JSON_BUILD_PAIR_STRING("path", path), + SD_JSON_BUILD_PAIR_VARIANT("stat", v), + JSON_BUILD_PAIR_INTEGER_NON_NEGATIVE("mountId", mntid), + SD_JSON_BUILD_PAIR_VARIANT("fileHandle", w)); +} diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h index 6b72d0d93d..2aeb076823 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -114,6 +114,7 @@ int json_dispatch_const_user_group_name(const char *name, sd_json_variant *varia int json_dispatch_in_addr(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); int json_dispatch_path(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); int json_dispatch_pidref(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); +int json_dispatch_devnum(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata); static inline int json_variant_unbase64_iovec(sd_json_variant *v, struct iovec *ret) { return sd_json_variant_unbase64(v, ret ? &ret->iov_base : NULL, ret ? &ret->iov_len : NULL); @@ -147,6 +148,7 @@ enum { _JSON_BUILD_RATELIMIT, _JSON_BUILD_TRISTATE, _JSON_BUILD_PIDREF, + _JSON_BUILD_DEVNUM, _JSON_BUILD_PAIR_INTEGER_NON_ZERO, _JSON_BUILD_PAIR_INTEGER_NON_NEGATIVE, @@ -172,6 +174,7 @@ enum { _JSON_BUILD_PAIR_OCTESCAPE_NON_EMPTY, _JSON_BUILD_PAIR_TRISTATE_NON_NULL, _JSON_BUILD_PAIR_PIDREF_NON_NULL, + _JSON_BUILD_PAIR_DEVNUM, _SD_JSON_BUILD_REALLYMAX, }; @@ -192,6 +195,7 @@ enum { #define JSON_BUILD_RATELIMIT(rl) _JSON_BUILD_RATELIMIT, (const RateLimit*) { rl } #define JSON_BUILD_TRISTATE(i) _JSON_BUILD_TRISTATE, (int) { i } #define JSON_BUILD_PIDREF(p) _JSON_BUILD_PIDREF, (const PidRef*) { p } +#define JSON_BUILD_DEVNUM(d) _JSON_BUILD_DEVNUM, (dev_t) { d } #define JSON_BUILD_PAIR_INTEGER_NON_ZERO(name, i) _JSON_BUILD_PAIR_INTEGER_NON_ZERO, (const char*) { name }, (int64_t) { i } #define JSON_BUILD_PAIR_INTEGER_NON_NEGATIVE(name, i) _JSON_BUILD_PAIR_INTEGER_NON_NEGATIVE, (const char*) { name }, (int64_t) { i } @@ -230,5 +234,8 @@ enum { #define JSON_BUILD_PAIR_RATELIMIT(name, rl) SD_JSON_BUILD_PAIR(name, JSON_BUILD_RATELIMIT(rl)) #define JSON_BUILD_PAIR_TRISTATE(name, i) SD_JSON_BUILD_PAIR(name, JSON_BUILD_TRISTATE(i)) #define JSON_BUILD_PAIR_PIDREF(name, p) SD_JSON_BUILD_PAIR(name, JSON_BUILD_PIDREF(p)) +#define JSON_BUILD_PAIR_DEVNUM(name, d) SD_JSON_BUILD_PAIR(name, JSON_BUILD_DEVNUM(d)) int json_variant_new_pidref(sd_json_variant **ret, PidRef *pidref); +int json_variant_new_devnum(sd_json_variant **ret, dev_t devnum); +int json_variant_new_fd_info(sd_json_variant **ret, int fd); diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index 2028f222cb..297052bdb4 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -4224,6 +4224,34 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { break; } + case _JSON_BUILD_DEVNUM: { + dev_t devnum; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + devnum = va_arg(ap, dev_t); + + if (current->n_suppress == 0) { + r = json_variant_new_devnum(&add, devnum); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + case _JSON_BUILD_TRISTATE: { int tristate; diff --git a/src/test/test-json.c b/src/test/test-json.c index 32cd285841..75dff429d5 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -17,6 +17,7 @@ #include "string-util.h" #include "strv.h" #include "tests.h" +#include "tmpfile-util.h" static void test_tokenizer_one(const char *data, ...) { unsigned line = 0, column = 0; @@ -1307,4 +1308,97 @@ TEST(pidref) { pidref_done(&data.pid1); } +TEST(devnum) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + dev_t dev = makedev(123, 456), parsed; + + ASSERT_OK(json_variant_new_devnum(&v, dev)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + ASSERT_OK(json_dispatch_devnum("devnum", v, /* flags= */ 0, &parsed)); + ASSERT_EQ(major(parsed), major(dev)); + ASSERT_EQ(minor(parsed), minor(dev)); + v = sd_json_variant_unref(v); + + dev = makedev(1 << 12, 456); + ASSERT_OK(json_variant_new_devnum(&v, dev)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + ASSERT_FAIL(json_dispatch_devnum("devnum", v, /* flags= */ 0, &parsed)); + v = sd_json_variant_unref(v); + + dev = makedev(123, 1 << 20); + ASSERT_OK(json_variant_new_devnum(&v, dev)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + ASSERT_FAIL(json_dispatch_devnum("devnum", v, /* flags= */ 0, &parsed)); +} + +TEST(fd_info) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL; + _cleanup_close_ int fd = -EBADF; + + /* directories */ + ASSERT_OK(json_variant_new_fd_info(&v, AT_FDCWD)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + + ASSERT_OK_ERRNO(fd = openat(AT_FDCWD, ".", O_CLOEXEC | O_DIRECTORY | O_PATH)); + ASSERT_OK(json_variant_new_fd_info(&v, fd)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + fd = safe_close(fd); + + /* regular file */ + ASSERT_OK(fd = open_tmpfile_unlinkable(NULL, O_RDWR)); + ASSERT_OK(json_variant_new_fd_info(&v, fd)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + fd = safe_close(fd); + + if (access("/sys/class/net/lo/uevent", F_OK) >= 0) { + ASSERT_OK_ERRNO(fd = open("/sys/class/net/lo/uevent", O_CLOEXEC | O_PATH)); + ASSERT_OK(json_variant_new_fd_info(&v, fd)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + fd = safe_close(fd); + } + + /* block device */ + if (access("/dev/sda", F_OK) >= 0) { + ASSERT_OK_ERRNO(fd = open("/dev/sda", O_CLOEXEC | O_PATH)); + ASSERT_OK(json_variant_new_fd_info(&v, fd)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + fd = safe_close(fd); + } + + /* stream */ + ASSERT_OK(json_variant_new_fd_info(&v, fileno(stdout))); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + + /* socket */ + ASSERT_OK_ERRNO(fd = socket(AF_INET, SOCK_DGRAM, 0)); + ASSERT_OK(json_variant_new_fd_info(&v, fd)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + fd = safe_close(fd); + + /* pidfd */ + ASSERT_OK(pidref_set_pid(&pidref, 0)); + if (pidref.fd >= 0) { + ASSERT_OK(json_variant_new_fd_info(&v, pidref.fd)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + } + pidref_done(&pidref); + + ASSERT_OK(pidref_set_pid(&pidref, 1)); + if (pidref.fd >= 0) { + ASSERT_OK(json_variant_new_fd_info(&v, pidref.fd)); + ASSERT_OK(sd_json_variant_dump(v, SD_JSON_FORMAT_PRETTY_AUTO | SD_JSON_FORMAT_COLOR_AUTO, NULL, NULL)); + v = sd_json_variant_unref(v); + } + pidref_done(&pidref); +} + DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/test/units/TEST-74-AUX-UTILS.busctl.sh b/test/units/TEST-74-AUX-UTILS.busctl.sh index eb1f9e265d..4949f4bac7 100755 --- a/test/units/TEST-74-AUX-UTILS.busctl.sh +++ b/test/units/TEST-74-AUX-UTILS.busctl.sh @@ -46,6 +46,10 @@ busctl call -j \ busctl call --verbose --timeout=60 --expect-reply=yes \ org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager \ ListUnitsByPatterns asas 1 "active" 2 "systemd-*.socket" "*.mount" +# show information passed fd +busctl call --json=pretty \ + org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager \ + DumpByFileDescriptor | jq busctl emit /org/freedesktop/login1 org.freedesktop.login1.Manager \ PrepareForSleep b false |