volinfo: separate volscan binary
authorMichael Meffie <mmeffie@sinenomine.net>
Wed, 12 Mar 2014 19:15:32 +0000 (15:15 -0400)
committerD Brashear <shadow@your-file-system.com>
Tue, 25 Mar 2014 16:58:55 +0000 (09:58 -0700)
Refactor vol-info.c into several files and change the makefile to
build a separate volscan binary, instead of using the program name
to determine if the user is running volinfo or volscan.

This commit adds new source files for the volinfo and volscan main()
function and a common header file.

Change-Id: I53a2a503812237a850170c39c81ee3fb56c8282e
Reviewed-on: http://gerrit.openafs.org/10903
Reviewed-by: D Brashear <shadow@your-file-system.com>
Tested-by: D Brashear <shadow@your-file-system.com>

src/vol/.gitignore
src/vol/Makefile.in
src/vol/NTMakefile
src/vol/vol-info.c
src/vol/vol-info.h [new file with mode: 0644]
src/vol/volinfo-main.c [new file with mode: 0644]
src/vol/volscan-main.c [new file with mode: 0644]

index abfec40..a627159 100644 (file)
@@ -4,6 +4,7 @@
 
 /salvager
 /volinfo
+/volscan
 /gi
 /fs_conv_sol26
 /fssync-debug
index ac094f8..59c75d0 100644 (file)
@@ -28,13 +28,15 @@ VLIBOBJS=vnode.o volume.o vutil.o partition.o fssync-server.o fssync-client.o \
         clone.o nuke.o devname.o listinodes.o common.o ihandle.o purge.o \
         namei_ops.o salvsync-server.o salvsync-client.o daemon_com.o
 
-OBJECTS=${VLIBOBJS} physio.o vol-salvage.o vol-info.o vol-dump.o vol-bless.o fssync-debug.o
+OBJECTS=${VLIBOBJS} physio.o vol-salvage.o vol-info.o vol-dump.o vol-bless.o fssync-debug.o \
+       volinfo-main.o volscan-main.o
 
 all: gi \
        ${TOP_LIBDIR}/vlib.a \
        ${TOP_LIBDIR}/libvlib.a \
        salvager \
        volinfo \
+       volscan \
        fssync-debug \
        $(XFS_SIZE_CHECK) \
        ${TOP_INCDIR}/afs/nfs.h \
@@ -109,7 +111,7 @@ ${TOP_INCDIR}/afs/vol_prototypes.h: vol_prototypes.h
 #
 # Installation targets
 #
-install: vlib.a salvager volinfo fssync-debug
+install: vlib.a salvager volinfo volscan fssync-debug
        ${INSTALL} -d ${DESTDIR}${libdir}/afs
        ${INSTALL} -d ${DESTDIR}${afssrvlibexecdir}
        ${INSTALL} -d ${DESTDIR}${afssrvsbindir}
@@ -118,6 +120,7 @@ install: vlib.a salvager volinfo fssync-debug
        ${INSTALL_DATA} vlib.a ${DESTDIR}${libdir}/afs/libvlib.a
        ${INSTALL_PROGRAM} salvager ${DESTDIR}${afssrvlibexecdir}/salvager
        ${INSTALL_PROGRAM} volinfo ${DESTDIR}${afssrvsbindir}/volinfo
+       ${INSTALL_PROGRAM} volscan ${DESTDIR}${afssrvsbindir}/volscan
        ${INSTALL_PROGRAM} fssync-debug ${DESTDIR}${afssrvsbindir}/fssync-debug
        ${INSTALL_DATA} ${srcdir}/nfs.h ${DESTDIR}${includedir}/afs/nfs.h
        ${INSTALL_DATA} ${srcdir}/vnode.h ${DESTDIR}${includedir}/afs/vnode.h
@@ -137,7 +140,7 @@ install: vlib.a salvager volinfo fssync-debug
                        ${DESTDIR}${afssrvsbindir}/xfs_size_check ; \
        fi
 
-dest: vlib.a salvager volinfo fssync-debug
+dest: vlib.a salvager volinfo volscan fssync-debug
        ${INSTALL} -d ${DEST}/lib/afs
        ${INSTALL} -d ${DEST}/root.server/usr/afs/bin
        ${INSTALL} -d ${DEST}/include/afs
@@ -145,6 +148,7 @@ dest: vlib.a salvager volinfo fssync-debug
        ${INSTALL_DATA} vlib.a ${DEST}/lib/afs/libvlib.a
        ${INSTALL_PROGRAM} salvager ${DEST}/root.server/usr/afs/bin/salvager
        ${INSTALL_PROGRAM} volinfo ${DEST}/root.server/usr/afs/bin/volinfo
+       ${INSTALL_PROGRAM} volscan ${DEST}/root.server/usr/afs/bin/volscan
        ${INSTALL_PROGRAM} fssync-debug ${DEST}/root.server/usr/afs/bin/fssync-debug
        ${INSTALL_DATA} ${srcdir}/nfs.h ${DEST}/include/afs/nfs.h
        ${INSTALL_DATA} ${srcdir}/vnode.h ${DEST}/include/afs/vnode.h
@@ -214,8 +218,12 @@ namei_map: ${TOP_LIBDIR}/libsys.a namei_map.o
        $(AFS_LDRULE) namei_map.o ${TOP_LIBDIR}/libafsutil.a \
                ${LIBS} $(LIB_roken) ${XLIBS}
 
-volinfo: vol-info.o physio.o ihandle.o ${LIBS}
-       $(AFS_LDRULE) vol-info.o physio.o ihandle.o \
+volinfo: volinfo-main.c vol-info.o physio.o ihandle.o ${LIBS}
+       $(AFS_LDRULE) volinfo-main.c vol-info.o physio.o ihandle.o \
+               ${LIBS} $(LIB_roken) ${XLIBS}
+
+volscan: volscan-main.c vol-info.o physio.o ihandle.o ${LIBS}
+       $(AFS_LDRULE) volscan-main.c vol-info.o physio.o ihandle.o \
                ${LIBS} $(LIB_roken) ${XLIBS}
 
 fssync-debug: fssync-debug.o physio.o AFS_component_version_number.c ${LIBS}
@@ -234,7 +242,7 @@ xfs_size_check: xfs_size_check.o
 #
 clean:
        $(RM) -f *.o *.a AFS_component_version_number.c
-       $(RM) -f ${SCMPROGS} ${STAGEPROGS} core salvager volinfo gi fssync-debug
+       $(RM) -f ${SCMPROGS} ${STAGEPROGS} core salvager volinfo volscan gi fssync-debug
 
 test:
        cd test; $(MAKE)
@@ -246,4 +254,5 @@ check-splint::
            vnode.c volume.c vutil.c partition.c fssync-server.c fssync-client.c \
            clone.c nuke.c devname.c listinodes.c common.c ihandle.c \
            namei_ops.c salvsync-server.c salvsync-client.c daemon_com.c purge.c \
-           physio.c vol-salvage.c vol-info.c vol-bless.c fssync-debug.c
+           physio.c vol-salvage.c vol-info.c vol-bless.c fssync-debug.c \
+           volinfo-main.c volscan-main.c
index d3605c3..ecced42 100644 (file)
@@ -234,21 +234,35 @@ $(FSSYNC_DEBUG): $(FSSYNC_DEBUG_EXEOBJS) $(EXEC_LIBS)
         $(SYMSTORE_IMPORT)
 
 ############################################################################
-# build volinfo
+# build volinfo and volscan
 VOLINFO = $(DESTDIR)\root.server\usr\afs\bin\volinfo.exe
+VOLSCAN = $(DESTDIR)\root.server\usr\afs\bin\volscan.exe
 
 $(OUT)\vol-info.obj: vol-info.c
        $(C2OBJ) $** -DAFS_PTHREAD_ENV
 
-$(VOLINFO): $(OUT)\vol-info.obj $(OUT)\physio.obj $(OUT)\volinfo.res $(EXEC_LIBS)
+$(OUT)\volinfo-main.obj: volinfo-main.c
+       $(C2OBJ) $** -DAFS_PTHREAD_ENV
+
+$(OUT)\volscan-main.obj: volscan-main.c
+       $(C2OBJ) $** -DAFS_PTHREAD_ENV
+
+$(VOLINFO): $(OUT)\volinfo-main.obj $(OUT)\vol-info.obj $(OUT)\physio.obj $(OUT)\volinfo.res $(EXEC_LIBS)
        $(EXECONLINK) shell32.lib
-        $(_VC_MANIFEST_EMBED_EXE)
+       $(_VC_MANIFEST_EMBED_EXE)
        $(EXEPREP)
-        $(CODESIGN_USERLAND)
-        $(SYMSTORE_IMPORT)
+       $(CODESIGN_USERLAND)
+       $(SYMSTORE_IMPORT)
+
+$(VOLSCAN): $(OUT)\volscan-main.obj $(OUT)\vol-info.obj $(OUT)\physio.obj $(OUT)\volinfo.res $(EXEC_LIBS)
+       $(EXECONLINK) shell32.lib
+       $(_VC_MANIFEST_EMBED_EXE)
+       $(EXEPREP)
+       $(CODESIGN_USERLAND)
+       $(SYMSTORE_IMPORT)
 
 ############################################################################
-# build volinfo
+# build vol-bless
 VOLBLESS = $(DESTDIR)\root.server\usr\afs\bin\vol-bless.exe
 
 $(OUT)\vol-bless.obj: vol-bless.c
@@ -269,7 +283,7 @@ $(OUT)\volinfo.res: AFS_component_version_number.h
 
 ############################################################################
 # Install targets
-install: $(INCFILES) $(LIBFILE) $(MT_LIBFILE) $(DAFS_LIBFILE) $(SALVAGER) $(VOLINFO)
+install: $(INCFILES) $(LIBFILE) $(MT_LIBFILE) $(DAFS_LIBFILE) $(SALVAGER) $(VOLINFO) $(VOLSCAN)
 
 mkdir:
        
index 6f8274f..956b738 100644 (file)
 #include "salvage.h"
 #include "daemon_com_inline.h"
 #include "fssync_inline.h"
+#include "vol-info.h"
 
-#ifndef AFS_NT40_ENV
-#include "AFS_component_version_number.c"
-#endif
-
-static const char *progname = NULL;
+static int volinfo_init = 0;
+static const char *progname = "";
 static const char *PLACEHOLDER = "-";
 
-/* Command line options */
-typedef enum {
-    P_CHECKOUT,
-    P_VNODE,
-    P_DATE,
-    P_INODE,
-    P_ITIME,
-    P_PART,
-    P_VOLUMEID,
-    P_HEADER,
-    P_SIZEONLY,
-    P_FIXHEADER,
-    P_SAVEINODES,
-    P_ORPHANED,
-    P_FILENAMES,
-    P_TYPE,
-    P_FIND,
-    P_MASK,
-    P_OUTPUT,
-    P_DELIM,
-    P_NOHEADING,
-    P_NOMAGIC,
-} volinfo_parm_t;
-
-/*
- * volscan output columns
- */
-#define VOLSCAN_COLUMNS \
-    c(host) \
-    c(desc) \
-    c(vid) \
-    c(offset) \
-    c(vtype) \
-    c(vname) \
-    c(part) \
-    c(partid) \
-    c(fid) \
-    c(path) \
-    c(target) \
-    c(mount) \
-    c(mtype) \
-    c(mcell) \
-    c(mvol) \
-    c(aid) \
-    c(arights) \
-    c(vntype) \
-    c(cloned) \
-    c(mode) \
-    c(links) \
-    c(length) \
-    c(uniq) \
-    c(dv) \
-    c(inode) \
-    c(namei) \
-    c(modtime) \
-    c(author) \
-    c(owner) \
-    c(parent) \
-    c(magic) \
-    c(lock) \
-    c(smodtime) \
-    c(group)
 
 /* Numeric column type ids */
 typedef enum columnType {
@@ -134,12 +70,6 @@ struct columnName ColumnName[] = {
     {max_column_type, NULL}
 };
 
-/* All columns names as a single string. */
-#define c(x) #x " "
-static char *ColumnNames = VOLSCAN_COLUMNS;
-#undef c
-#undef VOLSCAN_COLUMNS
-
 
 /* VnodeDetails union descriminator */
 typedef enum {
@@ -170,27 +100,6 @@ struct VnodeDetails {
     } u;
 };
 
-struct VolInfoOpt {
-    int checkout;            /**< Use FSSYNC to checkout volumes from the fileserver. */
-    int dumpInfo;            /**< Dump volume information */
-    int dumpHeader;          /**< Dump volume header files info */
-    int dumpVnodes;          /**< Dump vnode info */
-    int dumpInodeNumber;     /**< Dump inode numbers with vnodes */
-    int dumpDate;            /**< Dump vnode date (server modify date) with vnode */
-    int dumpInodeTimes;      /**< Dump some of the dates associated with inodes */
-    int dumpFileNames;       /**< Dump vnode and special file name filenames */
-    int showOrphaned;        /**< Show "orphaned" vnodes (vnodes with parent of 0) */
-    int showSizes;           /**< Show volume size summary */
-    int saveInodes;          /**< Save vnode data to files */
-    int fixHeader;           /**< Repair header files magic and version fields. */
-    char hostname[64];       /**< This hostname, for volscan output. */
-    char columnDelim[16];    /**< Column delimiter char(s) */
-    char printHeading;       /**< Print column heading */
-    int checkMagic;          /**< Check directory vnode magic when looking up paths */
-    unsigned int modeMask[64]; /**< unix mode bit pattern for searching for specific modes */
-    int scanVolType;        /**< volume types to scan; zero means do not check */
-    int findVnType;         /**< types of objects to find */
-};
 
 static int NeedDirIndex;        /**< Large vnode index handle is needed for path lookups. */
 static FdHandle_t *DirIndexFd = NULL; /**< Current large vnode index handle for path lookups. */
@@ -198,18 +107,6 @@ static FdHandle_t *DirIndexFd = NULL; /**< Current large vnode index handle for
 static int NumOutputColumns = 0;
 static columnType OutputColumn[max_column_type];
 
-/* scanVolType flags */
-#define SCAN_RW  0x01          /**< scan read-write volumes vnodes */
-#define SCAN_RO  0x02          /**< scan read-only volume vnodes */
-#define SCAN_BK  0x04          /**< scan backup volume vnodes */
-
-/* findVnType flags */
-#define FIND_FILE       0x01   /**< find regular files */
-#define FIND_DIR        0x02   /**< find directories */
-#define FIND_MOUNT      0x04   /**< find afs mount points */
-#define FIND_SYMLINK    0x08   /**< find symlinks */
-#define FIND_ACL        0x10   /**< find access entiries */
-
 /**
  * Volume size running totals
  */
@@ -238,19 +135,14 @@ struct VnodeScanProc {
 static struct opr_queue VnodeScanLists[nVNODECLASSES];
 
 /* Forward Declarations */
-void PrintHeader(Volume * vp);
-void HandleAllPart(struct VolInfoOpt *opt);
-void HandlePart(struct VolInfoOpt *opt, struct DiskPartition64 *partP);
-void HandleVolume(struct VolInfoOpt *opt, struct DiskPartition64 *partP, char *name);
-struct DiskPartition64 *FindCurrentPartition(void);
-Volume *AttachVolume(struct VolInfoOpt *opt, struct DiskPartition64 *dp, char *volname,
+static void PrintHeader(Volume * vp);
+static void HandleAllPart(struct VolInfoOpt *opt);
+static void HandlePart(struct VolInfoOpt *opt, struct DiskPartition64 *partP);
+static void HandleVolume(struct VolInfoOpt *opt, struct DiskPartition64 *partP, char *name);
+static struct DiskPartition64 *FindCurrentPartition(void);
+static Volume *AttachVolume(struct VolInfoOpt *opt, struct DiskPartition64 *dp, char *volname,
                     struct VolumeHeader *header);
-void HandleVnodes(struct VolInfoOpt *opt, Volume * vp, VnodeClass class);
-static void AddVnodeToSizeTotals(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
-static void SaveInode(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
-static void PrintVnode(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
-static void PrintVnodeDetails(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
-static void ScanAcl(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
+static void HandleVnodes(struct VolInfoOpt *opt, Volume * vp, VnodeClass class);
 static void PrintColumnHeading(struct VolInfoOpt *opt);
 static void PrintColumns(struct VolInfoOpt *opt, struct VnodeDetails *vdp, const char *desc);
 
@@ -272,7 +164,7 @@ extern void FidZap(DirHandle * file);
  *       caller must not reference the returned string after
  *       seven additional calls to this function.
  */
-char *
+static char *
 date(time_t date)
 {
 #define MAX_DATE_RESULT        100
@@ -300,7 +192,7 @@ date(time_t date)
  *       caller must not reference the returned string after
  *       seven additional calls to this function.
  */
-char *
+static char *
 NT_date(FILETIME * ft)
 {
     static char result[8][64];
@@ -326,8 +218,8 @@ NT_date(FILETIME * ft)
  *
  * @return none
  */
-static void
-AddVnodeToSizeTotals(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
+void
+volinfo_AddVnodeToSizeTotals(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
 {
     afs_fsize_t fileLength;
 
@@ -432,7 +324,7 @@ PrintServerTotals(void)
  *   @retval 0 success
  *   @retval -1 failed to read file
  */
-int
+static int
 ReadHdr1(struct VolInfoOpt *opt, IHandle_t * ih, char *to, afs_sfsize_t size,
         u_int magic, u_int version)
 {
@@ -487,7 +379,7 @@ ReadHdr1(struct VolInfoOpt *opt, IHandle_t * ih, char *to, afs_sfsize_t size,
  *
  * @return volume object or null on error
  */
-Volume *
+static Volume *
 AttachVolume(struct VolInfoOpt *opt, struct DiskPartition64 *dp,
             char *volname, struct VolumeHeader *header)
 {
@@ -659,20 +551,13 @@ GetPartitionName(afs_uint32 partId, char *partName, afs_size_t partNameSize)
  *
  * @return 0 if successful
  */
-static int
-ScanPartitions(struct VolInfoOpt *opt, char *partNameOrId, VolumeId volumeId)
+int
+volinfo_ScanPartitions(struct VolInfoOpt *opt, char *partNameOrId, VolumeId volumeId)
 {
     int err = 0;
     char partName[64] = "";
     struct DiskPartition64 *partP = NULL;
 
-#ifndef AFS_NT40_ENV
-    if (geteuid() != 0) {
-       fprintf(stderr, "%s: Must be run as root; sorry\n", progname);
-       return 1;
-    }
-#endif
-
     if (opt->checkout) {
        if (!FSYNC_clientInit()) {
            fprintf(stderr, "%s: Failed to connect to fileserver.\n",
@@ -681,9 +566,6 @@ ScanPartitions(struct VolInfoOpt *opt, char *partNameOrId, VolumeId volumeId)
        }
     }
 
-    DInit(1024);
-    VInitVnodes(vLarge, 0);
-    VInitVnodes(vSmall, 0);
 
     /* Allow user to specify partition by name or id. */
     if (partNameOrId) {
@@ -768,130 +650,65 @@ ScanPartitions(struct VolInfoOpt *opt, char *partNameOrId, VolumeId volumeId)
  *
  * @return none
  */
-static void
-AddVnodeHandler(VnodeClass class,
+void
+volinfo_AddVnodeHandler(int vnodeClass,
                void (*proc) (struct VolInfoOpt * opt,
                              struct VnodeDetails * vdp), const char *heading)
 {
     struct VnodeScanProc *entry = malloc(sizeof(struct VnodeScanProc));
     entry->proc = proc;
     entry->heading = heading;
-    opr_queue_Append(&VnodeScanLists[class], (struct opr_queue *)entry);
+    opr_queue_Append(&VnodeScanLists[vnodeClass], (struct opr_queue *)entry);
 }
 
-static int
-VolInfoOptions(struct VolInfoOpt **optp)
+/**
+ * Initialize the vol-info module.
+ */
+int
+volinfo_Init(const char *aprogname)
 {
-    struct VolInfoOpt *opt;
-
-    opt = calloc(1, sizeof(struct VolInfoOpt));
-    if (!opt) {
-        return ENOMEM;
+    if (!volinfo_init) {
+       progname = aprogname;  /* for error messages */
+#ifndef AFS_NT40_ENV
+       if (geteuid() != 0) {
+           fprintf(stderr, "%s: Must be run as root.\n", progname);
+           return EPERM;
+       }
+#endif
+       DInit(1024);
+       VInitVnodes(vLarge, 0);
+       VInitVnodes(vSmall, 0);
+       opr_queue_Init(&VnodeScanLists[vLarge]);
+       opr_queue_Init(&VnodeScanLists[vSmall]);
+        volinfo_init = 1;
     }
-    opt->dumpInfo = 1;         /* volinfo default mode */
-    gethostname(opt->hostname, sizeof(opt->hostname));
-    opt->columnDelim[0] = ' ';
-    opt->checkMagic = 1;
-    *optp = opt;
     return 0;
 }
 
 /**
- * Process command line options and start scanning
+ * Alloc an options structure with default values.
  *
- * @param[in] as     command syntax object
- * @param[in] arock  opaque object; not used
+ * The caller must free the options pointer after use.
  *
- * @return error code
+ * @param[out] optp address of options pointer
+ * @return 0 on success
  */
-static int
-VolInfo(struct cmd_syndesc *as, void *arock)
+int
+volinfo_Options(struct VolInfoOpt **optp)
 {
-    int code;
-    struct cmd_item *ti;
-    VolumeId volumeId = 0;
-    char *partNameOrId = NULL;
     struct VolInfoOpt *opt;
 
-    code = VolInfoOptions(&opt);
-    if (code) {
-       fprintf(stderr, "%s: Failed to initialize options (%d).\n", progname, code);
-       return code;
-    }
-
-    if (as->parms[P_CHECKOUT].items) {
-       opt->checkout = 1;
-    }
-    if (as->parms[P_VNODE].items) {
-       opt->dumpVnodes = 1;
-    }
-    if (as->parms[P_DATE].items) {
-       opt->dumpDate = 1;
-    }
-    if (as->parms[P_INODE].items) {
-       opt->dumpInodeNumber = 1;
-    }
-    if (as->parms[P_ITIME].items) {
-       opt->dumpInodeTimes = 1;
-    }
-    if ((ti = as->parms[P_PART].items)) {
-       partNameOrId = ti->data;
-    }
-    if ((ti = as->parms[P_VOLUMEID].items)) {
-       volumeId = strtoul(ti->data, NULL, 10);
-    }
-    if (as->parms[P_HEADER].items) {
-       opt->dumpHeader = 1;
-    }
-    if (as->parms[P_SIZEONLY].items) {
-       opt->showSizes = 1;
-    }
-    if (as->parms[P_FIXHEADER].items) {
-       opt->fixHeader = 1;
-    }
-    if (as->parms[P_SAVEINODES].items) {
-       opt->saveInodes = 1;
-    }
-    if (as->parms[P_ORPHANED].items) {
-       opt->showOrphaned = 1;
-    }
-    if (as->parms[P_FILENAMES].items) {
-       opt->dumpFileNames = 1;
-    }
-
-    /* -saveinodes and -sizeOnly override the default mode.
-     * For compatibility with old versions of volinfo, -orphaned
-     * and -filename options imply -vnodes */
-    if (opt->saveInodes || opt->showSizes) {
-       opt->dumpInfo = 0;
-       opt->dumpHeader = 0;
-       opt->dumpVnodes = 0;
-       opt->dumpInodeTimes = 0;
-       opt->showOrphaned = 0;
-    } else if (opt->showOrphaned) {
-       opt->dumpVnodes = 1;            /* implied */
-    } else if (opt->dumpFileNames) {
-       opt->dumpVnodes = 1;            /* implied */
-    }
-
-    if (opt->saveInodes) {
-       AddVnodeHandler(vSmall, SaveInode,
-                       "Saving all volume files to current directory ...\n");
-    }
-    if (opt->showSizes) {
-       AddVnodeHandler(vLarge, AddVnodeToSizeTotals, NULL);
-       AddVnodeHandler(vSmall, AddVnodeToSizeTotals, NULL);
-    }
-    if (opt->dumpVnodes) {
-       AddVnodeHandler(vLarge, PrintVnode, "\nLarge vnodes (directories)\n");
-       AddVnodeHandler(vSmall, PrintVnode,
-                       "\nSmall vnodes(files, symbolic links)\n");
-    }
-    code = ScanPartitions(opt, partNameOrId, volumeId);
-    if (opt) {
-        free(opt);
+    opt = calloc(1, sizeof(struct VolInfoOpt));
+    if (!opt) {
+       fprintf(stderr, "%s: Failed to allocate options (%d).\n", progname, ENOMEM);
+        return ENOMEM;
     }
-    return code;
+    opt->dumpInfo = 1;
+    gethostname(opt->hostname, sizeof(opt->hostname));
+    opt->columnDelim[0] = ' ';
+    opt->checkMagic = 1;
+    *optp = opt;
+    return 0;
 }
 
 /**
@@ -904,8 +721,8 @@ VolInfo(struct cmd_syndesc *as, void *arock)
  *   @retval 1 too many columns
  *   @retval 2 invalid column name
  */
-static int
-AddOutputColumn(char *name)
+int
+volinfo_AddOutputColumn(char *name)
 {
     int i;
 
@@ -928,148 +745,6 @@ AddOutputColumn(char *name)
     return 2;
 }
 
-/**
- * Process command line options and start scanning
- *
- * @param[in] as     command syntax object
- * @param[in] arock  opaque object; not used
- *
- * @return error code
- *    @retval 0 success
- *    @retvol 1 failure
- */
-static int
-VolScan(struct cmd_syndesc *as, void *arock)
-{
-    int code;
-    struct cmd_item *ti;
-    VolumeId volumeId = 0;
-    char *partNameOrId = NULL;
-    int i;
-    struct VolInfoOpt *opt;
-
-    code = VolInfoOptions(&opt);
-    if (code) {
-       fprintf(stderr, "%s: Failed to initialize options (%d).\n", progname, code);
-       return code;
-    }
-
-    if (as->parms[P_CHECKOUT].items) {
-       opt->checkout = 1;
-    }
-    if ((ti = as->parms[P_PART].items)) {
-       partNameOrId = ti->data;
-    }
-    if ((ti = as->parms[P_VOLUMEID].items)) {
-       volumeId = strtoul(ti->data, NULL, 10);
-    }
-    if (as->parms[P_NOHEADING].items) {
-       opt->printHeading = 0;
-    } else {
-       opt->printHeading = 1;
-    }
-    if (as->parms[P_NOMAGIC].items) {
-        opt->checkMagic = 0;
-    }
-    if ((ti = as->parms[P_DELIM].items)) {
-       strncpy(opt->columnDelim, ti->data, 15);
-       opt->columnDelim[15] = '\0';
-    }
-
-    /* Limit types of volumes to scan. */
-    if (!as->parms[P_TYPE].items) {
-       opt->scanVolType = (SCAN_RW | SCAN_RO | SCAN_BK);
-    } else {
-       opt->scanVolType = 0;
-       for (ti = as->parms[P_TYPE].items; ti; ti = ti->next) {
-           if (strcmp(ti->data, "rw") == 0) {
-               opt->scanVolType |= SCAN_RW;
-           } else if (strcmp(ti->data, "ro") == 0) {
-               opt->scanVolType |= SCAN_RO;
-           } else if (strcmp(ti->data, "bk") == 0) {
-               opt->scanVolType |= SCAN_BK;
-           } else {
-               fprintf(stderr, "%s: Unknown -type value: %s\n", progname,
-                       ti->data);
-               return 1;
-           }
-       }
-    }
-
-    /* Limit types of vnodes to find (plus access entries) */
-    if (!as->parms[P_FIND].items) {
-       opt->findVnType = (FIND_FILE | FIND_DIR | FIND_MOUNT | FIND_SYMLINK);
-    } else {
-       opt->findVnType = 0;
-       for (ti = as->parms[P_FIND].items; ti; ti = ti->next) {
-           if (strcmp(ti->data, "file") == 0) {
-               opt->findVnType |= FIND_FILE;
-           } else if (strcmp(ti->data, "dir") == 0) {
-               opt->findVnType |= FIND_DIR;
-           } else if (strcmp(ti->data, "mount") == 0) {
-               opt->findVnType |= FIND_MOUNT;
-           } else if (strcmp(ti->data, "symlink") == 0) {
-               opt->findVnType |= FIND_SYMLINK;
-           } else if (strcmp(ti->data, "acl") == 0) {
-               opt->findVnType |= FIND_ACL;
-           } else {
-               fprintf(stderr, "%s: Unknown -find value: %s\n", progname,
-                       ti->data);
-               return 1;
-           }
-       }
-    }
-
-    /* Show vnodes matching one of the mode masks */
-    for (i = 0, ti = as->parms[P_MASK].items; ti; i++, ti = ti->next) {
-       if (i >= (sizeof(opt->modeMask) / sizeof(*opt->modeMask))) {
-           fprintf(stderr, "Too many -mask values\n");
-           return -1;
-       }
-       opt->modeMask[i] = strtol(ti->data, NULL, 8);
-       if (!opt->modeMask[i]) {
-           fprintf(stderr, "Invalid -mask value: %s\n", ti->data);
-           return 1;
-       }
-    }
-
-    /* Set which columns to be printed. */
-    if (!as->parms[P_OUTPUT].items) {
-       AddOutputColumn("host");
-       AddOutputColumn("desc");
-       AddOutputColumn("fid");
-       AddOutputColumn("dv");
-       if (opt->findVnType & FIND_ACL) {
-           AddOutputColumn("aid");
-           AddOutputColumn("arights");
-       }
-       AddOutputColumn("path");
-    } else {
-       for (ti = as->parms[P_OUTPUT].items; ti; ti = ti->next) {
-           if (AddOutputColumn(ti->data) != 0) {;
-               fprintf(stderr, "%s: Unknown -output value: %s\n", progname,
-                       ti->data);
-               return 1;
-           }
-       }
-    }
-
-    if (opt->findVnType & FIND_DIR) {
-       AddVnodeHandler(vLarge, PrintVnodeDetails, NULL);
-    }
-    if (opt->findVnType & (FIND_FILE | FIND_MOUNT | FIND_SYMLINK)) {
-       AddVnodeHandler(vSmall, PrintVnodeDetails, NULL);
-    }
-    if (opt->findVnType & FIND_ACL) {
-       AddVnodeHandler(vLarge, ScanAcl, NULL);
-    }
-
-    code = ScanPartitions(opt, partNameOrId, volumeId);
-    if (opt) {
-       free(opt);
-    }
-    return code;
-}
 
 /**
  * Determine if the current directory is a vice partition
@@ -1078,7 +753,7 @@ VolScan(struct cmd_syndesc *as, void *arock)
  */
 #ifdef AFS_NT40_ENV
 #include <direct.h>
-struct DiskPartition64 *
+static struct DiskPartition64 *
 FindCurrentPartition(void)
 {
     int dr = _getdrive();
@@ -1096,7 +771,7 @@ FindCurrentPartition(void)
     return dp;
 }
 #else
-struct DiskPartition64 *
+static struct DiskPartition64 *
 FindCurrentPartition(void)
 {
     char partName[1024];
@@ -1131,7 +806,7 @@ FindCurrentPartition(void)
  *
  * @return none
  */
-void
+static void
 HandleAllPart(struct VolInfoOpt *opt)
 {
     struct DiskPartition64 *partP;
@@ -1158,7 +833,7 @@ HandleAllPart(struct VolInfoOpt *opt)
  *
  * @return none
  */
-void
+static void
 HandlePart(struct VolInfoOpt *opt, struct DiskPartition64 *partP)
 {
     afs_int64 nvols = 0;
@@ -1204,7 +879,7 @@ HandlePart(struct VolInfoOpt *opt, struct DiskPartition64 *partP)
  *
  * @return none
  */
-void
+static void
 HandleSpecialFile(struct VolInfoOpt *opt, const char *name, struct DiskPartition64 *dp,
                  struct VolumeHeader *header, Inode inode,
                  afs_sfsize_t * psize)
@@ -1267,7 +942,7 @@ HandleSpecialFile(struct VolInfoOpt *opt, const char *name, struct DiskPartition
  *
  * @return none
  */
-void
+static void
 HandleHeaderFiles(struct VolInfoOpt *opt, struct DiskPartition64 *dp, FD_t header_fd,
                  struct VolumeHeader *header)
 {
@@ -1343,7 +1018,7 @@ IsScannable(struct VolInfoOpt *opt, Volume * vp)
  *
  * @return none
  */
-void
+static void
 HandleVolume(struct VolInfoOpt *opt, struct DiskPartition64 *dp, char *name)
 {
     struct VolumeHeader header;
@@ -1430,131 +1105,6 @@ HandleVolume(struct VolInfoOpt *opt, struct DiskPartition64 *dp, char *name)
 }
 
 /**
- * Declare volinfo command line syntax
- *
- * @returns none
- */
-static void
-VolInfoSyntax(void)
-{
-    struct cmd_syndesc *ts;
-
-    ts = cmd_CreateSyntax(NULL, VolInfo, NULL,
-                         "Dump volume's internal state");
-    cmd_AddParmAtOffset(ts, P_CHECKOUT, "-checkout", CMD_FLAG, CMD_OPTIONAL,
-                       "Checkout volumes from running fileserver");
-    cmd_AddParmAtOffset(ts, P_VNODE, "-vnode", CMD_FLAG, CMD_OPTIONAL,
-                       "Dump vnode info");
-    cmd_AddParmAtOffset(ts, P_DATE, "-date", CMD_FLAG, CMD_OPTIONAL,
-                       "Also dump vnode's mod date");
-    cmd_AddParmAtOffset(ts, P_INODE, "-inode", CMD_FLAG, CMD_OPTIONAL,
-                       "Also dump vnode's inode number");
-    cmd_AddParmAtOffset(ts, P_ITIME, "-itime", CMD_FLAG, CMD_OPTIONAL,
-                       "Dump special inode's mod times");
-    cmd_AddParmAtOffset(ts, P_PART, "-part", CMD_LIST, CMD_OPTIONAL,
-                       "AFS partition name or id (default current partition)");
-    cmd_AddParmAtOffset(ts, P_VOLUMEID, "-volumeid", CMD_LIST, CMD_OPTIONAL,
-                       "Volume id");
-    cmd_AddParmAtOffset(ts, P_HEADER, "-header", CMD_FLAG, CMD_OPTIONAL,
-                       "Dump volume's header info");
-    cmd_AddParmAtOffset(ts, P_SIZEONLY, "-sizeonly", CMD_FLAG, CMD_OPTIONAL,
-                       "Dump volume's size");
-    cmd_AddParmAtOffset(ts, P_FIXHEADER, "-fixheader", CMD_FLAG,
-                       CMD_OPTIONAL, "Try to fix header");
-    cmd_AddParmAtOffset(ts, P_SAVEINODES, "-saveinodes", CMD_FLAG,
-                       CMD_OPTIONAL, "Try to save all inodes");
-    cmd_AddParmAtOffset(ts, P_ORPHANED, "-orphaned", CMD_FLAG, CMD_OPTIONAL,
-                       "List all dir/files without a parent");
-#if defined(AFS_NAMEI_ENV)
-    cmd_AddParmAtOffset(ts, P_FILENAMES, "-filenames", CMD_FLAG,
-                       CMD_OPTIONAL, "Also dump vnode's namei filename");
-#endif
-
-    /* For compatibility with older versions. */
-    cmd_AddParmAlias(ts, P_SIZEONLY, "-sizeOnly");
-}
-
-/**
- * Declare volscan command line syntax
- *
- * @returns none
- */
-static void
-VolScanSyntax(void)
-{
-    struct cmd_syndesc *ts;
-
-    ts = cmd_CreateSyntax(NULL, VolScan, NULL,
-                         "Print volume vnode information");
-
-    cmd_AddParmAtOffset(ts, P_CHECKOUT, "-checkout", CMD_FLAG, CMD_OPTIONAL,
-                       "Checkout volumes from running fileserver");
-    cmd_AddParmAtOffset(ts, P_PART, "-partition", CMD_SINGLE, CMD_OPTIONAL,
-                       "AFS partition name or id (default current partition)");
-    cmd_AddParmAtOffset(ts, P_VOLUMEID, "-volumeid", CMD_SINGLE, CMD_OPTIONAL,
-                       "Volume id (-partition required)");
-    cmd_AddParmAtOffset(ts, P_TYPE, "-type", CMD_LIST, CMD_OPTIONAL,
-                       "Volume types: rw, ro, bk");
-    cmd_AddParmAtOffset(ts, P_FIND, "-find", CMD_LIST, CMD_OPTIONAL,
-                       "Objects to find: file, dir, mount, symlink, acl");
-    cmd_AddParmAtOffset(ts, P_MASK, "-mask", CMD_LIST, (CMD_OPTIONAL | CMD_HIDE),
-                        "Unix mode mask (example: 06000)");
-    cmd_AddParmAtOffset(ts, P_OUTPUT, "-output", CMD_LIST, CMD_OPTIONAL,
-                       ColumnNames);
-    cmd_AddParmAtOffset(ts, P_DELIM, "-delim", CMD_SINGLE, CMD_OPTIONAL,
-                       "Output field delimiter");
-    cmd_AddParmAtOffset(ts, P_NOHEADING, "-noheading", CMD_FLAG, CMD_OPTIONAL,
-                       "Do not print the heading line");
-    cmd_AddParmAtOffset(ts, P_NOMAGIC, "-ignore-magic", CMD_FLAG, CMD_OPTIONAL,
-                       "Skip directory vnode magic checks when looking up paths.");
-}
-
-/**
- * volinfo/volscan program entry
- */
-int
-main(int argc, char **argv)
-{
-    afs_int32 code;
-    char *base;
-
-    opr_queue_Init(&VnodeScanLists[vLarge]);
-    opr_queue_Init(&VnodeScanLists[vSmall]);
-
-    base = strrchr(argv[0], '/');
-#ifdef AFS_NT40_ENV
-    if (!base) {
-       base = strrchr(argv[0], '\\');
-    }
-#endif /* AFS_NT40_ENV */
-    if (!base) {
-       base = argv[0];
-    }
-#ifdef AFS_NT40_ENV
-    if ((base[0] == '/' || base[0] == '\\') && base[1] != '\0') {
-#else /* AFS_NT40_ENV */
-    if (base[0] == '/' && base[1] != '\0') {
-#endif /* AFS_NT40_ENV */
-       base++;
-    }
-    progname = base;
-
-#ifdef AFS_NT40_ENV
-    if (stricmp(progname, "volscan") == 0
-       || stricmp(progname, "volscan.exe") == 0) {
-#else /* AFS_NT40_ENV */
-    if (strcmp(progname, "volscan") == 0) {
-#endif /* AFS_NT40_ENV */
-       VolScanSyntax();
-    } else {
-       VolInfoSyntax();
-    }
-
-    code = cmd_Dispatch(argc, argv);
-    return code;
-}
-
-/**
  * Return a display string for the volume type.
  *
  * @param[in]  type  volume type
@@ -1592,7 +1142,7 @@ volumeTypeShortString(int type)
  *
  * @return none
  */
-void
+static void
 PrintHeader(Volume * vp)
 {
     printf("Volume header for volume %" AFS_VOLID_FMT " (%s)\n", afs_printable_VolumeId_lu(V_id(vp)), V_name(vp));
@@ -1682,8 +1232,8 @@ GetFileInfo(FD_t fd, afs_sfsize_t * size, char **ctime, char **mtime,
  *
  * @return none
  */
-static void
-SaveInode(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
+void
+volinfo_SaveInode(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
 {
     IHandle_t *ih;
     FdHandle_t *fdP;
@@ -1766,7 +1316,7 @@ SaveInode(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
  *   @retval 0   success
  *   @retval -1  failure
  */
-int
+static int
 GetDirVnode(struct VolInfoOpt *opt, Volume * vp, VnodeId parent, VnodeDiskObject * pvn)
 {
     afs_int32 code;
@@ -1862,7 +1412,7 @@ GetDirEntry(Volume * vp, VnodeDiskObject * pvnode, VnodeId cvnid,
  *   @retval 0 success
  *   @retval -1 error
  */
-int
+static int
 LookupPath(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
 {
 #define MAX_PATH_LEN 1023
@@ -2068,8 +1618,8 @@ ReadSymlinkTarget(struct VnodeDetails *vdp)
  *
  * @return none
  */
-static void
-PrintVnodeDetails(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
+void
+volinfo_PrintVnodeDetails(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
 {
     switch (vdp->vnode->type) {
     case vNull:
@@ -2112,8 +1662,8 @@ PrintVnodeDetails(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
  *
  * @return none
  */
-static void
-ScanAcl(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
+void
+volinfo_ScanAcl(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
 {
     int i;
     struct acl_accessList *acl;
@@ -2167,7 +1717,7 @@ ModeMaskMatch(struct VolInfoOpt *opt, unsigned int modeBits)
  *
  * @return none
  */
-void
+static void
 HandleVnodes(struct VolInfoOpt *opt, Volume * vp, VnodeClass class)
 {
     afs_int32 diskSize =
@@ -2265,7 +1815,7 @@ HandleVnodes(struct VolInfoOpt *opt, Volume * vp, VnodeClass class)
  * @return none
  */
 void
-PrintVnode(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
+volinfo_PrintVnode(struct VolInfoOpt *opt, struct VnodeDetails *vdp)
 {
 #if defined(AFS_NAMEI_ENV)
     IHandle_t *ihtmpp;
@@ -2339,7 +1889,7 @@ PrintPartitionId(Volume * vp)
  * @return none
  */
 static void
-PrintVnodeType(int type)
+volinfo_PrintVnodeType(int type)
 {
     switch (type) {
     case vNull:
@@ -2553,7 +2103,7 @@ PrintColumns(struct VolInfoOpt *opt, struct VnodeDetails *vdp, const char *desc)
            }
            break;
        case col_vntype:
-           PrintVnodeType(vdp->vnode->type);
+           volinfo_PrintVnodeType(vdp->vnode->type);
            break;
        case col_cloned:
            printf("%c", vdp->vnode->cloned ? 'y' : 'n');
diff --git a/src/vol/vol-info.h b/src/vol/vol-info.h
new file mode 100644 (file)
index 0000000..c569ce6
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifndef AFS_VOL_INFO_H
+#define AFS_VOL_INFO_H
+
+#include <afs/afsint.h>
+
+/* scanVolType flags */
+#define SCAN_RW  0x01          /**< scan read-write volumes vnodes */
+#define SCAN_RO  0x02          /**< scan read-only volume vnodes */
+#define SCAN_BK  0x04          /**< scan backup volume vnodes */
+
+/* findVnType flags */
+#define FIND_FILE       0x01   /**< find regular files */
+#define FIND_DIR        0x02   /**< find directories */
+#define FIND_MOUNT      0x04   /**< find afs mount points */
+#define FIND_SYMLINK    0x08   /**< find symlinks */
+#define FIND_ACL        0x10   /**< find access entiries */
+
+
+struct VolInfoOpt {
+    int checkout;            /**< Use FSSYNC to checkout volumes from the fileserver. */
+    int dumpInfo;            /**< Dump volume information */
+    int dumpHeader;          /**< Dump volume header files info */
+    int dumpVnodes;          /**< Dump vnode info */
+    int dumpInodeNumber;     /**< Dump inode numbers with vnodes */
+    int dumpDate;            /**< Dump vnode date (server modify date) with vnode */
+    int dumpInodeTimes;      /**< Dump some of the dates associated with inodes */
+    int dumpFileNames;       /**< Dump vnode and special file name filenames */
+    int showOrphaned;        /**< Show "orphaned" vnodes (vnodes with parent of 0) */
+    int showSizes;           /**< Show volume size summary */
+    int saveInodes;          /**< Save vnode data to files */
+    int fixHeader;           /**< Repair header files magic and version fields. */
+    char hostname[64];       /**< This hostname, for volscan output. */
+    char columnDelim[16];    /**< Column delimiter char(s) */
+    char printHeading;       /**< Print column heading */
+    int checkMagic;          /**< Check directory vnode magic when looking up paths */
+    unsigned int modeMask[64]; /**< unix mode bit pattern for searching for specific modes */
+    int scanVolType;        /**< volume types to scan; zero means do not check */
+    int findVnType;         /**< types of objects to find */
+};
+
+
+/*
+ * volscan output columns
+ */
+#define VOLSCAN_COLUMNS \
+    c(host) \
+    c(desc) \
+    c(vid) \
+    c(offset) \
+    c(vtype) \
+    c(vname) \
+    c(part) \
+    c(partid) \
+    c(fid) \
+    c(path) \
+    c(target) \
+    c(mount) \
+    c(mtype) \
+    c(mcell) \
+    c(mvol) \
+    c(aid) \
+    c(arights) \
+    c(vntype) \
+    c(cloned) \
+    c(mode) \
+    c(links) \
+    c(length) \
+    c(uniq) \
+    c(dv) \
+    c(inode) \
+    c(namei) \
+    c(modtime) \
+    c(author) \
+    c(owner) \
+    c(parent) \
+    c(magic) \
+    c(lock) \
+    c(smodtime) \
+    c(group)
+
+
+struct VnodeDetails;
+int volinfo_Init(const char *name);
+int volinfo_Options(struct VolInfoOpt **optp);
+void volinfo_AddVnodeToSizeTotals(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
+void volinfo_SaveInode(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
+void volinfo_PrintVnode(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
+void volinfo_PrintVnodeDetails(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
+void volinfo_ScanAcl(struct VolInfoOpt *opt, struct VnodeDetails *vdp);
+void volinfo_AddVnodeHandler(int vnodeClass,
+                    void (*proc) (struct VolInfoOpt * opt,
+                                  struct VnodeDetails * vdp),
+                    const char *heading);
+int volinfo_AddOutputColumn(char *name);
+int volinfo_ScanPartitions(struct VolInfoOpt *opt, char *partNameOrId, VolumeId volumeId);
+
+#endif /* AFS_VOL_INFO_H */
diff --git a/src/vol/volinfo-main.c b/src/vol/volinfo-main.c
new file mode 100644 (file)
index 0000000..55264c1
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+
+#include <roken.h>
+#include <ctype.h>
+#include <afs/cmd.h>
+#include <afs/afsint.h>
+#include <rx/rx_queue.h>
+#include "nfs.h"
+#include "ihandle.h"
+#include "lock.h"
+#include "vnode.h"  /* for vSmall, vLarge */
+#include "vol-info.h"
+
+#ifndef AFS_NT40_ENV
+#include "AFS_component_version_number.c"
+#endif
+
+static const char *progname = "volinfo";
+
+/* Command line options */
+typedef enum {
+    P_CHECKOUT,
+    P_VNODE,
+    P_DATE,
+    P_INODE,
+    P_ITIME,
+    P_PART,
+    P_VOLUMEID,
+    P_HEADER,
+    P_SIZEONLY,
+    P_FIXHEADER,
+    P_SAVEINODES,
+    P_ORPHANED,
+    P_FILENAMES,
+} volinfo_parm_t;
+
+/**
+ * Process command line options and start scanning
+ *
+ * @param[in] as     command syntax object
+ * @param[in] arock  opaque object; not used
+ *
+ * @return error code
+ */
+static int
+VolInfo(struct cmd_syndesc *as, void *arock)
+{
+    int code;
+    struct cmd_item *ti;
+    VolumeId volumeId = 0;
+    char *partNameOrId = NULL;
+    struct VolInfoOpt *opt;
+
+    code = volinfo_Init(progname);
+    if (code) {
+       return code;
+    }
+    code = volinfo_Options(&opt);
+    if (code) {
+       return code;
+    }
+
+    if (as->parms[P_CHECKOUT].items) {
+       opt->checkout = 1;
+    }
+    if (as->parms[P_VNODE].items) {
+       opt->dumpVnodes = 1;
+    }
+    if (as->parms[P_DATE].items) {
+       opt->dumpDate = 1;
+    }
+    if (as->parms[P_INODE].items) {
+       opt->dumpInodeNumber = 1;
+    }
+    if (as->parms[P_ITIME].items) {
+       opt->dumpInodeTimes = 1;
+    }
+    if ((ti = as->parms[P_PART].items)) {
+       partNameOrId = ti->data;
+    }
+    if ((ti = as->parms[P_VOLUMEID].items)) {
+       volumeId = strtoul(ti->data, NULL, 10);
+    }
+    if (as->parms[P_HEADER].items) {
+       opt->dumpHeader = 1;
+    }
+    if (as->parms[P_SIZEONLY].items) {
+       opt->showSizes = 1;
+    }
+    if (as->parms[P_FIXHEADER].items) {
+       opt->fixHeader = 1;
+    }
+    if (as->parms[P_SAVEINODES].items) {
+       opt->saveInodes = 1;
+    }
+    if (as->parms[P_ORPHANED].items) {
+       opt->showOrphaned = 1;
+    }
+    if (as->parms[P_FILENAMES].items) {
+       opt->dumpFileNames = 1;
+    }
+
+    /* -saveinodes and -sizeOnly override the default mode.
+     * For compatibility with old versions of volinfo, -orphaned
+     * and -filename options imply -vnodes */
+    if (opt->saveInodes || opt->showSizes) {
+       opt->dumpInfo = 0;
+       opt->dumpHeader = 0;
+       opt->dumpVnodes = 0;
+       opt->dumpInodeTimes = 0;
+       opt->showOrphaned = 0;
+    } else if (opt->showOrphaned) {
+       opt->dumpVnodes = 1;            /* implied */
+    } else if (opt->dumpFileNames) {
+       opt->dumpVnodes = 1;            /* implied */
+    }
+
+    if (opt->saveInodes) {
+       volinfo_AddVnodeHandler(vSmall, volinfo_SaveInode,
+                       "Saving all volume files to current directory ...\n");
+    }
+    if (opt->showSizes) {
+       volinfo_AddVnodeHandler(vLarge, volinfo_AddVnodeToSizeTotals, NULL);
+       volinfo_AddVnodeHandler(vSmall, volinfo_AddVnodeToSizeTotals, NULL);
+    }
+    if (opt->dumpVnodes) {
+       volinfo_AddVnodeHandler(vLarge, volinfo_PrintVnode, "\nLarge vnodes (directories)\n");
+       volinfo_AddVnodeHandler(vSmall, volinfo_PrintVnode,
+                       "\nSmall vnodes(files, symbolic links)\n");
+    }
+    code = volinfo_ScanPartitions(opt, partNameOrId, volumeId);
+    if (opt) {
+        free(opt);
+    }
+    return code;
+}
+
+/**
+ * volinfo program entry
+ */
+int
+main(int argc, char **argv)
+{
+    afs_int32 code;
+    struct cmd_syndesc *ts;
+
+    ts = cmd_CreateSyntax(NULL, VolInfo, NULL,
+                         "Dump volume's internal state");
+    cmd_AddParmAtOffset(ts, P_CHECKOUT, "-checkout", CMD_FLAG, CMD_OPTIONAL,
+                       "Checkout volumes from running fileserver");
+    cmd_AddParmAtOffset(ts, P_VNODE, "-vnode", CMD_FLAG, CMD_OPTIONAL,
+                       "Dump vnode info");
+    cmd_AddParmAtOffset(ts, P_DATE, "-date", CMD_FLAG, CMD_OPTIONAL,
+                       "Also dump vnode's mod date");
+    cmd_AddParmAtOffset(ts, P_INODE, "-inode", CMD_FLAG, CMD_OPTIONAL,
+                       "Also dump vnode's inode number");
+    cmd_AddParmAtOffset(ts, P_ITIME, "-itime", CMD_FLAG, CMD_OPTIONAL,
+                       "Dump special inode's mod times");
+    cmd_AddParmAtOffset(ts, P_PART, "-part", CMD_LIST, CMD_OPTIONAL,
+                       "AFS partition name or id (default current partition)");
+    cmd_AddParmAtOffset(ts, P_VOLUMEID, "-volumeid", CMD_LIST, CMD_OPTIONAL,
+                       "Volume id");
+    cmd_AddParmAtOffset(ts, P_HEADER, "-header", CMD_FLAG, CMD_OPTIONAL,
+                       "Dump volume's header info");
+    cmd_AddParmAtOffset(ts, P_SIZEONLY, "-sizeonly", CMD_FLAG, CMD_OPTIONAL,
+                       "Dump volume's size");
+    cmd_AddParmAtOffset(ts, P_FIXHEADER, "-fixheader", CMD_FLAG,
+                       CMD_OPTIONAL, "Try to fix header");
+    cmd_AddParmAtOffset(ts, P_SAVEINODES, "-saveinodes", CMD_FLAG,
+                       CMD_OPTIONAL, "Try to save all inodes");
+    cmd_AddParmAtOffset(ts, P_ORPHANED, "-orphaned", CMD_FLAG, CMD_OPTIONAL,
+                       "List all dir/files without a parent");
+#if defined(AFS_NAMEI_ENV)
+    cmd_AddParmAtOffset(ts, P_FILENAMES, "-filenames", CMD_FLAG,
+                       CMD_OPTIONAL, "Also dump vnode's namei filename");
+#endif
+
+    /* For compatibility with older versions. */
+    cmd_AddParmAlias(ts, P_SIZEONLY, "-sizeOnly");
+
+    code = cmd_Dispatch(argc, argv);
+    return code;
+}
diff --git a/src/vol/volscan-main.c b/src/vol/volscan-main.c
new file mode 100644 (file)
index 0000000..3a15c92
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+
+#include <roken.h>
+#include <ctype.h>
+#include <afs/cmd.h>
+#include <afs/afsint.h>
+#include <rx/rx_queue.h>
+#include "nfs.h"
+#include "ihandle.h"
+#include "lock.h"
+#include "vnode.h"  /* for vSmall, vLarge */
+#include "vol-info.h"
+
+#ifndef AFS_NT40_ENV
+#include "AFS_component_version_number.c"
+#endif
+
+static const char *progname = "volscan";
+
+/* All columns names as a single string. */
+#define c(x) #x " "
+static char *ColumnNames = VOLSCAN_COLUMNS;
+#undef c
+#undef VOLSCAN_COLUMNS
+
+/* Command line options */
+typedef enum {
+    P_CHECKOUT,
+    P_PART,
+    P_VOLUMEID,
+    P_TYPE,
+    P_FIND,
+    P_MASK,
+    P_OUTPUT,
+    P_DELIM,
+    P_NOHEADING,
+    P_NOMAGIC,
+} volscan_parm_t;
+
+/**
+ * Process command line options and start scanning
+ *
+ * @param[in] as     command syntax object
+ * @param[in] arock  opaque object; not used
+ *
+ * @return error code
+ *    @retval 0 success
+ *    @retvol 1 failure
+ */
+static int
+VolScan(struct cmd_syndesc *as, void *arock)
+{
+    int code;
+    struct cmd_item *ti;
+    VolumeId volumeId = 0;
+    char *partNameOrId = NULL;
+    int i;
+    struct VolInfoOpt *opt;
+
+    code = volinfo_Init(progname);
+    if (code) {
+       return code;
+    }
+    code = volinfo_Options(&opt);
+    if (code) {
+       return code;
+    }
+
+    opt->dumpInfo = 0;         /* volscan mode */
+    if (as->parms[P_CHECKOUT].items) {
+       opt->checkout = 1;
+    }
+    if ((ti = as->parms[P_PART].items)) {
+       partNameOrId = ti->data;
+    }
+    if ((ti = as->parms[P_VOLUMEID].items)) {
+       volumeId = strtoul(ti->data, NULL, 10);
+    }
+    if (as->parms[P_NOHEADING].items) {
+       opt->printHeading = 0;
+    } else {
+       opt->printHeading = 1;
+    }
+    if (as->parms[P_NOMAGIC].items) {
+        opt->checkMagic = 0;
+    }
+    if ((ti = as->parms[P_DELIM].items)) {
+       strncpy(opt->columnDelim, ti->data, 15);
+       opt->columnDelim[15] = '\0';
+    }
+
+    /* Limit types of volumes to scan. */
+    if (!as->parms[P_TYPE].items) {
+       opt->scanVolType = (SCAN_RW | SCAN_RO | SCAN_BK);
+    } else {
+       opt->scanVolType = 0;
+       for (ti = as->parms[P_TYPE].items; ti; ti = ti->next) {
+           if (strcmp(ti->data, "rw") == 0) {
+               opt->scanVolType |= SCAN_RW;
+           } else if (strcmp(ti->data, "ro") == 0) {
+               opt->scanVolType |= SCAN_RO;
+           } else if (strcmp(ti->data, "bk") == 0) {
+               opt->scanVolType |= SCAN_BK;
+           } else {
+               fprintf(stderr, "%s: Unknown -type value: %s\n", progname,
+                       ti->data);
+               return 1;
+           }
+       }
+    }
+
+    /* Limit types of vnodes to find (plus access entries) */
+    if (!as->parms[P_FIND].items) {
+       opt->findVnType = (FIND_FILE | FIND_DIR | FIND_MOUNT | FIND_SYMLINK);
+    } else {
+       opt->findVnType = 0;
+       for (ti = as->parms[P_FIND].items; ti; ti = ti->next) {
+           if (strcmp(ti->data, "file") == 0) {
+               opt->findVnType |= FIND_FILE;
+           } else if (strcmp(ti->data, "dir") == 0) {
+               opt->findVnType |= FIND_DIR;
+           } else if (strcmp(ti->data, "mount") == 0) {
+               opt->findVnType |= FIND_MOUNT;
+           } else if (strcmp(ti->data, "symlink") == 0) {
+               opt->findVnType |= FIND_SYMLINK;
+           } else if (strcmp(ti->data, "acl") == 0) {
+               opt->findVnType |= FIND_ACL;
+           } else {
+               fprintf(stderr, "%s: Unknown -find value: %s\n", progname,
+                       ti->data);
+               return 1;
+           }
+       }
+    }
+
+    /* Show vnodes matching one of the mode masks */
+    for (i = 0, ti = as->parms[P_MASK].items; ti; i++, ti = ti->next) {
+       if (i >= (sizeof(opt->modeMask) / sizeof(*opt->modeMask))) {
+           fprintf(stderr, "Too many -mask values\n");
+           return -1;
+       }
+       opt->modeMask[i] = strtol(ti->data, NULL, 8);
+       if (!opt->modeMask[i]) {
+           fprintf(stderr, "Invalid -mask value: %s\n", ti->data);
+           return 1;
+       }
+    }
+
+    /* Set which columns to be printed. */
+    if (!as->parms[P_OUTPUT].items) {
+       volinfo_AddOutputColumn("host");
+       volinfo_AddOutputColumn("desc");
+       volinfo_AddOutputColumn("fid");
+       volinfo_AddOutputColumn("dv");
+       if (opt->findVnType & FIND_ACL) {
+           volinfo_AddOutputColumn("aid");
+           volinfo_AddOutputColumn("arights");
+       }
+       volinfo_AddOutputColumn("path");
+    } else {
+       for (ti = as->parms[P_OUTPUT].items; ti; ti = ti->next) {
+           if (volinfo_AddOutputColumn(ti->data) != 0) {;
+               fprintf(stderr, "%s: Unknown -output value: %s\n", progname,
+                       ti->data);
+               return 1;
+           }
+       }
+    }
+
+    if (opt->findVnType & FIND_DIR) {
+       volinfo_AddVnodeHandler(vLarge, volinfo_PrintVnodeDetails, NULL);
+    }
+    if (opt->findVnType & (FIND_FILE | FIND_MOUNT | FIND_SYMLINK)) {
+       volinfo_AddVnodeHandler(vSmall, volinfo_PrintVnodeDetails, NULL);
+    }
+    if (opt->findVnType & FIND_ACL) {
+       volinfo_AddVnodeHandler(vLarge, volinfo_ScanAcl, NULL);
+    }
+
+    code = volinfo_ScanPartitions(opt, partNameOrId, volumeId);
+    if (opt) {
+       free(opt);
+    }
+    return code;
+}
+/**
+ * volscan program entry
+ */
+int
+main(int argc, char **argv)
+{
+    afs_int32 code;
+    struct cmd_syndesc *ts;
+
+    ts = cmd_CreateSyntax(NULL, VolScan, NULL,
+                         "Print volume vnode information");
+
+    cmd_AddParmAtOffset(ts, P_CHECKOUT, "-checkout", CMD_FLAG, CMD_OPTIONAL,
+                       "Checkout volumes from running fileserver");
+    cmd_AddParmAtOffset(ts, P_PART, "-partition", CMD_SINGLE, CMD_OPTIONAL,
+                       "AFS partition name or id (default current partition)");
+    cmd_AddParmAtOffset(ts, P_VOLUMEID, "-volumeid", CMD_SINGLE, CMD_OPTIONAL,
+                       "Volume id (-partition required)");
+    cmd_AddParmAtOffset(ts, P_TYPE, "-type", CMD_LIST, CMD_OPTIONAL,
+                       "Volume types: rw, ro, bk");
+    cmd_AddParmAtOffset(ts, P_FIND, "-find", CMD_LIST, CMD_OPTIONAL,
+                       "Objects to find: file, dir, mount, symlink, acl");
+    cmd_AddParmAtOffset(ts, P_MASK, "-mask", CMD_LIST, CMD_OPTIONAL,
+                        "Unix mode mask (example: 06000)");
+    cmd_AddParmAtOffset(ts, P_OUTPUT, "-output", CMD_LIST, CMD_OPTIONAL,
+                       ColumnNames);
+    cmd_AddParmAtOffset(ts, P_DELIM, "-delim", CMD_SINGLE, CMD_OPTIONAL,
+                       "Output field delimiter");
+    cmd_AddParmAtOffset(ts, P_NOHEADING, "-noheading", CMD_FLAG, CMD_OPTIONAL,
+                       "Do not print the heading line");
+    cmd_AddParmAtOffset(ts, P_NOMAGIC, "-ignore-magic", CMD_FLAG, CMD_OPTIONAL,
+                       "Skip directory vnode magic checks when looking up paths.");
+
+    code = cmd_Dispatch(argc, argv);
+    return code;
+}