Merge pull request #34747 from yuwata/busctl-json-fd
busctl: dump passed fd info
This commit is contained in:
@@ -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;
|
||||
|
||||
+4
-2
@@ -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) {
|
||||
|
||||
+51
-40
@@ -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);
|
||||
|
||||
r = json_transform_message(reply, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sd_json_variant_dump(v, arg_json_format_flags, NULL, NULL);
|
||||
|
||||
} else if (arg_verbose) {
|
||||
if (arg_json_format_flags & (SD_JSON_FORMAT_PRETTY|SD_JSON_FORMAT_PRETTY_AUTO))
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
r = sd_bus_message_dump(reply, stdout, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
r = json_transform_message(reply, &v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fputs(sd_bus_message_get_signature(reply, true), stdout);
|
||||
fputc(' ', stdout);
|
||||
sd_json_variant_dump(v, arg_json_format_flags, NULL, NULL);
|
||||
|
||||
r = format_cmdline(reply, stdout, false);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
} else if (arg_verbose) {
|
||||
pager_open(arg_pager_flags);
|
||||
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
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);
|
||||
|
||||
r = format_cmdline(reply, stdout, false);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user