blob: 941fdc1ac587af47f12daa1be1328395303b9acf [file] [log] [blame]
/*
* Copyright (c) 2003-2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "command.h"
#include "input.h"
#include "init.h"
#include "io.h"
#include "libxfs.h"
#ifndef __O_TMPFILE
#if defined __alpha__
#define __O_TMPFILE 0100000000
#elif defined(__hppa__)
#define __O_TMPFILE 040000000
#elif defined(__sparc__)
#define __O_TMPFILE 0x2000000
#else
#define __O_TMPFILE 020000000
#endif
#endif /* __O_TMPFILE */
#ifndef O_TMPFILE
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
#endif
static cmdinfo_t open_cmd;
static cmdinfo_t stat_cmd;
static cmdinfo_t close_cmd;
static cmdinfo_t statfs_cmd;
static cmdinfo_t chproj_cmd;
static cmdinfo_t lsproj_cmd;
static cmdinfo_t extsize_cmd;
static cmdinfo_t inode_cmd;
static prid_t prid;
static long extsize;
off64_t
filesize(void)
{
struct stat st;
if (fstat(file->fd, &st) < 0) {
perror("fstat");
return -1;
}
return st.st_size;
}
static char *
filetype(mode_t mode)
{
switch (mode & S_IFMT) {
case S_IFSOCK:
return _("socket");
case S_IFDIR:
return _("directory");
case S_IFCHR:
return _("char device");
case S_IFBLK:
return _("block device");
case S_IFREG:
return _("regular file");
case S_IFLNK:
return _("symbolic link");
case S_IFIFO:
return _("fifo");
}
return NULL;
}
static int
stat_f(
int argc,
char **argv)
{
struct dioattr dio;
struct fsxattr fsx, fsxa;
struct stat st;
int verbose = (argc == 2 && !strcmp(argv[1], "-v"));
printf(_("fd.path = \"%s\"\n"), file->name);
printf(_("fd.flags = %s,%s,%s%s%s%s%s\n"),
file->flags & IO_OSYNC ? _("sync") : _("non-sync"),
file->flags & IO_DIRECT ? _("direct") : _("non-direct"),
file->flags & IO_READONLY ? _("read-only") : _("read-write"),
file->flags & IO_REALTIME ? _(",real-time") : "",
file->flags & IO_APPEND ? _(",append-only") : "",
file->flags & IO_NONBLOCK ? _(",non-block") : "",
file->flags & IO_TMPFILE ? _(",tmpfile") : "");
if (fstat(file->fd, &st) < 0) {
perror("fstat");
} else {
printf(_("stat.ino = %lld\n"), (long long)st.st_ino);
printf(_("stat.type = %s\n"), filetype(st.st_mode));
printf(_("stat.size = %lld\n"), (long long)st.st_size);
printf(_("stat.blocks = %lld\n"), (long long)st.st_blocks);
if (verbose) {
printf(_("stat.atime = %s"), ctime(&st.st_atime));
printf(_("stat.mtime = %s"), ctime(&st.st_mtime));
printf(_("stat.ctime = %s"), ctime(&st.st_ctime));
}
}
if (file->flags & IO_FOREIGN)
return 0;
if ((xfsctl(file->name, file->fd, FS_IOC_FSGETXATTR, &fsx)) < 0 ||
(xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTRA, &fsxa)) < 0) {
perror("FS_IOC_FSGETXATTR");
} else {
printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags);
printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1);
printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid);
printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize);
printf(_("fsxattr.cowextsize = %u\n"), fsx.fsx_cowextsize);
printf(_("fsxattr.nextents = %u\n"), fsx.fsx_nextents);
printf(_("fsxattr.naextents = %u\n"), fsxa.fsx_nextents);
}
if ((xfsctl(file->name, file->fd, XFS_IOC_DIOINFO, &dio)) < 0) {
perror("XFS_IOC_DIOINFO");
} else {
printf(_("dioattr.mem = 0x%x\n"), dio.d_mem);
printf(_("dioattr.miniosz = %u\n"), dio.d_miniosz);
printf(_("dioattr.maxiosz = %u\n"), dio.d_maxiosz);
}
return 0;
}
int
openfile(
char *path,
xfs_fsop_geom_t *geom,
int flags,
mode_t mode)
{
int fd;
int oflags;
oflags = flags & IO_READONLY ? O_RDONLY : O_RDWR;
if (flags & IO_APPEND)
oflags |= O_APPEND;
if (flags & IO_CREAT)
oflags |= O_CREAT;
if (flags & IO_DIRECT)
oflags |= O_DIRECT;
if (flags & IO_OSYNC)
oflags |= O_SYNC;
if (flags & IO_TRUNC)
oflags |= O_TRUNC;
if (flags & IO_NONBLOCK)
oflags |= O_NONBLOCK;
if (flags & IO_TMPFILE)
oflags |= O_TMPFILE;
fd = open(path, oflags, mode);
if (fd < 0) {
if (errno == EISDIR &&
((oflags & (O_RDWR|O_TMPFILE)) == O_RDWR)) {
/* make it as if we asked for O_RDONLY & try again */
oflags &= ~O_RDWR;
oflags |= O_RDONLY;
flags |= IO_READONLY;
fd = open(path, oflags, mode);
if (fd < 0) {
perror(path);
return -1;
}
} else {
perror(path);
return -1;
}
}
if (!geom || !platform_test_xfs_fd(fd))
return fd;
if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
perror("XFS_IOC_FSGEOMETRY");
close(fd);
return -1;
}
if (!(flags & IO_READONLY) && (flags & IO_REALTIME)) {
struct fsxattr attr;
if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &attr) < 0) {
perror("FS_IOC_FSGETXATTR");
close(fd);
return -1;
}
if (!(attr.fsx_xflags & FS_XFLAG_REALTIME)) {
attr.fsx_xflags |= FS_XFLAG_REALTIME;
if (xfsctl(path, fd, FS_IOC_FSSETXATTR, &attr) < 0) {
perror("FS_IOC_FSSETXATTR");
close(fd);
return -1;
}
}
}
return fd;
}
int
addfile(
char *name,
int fd,
xfs_fsop_geom_t *geometry,
int flags)
{
char *filename;
filename = strdup(name);
if (!filename) {
perror("strdup");
close(fd);
return -1;
}
/* Extend the table of currently open files */
filetable = (fileio_t *)realloc(filetable, /* growing */
++filecount * sizeof(fileio_t));
if (!filetable) {
perror("realloc");
filecount = 0;
free(filename);
close(fd);
return -1;
}
/* Finally, make this the new active open file */
file = &filetable[filecount - 1];
file->fd = fd;
file->flags = flags;
file->name = filename;
file->geom = *geometry;
return 0;
}
static void
open_help(void)
{
printf(_(
"\n"
" opens a new file in the requested mode\n"
"\n"
" Example:\n"
" 'open -cd /tmp/data' - creates/opens data file read-write for direct IO\n"
"\n"
" Opens a file for subsequent use by all of the other xfs_io commands.\n"
" With no arguments, open uses the stat command to show the current file.\n"
" -a -- open with the O_APPEND flag (append-only mode)\n"
" -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\n"
" -f -- open with O_CREAT (create the file if it doesn't exist)\n"
" -m -- permissions to use in case a new file is created (default 0600)\n"
" -n -- open with O_NONBLOCK\n"
" -r -- open with O_RDONLY, the default is O_RDWR\n"
" -s -- open with O_SYNC\n"
" -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n"
" -R -- mark the file as a realtime XFS file immediately after opening it\n"
" -T -- open with O_TMPFILE (create a file not visible in the namespace)\n"
" Note1: usually read/write direct IO requests must be blocksize aligned;\n"
" some kernels, however, allow sectorsize alignment for direct IO.\n"
" Note2: the bmap for non-regular files can be obtained provided the file\n"
" was opened correctly (in particular, must be opened read-only).\n"
"\n"));
}
static int
open_f(
int argc,
char **argv)
{
int c, fd, flags = 0;
char *sp;
mode_t mode = 0600;
xfs_fsop_geom_t geometry = { 0 };
if (argc == 1) {
if (file)
return stat_f(argc, argv);
fprintf(stderr, _("no files are open, try 'help open'\n"));
return 0;
}
while ((c = getopt(argc, argv, "FRTacdfm:nrstx")) != EOF) {
switch (c) {
case 'F':
/* Ignored / deprecated now, handled automatically */
break;
case 'a':
flags |= IO_APPEND;
break;
case 'c':
case 'f':
flags |= IO_CREAT;
break;
case 'd':
flags |= IO_DIRECT;
break;
case 'm':
mode = strtoul(optarg, &sp, 0);
if (!sp || sp == optarg) {
printf(_("non-numeric mode -- %s\n"), optarg);
return 0;
}
break;
case 'n':
flags |= IO_NONBLOCK;
break;
case 'r':
flags |= IO_READONLY;
break;
case 's':
flags |= IO_OSYNC;
break;
case 't':
flags |= IO_TRUNC;
break;
case 'R':
case 'x': /* backwards compatibility */
flags |= IO_REALTIME;
break;
case 'T':
flags |= IO_TMPFILE;
break;
default:
return command_usage(&open_cmd);
}
}
if (optind != argc - 1)
return command_usage(&open_cmd);
if ((flags & (IO_READONLY|IO_TMPFILE)) == (IO_READONLY|IO_TMPFILE)) {
fprintf(stderr, _("-T and -r options are incompatible\n"));
return -1;
}
fd = openfile(argv[optind], &geometry, flags, mode);
if (fd < 0)
return 0;
if (!platform_test_xfs_fd(fd))
flags |= IO_FOREIGN;
addfile(argv[optind], fd, &geometry, flags);
return 0;
}
static int
close_f(
int argc,
char **argv)
{
size_t length;
unsigned int offset;
if (close(file->fd) < 0) {
perror("close");
return 0;
}
free(file->name);
/* Shuffle the file table entries down over the removed entry */
offset = file - &filetable[0];
length = filecount * sizeof(fileio_t);
length -= (offset + 1) * sizeof(fileio_t);
if (length)
memmove(file, file + 1, length);
/* Resize the memory allocated for the table, possibly freeing */
if (--filecount) {
filetable = (fileio_t *)realloc(filetable, /* shrinking */
filecount * sizeof(fileio_t));
if (offset == filecount)
offset--;
file = filetable + offset;
} else {
free(filetable);
file = filetable = NULL;
}
filelist_f();
return 0;
}
static void
lsproj_help(void)
{
printf(_(
"\n"
" displays the project identifier associated with the current path\n"
"\n"
" Options:\n"
" -R -- recursively descend (useful when current path is a directory)\n"
" -D -- recursively descend, but only list projects on directories\n"
"\n"));
}
static int
lsproj_callback(
const char *path,
const struct stat *stat,
int status,
struct FTW *data)
{
prid_t projid;
int fd;
if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
if ((fd = open(path, O_RDONLY)) == -1) {
fprintf(stderr, _("%s: cannot open %s: %s\n"),
progname, path, strerror(errno));
} else {
if (getprojid(path, fd, &projid) == 0)
printf("[%u] %s\n", (unsigned int)projid, path);
close(fd);
}
return 0;
}
static int
lsproj_f(
int argc,
char **argv)
{
prid_t projid;
int c;
recurse_all = recurse_dir = 0;
while ((c = getopt(argc, argv, "DR")) != EOF) {
switch (c) {
case 'D':
recurse_all = 0;
recurse_dir = 1;
break;
case 'R':
recurse_all = 1;
recurse_dir = 0;
break;
default:
return command_usage(&lsproj_cmd);
}
}
if (argc != optind)
return command_usage(&lsproj_cmd);
if (recurse_all || recurse_dir)
nftw(file->name, lsproj_callback,
100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
else if (getprojid(file->name, file->fd, &projid) < 0)
perror("getprojid");
else
printf(_("projid = %u\n"), (unsigned int)projid);
return 0;
}
static void
chproj_help(void)
{
printf(_(
"\n"
" modifies the project identifier associated with the current path\n"
"\n"
" -R -- recursively descend (useful when current path is a directory)\n"
" -D -- recursively descend, only modifying projects on directories\n"
"\n"));
}
static int
chproj_callback(
const char *path,
const struct stat *stat,
int status,
struct FTW *data)
{
int fd;
if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
if ((fd = open(path, O_RDONLY)) == -1) {
fprintf(stderr, _("%s: cannot open %s: %s\n"),
progname, path, strerror(errno));
} else {
if (setprojid(path, fd, prid) < 0)
perror("setprojid");
close(fd);
}
return 0;
}
static int
chproj_f(
int argc,
char **argv)
{
int c;
recurse_all = recurse_dir = 0;
while ((c = getopt(argc, argv, "DR")) != EOF) {
switch (c) {
case 'D':
recurse_all = 0;
recurse_dir = 1;
break;
case 'R':
recurse_all = 1;
recurse_dir = 0;
break;
default:
return command_usage(&chproj_cmd);
}
}
if (argc != optind + 1)
return command_usage(&chproj_cmd);
prid = prid_from_string(argv[optind]);
if (prid == -1) {
printf(_("invalid project ID -- %s\n"), argv[optind]);
return 0;
}
if (recurse_all || recurse_dir)
nftw(file->name, chproj_callback,
100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
else if (setprojid(file->name, file->fd, prid) < 0)
perror("setprojid");
return 0;
}
static void
extsize_help(void)
{
printf(_(
"\n"
" report or modify preferred extent size (in bytes) for the current path\n"
"\n"
" -R -- recursively descend (useful when current path is a directory)\n"
" -D -- recursively descend, only modifying extsize on directories\n"
"\n"));
}
static int
get_extsize(const char *path, int fd)
{
struct fsxattr fsx;
if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
printf("%s: FS_IOC_FSGETXATTR %s: %s\n",
progname, path, strerror(errno));
return 0;
}
printf("[%u] %s\n", fsx.fsx_extsize, path);
return 0;
}
static int
set_extsize(const char *path, int fd, long extsz)
{
struct fsxattr fsx;
struct stat stat;
if (fstat(fd, &stat) < 0) {
perror("fstat");
return 0;
}
if ((xfsctl(path, fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
printf("%s: FS_IOC_FSGETXATTR %s: %s\n",
progname, path, strerror(errno));
return 0;
}
if (S_ISREG(stat.st_mode)) {
fsx.fsx_xflags |= FS_XFLAG_EXTSIZE;
} else if (S_ISDIR(stat.st_mode)) {
fsx.fsx_xflags |= FS_XFLAG_EXTSZINHERIT;
} else {
printf(_("invalid target file type - file %s\n"), path);
return 0;
}
fsx.fsx_extsize = extsz;
if ((xfsctl(path, fd, FS_IOC_FSSETXATTR, &fsx)) < 0) {
printf("%s: FS_IOC_FSSETXATTR %s: %s\n",
progname, path, strerror(errno));
return 0;
}
return 0;
}
static int
get_extsize_callback(
const char *path,
const struct stat *stat,
int status,
struct FTW *data)
{
int fd;
if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
if ((fd = open(path, O_RDONLY)) == -1) {
fprintf(stderr, _("%s: cannot open %s: %s\n"),
progname, path, strerror(errno));
} else {
get_extsize(path, fd);
close(fd);
}
return 0;
}
static int
set_extsize_callback(
const char *path,
const struct stat *stat,
int status,
struct FTW *data)
{
int fd;
if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
if ((fd = open(path, O_RDONLY)) == -1) {
fprintf(stderr, _("%s: cannot open %s: %s\n"),
progname, path, strerror(errno));
} else {
set_extsize(path, fd, extsize);
close(fd);
}
return 0;
}
static int
extsize_f(
int argc,
char **argv)
{
size_t blocksize, sectsize;
int c;
recurse_all = recurse_dir = 0;
init_cvtnum(&blocksize, &sectsize);
while ((c = getopt(argc, argv, "DR")) != EOF) {
switch (c) {
case 'D':
recurse_all = 0;
recurse_dir = 1;
break;
case 'R':
recurse_all = 1;
recurse_dir = 0;
break;
default:
return command_usage(&extsize_cmd);
}
}
if (optind < argc) {
extsize = (long)cvtnum(blocksize, sectsize, argv[optind]);
if (extsize < 0) {
printf(_("non-numeric extsize argument -- %s\n"),
argv[optind]);
return 0;
}
} else {
extsize = -1;
}
if (recurse_all || recurse_dir)
nftw(file->name, (extsize >= 0) ?
set_extsize_callback : get_extsize_callback,
100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
else if (extsize >= 0)
set_extsize(file->name, file->fd, extsize);
else
get_extsize(file->name, file->fd);
return 0;
}
static int
statfs_f(
int argc,
char **argv)
{
struct xfs_fsop_counts fscounts;
struct xfs_fsop_geom fsgeo;
struct statfs st;
printf(_("fd.path = \"%s\"\n"), file->name);
if (platform_fstatfs(file->fd, &st) < 0) {
perror("fstatfs");
} else {
printf(_("statfs.f_bsize = %lld\n"), (long long) st.f_bsize);
printf(_("statfs.f_blocks = %lld\n"), (long long) st.f_blocks);
printf(_("statfs.f_bavail = %lld\n"), (long long) st.f_bavail);
printf(_("statfs.f_files = %lld\n"), (long long) st.f_files);
printf(_("statfs.f_ffree = %lld\n"), (long long) st.f_ffree);
}
if (file->flags & IO_FOREIGN)
return 0;
if ((xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) {
perror("XFS_IOC_FSGEOMETRY_V1");
} else {
printf(_("geom.bsize = %u\n"), fsgeo.blocksize);
printf(_("geom.agcount = %u\n"), fsgeo.agcount);
printf(_("geom.agblocks = %u\n"), fsgeo.agblocks);
printf(_("geom.datablocks = %llu\n"),
(unsigned long long) fsgeo.datablocks);
printf(_("geom.rtblocks = %llu\n"),
(unsigned long long) fsgeo.rtblocks);
printf(_("geom.rtextents = %llu\n"),
(unsigned long long) fsgeo.rtextents);
printf(_("geom.rtextsize = %u\n"), fsgeo.rtextsize);
printf(_("geom.sunit = %u\n"), fsgeo.sunit);
printf(_("geom.swidth = %u\n"), fsgeo.swidth);
}
if ((xfsctl(file->name, file->fd, XFS_IOC_FSCOUNTS, &fscounts)) < 0) {
perror("XFS_IOC_FSCOUNTS");
} else {
printf(_("counts.freedata = %llu\n"),
(unsigned long long) fscounts.freedata);
printf(_("counts.freertx = %llu\n"),
(unsigned long long) fscounts.freertx);
printf(_("counts.freeino = %llu\n"),
(unsigned long long) fscounts.freeino);
printf(_("counts.allocino = %llu\n"),
(unsigned long long) fscounts.allocino);
}
return 0;
}
static void
inode_help(void)
{
printf(_(
"\n"
"Query physical information about an inode"
"\n"
" Default: -- Return 1 if any inode number greater than 32 bits exists in\n"
" the filesystem, or 0 if none exist\n"
" num -- Return inode number [num] if in use, or 0 if not in use\n"
" -n num -- Return the next used inode after [num]\n"
" -v -- Verbose mode - display returned inode number's size in bits\n"
"\n"));
}
static __u64
get_last_inode(void)
{
__u64 lastip = 0;
__u64 lastgrp = 0;
__s32 ocount = 0;
__u64 last_ino;
struct xfs_inogrp igroup[1024];
struct xfs_fsop_bulkreq bulkreq;
bulkreq.lastip = &lastip;
bulkreq.ubuffer = &igroup;
bulkreq.icount = sizeof(igroup) / sizeof(struct xfs_inogrp);
bulkreq.ocount = &ocount;
for (;;) {
if (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS,
&bulkreq)) {
perror("XFS_IOC_FSINUMBERS");
return 0;
}
/* Did we reach the last inode? */
if (ocount == 0)
break;
/* last inode in igroup table */
lastgrp = ocount;
}
lastgrp--;
/* The last inode number in use */
last_ino = igroup[lastgrp].xi_startino +
libxfs_highbit64(igroup[lastgrp].xi_allocmask);
return last_ino;
}
static int
inode_f(
int argc,
char **argv)
{
__s32 count = 0;
__u64 result_ino = 0;
__u64 userino = NULLFSINO;
char *p;
int c;
int verbose = 0;
int ret_next = 0;
int cmd = 0;
struct xfs_fsop_bulkreq bulkreq;
struct xfs_bstat bstat;
while ((c = getopt(argc, argv, "nv")) != EOF) {
switch (c) {
case 'v':
verbose = 1;
break;
case 'n':
ret_next = 1;
break;
default:
return command_usage(&inode_cmd);
}
}
/* Last arg (if present) should be an inode number */
if (optind < argc) {
userino = strtoull(argv[optind], &p, 10);
if ((*p != '\0')) {
printf(_("%s is not a numeric inode value\n"),
argv[optind]);
exitcode = 1;
return 0;
}
optind++;
}
/* Extra junk? */
if (optind < argc)
return command_usage(&inode_cmd);
/* -n option requires an inode number */
if (ret_next && userino == NULLFSINO)
return command_usage(&inode_cmd);
if (userino == NULLFSINO) {
/* We are finding last inode in use */
result_ino = get_last_inode();
if (!result_ino) {
exitcode = 1;
return 0;
}
} else {
if (ret_next) /* get next inode */
cmd = XFS_IOC_FSBULKSTAT;
else /* get this inode */
cmd = XFS_IOC_FSBULKSTAT_SINGLE;
bulkreq.lastip = &userino;
bulkreq.icount = 1;
bulkreq.ubuffer = &bstat;
bulkreq.ocount = &count;
if (xfsctl(file->name, file->fd, cmd, &bulkreq)) {
if (!ret_next && errno == EINVAL) {
/* Not in use */
result_ino = 0;
} else {
perror("xfsctl");
exitcode = 1;
return 0;
}
} else if (ret_next) {
/* The next inode in use, or 0 if none */
if (*bulkreq.ocount)
result_ino = bstat.bs_ino;
else
result_ino = 0;
} else {
/* The inode we asked about */
result_ino = userino;
}
}
if (verbose && result_ino) {
/* Requested verbose and we have an answer */
printf("%llu:%d\n", result_ino,
result_ino > XFS_MAXINUMBER_32 ? 64 : 32);
} else if (userino == NULLFSINO) {
/* Just checking 32 or 64 bit presence, non-verbose */
printf("%d\n", result_ino > XFS_MAXINUMBER_32 ? 1 : 0);
} else {
/* We asked about a specific inode, non-verbose */
printf("%llu\n", result_ino);
}
return 0;
}
void
open_init(void)
{
open_cmd.name = "open";
open_cmd.altname = "o";
open_cmd.cfunc = open_f;
open_cmd.argmin = 0;
open_cmd.argmax = -1;
open_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK |
CMD_FOREIGN_OK | CMD_FLAG_ONESHOT;
open_cmd.args = _("[-acdrstxT] [-m mode] [path]");
open_cmd.oneline = _("open the file specified by path");
open_cmd.help = open_help;
stat_cmd.name = "stat";
stat_cmd.cfunc = stat_f;
stat_cmd.argmin = 0;
stat_cmd.argmax = 1;
stat_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
stat_cmd.args = _("[-v]");
stat_cmd.oneline = _("statistics on the currently open file");
close_cmd.name = "close";
close_cmd.altname = "c";
close_cmd.cfunc = close_f;
close_cmd.argmin = 0;
close_cmd.argmax = 0;
close_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK | CMD_FLAG_ONESHOT;
close_cmd.oneline = _("close the current open file");
statfs_cmd.name = "statfs";
statfs_cmd.cfunc = statfs_f;
statfs_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
statfs_cmd.oneline =
_("statistics on the filesystem of the currently open file");
chproj_cmd.name = "chproj";
chproj_cmd.cfunc = chproj_f;
chproj_cmd.args = _("[-D | -R] projid");
chproj_cmd.argmin = 1;
chproj_cmd.argmax = -1;
chproj_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
chproj_cmd.oneline =
_("change project identifier on the currently open file");
chproj_cmd.help = chproj_help;
lsproj_cmd.name = "lsproj";
lsproj_cmd.cfunc = lsproj_f;
lsproj_cmd.args = _("[-D | -R]");
lsproj_cmd.argmin = 0;
lsproj_cmd.argmax = -1;
lsproj_cmd.flags = CMD_NOMAP_OK;
lsproj_cmd.oneline =
_("list project identifier set on the currently open file");
lsproj_cmd.help = lsproj_help;
extsize_cmd.name = "extsize";
extsize_cmd.cfunc = extsize_f;
extsize_cmd.args = _("[-D | -R] [extsize]");
extsize_cmd.argmin = 0;
extsize_cmd.argmax = -1;
extsize_cmd.flags = CMD_NOMAP_OK;
extsize_cmd.oneline =
_("get/set preferred extent size (in bytes) for the open file");
extsize_cmd.help = extsize_help;
inode_cmd.name = "inode";
inode_cmd.cfunc = inode_f;
inode_cmd.args = _("[-nv] [num]");
inode_cmd.argmin = 0;
inode_cmd.argmax = 3;
inode_cmd.flags = CMD_NOMAP_OK | CMD_FLAG_ONESHOT;
inode_cmd.oneline =
_("Query inode number usage in the filesystem");
inode_cmd.help = inode_help;
add_command(&open_cmd);
add_command(&stat_cmd);
add_command(&close_cmd);
add_command(&statfs_cmd);
add_command(&chproj_cmd);
add_command(&lsproj_cmd);
add_command(&extsize_cmd);
add_command(&inode_cmd);
}