Implement argp support for ino-path

Signed-off-by: Andy Grover <agrover@versity.com>
This commit is contained in:
Andy Grover
2020-11-20 16:14:01 -08:00
parent 68b8e4098d
commit 10df01eb7a

View File

@@ -8,44 +8,32 @@
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <argp.h>
#include "sparse.h"
#include "parse.h"
#include "util.h"
#include "format.h"
#include "ioctl.h"
#include "parse.h"
#include "cmd.h"
static int ino_path_cmd(int argc, char **argv)
struct ino_args {
char *path;
u64 ino;
};
static int do_ino_path(struct ino_args *args)
{
struct scoutfs_ioctl_ino_path args;
struct scoutfs_ioctl_ino_path ioctl_args;
struct scoutfs_ioctl_ino_path_result *res;
unsigned int result_bytes;
char *endptr = NULL;
u64 ino;
int ret;
int fd;
if (argc != 3) {
fprintf(stderr, "must specify ino and path\n");
return -EINVAL;
}
ino = strtoull(argv[1], &endptr, 0);
if (*endptr != '\0' ||
((ino == LLONG_MIN || ino == LLONG_MAX) && errno == ERANGE)) {
fprintf(stderr, "error parsing inode number '%s'\n",
argv[1]);
return -EINVAL;
}
fd = open(argv[2], O_RDONLY);
if (fd < 0) {
ret = -errno;
fprintf(stderr, "failed to open '%s': %s (%d)\n",
argv[2], strerror(errno), errno);
return ret;
}
fd = get_path(args->path, O_RDONLY);
if (fd < 0)
return fd;
result_bytes = offsetof(struct scoutfs_ioctl_ino_path_result,
path[PATH_MAX]);
@@ -57,13 +45,13 @@ static int ino_path_cmd(int argc, char **argv)
goto out;
}
args.ino = ino;
args.dir_ino = 0;
args.dir_pos = 0;
args.result_ptr = (intptr_t)res;
args.result_bytes = result_bytes;
ioctl_args.ino = args->ino;
ioctl_args.dir_ino = 0;
ioctl_args.dir_pos = 0;
ioctl_args.result_ptr = (intptr_t)res;
ioctl_args.result_bytes = result_bytes;
for (;;) {
ret = ioctl(fd, SCOUTFS_IOC_INO_PATH, &args);
ret = ioctl(fd, SCOUTFS_IOC_INO_PATH, &ioctl_args);
if (ret < 0) {
ret = -errno;
if (ret == -ENOENT)
@@ -73,10 +61,10 @@ static int ino_path_cmd(int argc, char **argv)
printf("%.*s\n", res->path_bytes, res->path);
args.dir_ino = res->dir_ino;
args.dir_pos = res->dir_pos;
if (++args.dir_pos == 0) {
if (++args.dir_ino == 0)
ioctl_args.dir_ino = res->dir_ino;
ioctl_args.dir_pos = res->dir_pos;
if (++ioctl_args.dir_pos == 0) {
if (++ioctl_args.dir_ino == 0)
break;
}
}
@@ -92,6 +80,58 @@ out:
return ret;
};
static int parse_opt(int key, char *arg, struct argp_state *state)
{
struct ino_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 int ino_path_cmd(int argc, char **argv)
{
struct argp argp = {
options,
parse_opt,
"INODE-NUM",
"Print paths that refer to inode number"
};
struct ino_args ino_args = {NULL};
int ret;
ret = argp_parse(&argp, argc, argv, 0, NULL, &ino_args);
if (ret)
return ret;
return do_ino_path(&ino_args);
}
static void __attribute__((constructor)) ino_path_ctor(void)
{
cmd_register("ino-path", "<ino> <path>",