mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-06 19:52:33 +00:00
scoutfs-utils: add stat command
The scoutfs stat command is modeled after stat(1) and uses the STAT_MORE ioctl. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -10,6 +10,27 @@ struct scoutfs_ioctl_walk_inodes_entry {
|
||||
__u64 ino;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Walk inodes in an index that is sorted by one of their fields.
|
||||
*
|
||||
* Each index is built from generic index items that have major and
|
||||
* minor values that are set to the field being indexed. In time
|
||||
* indices, for example, major is seconds and minor is nanoseconds.
|
||||
*
|
||||
* @first The first index entry that can be returned.
|
||||
* @last The last index entry that can be returned.
|
||||
* @entries_ptr Pointer to emory containing buffer for entry results.
|
||||
* @nr_entries The number of entries that can fit in the buffer.
|
||||
* @index Which index to walk, enumerated in _WALK_INODES_ constants.
|
||||
*
|
||||
* To start iterating first can be memset to 0 and last to 0xff. Then
|
||||
* after each set of results first can be set to the last entry returned
|
||||
* and then the fields can be incremented in reverse sort order (ino <
|
||||
* minor < major) as each increasingly significant value wraps around to
|
||||
* 0.
|
||||
*
|
||||
* If first is greater than last then the walk will return 0 entries.
|
||||
*/
|
||||
struct scoutfs_ioctl_walk_inodes {
|
||||
struct scoutfs_ioctl_walk_inodes_entry first;
|
||||
struct scoutfs_ioctl_walk_inodes_entry last;
|
||||
@@ -107,4 +128,25 @@ struct scoutfs_ioctl_stage {
|
||||
#define SCOUTFS_IOC_STAGE _IOW(SCOUTFS_IOCTL_MAGIC, 6, \
|
||||
struct scoutfs_ioctl_stage)
|
||||
|
||||
/*
|
||||
* Give the user inode fields that are not otherwise visible. statx()
|
||||
* isn't always available and xattrs are relatively expensive.
|
||||
*
|
||||
* @valid_bytes stores the number of bytes that are valid in the
|
||||
* structure. The caller sets this to the size of the struct that they
|
||||
* understand. The kernel then fills and copies back the min of the
|
||||
* size they and the user caller understand. The user can tell if a
|
||||
* field is set if all of its bytes are within the valid_bytes that the
|
||||
* kernel set on return.
|
||||
*
|
||||
* New fields are only added to the end of the struct.
|
||||
*/
|
||||
struct scoutfs_ioctl_stat_more {
|
||||
__u64 valid_bytes;
|
||||
__u64 data_version;
|
||||
} __packed;
|
||||
|
||||
#define SCOUTFS_IOC_STAT_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 7, \
|
||||
struct scoutfs_ioctl_stat_more)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -193,41 +193,3 @@ static void __attribute__((constructor)) release_ctor(void)
|
||||
cmd_register("release", "<path> <vers> <offset> <count>",
|
||||
"mark file region offline and free extents", release_cmd);
|
||||
}
|
||||
|
||||
static int data_version_cmd(int argc, char **argv)
|
||||
{
|
||||
u64 vers;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "must specify path\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd = open(argv[0], O_RDWR);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "failed to open '%s': %s (%d)\n",
|
||||
argv[0], strerror(errno), errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, SCOUTFS_IOC_DATA_VERSION, &vers);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "data version ioctl failed: %s (%d)\n",
|
||||
strerror(errno), errno);
|
||||
} else {
|
||||
printf("%llu\n", vers);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
};
|
||||
|
||||
static void __attribute__((constructor)) data_version_ctor(void)
|
||||
{
|
||||
cmd_register("data_version", "<path>",
|
||||
"print the file's data version", data_version_cmd);
|
||||
}
|
||||
|
||||
65
utils/src/stat.c
Normal file
65
utils/src/stat.c
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sparse.h"
|
||||
#include "util.h"
|
||||
#include "format.h"
|
||||
#include "ioctl.h"
|
||||
#include "cmd.h"
|
||||
|
||||
static int stat_more_cmd(int argc, char **argv)
|
||||
{
|
||||
struct scoutfs_ioctl_stat_more stm;
|
||||
char *path;
|
||||
int ret;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
if (argc == 0) {
|
||||
fprintf(stderr, "must specify at least one path argument\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
path = argv[i];
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "failed to open '%s': %s (%d)\n",
|
||||
path, strerror(errno), errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&stm, 0, sizeof(stm));
|
||||
stm.valid_bytes = sizeof(stm);
|
||||
|
||||
ret = ioctl(fd, SCOUTFS_IOC_STAT_MORE, &stm);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "stat_more ioctl failed on '%s': "
|
||||
"%s (%d)\n", path, strerror(errno), errno);
|
||||
} else {
|
||||
printf(" File: '%s'\n"
|
||||
" data_version: %-20llu\n",
|
||||
path, stm.data_version);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) stat_more_ctor(void)
|
||||
{
|
||||
cmd_register("stat", "<path>",
|
||||
"print scoutfs stat information for path", stat_more_cmd);
|
||||
}
|
||||
Reference in New Issue
Block a user