From 2279e9657f73b526d4c9af34b20663c4dbc625f6 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Thu, 8 Jun 2023 12:20:01 -0700 Subject: [PATCH] Add get_referring_entries scoutfs command Add a cli command for the get_referring_entries ioctl. Signed-off-by: Zach Brown --- utils/man/scoutfs.8 | 23 +++++ utils/src/get_referring_entries.c | 150 ++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 utils/src/get_referring_entries.c diff --git a/utils/man/scoutfs.8 b/utils/man/scoutfs.8 index 8cfd2af1..60566c97 100644 --- a/utils/man/scoutfs.8 +++ b/utils/man/scoutfs.8 @@ -209,6 +209,29 @@ A path within a ScoutFS filesystem. .RE .PD +.TP +.BI "get-referring-entries [-p|--path PATH] INO" +.sp +Find directory entries that reference an inode number. +.sp +Display all the directory entries that refer to a given inode. Each +entry includes the inode number of the directory that contains it, the +d_off and d_type values for the entry as described by +.BR readdir (3) +, and the name of the entry. +.RS 1.0i +.PD 0 +.TP +.sp +.TP +.B "-p, --path PATH" +A path within a ScoutFS filesystem. +.TP +.B "INO" +The inode number of the target inode. +.RE +.PD + .TP .BI "ino-path INODE-NUM [-p|--path PATH]" .sp diff --git a/utils/src/get_referring_entries.c b/utils/src/get_referring_entries.c new file mode 100644 index 00000000..f0a1207c --- /dev/null +++ b/utils/src/get_referring_entries.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sparse.h" +#include "parse.h" +#include "util.h" +#include "format.h" +#include "ioctl.h" +#include "parse.h" +#include "cmd.h" + +struct gre_args { + char *path; + u64 ino; +}; + +static int do_get_referring_entries(struct gre_args *args) +{ + struct scoutfs_ioctl_get_referring_entries gre; + struct scoutfs_ioctl_dirent *dent; + unsigned int bytes; + void *buf; + int ret; + int fd; + + fd = get_path(args->path, O_RDONLY); + if (fd < 0) + return fd; + + bytes = PATH_MAX * 1024; + buf = malloc(bytes); + if (!buf) { + fprintf(stderr, "couldn't allocate %u byte buffer\n", bytes); + ret = -ENOMEM; + goto out; + } + + gre.ino = args->ino; + gre.dir_ino = 0; + gre.dir_pos = 0; + gre.entries_ptr = (intptr_t)buf; + gre.entries_bytes = bytes; + + for (;;) { + ret = ioctl(fd, SCOUTFS_IOC_GET_REFERRING_ENTRIES, &gre); + if (ret <= 0) { + if (ret < 0) { + ret = -errno; + fprintf(stderr, "ioctl failed: %s (%d)\n", strerror(errno), errno); + } + goto out; + } + + dent = buf; + while (ret-- > 0) { + printf("dir %llu pos %llu type %u name %s\n", + dent->dir_ino, dent->dir_pos, dent->d_type, dent->name); + + gre.dir_ino = dent->dir_ino; + gre.dir_pos = dent->dir_pos; + + if (dent->flags & SCOUTFS_IOCTL_DIRENT_FLAG_LAST) { + ret = 0; + goto out; + } + + dent = (void *)dent + dent->entry_bytes; + } + + if (++gre.dir_pos == 0) { + if (++gre.dir_ino == 0) { + ret = 0; + goto out; + } + } + } + +out: + close(fd); + free(buf); + + return ret; +}; + +static int parse_opt(int key, char *arg, struct argp_state *state) +{ + struct gre_args *args = state->input; + int ret; + + switch (key) { + case 'p': + args->path = strdup_or_error(state, arg); + break; + case ARGP_KEY_ARG: + if (args->ino) + argp_error(state, "more than one argument given"); + ret = parse_u64(arg, &args->ino); + if (ret) + argp_error(state, "inode parse error"); + break; + case ARGP_KEY_FINI: + if (!args->ino) { + argp_error(state, "must provide inode number"); + } + break; + default: + break; + } + + return 0; +} + +static struct argp_option options[] = { + { "path", 'p', "PATH", 0, "Path to ScoutFS filesystem"}, + { NULL } +}; + +static struct argp argp = { + options, + parse_opt, + "INODE-NUM", + "Print directory entries that refer to inode number" +}; + +static int get_referring_entries_cmd(int argc, char **argv) +{ + struct gre_args args = {NULL}; + int ret; + + ret = argp_parse(&argp, argc, argv, 0, NULL, &args); + if (ret) + return ret; + + return do_get_referring_entries(&args); +} + + +static void __attribute__((constructor)) get_referring_entries_ctor(void) +{ + cmd_register_argp("get-referring-entries", &argp, GROUP_SEARCH, get_referring_entries_cmd); +}