sd-json: introduce json_variant_new_fd_info()
Currently this is not used, but will be used later.
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user