summaryrefslogtreecommitdiffstats
path: root/src/libsystemd
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2024-10-15 14:38:18 +0200
committerGitHub <noreply@github.com>2024-10-15 14:38:18 +0200
commit34599ddfc650585a2c254278e813c162f17d52e0 (patch)
treeaa31c95d6dc5490864cd202e294fd76d3d3db643 /src/libsystemd
parentnetwork: add AF_TO_ADDRESS_FAMILY() helper (diff)
parentbusctl: show information of passed file descriptor (diff)
downloadsystemd-34599ddfc650585a2c254278e813c162f17d52e0.tar.xz
systemd-34599ddfc650585a2c254278e813c162f17d52e0.zip
Merge pull request #34747 from yuwata/busctl-json-fd
busctl: dump passed fd info
Diffstat (limited to 'src/libsystemd')
-rw-r--r--src/libsystemd/sd-json/json-util.c124
-rw-r--r--src/libsystemd/sd-json/json-util.h7
-rw-r--r--src/libsystemd/sd-json/sd-json.c28
3 files changed, 159 insertions, 0 deletions
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;