From 32944d1c7a5444ccc72e957a2dd39c12b3ce625a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 15 Oct 2024 09:15:19 +0900 Subject: sd-json: introduce json_variant_new_devnum() and friends --- src/test/test-json.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/test') diff --git a/src/test/test-json.c b/src/test/test-json.c index 32cd285841..fdf69ac2f7 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -1307,4 +1307,27 @@ 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)); +} + DEFINE_TEST_MAIN(LOG_DEBUG); -- cgit v1.2.3 From 60ae3b86fb52d545b279e3927d2214462385e734 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 13 Oct 2024 12:56:10 +0900 Subject: sd-json: introduce json_variant_new_fd_info() Currently this is not used, but will be used later. --- src/libsystemd/sd-json/json-util.c | 80 ++++++++++++++++++++++++++++++++++++++ src/libsystemd/sd-json/json-util.h | 1 + src/test/test-json.c | 71 +++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) (limited to 'src/test') diff --git a/src/libsystemd/sd-json/json-util.c b/src/libsystemd/sd-json/json-util.c index d49a5d97f9..4c978850c4 100644 --- a/src/libsystemd/sd-json/json-util.c +++ b/src/libsystemd/sd-json/json-util.c @@ -2,10 +2,12 @@ #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" @@ -338,3 +340,81 @@ int json_dispatch_devnum(const char *name, sd_json_variant *variant, sd_json_dis *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 1bc5f63aba..2aeb076823 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -238,3 +238,4 @@ enum { 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/test/test-json.c b/src/test/test-json.c index fdf69ac2f7..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; @@ -1330,4 +1331,74 @@ TEST(devnum) { 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); -- cgit v1.2.3