]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Add xfs_io into xfsprogs, an xfs_db-alike program for the XFS IO path
authorNathan Scott <nathans@sgi.com>
Tue, 25 Mar 2003 03:48:48 +0000 (03:48 +0000)
committerNathan Scott <nathans@sgi.com>
Tue, 25 Mar 2003 03:48:48 +0000 (03:48 +0000)
which knows about direct IO, space preallocation, realtime files, etc
which the usual tools like dd don't unfortunately.  This is a fixed-up
version of a hacked tool that I found useful for coding, debugging and
testing unwritten extents; hopefully it'll be useful for realtime too.

29 files changed:
Makefile
VERSION
configure.in
db/Makefile
db/input.c
debian/changelog
debian/control
debian/rules
doc/CHANGES
include/builddefs.in
include/xfs_fs.h
io/Makefile [moved from bmap/Makefile with 77% similarity]
io/bmap.c [moved from bmap/xfs_bmap.c with 73% similarity]
io/command.c [new file with mode: 0644]
io/command.h [new file with mode: 0644]
io/help.c [new file with mode: 0644]
io/init.c [new file with mode: 0644]
io/init.h [new file with mode: 0644]
io/input.c [new file with mode: 0644]
io/input.h [new file with mode: 0644]
io/open.c [new file with mode: 0644]
io/pread.c [new file with mode: 0644]
io/prealloc.c [new file with mode: 0644]
io/pwrite.c [new file with mode: 0644]
io/quit.c [new file with mode: 0644]
io/resblks.c [new file with mode: 0644]
io/truncate.c [new file with mode: 0644]
io/xfs_bmap.sh [new file with mode: 0755]
man/man8/xfs_io.8 [new file with mode: 0644]

index fa0db078aecc69459965879051128313103fd8cd..552b8fc130a1debf6af6f9d5d4ac4ce66d804786 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -44,7 +44,7 @@ LDIRT = config.log .dep config.status config.cache confdefs.h conftest* \
        Logs/* built .census install.* install-dev.* *.gz
 
 SUBDIRS = include libxfs libxlog libhandle libdisk \
-       bmap db freeze fsck growfs imap logprint mkfile mkfs repair rtcp \
+       db freeze fsck growfs io imap logprint mkfile mkfs repair rtcp \
        man doc po debian build
 
 default: $(CONFIGURE)
@@ -60,7 +60,7 @@ else
 clean: # if configure hasn't run, nothing to clean
 endif
 
-$(CONFIGURE): configure.in
+$(CONFIGURE):
        autoconf
        ./configure \
                --prefix=/ \
diff --git a/VERSION b/VERSION
index 487da79313f37b1cbc7249d4591ed83567c84a93..cb5e8205cd3a48b00886f2183218a91caa8ce0f2 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -3,5 +3,5 @@
 #
 PKG_MAJOR=2
 PKG_MINOR=4
-PKG_REVISION=1
+PKG_REVISION=2
 PKG_BUILD=0
index 1b3da7b20c2b1e388ebb747c8a53c604b8cdaa19..2f42861fcec88960276970f94fa2b3b3b943afd5 100644 (file)
@@ -160,9 +160,16 @@ dnl will we be making use of gettext?
 AC_ARG_ENABLE(gettext,
        [ --enable-gettext=[yes/no] Enable alternate language support [default=yes]],,
        enable_gettext=yes)
-test $enable_gettext = "yes" && AC_DEFINE(ENABLE_GETTEXT)
 AC_SUBST(enable_gettext)
 
+dnl will we be making use of readline?
+AC_ARG_ENABLE(readline,
+       [ --enable-readline=[yes/no] Enable readline command editing [default=no]],,
+       enable_readline=no)
+libreadline="-lreadline"
+AC_SUBST(libreadline)
+AC_SUBST(enable_readline)
+
 dnl Checks for UUID header and library.
 AC_CHECK_HEADER(uuid/uuid.h,, [
        echo
index 54c24b34b3928cba62c91a15ecb16c4292484461..bede36fed9ca5f7fcf53d9c392ad4f72e4657fd4 100644 (file)
@@ -47,6 +47,11 @@ LLDLIBS      = $(LIBXFS) $(LIBXLOG) $(LIBUUID)
 LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG)
 LLDFLAGS += -static
 
+ifeq ($(ENABLE_READLINE),yes)
+LLDLIBS += $(LIBREADLINE)
+CFLAGS += -DENABLE_READLINE
+endif
+
 default: $(LTCOMMAND)
 
 include $(BUILDRULES)
index 0339985def9a0648b589bec935a27caa974dda74..5cd6f40131eb987876ada0939fb165126f7b877a 100644 (file)
 #include "malloc.h"
 #include "init.h"
 
+#ifdef ENABLE_READLINE
+# include <readline/history.h>
+# include <readline/readline.h>
+#endif
+
 int    inputstacksize;
 FILE   **inputstack;
 FILE   *curinput;
@@ -142,8 +147,8 @@ doneline(
        xfree(vec);
 }
 
-char *
-fetchline(void)
+static char *
+fetchline_internal(void)
 {
        char    buf[1024];
        int     iscont;
@@ -157,7 +162,7 @@ fetchline(void)
                        if (iscont)
                                dbprintf("... ");
                        else
-                               dbprintf("%s: ", progname);
+                               dbprintf("%s> ", progname);
                        fflush(stdin);
                }
                if (seenint() ||
@@ -214,11 +219,34 @@ fetchline(void)
        return rval;
 }
 
-void
-input_init(void)
+#ifdef ENABLE_READLINE
+char *
+fetchline(void)
 {
-       add_command(&source_cmd);
+       static char     prompt[FILENAME_MAX + 1];
+       char            *line;
+
+       if (!prompt[0])
+               snprintf(prompt, sizeof(prompt), "%s> ", progname);
+
+       if (inputstacksize == 1) {
+               line = readline(prompt);
+               if (line && *line)
+                       add_history(line);
+               else
+                       logprintf("%s", line);
+       } else {
+               line = fetchline_internal();
+       }
+       return line;
+}
+#else
+char *
+fetchline(void)
+{
+       return fetchline_internal();
 }
+#endif
 
 static void
 popfile(void)
@@ -268,3 +296,9 @@ source_f(
                pushfile(f);
        return 0;
 }
+
+void
+input_init(void)
+{
+       add_command(&source_cmd);
+}
index 6fde2d1f6a7c1bdf5c35af5606771c81aceca7e3..e54a931fa1f94a500d0c9cac6675363ef8908ceb 100644 (file)
@@ -1,7 +1,14 @@
+xfsprogs (2.4.2-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Nathan Scott <nathans@debian.org>  Tue, 25 Mar 2003 11:25:02 +1100
+
 xfsprogs (2.4.1-1) unstable; urgency=low
 
   * New upstream release
-  * Note: unwritten extents are now enabled by default in mkfs.xfs.
+  * Updated policy version this package conforms to
+  * Note: unwritten extents are now enabled by default in mkfs.xfs
 
  -- Nathan Scott <nathans@debian.org>  Tue, 18 Mar 2003 16:16:43 +1100
 
index 3aa81c465470f754c420db6602880c99f4401e50..15b7e773642d98f2cee29fc035e5ba633e65b088 100644 (file)
@@ -2,8 +2,8 @@ Source: xfsprogs
 Section: admin
 Priority: optional
 Maintainer: Nathan Scott <nathans@debian.org>
-Build-Depends: uuid-dev, autoconf, debmake, gettext, libtool
-Standards-Version: 3.5.5
+Build-Depends: uuid-dev, autoconf, debmake, gettext, libtool, libreadline4-dev
+Standards-Version: 3.5.9
 
 Package: xfsprogs
 Depends: ${shlibs:Depends}
index f49b8bdf78da990c0fb8717aad49fc6b5312cd15..684624d2ffd5cc9712adf049b8b6169aa7623f09 100755 (executable)
@@ -12,8 +12,8 @@ pkgdev = DIST_ROOT=`pwd`/$(dirdev); export DIST_ROOT;
 pkgbfs = DIST_ROOT=`pwd`/$(dirbfs); export DIST_ROOT;
 stdenv = @GZIP=-q; export GZIP;
 
-options = DEBUG=-DNDEBUG; DISTRIBUTION=debian; export DEBUG DISTRIBUTION;
-bfsopts = OPTIMIZER=-Os; LOCAL_CONFIGURE_OPTIONS="--enable-shared-uuid=yes --enable-gettext=no"; $(options) export OPTIMIZER LOCAL_CONFIGURE_OPTIONS;
+options = DEBUG=-DNDEBUG; DISTRIBUTION=debian; LOCAL_CONFIGURE_OPTIONS=--enable-readline=yes; export DEBUG DISTRIBUTION LOCAL_CONFIGURE_OPTIONS;
+bfsopts = $(options); OPTIMIZER=-Os; LOCAL_CONFIGURE_OPTIONS="--enable-shared-uuid=yes --enable-gettext=no"; export OPTIMIZER LOCAL_CONFIGURE_OPTIONS;
 checkdir = test -f debian/rules
 
 build: built
index 8600ca6bc6bad6aaf66b054f5a8949cb8a89e24f..e93cb37f550c8323092a39829fd22e3f83baf29e 100644 (file)
@@ -1,4 +1,16 @@
-xfsprogs-2.4.1 (18 March 2002)
+xfsprogs-2.4.2 (27 March 2003)
+       - Added the xfs_io(8) command, an xfs_db(8) alike command
+         for testing and debugging the XFS file IO path.
+       - Added an optional dependency on the GNU readline library
+         which is "off" by default and enabled with the configure
+         option --enable-readline=yes; it affects the interactive
+         tools only (xfs_db and now xfs_io).
+       - Implemented xfs_bmap(8) as a shell script wrapper.
+       - Documented the mkfs.xfs -f, -llogdev and -rrtdev options.
+       - Corrected size check for realtime summary inode (not the
+         same as the realtime bitmap inode) in xfs_repair.
+
+xfsprogs-2.4.1 (18 March 2003)
        - Fix error reporting when zeroing parts of the realtime
          device in phase6 of xfs_repair.
        - Add a mkfs.xfs check for Mac partitions before writing
@@ -7,7 +19,7 @@ xfsprogs-2.4.1 (18 March 2002)
        - Minor fix to the xfs_bmap(8) man page.
        - Sync up user/kernel source in libxfs and headers.
 
-xfsprogs-2.4.0 (06 March 2002)
+xfsprogs-2.4.0 (06 March 2003)
        - Enable unwritten extents by default in mkfs.xfs.
        - Add a command to xfs_db to enable unwritten extents.
        - Add an option to xfs_admin to use the above command.
@@ -22,10 +34,10 @@ xfsprogs-2.4.0 (06 March 2002)
        - Update man pages, fix a typo in the xfs_admin man page
          relating to the UUID options.
 
-xfsprogs-2.3.11 (18 February 2002)
+xfsprogs-2.3.11 (18 February 2003)
        - Missed a build dependency for the Debian build process.
 
-xfsprogs-2.3.10 (17 February 2002)
+xfsprogs-2.3.10 (17 February 2003)
        - Fix a divide-by-zero error in mkfs with certain stripe unit
          and/or width options specified.
        - Sync up user/kernel source in libxfs and headers.
index a8caf6e0a2d590ca18a56e9d1cfc7a1633a22448..a224bc389d3e2f482beddd47c3619cfc03ff1e35 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2002 Silicon Graphics, Inc.  All Rights Reserved.
+# Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
 # 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of version 2 of the GNU General Public License as
@@ -40,6 +40,7 @@ OPTIMIZER = @opt_build@
 MALLOCLIB = @malloc_lib@
 
 LIBUUID = @libuuid@
+LIBREADLINE = @libreadline@
 LIBXFS = $(TOPDIR)/libxfs/libxfs.la
 LIBXLOG = $(TOPDIR)/libxlog/libxlog.la
 LIBDISK = $(TOPDIR)/libdisk/libdisk.la
@@ -87,6 +88,7 @@ RPM_VERSION   = @rpm_version@
 
 ENABLE_SHARED = @enable_shared@
 ENABLE_GETTEXT = @enable_gettext@
+ENABLE_READLINE = @enable_readline@
 HAVE_ZIPPED_MANPAGES = @have_zipped_manpages@
 
 LCFLAGS += -DXFS_BIG_FILES=1 -DXFS_BIG_FILESYSTEMS=1
index c66ccc57e123d3dca404ec6b82f9e21da4c15016..c008c24d5acaeba81223d70fc98dc71feca27ec6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 1995-2003 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2.1 of the GNU Lesser General Public License
@@ -472,7 +472,7 @@ typedef struct xfs_handle {
 #define XFS_IOC_FSGROWFSLOG         _IOW ('X', 111, struct xfs_growfs_log)
 #define XFS_IOC_FSGROWFSRT          _IOW ('X', 112, struct xfs_growfs_rt)
 #define XFS_IOC_FSCOUNTS            _IOR ('X', 113, struct xfs_fsop_counts)
-#define XFS_IOC_SET_RESBLKS         _IO('X', 114, struct xfs_fsop_resblks)
+#define XFS_IOC_SET_RESBLKS         _IOWR('X', 114, struct xfs_fsop_resblks)
 #define XFS_IOC_GET_RESBLKS         _IOR ('X', 115, struct xfs_fsop_resblks)
 #define XFS_IOC_ERROR_INJECTION             _IOW ('X', 116, struct xfs_error_injection)
 #define XFS_IOC_ERROR_CLEARALL      _IOW ('X', 117, struct xfs_error_injection)
similarity index 77%
rename from bmap/Makefile
rename to io/Makefile
index 7da8012adff188f9d237ac0304cf66aee7a3995c..6cf4c8d544613192ecc5f9a6ab225942367ad114 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
+# Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
 # 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of version 2 of the GNU General Public License as
 TOPDIR = ..
 include $(TOPDIR)/include/builddefs
 
-LTCOMMAND = xfs_bmap
-CFILES = xfs_bmap.c
+LTCOMMAND = xfs_io
+HFILES = command.h input.h init.h
+CFILES = command.c input.c init.c \
+       bmap.c fsync.c help.c open.c pread.c prealloc.c pwrite.c \
+       quit.c resblks.c truncate.c
+LSRCFILES = xfs_bmap.sh
+
+ifeq ($(ENABLE_READLINE),yes)
+LLDLIBS += $(LIBREADLINE)
+CFLAGS += -DENABLE_READLINE
+endif
 
 default: $(LTCOMMAND)
 
@@ -43,4 +52,5 @@ include $(BUILDRULES)
 install: default
        $(INSTALL) -m 755 -d $(PKG_BIN_DIR)
        $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR)
+       $(LTINSTALL) -m 755 xfs_bmap.sh $(PKG_BIN_DIR)/xfs_bmap
 install-dev:
similarity index 73%
rename from bmap/xfs_bmap.c
rename to io/bmap.c
index a24dfb8f2c2fdce0572515f23ab9ff222a73b035..09d11a7c76424771b5050591038395750106b726 100644 (file)
+++ b/io/bmap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
  * 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-/* 
- * Bmap display utility for xfs.
- */
-
 #include <libxfs.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
+#include "command.h"
+#include "init.h"
 
-int aflag = 0; /* Attribute fork. */
-int lflag = 0; /* list number of blocks with each extent */
-int nflag = 0; /* number of extents specified */
-int vflag = 0; /* Verbose output */
-int bmv_iflags = 0;    /* Input flags for XFS_IOC_GETBMAPX */
-char *progname;
+static cmdinfo_t bmap_cmd;
 
-int dofile(char *);
-off64_t file_size(int fd, char * fname);
-int numlen(off64_t);
+static int
+usage(void)
+{
+       printf("%s %s\n", bmap_cmd.name, bmap_cmd.oneline);
+       return 0;
+}
 
-int
-main(int argc, char **argv)
+static void
+bmap_help(void)
 {
-       char    *fname;
-       int     i = 0;
-       int     option;
+       printf(_(
+"\n"
+" prints the block mapping for an XFS file's data or attribute forks"
+"\n"
+" Example:\n"
+" 'bmap -vp' - tabular format verbose map, including unwritten extents\n"
+"\n"
+" bmap prints the map of disk blocks used by the current file.\n"
+" The map lists each extent used by the file, as well as regions in the\n"
+" file that do not have any corresponding blocks (holes).\n"
+" By default, each line of the listing takes the following form:\n"
+"     extent: [startoffset..endoffset]: startblock..endblock\n"
+" Holes are marked by replacing the startblock..endblock with 'hole'.\n"
+" All the file offsets and disk blocks are in units of 512-byte blocks.\n"
+" -a -- prints the attribute fork map instead of the data fork.\n"
+" -d -- suppresses a DMAPI read event, offline portions shown as holes.\n"
+" -l -- also displays the length of each extent in 512-byte blocks.\n"
+" Note: the bmap for non-regular files can be obtained provided the file\n"
+" was opened appropriately (in particular, must be opened read-only).\n"
+"\n"));
+}
 
-       progname = basename(argv[0]);
-       setlocale(LC_ALL, "");
-       bindtextdomain(PACKAGE, LOCALEDIR);
-       textdomain(PACKAGE);
+static int
+numlen(
+       off64_t val)
+{
+       off64_t tmp;
+       int     len;
 
-       while ((option = getopt(argc, argv, "adln:pvV")) != EOF) {
-               switch (option) {
-               case 'a':
+       for (len = 0, tmp = val; tmp > 0; tmp = tmp/10)
+               len++;
+       return (len == 0 ? 1 : len);
+}
+
+int
+bmap_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct fsxattr          fsx;
+       struct getbmapx         *map;
+       struct xfs_fsop_geom_v1 fsgeo;
+       int                     map_size;
+       int                     loop = 0;
+       int                     flg = 0;
+       int                     aflag = 0;
+       int                     lflag = 0;
+       int                     nflag = 0;
+       int                     vflag = 0;
+       int                     bmv_iflags = 0; /* flags for XFS_IOC_GETBMAPX */
+       int                     i = 0;
+       int                     c;
+
+       while ((c = getopt(argc, argv, "adln:pv")) != EOF) {
+               switch (c) {
+               case 'a':       /* Attribute fork. */
                        bmv_iflags |= BMV_IF_ATTRFORK;
                        aflag = 1;
                        break;
-               case 'l':
+               case 'l':       /* list number of blocks with each extent */
                        lflag = 1;
                        break;
-               case 'n':
+               case 'n':       /* number of extents specified */
                        nflag = atoi(optarg);
                        break;
                case 'd':
@@ -81,105 +119,32 @@ main(int argc, char **argv)
                /* report unwritten preallocated blocks */
                        bmv_iflags |= BMV_IF_PREALLOC;
                        break;
-               case 'v':
+               case 'v':       /* Verbose output */
                        vflag++;
                        break;
-               case 'V':
-                       printf(_("%s version %s\n"), progname, VERSION);
-                       exit(0);
                default:
-                       fprintf(stderr,
-                               _("Usage: %s [-adlpV] [-n nx] file...\n"),
-                               progname);
-                       exit(1);
+                       return usage();
                }
        }
        if (aflag) 
-               bmv_iflags &=  ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ);
-       while (optind < argc) {
-               fname = argv[optind];
-               i += dofile(fname);
-               optind++;
-       }
-       return(i ? 1 : 0);
-}
-
-off64_t
-file_size(int  fd, char *fname)
-{
-       struct stat64   st;
-       int             i;
-       int             errno_save;
-
-       errno_save = errno;     /* in case fstat64 fails */
-       i = fstat64(fd, &st);
-       if (i < 0) {
-               fprintf(stderr, _("%s: fstat64 failed for %s: %s\n"),
-                       progname, fname, strerror(errno));
-               errno = errno_save;
-               return -1;
-       }
-       return st.st_size;
-}
-       
-
-int
-dofile(char *fname)
-{
-       int             i;
-       int             fd;
-       struct statfs   buf;
-       struct fsxattr  fsx;
-       struct getbmapx *map;
-       int             map_size;
-       int             loop = 0;
-       xfs_fsop_geom_v1_t fsgeo;
-       int             flg = 0;
-
-       fd = open(fname, O_RDONLY);
-       if (fd < 0) {
-               fprintf(stderr, _("%s: cannot open \"%s\": %s\n"),
-                       progname, fname, strerror(errno));
-               return 1;
-       }
-       fstatfs(fd, &buf);
-       if (statfstype(&buf) != XFS_SUPER_MAGIC) {
-               fprintf(stderr, _("%s: specified file "
-                       "[\"%s\"] is not on an XFS filesystem\n"),
-                       progname, fname);
-               close(fd);
-               return 1;
-        }
+               bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ);
 
        if (vflag) {
-               if (ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo) < 0) {
+               if (ioctl(fdesc, XFS_IOC_FSGEOMETRY_V1, &fsgeo) < 0) {
                        fprintf(stderr,
                                _("%s: can't get geometry [\"%s\"]: %s\n"),
                                progname, fname, strerror(errno));
-                       close(fd);
-                       return 1;
+                       exitcode = 1;
+                       return 0;
                }
-               
-               if (vflag > 1)
-                       printf(_(
-       "xfs_bmap: fsgeo.agblocks=%u, fsgeo.blocksize=%u, fsgeo.agcount=%u\n"),
-                                       fsgeo.agblocks, fsgeo.blocksize,
-                                       fsgeo.agcount);
-
-               if ((ioctl(fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
+               if ((ioctl(fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
                        fprintf(stderr,
                                _("%s: cannot read attrs on \"%s\": %s\n"),
                                progname, fname, strerror(errno));
-                       close(fd);
-                       return 1;
+                       exitcode = 1;
+                       return 0;
                }
 
-               if (vflag > 1)
-                       printf(_(
-    "xfs_bmap: fsx.dsx_xflags=%u, fsx.fsx_extsize=%u, fsx.fsx_nextents=%u\n"),
-                                       fsx.fsx_xflags, fsx.fsx_extsize,
-                                       fsx.fsx_nextents);
-
                if (fsx.fsx_xflags == XFS_XFLAG_REALTIME) {
                        /* 
                         * ag info not applicable to rt, continue
@@ -189,13 +154,13 @@ dofile(char *fname)
                }
        }
 
-       map_size = nflag ? nflag+1 : 32;        /* initial guess - 256 for checkin KCM */
+       map_size = nflag ? nflag+1 : 32;        /* initial guess - 256 */
        map = malloc(map_size*sizeof(*map));
        if (map == NULL) {
                fprintf(stderr, _("%s: malloc of %d bytes failed.\n"),
                        progname, (int)(map_size * sizeof(*map)));
-               close(fd);
-               return 1;
+               exitcode = 1;
+               return 0;
        }
                
 
@@ -234,28 +199,19 @@ dofile(char *fname)
                map->bmv_count = map_size;
                map->bmv_iflags = bmv_iflags;
 
-               i = ioctl(fd, XFS_IOC_GETBMAPX, map);
-
-               if (vflag > 1)
-                       printf(_(
-               "xfs_bmap: i=%d map.bmv_offset=%lld, map.bmv_block=%lld, "
-               "map.bmv_length=%lld, map.bmv_count=%d, map.bmv_entries=%d\n"),
-                                       i, (long long)map->bmv_offset,
-                                       (long long)map->bmv_block,
-                                       (long long)map->bmv_length,
-                                       map->bmv_count, map->bmv_entries);
+               i = ioctl(fdesc, XFS_IOC_GETBMAPX, map);
                if (i < 0) {
                        if (   errno == EINVAL
-                           && !aflag && file_size(fd, fname) == 0) {
+                           && !aflag && filesize() == 0) {
                                break;
                        } else  {
                                fprintf(stderr, _("%s: ioctl(XFS_IOC_GETBMAPX) "
                                        "iflags=0x%x [\"%s\"]: %s\n"),
                                        progname, map->bmv_iflags, fname,
                                        strerror(errno));
-                               close(fd);
                                free(map);
-                               return 1;
+                               exitcode = 1;
+                               return 0;
                        }
                }
                if (nflag)
@@ -265,14 +221,15 @@ dofile(char *fname)
                /* Get number of extents from ioctl XFS_IOC_FSGETXATTR[A]
                 * syscall.
                 */
-               i = ioctl(fd, aflag ? XFS_IOC_FSGETXATTRA : XFS_IOC_FSGETXATTR, &fsx);
+               i = ioctl(fdesc, aflag ?
+                               XFS_IOC_FSGETXATTRA : XFS_IOC_FSGETXATTR, &fsx);
                if (i < 0) {
                        fprintf(stderr, _("%s: ioctl(XFS_IOC_FSGETXATTR%s) "
                                "[\"%s\"]: %s\n"), progname, aflag ? "A" : "",
                                fname, strerror(errno));
-                       close(fd);
                        free(map);
-                       return 1;
+                       exitcode = 1;
+                       return 0;
                }
                if (fsx.fsx_nextents >= map_size-1) {
                        map_size = 2*(fsx.fsx_nextents+1);
@@ -281,20 +238,18 @@ dofile(char *fname)
                                fprintf(stderr,
                                        _("%s: cannot realloc %d bytes\n"),
                                        progname, (int)(map_size*sizeof(*map)));
-                               close(fd);
-                               return 1;
+                               exitcode = 1;
+                               return 0;
                        }
                }
        } while (++loop < 2);
        if (!nflag) {
                if (map->bmv_entries <= 0) {
                        printf(_("%s: no extents\n"), fname);
-                       close(fd);
                        free(map);
                        return 0;
                }
        }
-       close(fd);
        printf("%s:\n", fname);
        if (!vflag) {
                for (i = 0; i < map->bmv_entries; i++) {
@@ -341,7 +296,7 @@ dofile(char *fname)
                foff_w = boff_w = aoff_w = MINRANGE_WIDTH;
                tot_w = MINTOT_WIDTH;
                bbperag = (off64_t)fsgeo.agblocks * 
-                         (off64_t)fsgeo.blocksize / BBSIZE;
+                         (off64_t)fsgeo.blocksize / BBSIZE;
                sunit = fsgeo.sunit;
                swidth = fsgeo.swidth;
 
@@ -423,7 +378,7 @@ dofile(char *fname)
                                snprintf(abuf, sizeof(abuf), "(%lld..%lld)", 
                                        (long long)agoff,  (long long)
                                        (agoff + map[i + 1].bmv_length - 1LL));
-                               printf("%4d: %-*s %-*s %*d %-*s %*lld\n", 
+                               printf("%4d: %-*s %-*s %*d %-*s %*lld",
                                        i, 
                                        foff_w, rbuf, 
                                        boff_w, bbuf, 
@@ -453,12 +408,16 @@ dofile(char *fname)
        return 0;
 }
 
-int
-numlen(off64_t val)
+void
+bmap_init(void)
 {
-       off64_t tmp;
-       int len;
+       bmap_cmd.name = _("bmap");
+       bmap_cmd.cfunc = bmap_f;
+       bmap_cmd.argmin = 0;
+       bmap_cmd.argmax = -1;
+       bmap_cmd.args = _("[-adlpv] [-n nx]");
+       bmap_cmd.oneline = _("print block mapping for an XFS file");
+       bmap_cmd.help = bmap_help;
 
-       for (len=0, tmp=val; tmp > 0; tmp=tmp/10) len++;
-       return(len == 0 ? 1 : len);
+       add_command(&bmap_cmd);
 }
diff --git a/io/command.c b/io/command.c
new file mode 100644 (file)
index 0000000..af7ea0e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <libxfs.h>
+#include "command.h"
+
+cmdinfo_t      *cmdtab;
+int            ncmds;
+
+static int
+cmd_compare(const void *a, const void *b)
+{
+       return strcmp(((const cmdinfo_t *)a)->name,
+                     ((const cmdinfo_t *)b)->name);
+}
+
+void
+add_command(
+       const cmdinfo_t *ci)
+{
+       cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
+       cmdtab[ncmds - 1] = *ci;
+       qsort(cmdtab, ncmds, sizeof(*cmdtab), cmd_compare);
+}
+
+int
+command(
+       int             argc,
+       char            **argv)
+{
+       char            *cmd;
+       const cmdinfo_t *ct;
+
+       cmd = argv[0];
+       ct = find_command(cmd);
+       if (!ct) {
+               fprintf(stderr, _("command \"%s\" not found\n"), cmd);
+               return 0;
+       }
+       if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
+               if (ct->argmax == -1)
+                       fprintf(stderr,
+       _("bad argument count %d to %s, expected at least %d arguments\n"),
+                               argc-1, cmd, ct->argmin);
+               else if (ct->argmin == ct->argmax)
+                       fprintf(stderr,
+       _("bad argument count %d to %s, expected %d arguments\n"),
+                               argc-1, cmd, ct->argmin);
+               else
+                       fprintf(stderr,
+       _("bad argument count %d to %s, expected between %d and %d arguments\n"),
+                       argc-1, cmd, ct->argmin, ct->argmax);
+               return 0;
+       }
+       optind = 0;
+       return ct->cfunc(argc, argv);
+}
+
+const cmdinfo_t *
+find_command(
+       const char      *cmd)
+{
+       cmdinfo_t       *ct;
+
+       for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++) {
+               if (strcmp(ct->name, cmd) == 0 ||
+                   (ct->altname && strcmp(ct->altname, cmd) == 0))
+                       return (const cmdinfo_t *)ct;
+       }
+       return NULL;
+}
+
+void
+init_commands(void)
+{
+       bmap_init();
+       help_init();
+       open_init();
+       pread_init();
+       prealloc_init();
+       pwrite_init();
+       quit_init();
+       resblks_init();
+       fsync_init();
+       truncate_init();
+}
diff --git a/io/command.h b/io/command.h
new file mode 100644 (file)
index 0000000..4890a8a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#define min(a,b)       (((a)<(b))?(a):(b))
+
+typedef int (*cfunc_t)(int argc, char **argv);
+typedef void (*helpfunc_t)(void);
+
+typedef struct cmdinfo {
+       const char      *name;
+       const char      *altname;
+       cfunc_t         cfunc;
+       int             argmin;
+       int             argmax;
+       int             canpush;
+       const char      *args;
+       const char      *oneline;
+       helpfunc_t      help;
+} cmdinfo_t;
+
+extern cmdinfo_t       *cmdtab;
+extern int             ncmds;
+
+extern void            add_command(const cmdinfo_t *ci);
+extern int             command(int argc, char **argv);
+extern const cmdinfo_t *find_command(const char *cmd);
+extern void            init_commands(void);
+
+extern void            bmap_init(void);
+extern void            help_init(void);
+extern void            open_init(void);
+extern void            pread_init(void);
+extern void            prealloc_init(void);
+extern void            pwrite_init(void);
+extern void            quit_init(void);
+extern void            resblks_init(void);
+extern void            fsync_init(void);
+extern void            truncate_init(void);
+
+extern off64_t         filesize(void);
+extern int             openfile(char *, int, int, int, int, int, int, int);
+
+extern void            *buffer;
+extern ssize_t         buffersize;
+extern int             alloc_buffer(ssize_t, unsigned int);
+extern int             read_buffer(int, off64_t, ssize_t, ssize_t *, int, int);
diff --git a/io/help.c b/io/help.c
new file mode 100644 (file)
index 0000000..eca80ef
--- /dev/null
+++ b/io/help.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include "command.h"
+
+static cmdinfo_t help_cmd;
+static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
+static void help_oneline(const char *cmd, const cmdinfo_t *ct);
+
+static void
+help_all(void)
+{
+       const cmdinfo_t *ct;
+
+       for (ct = cmdtab; ct < &cmdtab[ncmds]; ct++)
+               help_oneline(ct->name, ct);
+       printf(_("\nUse 'help commandname' for extended help.\n"));
+}
+
+static int
+help_f(
+       int             argc,
+       char            **argv)
+{
+       const cmdinfo_t *ct;
+
+       if (argc == 1) {
+               help_all();
+               return 0;
+       }
+       ct = find_command(argv[1]);
+       if (ct == NULL) {
+               printf(_("command %s not found\n"), argv[1]);
+               return 0;
+       }
+       help_onecmd(argv[1], ct);
+       return 0;
+}
+
+static void
+help_onecmd(
+       const char      *cmd,
+       const cmdinfo_t *ct)
+{
+       help_oneline(cmd, ct);
+       if (ct->help)
+               ct->help();
+}
+
+static void
+help_oneline(
+       const char      *cmd,
+       const cmdinfo_t *ct)
+{
+       if (cmd)
+               printf("%s ", cmd);
+       else {
+               printf("%s ", ct->name);
+               if (ct->altname)
+                       printf("(or %s) ", ct->altname);
+       }
+       if (ct->args)
+               printf("%s ", ct->args);
+       printf("-- %s\n", ct->oneline);
+}
+
+void
+help_init(void)
+{
+       help_cmd.name = _("help");
+       help_cmd.altname = _("?");
+       help_cmd.cfunc = help_f;
+       help_cmd.argmin = 0;
+       help_cmd.argmax = 1;
+       help_cmd.args = _("[command]");
+       help_cmd.oneline = _("help for one or all commands");
+
+       add_command(&help_cmd);
+}
diff --git a/io/init.c b/io/init.c
new file mode 100644 (file)
index 0000000..8d4731c
--- /dev/null
+++ b/io/init.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <libxfs.h>
+#include "input.h"
+#include "command.h"
+
+int    fdesc;
+char   *fname;
+char   *progname;
+int    exitcode;
+
+int    readonly;
+int    directio;
+int    realtime;
+int    append;
+int    osync;
+int    trunc;
+
+static int     ncmdline;
+static char    **cmdline;
+
+void
+usage(void)
+{
+       fprintf(stderr,
+               _("Usage: %s [-r] [-p prog] [-c cmd]... file\n"), progname);
+       exit(1);
+}
+
+void
+init(
+       int             argc,
+       char            **argv)
+{
+       int             c;
+
+       progname = basename(argv[0]);
+       setlocale(LC_ALL, "");
+       bindtextdomain(PACKAGE, LOCALEDIR);
+       textdomain(PACKAGE);
+
+       while ((c = getopt(argc, argv, "ac:dfp:rstVx")) != EOF) {
+               switch (c) {
+               case 'a':       /* append */
+                       append = 1;
+                       break;
+               case 'c':       /* commands */
+                       ncmdline++;
+                       cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
+                       if (!cmdline) {
+                               perror("realloc");
+                               exit(1);
+                       }
+                       cmdline[ncmdline-1] = optarg;
+                       break;
+               case 'd':       /* directIO */
+                       directio = 1;
+                       break;
+               case 'f':       /* ignore */
+                       break;
+               case 'p':       /* progname */
+                       progname = optarg;
+                       break;
+               case 'r':       /* readonly */
+                       readonly = 1;
+                       break;
+               case 's':       /* sync */
+                       osync = 1;
+                       break;
+               case 't':       /* truncate */
+                       trunc = 1;
+                       break;
+               case 'x':       /* realtime */
+                       realtime = 1;
+                       break;
+               case 'V':
+                       printf(_("%s version %s\n"), progname, VERSION);
+                       exit(0);
+               default:
+                       usage();
+               }
+       }
+
+       if (optind != argc - 1)
+               usage();
+
+       fname = strdup(argv[optind]);
+       if ((fdesc = openfile(fname, append, 0, directio,
+                               readonly, osync, trunc, realtime)) < 0)
+               exit(1);
+
+       init_commands();
+}
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       int     c, i, done = 0;
+       char    *input;
+       char    **v;
+
+       init(argc, argv);
+
+       for (i = 0; !done && i < ncmdline; i++) {
+               v = breakline(cmdline[i], &c);
+               if (c)
+                       done = command(c, v);
+               free(v);
+       }
+       if (cmdline) {
+               free(cmdline);
+               return exitcode;
+       }
+       while (!done) {
+               if ((input = fetchline()) == NULL)
+                       break;
+               v = breakline(input, &c);
+               if (c)
+                       done = command(c, v);
+               doneline(input, v);
+       }
+       return exitcode;
+}
diff --git a/io/init.h b/io/init.h
new file mode 100644 (file)
index 0000000..a49a15e
--- /dev/null
+++ b/io/init.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+extern int     fdesc;
+extern char    *fname;
+extern int     exitcode;
+extern char    *progname;
+
+extern int     readonly;
+extern int     directio;
+extern int     realtime;
+extern int     append;
+extern int     osync;
+extern int     trunc;
diff --git a/io/input.c b/io/input.c
new file mode 100644 (file)
index 0000000..c91e824
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <libxfs.h>
+#include "input.h"
+#include "init.h"
+
+#ifdef ENABLE_READLINE
+# include <readline/history.h>
+# include <readline/readline.h>
+#else
+# define MAXREADLINESZ 1024
+static char *
+readline(char *prompt)
+{
+       char    *p, *line = malloc(MAXREADLINESZ);
+
+       if (!line)
+               return NULL;
+       printf(prompt);
+       fflush(stdout);
+       if (!fgets(line, MAXREADLINESZ, stdin)) {
+               free(line);
+               return NULL;
+       }
+       p = line + strlen(line);
+       if (p != line && p[-1] == '\n')
+               p[-1] = '\0';
+       return line;
+}
+static void add_history(char *line) { }
+# undef MAXREADLINESZ
+#endif
+
+char *
+fetchline(void)
+{
+       static char     prompt[FILENAME_MAX + 1];
+       char            *line;
+
+       if (!prompt[0])
+               snprintf(prompt, sizeof(prompt), "%s> ", progname);
+       line = readline(prompt);
+       if (line && *line)
+               add_history(line);
+       return line;
+}
+
+char **
+breakline(
+       char    *input,
+       int     *count)
+{
+       int     c = 0;
+       char    *p;
+       char    **rval = calloc(sizeof(char *), 1);
+
+       while ((p = strsep(&input, " ")) != NULL) {
+               if (!*p)
+                       continue;
+               c++;
+               rval = realloc(rval, sizeof(*rval) * (c + 1));
+               rval[c - 1] = p;
+               rval[c] = NULL;
+       }
+       *count = c;
+       return rval;
+}
+
+void
+doneline(
+       char    *input,
+       char    **vec)
+{
+       free(input);
+       free(vec);
+}
diff --git a/io/input.h b/io/input.h
new file mode 100644 (file)
index 0000000..b497146
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+extern char    **breakline(char *input, int *count);
+extern void    doneline(char *input, char **vec);
+extern char    *fetchline(void);
diff --git a/io/open.c b/io/open.c
new file mode 100644 (file)
index 0000000..c479a3b
--- /dev/null
+++ b/io/open.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <libxfs.h>
+#include "command.h"
+#include "init.h"
+
+static cmdinfo_t open_cmd;
+static cmdinfo_t stat_cmd;
+static cmdinfo_t statfs_cmd;
+static int stat_f(int, char **);
+
+int
+openfile(
+       char            *filename,
+       int             aflag,
+       int             cflag,
+       int             dflag,
+       int             rflag,
+       int             sflag,
+       int             tflag,
+       int             xflag)
+{
+       int             fd;
+       int             oflags;
+       struct statfs   buf;
+
+       oflags = (rflag ? O_RDONLY : O_RDWR);
+       if (aflag)
+               oflags |= O_APPEND;
+       if (cflag)
+               oflags |= O_CREAT;
+       if (dflag)
+               oflags |= O_DIRECT;
+       if (sflag)
+               oflags |= O_SYNC;
+       if (tflag)
+               oflags |= O_TRUNC;
+
+       fd = open(filename, oflags, 0666);
+       if (fd < 0) {
+               perror(filename);
+               return -1;
+       }
+       fstatfs(fd, &buf);
+       if (statfstype(&buf) != XFS_SUPER_MAGIC) {
+               fprintf(stderr, _("%s: specified file "
+                       "[\"%s\"] is not on an XFS filesystem\n"),
+                       progname, fname);
+               close(fd);
+               return -1;
+       }
+
+       if (!readonly && xflag) {       /* read/write and realtime */
+               struct fsxattr  attr;
+
+               if (ioctl(fd, XFS_IOC_FSGETXATTR, &attr) < 0) {
+                       perror("XFS_IOC_FSGETXATTR");
+                       close(fd);
+                       return -1;
+               }
+               if (!(attr.fsx_xflags & XFS_XFLAG_REALTIME)) {
+                       attr.fsx_xflags |= XFS_XFLAG_REALTIME;
+                       if (ioctl(fd, XFS_IOC_FSSETXATTR, &attr) < 0) {
+                               perror("XFS_IOC_FSSETXATTR");
+                               close(fd);
+                               return -1;
+                       }
+               }
+       }
+       return fd;
+}
+
+static int
+usage(void)
+{
+       printf("%s %s\n", open_cmd.name, open_cmd.oneline);
+       return 0;
+}
+
+static void
+open_help(void)
+{
+       printf(_(
+"\n"
+" opens a new file in the requested mode, after closing the current file\n"
+"\n"
+" Example:\n"
+" 'open -d /tmp/data' - 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"
+" -c -- open with O_CREAT (create the file if it doesn't exist)\n"
+" -d -- open with O_DIRECT (non-buffered IO, note alignment constraints)\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"
+" -x -- mark the file as a realtime XFS file immediately after opening it\n"
+" Note1: read/write direct IO requests must be blocksize aligned.\n"
+" Note2: the bmap for non-regular files can be obtained provided the file\n"
+" was opened appropriately (in particular, must be opened read-only).\n"
+"\n"));
+}
+
+static int
+open_f(
+       int             argc,
+       char            **argv)
+{
+       int             aflag = 0;
+       int             cflag = 0;
+       int             dflag = 0;
+       int             rflag = 0;
+       int             sflag = 0;
+       int             tflag = 0;
+       int             xflag = 0;
+       char            *filename;
+       int             fd;
+       int             c;
+
+       if (argc == 1)
+               return stat_f(argc, argv);
+
+       while ((c = getopt(argc, argv, "acdrstx")) != EOF) {
+               switch (c) {
+               case 'a':
+                       aflag = 1;
+                       break;
+               case 'c':
+                       cflag = 1;
+                       break;
+               case 'd':
+                       dflag = 1;
+                       break;
+               case 'r':
+                       rflag = 1;
+                       break;
+               case 's':
+                       sflag = 1;
+                       break;
+               case 't':
+                       tflag = 1;
+                       break;
+               case 'x':
+                       xflag = 1;
+                       break;
+               default:
+                       return usage();
+               }
+       }
+
+       if (optind != argc - 1)
+               return usage();
+
+       fd = openfile(argv[optind],
+                     aflag, cflag, dflag, rflag, sflag, tflag, xflag);
+       if (fd < 0)
+               return 0;
+
+       filename = strdup(argv[optind]);
+       if (!filename) {
+               perror("strdup");
+               close(fd);
+               return 0;
+       }
+
+       /*
+        * All OK, proceed to make this the new global open file
+        */
+       osync = sflag;
+       trunc = tflag;
+       append = aflag;
+       directio = dflag;
+       readonly = rflag;
+       realtime = xflag;
+       if (fname) {
+               close(fdesc);
+               free(fname);
+       }
+       fname = filename;
+       fdesc = fd;
+       return 0;
+}
+
+off64_t
+filesize(void)
+{
+       struct stat64   st;
+
+       if (fstat64(fdesc, &st) < 0) {
+               perror("fstat64");
+               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 fsxattr  fsx;
+       struct stat64   st;
+       char            fullname[PATH_MAX + 1];
+
+       printf(_("fd.path = \"%s\"\n"),
+               realpath(fname, fullname) ? fullname : fname);
+       printf(_("fd.flags = %s,%s,%s%s%s\n"),
+               osync ? _("sync") : _("non-sync"),
+               directio ? _("direct") : _("non-direct"),
+               readonly ? _("read-only") : _("read-write"),
+               realtime ? _(",real-time") : "",
+               append ? _(",append-only") : "");
+       if (fstat64(fdesc, &st) < 0) {
+               perror("fstat64");
+       } 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 (argc == 2 && !strcmp(argv[1], "-v")) {
+                       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 ((ioctl(fdesc, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
+               perror("XFS_IOC_FSGETXATTR");
+       } else {
+               printf(_("xattr.xflags = 0x%x\n"), fsx.fsx_xflags);
+               printf(_("xattr.nextents = %u\n"), fsx.fsx_nextents);
+       }
+       return 0;
+}
+
+static int
+statfs_f(
+       int                     argc,
+       char                    **argv)
+{
+       struct xfs_fsop_geom_v1 fsgeo;
+       struct statfs           st;
+       char                    fullname[PATH_MAX + 1];
+
+       printf(_("fd.path = \"%s\"\n"),
+               realpath(fname, fullname) ? fullname : fname);
+       if (fstatfs(fdesc, &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);
+       }
+       if ((ioctl(fdesc, 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);
+       }
+       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.args = _("[-acdrstx] [path]");
+       open_cmd.oneline =
+               _("close the current file, open 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.args = _("[-v]");
+       stat_cmd.oneline =
+               _("statistics on the currently open file");
+
+       statfs_cmd.name = _("statfs");
+       statfs_cmd.cfunc = statfs_f;
+       statfs_cmd.oneline =
+               _("statistics on the filesystem of the currently open file");
+
+       add_command(&open_cmd);
+       add_command(&stat_cmd);
+       add_command(&statfs_cmd);
+}
diff --git a/io/pread.c b/io/pread.c
new file mode 100644 (file)
index 0000000..1e69bea
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include <ctype.h>
+#include "command.h"
+#include "input.h"
+#include "init.h"
+
+static cmdinfo_t pread_cmd;
+
+static void
+pread_help(void)
+{
+       printf(_(
+"\n"
+" reads a range of bytes in a specified block size from the given offset\n"
+"\n"
+" Example:\n"
+" 'read -v 512 20' - dumps 20 bytes read from 512 bytes into the file\n"
+"\n"
+" Reads a segment of the currently open file, optionally dumping it to the\n"
+" standard output stream (with -v option) for subsequent inspection.\n"
+" The reads are performed in sequential blocks starting at offset, with the\n"
+" blocksize tunable using the -b option (default blocksize is 4096 bytes).\n"
+"\n"));
+}
+
+void   *buffer;
+ssize_t        buffersize;
+
+int
+alloc_buffer(
+       ssize_t         bsize,
+       unsigned int    seed)
+{
+       if (bsize > buffersize) {
+               buffer = realloc(buffer, buffersize = bsize);
+               if (!buffer) {
+                       perror("realloc");
+                       buffersize = 0;
+                       return 0;
+               }
+       }
+       memset(buffer, seed, buffersize);
+       return 1;
+}
+
+static void
+dump_buffer(
+       off64_t         offset,
+       ssize_t         len)
+{
+       int             i, j;
+       char            *p;
+
+       for (i = 0, p = (char *)buffer; i < len; i += 16) {
+               char    *s = p;
+
+               printf("%08llx:  ", (off64_t)i + offset);
+               for (j = 0; j < 16 && i + j < len; j++, p++)
+                       printf("%02x ", *p);
+               printf(" ");
+               for (j = 0; j < 16 && i + j < len; j++, s++) {
+                       if (isalnum(*s))
+                               printf("%c", *s);
+                       else
+                               printf(".");
+               }
+               printf("\n");
+       }
+}
+
+int
+read_buffer(
+       int             fd,
+       off64_t         offset,
+       ssize_t         count,
+       ssize_t         *total,
+       int             verbose,
+       int             onlyone)
+{
+       ssize_t         bytes;
+
+       *total = 0;
+       while (count > 0) {
+               bytes = pread64(fd, buffer, min(count,buffersize), offset);
+               if (bytes == 0)
+                       break;
+               if (bytes < 0) {
+                       perror("pread64");
+                       return 0;
+               }
+               if (verbose)
+                       dump_buffer(offset, bytes);
+               *total += bytes;
+               if (onlyone || bytes < count)
+                       break;
+               offset += bytes;
+               count -= bytes;
+       }
+       return 1;
+}
+
+static int
+pread_f(
+       int             argc,
+       char            **argv)
+{
+       off64_t         offset;
+       ssize_t         count, total;
+       unsigned int    bsize = 4096;
+       char            *sp;
+       int             vflag = 0;
+       int             c;
+
+       while ((c = getopt(argc, argv, "b:v")) != EOF) {
+               switch (c) {
+               case 'b':
+                       bsize = strtoul(optarg, &sp, 0);
+                       if (!sp || sp == optarg) {
+                               printf(_("non-numeric bsize -- %s\n"), optarg);
+                               return 0;
+                       }
+                       break;
+               case 'v':
+                       vflag = 1;
+                       break;
+               default:
+                       printf("%s %s\n", pread_cmd.name, pread_cmd.oneline);
+                       return 0;
+               }
+       }
+       if (optind != argc - 2) {
+               printf("%s %s\n", pread_cmd.name, pread_cmd.oneline);
+               return 0;
+       }
+       offset = strtoul(argv[optind], &sp, 0);
+       if (!sp || sp == argv[optind]) {
+               printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
+               return 0;
+       }
+       optind++;
+       count = strtoul(argv[optind], &sp, 0);
+       if (!sp || sp == argv[optind]) {
+               printf(_("non-numeric length argument -- %s\n"), argv[optind]);
+               return 0;
+       }
+
+       if (!alloc_buffer(bsize, 0xabababab))
+               return 0;
+
+       if (!read_buffer(fdesc, offset, count, &total, vflag, 0))
+               return 0;
+
+       printf(_("read %u/%u bytes at offset %llu\n"), total, count, offset);
+       return 0;
+}
+
+void
+pread_init(void)
+{
+       pread_cmd.name = _("pread");
+       pread_cmd.altname = _("r");
+       pread_cmd.cfunc = pread_f;
+       pread_cmd.argmin = 2;
+       pread_cmd.argmax = -1;
+       pread_cmd.args = _("[-b bs] [-v] off len");
+       pread_cmd.oneline = _("reads a number of bytes at a specified offset");
+       pread_cmd.help = pread_help;
+
+       add_command(&pread_cmd);
+}
diff --git a/io/prealloc.c b/io/prealloc.c
new file mode 100644 (file)
index 0000000..128bcd5
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include "command.h"
+#include "init.h"
+
+static cmdinfo_t allocsp_cmd;
+static cmdinfo_t freesp_cmd;
+static cmdinfo_t resvsp_cmd;
+static cmdinfo_t unresvsp_cmd;
+
+static int
+offset_length(
+       char            *offset,
+       char            *length,
+       xfs_flock64_t   *segment)
+{
+       char            *sp;
+
+       memset(segment, 0, sizeof(*segment));
+       segment->l_whence = SEEK_SET;
+       segment->l_start = strtoul(offset, &sp, 0);
+       if (!sp || sp == offset) {
+               printf(_("non-numeric offset argument -- %s\n"), offset);
+               return 0;
+       }
+       segment->l_len = strtoul(length, &sp, 0);
+       if (!sp || sp == length) {
+               printf(_("non-numeric length argument -- %s\n"), length);
+               return 0;
+       }
+       return 1;
+}
+
+static int
+allocsp_f(
+       int             argc,
+       char            **argv)
+{
+       xfs_flock64_t   segment;
+
+       if (!offset_length(argv[1], argv[2], &segment))
+               return 0;
+
+       if (ioctl(fdesc, XFS_IOC_ALLOCSP64, &segment) < 0) {
+               perror("XFS_IOC_ALLOCSP64");
+               return 0;
+       }
+       return 0;
+}
+
+static int
+freesp_f(
+       int             argc,
+       char            **argv)
+{
+       xfs_flock64_t   segment;
+
+       if (!offset_length(argv[1], argv[2], &segment))
+               return 0;
+
+       if (ioctl(fdesc, XFS_IOC_FREESP64, &segment) < 0) {
+               perror("XFS_IOC_FREESP64");
+               return 0;
+       }
+       return 0;
+}
+
+static int
+resvsp_f(
+       int             argc,
+       char            **argv)
+{
+       xfs_flock64_t   segment;
+
+       if (!offset_length(argv[1], argv[2], &segment))
+               return 0;
+
+       if (ioctl(fdesc, XFS_IOC_RESVSP64, &segment) < 0) {
+               perror("XFS_IOC_RESVSP64");
+               return 0;
+       }
+       return 0;
+}
+
+static int
+unresvsp_f(
+       int             argc,
+       char            **argv)
+{
+       xfs_flock64_t   segment;
+
+       if (!offset_length(argv[1], argv[2], &segment))
+               return 0;
+
+       if (ioctl(fdesc, XFS_IOC_UNRESVSP64, &segment) < 0) {
+               perror("XFS_IOC_UNRESVSP64");
+               return 0;
+       }
+       return 0;
+}
+
+void
+prealloc_init(void)
+{
+       allocsp_cmd.name = _("allocsp");
+       allocsp_cmd.cfunc = allocsp_f;
+       allocsp_cmd.argmin = 2;
+       allocsp_cmd.argmax = 2;
+       allocsp_cmd.args = _("off len");
+       allocsp_cmd.oneline = _("allocates zeroed space for part of a file");
+
+       freesp_cmd.name = _("freesp");
+       freesp_cmd.cfunc = freesp_f;
+       freesp_cmd.argmin = 2;
+       freesp_cmd.argmax = 2;
+       freesp_cmd.args = _("off len");
+       freesp_cmd.oneline = _("frees space associated with part of a file");
+
+       resvsp_cmd.name = _("resvsp");
+       resvsp_cmd.cfunc = resvsp_f;
+       resvsp_cmd.argmin = 2;
+       resvsp_cmd.argmax = 2;
+       resvsp_cmd.args = _("off len");
+       resvsp_cmd.oneline =
+               _("reserves space associated with part of a file");
+
+       unresvsp_cmd.name = _("unresvsp");
+       unresvsp_cmd.cfunc = unresvsp_f;
+       unresvsp_cmd.argmin = 2;
+       unresvsp_cmd.argmax = 2;
+       unresvsp_cmd.args = _("off len");
+       unresvsp_cmd.oneline =
+               _("frees reserved space associated with part of a file");
+
+       add_command(&allocsp_cmd);
+       add_command(&freesp_cmd);
+       add_command(&resvsp_cmd);
+       add_command(&unresvsp_cmd);
+}
diff --git a/io/pwrite.c b/io/pwrite.c
new file mode 100644 (file)
index 0000000..bdf9747
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include "command.h"
+#include "input.h"
+#include "init.h"
+
+static cmdinfo_t pwrite_cmd;
+
+static void
+pwrite_help(void)
+{
+       printf(_(
+"\n"
+" writes a range of bytes (in block size increments) from the given offset\n"
+"\n"
+" Example:\n"
+" 'write 512 20' - writes 20 bytes at 512 bytes into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using either a buffer\n"
+" filled with a set pattern (0xcdcdcdcd) or data read from an input file.\n"
+" -S -- use an alternate seed number\n"
+" -i -- specifies an input file from which to source data to write\n"
+" -d -- open the input file for direct IO\n"
+" -s -- skip a number of bytes at the start of the input file\n"
+" The writes are performed in sequential blocks starting at offset, with the\n"
+" blocksize tunable using the -b option (default blocksize is 4096 bytes).\n"
+"\n"));
+}
+
+static int
+write_buffer(
+       off64_t         offset,
+       ssize_t         count,
+       ssize_t         bs,
+       int             fd,
+       off64_t         skip,
+       ssize_t         *total)
+{
+       ssize_t         bytes, itotal = min(bs,count);
+
+       *total = 0;
+       while (count > 0) {
+               if (fd > 0) {   /* input file given, read buffer first */
+                       if (!read_buffer(fd, skip + *total, bs, &itotal, 0, 1))
+                               break;
+               }
+               bytes = pwrite64(fdesc, buffer, min(itotal,count), offset);
+               if (bytes == 0)
+                       break;
+               if (bytes < 0) {
+                       perror("pwrite64");
+                       return 0;
+               }
+               *total += bytes;
+               if (bytes < count)
+                       break;
+               offset += bytes;
+               count -= bytes;
+       }
+       return 1;
+}
+
+static int
+pwrite_f(
+       int             argc,
+       char            **argv)
+{
+       off64_t         offset, skip = 0;
+       ssize_t         count, total;
+       unsigned int    seed = 0xcdcdcdcd;
+       unsigned int    bsize = 4096;
+       char            *sp, *infile = NULL;
+       int             c, fd = -1, dflag = 0;
+
+       while ((c = getopt(argc, argv, "b:df:i:s:S:")) != EOF) {
+               switch (c) {
+               case 'b':
+                       bsize = strtoul(optarg, &sp, 0);
+                       if (!sp || sp == optarg) {
+                               printf(_("non-numeric bsize -- %s\n"), optarg);
+                               return 0;
+                       }
+                       break;
+               case 'd':
+                       dflag = 1;
+                       break;
+               case 'f':
+               case 'i':
+                       infile = optarg;
+                       break;
+               case 's':
+                       skip = strtoul(optarg, &sp, 0);
+                       if (!sp || sp == optarg) {
+                               printf(_("non-numeric skip -- %s\n"), optarg);
+                               return 0;
+                       }
+                       break;
+               case 'S':
+                       seed = strtoul(optarg, &sp, 0);
+                       if (!sp || sp == optarg) {
+                               printf(_("non-numeric seed -- %s\n"), optarg);
+                               return 0;
+                       }
+                       break;
+               default:
+                       printf("%s %s\n", pwrite_cmd.name, pwrite_cmd.oneline);
+                       return 0;
+               }
+       }
+       if ( ((skip || dflag) && !infile) || (optind != argc - 2)) {
+               printf("%s %s\n", pwrite_cmd.name, pwrite_cmd.oneline);
+               return 0;
+       }
+       offset = strtoul(argv[optind], &sp, 0);
+       if (!sp || sp == argv[optind]) {
+               printf(_("non-numeric offset argument -- %s\n"), argv[optind]);
+               return 0;
+       }
+       optind++;
+       count = strtoul(argv[optind], &sp, 0);
+       if (!sp || sp == argv[optind]) {
+               printf(_("non-numeric length argument -- %s\n"), argv[optind]);
+               return 0;
+       }
+
+       if (!alloc_buffer(bsize, seed))
+               return 0;
+
+       if (infile && ((fd = openfile(infile, 0, 0, dflag, 1, 0, 0, 0)) < 0))
+               return 0;
+
+       if (!write_buffer(offset, count, bsize, fd, skip, &total)) {
+               close(fd);
+               return 0;
+       }
+       printf(_("wrote %u/%u bytes at offset %llu\n"), count, total, offset);
+       close(fd);
+       return 0;
+}
+
+void
+pwrite_init(void)
+{
+       pwrite_cmd.name = _("pwrite");
+       pwrite_cmd.altname = _("w");
+       pwrite_cmd.cfunc = pwrite_f;
+       pwrite_cmd.argmin = 2;
+       pwrite_cmd.argmax = -1;
+       pwrite_cmd.args =
+               _("[-i infile [-d] [-s skip]] [-b bs] [-S seed] off len");
+       pwrite_cmd.oneline =
+               _("writes a number of bytes at a specified offset");
+       pwrite_cmd.help = pwrite_help;
+
+       add_command(&pwrite_cmd);
+}
diff --git a/io/quit.c b/io/quit.c
new file mode 100644 (file)
index 0000000..731eb3a
--- /dev/null
+++ b/io/quit.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include "command.h"
+
+static cmdinfo_t quit_cmd;
+
+static int
+quit_f(
+       int     argc,
+       char    **argv)
+{
+       return 1;
+}
+
+void
+quit_init(void)
+{
+       quit_cmd.name = _("quit");
+       quit_cmd.altname = _("q");
+       quit_cmd.cfunc = quit_f;
+       quit_cmd.oneline = _("exit xfs_io");
+
+       add_command(&quit_cmd);
+}
diff --git a/io/resblks.c b/io/resblks.c
new file mode 100644 (file)
index 0000000..5191dca
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include "command.h"
+#include "init.h"
+
+static cmdinfo_t resblks_cmd;
+static int resblks_f(int argc, char **argv);
+
+static int
+resblks_f(
+       int                     argc,
+       char                    **argv)
+{
+       xfs_fsop_resblks_t      res;
+       char                    *sp;
+
+       if (argc == 2) {
+               res.resblks = strtoul(argv[1], &sp, 10);
+               if (!sp || sp == argv[1]) {
+                       printf(_("non-numeric argument -- %s\n"), argv[1]);
+                       return 0;
+               }
+               if (ioctl(fdesc, XFS_IOC_SET_RESBLKS, &res) < 0) {
+                       perror("XFS_IOC_SET_RESBLKS");
+                       return 0;
+               }
+       } else if (ioctl(fdesc, XFS_IOC_GET_RESBLKS, &res) < 0) {
+               perror("XFS_IOC_GET_RESBLKS");
+               return 0;
+       }
+       printf(_("reserved blocks = %llu\n"),
+                       (unsigned long long) res.resblks);
+       printf(_("available reserved blocks = %llu\n"),
+                       (unsigned long long) res.resblks_avail);
+       return 0;
+}
+
+void
+resblks_init(void)
+{
+       resblks_cmd.name = _("resblks");
+       resblks_cmd.cfunc = resblks_f;
+       resblks_cmd.argmin = 0;
+       resblks_cmd.argmax = 1;
+       resblks_cmd.args = _("[blocks]");
+       resblks_cmd.oneline =
+               _("get and/or set count of reserved filesystem blocks");
+
+       add_command(&resblks_cmd);
+}
diff --git a/io/truncate.c b/io/truncate.c
new file mode 100644 (file)
index 0000000..80bdce2
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 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.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <libxfs.h>
+#include "command.h"
+#include "init.h"
+
+static cmdinfo_t truncate_cmd;
+
+static int
+truncate_f(
+       int                     argc,
+       char                    **argv)
+{
+       off64_t                 offset;
+       char                    *sp;
+
+       offset = strtoul(argv[1], &sp, 10);
+       if (!sp || sp == argv[1]) {
+               printf(_("non-numeric truncate argument -- %s\n"), argv[1]);
+               return 0;
+       }
+
+       if (ftruncate64(fdesc, offset) < 0) {
+               perror("ftruncate");
+               return 0;
+       }
+       return 0;
+}
+
+void
+truncate_init(void)
+{
+       truncate_cmd.name = _("truncate");
+       truncate_cmd.cfunc = truncate_f;
+       truncate_cmd.argmin = 1;
+       truncate_cmd.argmax = 1;
+       truncate_cmd.args = _("off");
+       truncate_cmd.oneline =
+               _("truncates the current file at the given offset");
+
+       add_command(&truncate_cmd);
+}
diff --git a/io/xfs_bmap.sh b/io/xfs_bmap.sh
new file mode 100755 (executable)
index 0000000..ed63122
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/sh -f
+#
+# Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 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.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+OPTS=""
+VERSION=false
+USAGE="Usage: xfs_bmap [-adlpvV] [-n nx] file..."
+
+while getopts "adln:pvV" c
+do
+       case $c in
+       a)      OPTS=$OPTS" -a";;
+       d)      OPTS=$OPTS" -d";;
+       l)      OPTS=$OPTS" -l";;
+       n)      OPTS=$OPTS" '-n "$OPTARG"'";;
+       p)      OPTS=$OPTS" -p";;
+       v)      OPTS=$OPTS" -v";;
+       V)      VERSION=true;;
+       \?)     echo $USAGE 1>&2
+               exit 2
+               ;;
+       esac
+done
+$VERSION && xfs_io -p xfs_bmap -V
+
+set -- extra $@
+shift $OPTIND
+
+while [ "$1" != "" ]
+do
+       eval xfs_io -r -p xfs_bmap -c 'bmap $OPTS' $1
+       status=$?
+       [ $status -ne 0 ] && exit $status
+       shift $OPTIND
+done
+exit 0
diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
new file mode 100644 (file)
index 0000000..d0f9cd6
--- /dev/null
@@ -0,0 +1,169 @@
+.TH xfs_io 8
+.SH NAME
+xfs_io \- debug the IO path of an XFS filesystem
+.SH SYNOPSIS
+.nf
+\f3xfs_io\f1 [ \f3\-c\f1 cmd ] ... [ \f3\-p\f1 prog ] [ \f3\-r\f1 ] file
+.fi
+.SH DESCRIPTION
+\f2xfs_io\f1 is a debugging tool like \f2xfs_db\f1(8), but is aimed
+at examining the regular file IO path rather than the raw XFS volume
+itself.
+.PP
+The options to \f2xfs_io\f1 are:
+.TP 10
+\f3\-c\f1 \f2cmd\f1
+\f2xfs_io\f1 commands may be run interactively (the default)
+or as arguments on the command line.
+Multiple \f3\-c\f1 arguments may be given.
+The commands are run in the sequence given, then the program exits.
+This is the mechanism used to implement \f2xfs_bmap\f1(8).
+.TP
+\f3\-p\f1 \f2prog\f1
+Set the program name for prompts and some error messages,
+the default value is \f2xfs_io\f1.
+.TP
+\f3\-r\f1
+Open \f2file\f1 read-only, initially.
+.SH CONCEPTS
+\f2xfs_io\f1 always maintains one current open file in the filesystem.
+This is initially specified on the command line, but alternate files
+can be specified later (one at a time \- see the ``open'' command).
+.PP
+\f2xfs_io\f1 commands can be broken up into two distinct classes.
+Most commands are for doing IO to the file in some way - reads, writes,
+or space preallocation.
+Other commands are for the navigation and display of data structures
+relating to the open file or the filesystem it resides in.
+.SH COMMANDS
+.PP
+Many commands have extensive online help.
+Use the \f3help\f1 command for more details on any command.
+.TP 10
+\f3allocsp\f1 \f2offset\f1 \f2length\f1
+Allocates zeroed space for part of a file using the XFS_IOC_ALLOCSP
+system call described in \f2xfs\f1(5).
+.TP
+\f3freesp\f1 \f2offset\f1 \f2length\f1
+Frees space for part of a file using the XFS_IOC_FREESP
+system call described in \f2xfs\f1(5).
+.TP
+\f3bmap\f1 [ \f2-adlpv\f1 ] [ \f2-n nx\f1 ]
+Prints the block mapping for the open file.
+Refer to \f2xfs_bmap\f1(8) for complete documentation.
+.TP
+\f3fdatasync\f1
+Calls \f2fdatasync\f1(2) to flush the open file's in-core data to disk.
+.TP
+\f3fsync\f1
+Calls \f2fsync\f1(2) to flush all in-core file state to disk.
+.TP
+\f3o\f1
+See the \f3open\f1 command.
+.TP
+\f3open\f1 [ \f2-acdrstx\f1 ] [ \f2path\f1 ]
+Closes the current file, and opens the file specified by \f2path\f1 instead.
+Without any arguments, displays statistics about the currently open file \-
+see the \f3stat\f1 command.
+.br
+The \f3\-a\f1 option opens append-only (O_APPEND).
+.br
+The \f3\-c\f1 option creates the file if it doesn't already exist (O_CREAT).
+.br
+The \f3\-d\f1 option opens for direct IO (O_DIRECT).
+.br
+The \f3\-r\f1 option opens read-only (O_RDONLY).
+.br
+The \f3\-s\f1 option opens for synchronous IO (O_SYNC).
+.br
+The \f3\-t\f1 option truncates on open (O_TRUNC).
+.br
+The \f3\-x\f1 option marks the file as a realtime XFS file after
+opening it, if it is not already marked as such.
+.TP
+\f3pread\f1
+Reads a range of bytes in a specified blocksize from the given offset.
+.br
+The \f3\-b\f1 option can be used to set the blocksize into which the
+\f2read\f1(2) requests will be split.
+The default blocksize is 4096 bytes.
+.br
+The \f3\-v\f1 option will dump the contents of the buffer after reading,
+by default only the count of bytes actually read is dumped.
+.TP
+\f3pwrite\f1
+Writes a range of bytes in a specified blocksize from the given offset.
+The bytes written can be either a set pattern or read in from another
+file before writing.
+.br
+The \f3\-i\f1 option allows an input file to be specified as the source
+of the data to be written.
+.br
+The \f3\-d\f1 option will cause direct IO, rather than the usual buffered
+IO, to be used when reading the input file.
+.br
+The \f3\-s\f1 options specifies the number of bytes to skip from the
+start of the input file before starting to read.
+.br
+The \f3\-b\f1 option can be used to set the blocksize into which the
+\f2read\f1(2) requests will be split.
+The default blocksize is 4096 bytes.
+The \f3\-S\f1 option is used to set the (repeated) fill pattern which
+is used when the data to write is not coming from a file.
+The default buffer fill pattern value is 0xcdcdcdcd.
+.TP
+\f3q\f1
+See the \f3quit\f1 command.
+.TP
+\f3quit\f1
+Exit \f2xfs_io\f1.
+.TP
+\f3r\f1
+See the \f3pread\f1 command.
+.TP
+\f3resblks\f1 [ \f2blocks\f1 ]
+Get and/or set count of reserved filesystem blocks using the
+XFS_IOC_GET_RESBLKS or XFS_IOC_SET_RESBLKS system calls, as
+described in \f2xfs\f1(5).
+Note \-\- this can be useful for exercising out of space behavior.
+.TP
+\f3resvsp\f1 \f2offset\f1 \f2length\f1
+Allocates reserved, unwritten space for part of a file using the XFS_IOC_RESVSP
+system call described in \f2xfs\f1(5).
+.TP
+\f3unresvsp\f1 \f2offset\f1 \f2length\f1
+Frees reserved space for part of a file using the XFS_IOC_UNRESVSP
+system call described in \f2xfs\f1(5).
+.TP
+\f3s\f1
+See the \f3fsync\f1 command.
+.TP
+\f3stat\f1 [ \f2-v\f1 ]
+Selected statistics from \f2stat\f1(2) and the XFS_IOC_GETXATTR
+system call from \f2xfs\f1(5) on the currently open file.
+If the \f2-v\f1 option is specified, the atime (last access), mtime
+(last modify), and ctime (last change) timestamps are also displayed.
+.TP
+\f3statfs\f1
+Selected statistics from \f2statfs\f1(2) and the XFS_IOC_FSGEOMETRY
+system call from \f2xfs\f1(5) on the filesystem where the currently
+open file resides.
+.TP
+\f3truncate\f1 \f2offset\f1
+Truncates the current file at the given offset using \f2ftruncate\f1(2).
+.TP
+\f3w\f1
+See the \f3pwrite\f1 command.
+.SH SEE ALSO
+fdatasync(2),
+fstat(2),
+fstatfs(2),
+fsync(2),
+ftruncate(2),
+mkfs.xfs(8),
+open(2),
+pread(2),
+pwrite(2),
+xfs_bmap(8),
+xfs_db(8),
+xfs(5).