]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
tools: move useful tools from test dir to tools dir
authorDerrick Brashear <shadow@dementix.org>
Tue, 3 Apr 2012 17:51:38 +0000 (13:51 -0400)
committerDerrick Brashear <shadow@dementix.org>
Tue, 3 Apr 2012 18:35:30 +0000 (11:35 -0700)
move the dump utilities out of tests

Change-Id: I21d0550e09fde3b1feb078bde4e9b4dc7ca3614e
Reviewed-on: http://gerrit.openafs.org/7043
Reviewed-by: Derrick Brashear <shadow@dementix.org>
Tested-by: Derrick Brashear <shadow@dementix.org>
68 files changed:
Makefile.in
configure.ac
src/tests/Makefile.in
src/tests/TEMPLATE [deleted file]
src/tests/afsdump_dirlist.c [deleted file]
src/tests/afsdump_extract.c [deleted file]
src/tests/afsdump_scan.c [deleted file]
src/tests/afsdump_xsed.c [deleted file]
src/tests/backuphdr.c [deleted file]
src/tests/directory.c [deleted file]
src/tests/dump.c [deleted file]
src/tests/dumpfmt.h [deleted file]
src/tests/dumpscan.h [deleted file]
src/tests/dumpscan_errs.et [deleted file]
src/tests/dumptool.c [deleted file]
src/tests/int64.c [deleted file]
src/tests/intNN.h [deleted file]
src/tests/internal.h [deleted file]
src/tests/parsedump.c [deleted file]
src/tests/parsetag.c [deleted file]
src/tests/parsevnode.c [deleted file]
src/tests/parsevol.c [deleted file]
src/tests/pathname.c [deleted file]
src/tests/primitive.c [deleted file]
src/tests/repair.c [deleted file]
src/tests/stagehdr.c [deleted file]
src/tests/stagehdr.h [deleted file]
src/tests/util.c [deleted file]
src/tests/xf_errs.et [deleted file]
src/tests/xf_files.c [deleted file]
src/tests/xf_printf.c [deleted file]
src/tests/xf_profile.c [deleted file]
src/tests/xf_rxcall.c [deleted file]
src/tests/xfiles.c [deleted file]
src/tests/xfiles.h [deleted file]
src/tools/Makefile.in [new file with mode: 0644]
src/tools/TEMPLATE [new file with mode: 0644]
src/tools/afsdump_dirlist.c [new file with mode: 0644]
src/tools/afsdump_extract.c [new file with mode: 0644]
src/tools/afsdump_scan.c [new file with mode: 0644]
src/tools/afsdump_xsed.c [new file with mode: 0644]
src/tools/backuphdr.c [new file with mode: 0644]
src/tools/directory.c [new file with mode: 0644]
src/tools/dump.c [new file with mode: 0644]
src/tools/dumpfmt.h [new file with mode: 0644]
src/tools/dumpscan.h [new file with mode: 0644]
src/tools/dumpscan_errs.et [new file with mode: 0644]
src/tools/dumptool.c [new file with mode: 0644]
src/tools/int64.c [new file with mode: 0644]
src/tools/intNN.h [new file with mode: 0644]
src/tools/internal.h [new file with mode: 0644]
src/tools/parsedump.c [new file with mode: 0644]
src/tools/parsetag.c [new file with mode: 0644]
src/tools/parsevnode.c [new file with mode: 0644]
src/tools/parsevol.c [new file with mode: 0644]
src/tools/pathname.c [new file with mode: 0644]
src/tools/primitive.c [new file with mode: 0644]
src/tools/repair.c [new file with mode: 0644]
src/tools/stagehdr.c [new file with mode: 0644]
src/tools/stagehdr.h [new file with mode: 0644]
src/tools/util.c [new file with mode: 0644]
src/tools/xf_errs.et [new file with mode: 0644]
src/tools/xf_files.c [new file with mode: 0644]
src/tools/xf_printf.c [new file with mode: 0644]
src/tools/xf_profile.c [new file with mode: 0644]
src/tools/xf_rxcall.c [new file with mode: 0644]
src/tools/xfiles.c [new file with mode: 0644]
src/tools/xfiles.h [new file with mode: 0644]

index 01891e142a821201c4bd3321aa0544dc138d366d..f9a7f9bcb6dc23b4e56a51d7ded93200d106dad9 100644 (file)
@@ -401,6 +401,9 @@ authtools: pam tsm41 sgistuff aklog
 platform: config cmd vol
        +${COMPILE_PART1} platform ${COMPILE_PART2}
 
+tools: config audit volser vlserver
+       +${COMPILE_PART1} tools ${COMPILE_PART2}
+
 man-pages: config
        +if test -d "doc/man-pages" ; then \
                cd doc/man-pages ${COMPILE_PART2} ; \
@@ -650,7 +653,7 @@ finale: project cmd comerr afsd butc tbutc tbudb @ENABLE_KERNEL_MODULE@ libuafs
        dviced dvolser libafscp\
        venus update xstat afsmonitor rxdebug libafsrpc rfc3961 hcrypto \
        libafsauthent shlibafsrpc shlibafsauthent libadmin man-pages \
-       platform kopenafs authtools $(DIR_roken)
+       tools platform kopenafs authtools $(DIR_roken)
        +${COMPILE_PART1} finale ${COMPILE_PART2}
 
 finale_nolibafs: project cmd comerr afsd butc tbutc tbudb libuafs audit kauth log \
@@ -658,7 +661,7 @@ finale_nolibafs: project cmd comerr afsd butc tbutc tbudb libuafs audit kauth lo
        dviced dvolser libafscp\
        venus update xstat afsmonitor rxdebug libafsrpc rfc3961 hcrypto \
        libafsauthent shlibafsrpc shlibafsauthent libadmin man-pages \
-       platform kopenafs authtools $(DIR_roken)
+       tools platform kopenafs authtools $(DIR_roken)
        +${COMPILE_PART1} finale ${COMPILE_PART2}
 
 check test: finale
@@ -749,13 +752,13 @@ clean2:
        -${COMPILE_PART1} bucoord ${COMPILE_CLEAN}
        -${COMPILE_PART1} xstat ${COMPILE_CLEAN}
        -${COMPILE_PART1} afsmonitor ${COMPILE_CLEAN}
-       -${COMPILE_PART1} tests ${COMPILE_CLEAN}
        -${COMPILE_PART1} rxdebug ${COMPILE_CLEAN}
        -${COMPILE_PART1} libafsrpc ${COMPILE_CLEAN}
        -${COMPILE_PART1} libafsauthent ${COMPILE_CLEAN}
        -${COMPILE_PART1} shlibafsrpc ${COMPILE_CLEAN}
        -${COMPILE_PART1} shlibafsauthent ${COMPILE_CLEAN}
        -${COMPILE_PART1} kopenafs ${COMPILE_CLEAN}
+       -${COMPILE_PART1} tools ${COMPILE_CLEAN}
        -${COMPILE_PART1} platform ${COMPILE_CLEAN}
        -${COMPILE_PART1} libadmin ${COMPILE_CLEAN}
        -${COMPILE_PART1} libadmin/adminutil ${COMPILE_CLEAN}
@@ -904,6 +907,7 @@ distclean: clean
        src/tests/Makefile \
        src/tests/run-tests \
        src/tests/auth/Makefile \
+       src/tools/Makefile \
        src/tsalvaged/Makefile \
        src/tsm41/Makefile \
        src/tvolser/Makefile \
index 41789541e69b997de66f32fb382d882a00ce56d1..af9b1818722dd5c416ff5be72f8e736093232f55 100644 (file)
@@ -227,6 +227,7 @@ src/sys/Makefile \
 src/tbutc/Makefile \
 src/tests/Makefile \
 src/tests/run-tests \
+src/tools/Makefile \
 src/tsalvaged/Makefile \
 src/tsm41/Makefile \
 src/tvolser/Makefile \
index b0150a934f623c6b4dd44407567b456336fd952d..c9a82f5342ddf13c96e3d23e1b4008292fe903f4 100644 (file)
@@ -2,97 +2,11 @@ srcdir                = @srcdir@
 include @TOP_OBJDIR@/src/config/Makefile.config
 include @TOP_OBJDIR@/src/config/Makefile.lwp
 
-
 SHELL          = /bin/sh
 
-INCDIRS=-I${TOP_OBJDIR}/src/config -I${TOP_INCDIR}/afs -I${TOP_INCDIR}
-INCLIBS=-L${SRCDIR}/lib/afs -L${TOP_LIBDIR}
-
-LIBS=\
-       libdumpscan.a \
-       libxfiles.a \
-       ${TOP_LIBDIR}/libauth.a \
-       ${TOP_LIBDIR}/libaudit.a \
-       ${TOP_LIBDIR}/libvolser.a \
-       ${TOP_LIBDIR}/libvldb.a \
-       ${TOP_LIBDIR}/libubik.a \
-       ${TOP_LIBDIR}/librxkad.a \
-       ${TOP_LIBDIR}/libsys.a \
-       ${TOP_LIBDIR}/librx.a \
-       ${TOP_LIBDIR}/liblwp.a \
-       ${TOP_LIBDIR}/util.a \
-       ${TOP_LIBDIR}/libafscom_err.a \
-       $(LIB_roken) \
-       ${XLIBS}
-
-OBJS_afsdump_scan    = afsdump_scan.o repair.o
-OBJS_afsdump_xsed    = afsdump_xsed.o repair.o
-OBJS_libxfiles.a     = xfiles.o xf_errs.o xf_printf.o int64.o \
-                       xf_files.o xf_rxcall.o xf_profile.o
-OBJS_libdumpscan.a   = primitive.o util.o dumpscan_errs.o parsetag.o \
-                       parsedump.o parsevol.o parsevnode.o dump.o \
-                       directory.o pathname.o backuphdr.o stagehdr.o
-
-TARGETS = libxfiles.a libdumpscan.a \
-          afsdump_scan afsdump_dirlist afsdump_extract dumptool
-
-all: run-tests OpenAFS/Dirpath.pm libxfiles.a libdumpscan.a $(TEST_PROGRAMS)\
-       afsdump_scan afsdump_dirlist afsdump_extract dumptool OpenAFS/Dirpath.sh
+all: run-tests OpenAFS/Dirpath.pm $(TEST_PROGRAMS) OpenAFS/Dirpath.sh
        @chmod +x run-tests
 
-generated: xf_errs.c xf_errs.h dumpscan_errs.c dumpscan_errs.h
-
-afsdump_scan: libxfiles.a libdumpscan.a $(OBJS_afsdump_scan)
-       $(AFS_LDRULE) $(OBJS_afsdump_scan) $(LIBS)
-
-
-afsdump_xsed: libxfiles.a libdumpscan.a $(OBJS_afsdump_xsed)
-       $(AFS_LDRULE) $(OBJS_afsdump_xsed) $(LIBS)
-
-afsdump_dirlist: libxfiles.a libdumpscan.a afsdump_dirlist.o
-       $(AFS_LDRULE) afsdump_dirlist.o $(LIBS)
-
-afsdump_extract: libxfiles.a libdumpscan.a afsdump_extract.o
-       $(AFS_LDRULE) afsdump_extract.o $(LIBS)
-
-null-search: libxfiles.a libdumpscan.a null-search.c
-       $(AFS_LDRULE) null-search.c $(LIBS)
-
-dumptool: dumptool.c
-       $(AFS_LDRULE) dumptool.c
-
-libxfiles.a: $(OBJS_libxfiles.a)
-       -rm -f libxfiles.a
-       $(AR) r libxfiles.a $(OBJS_libxfiles.a)
-       $(RANLIB) libxfiles.a
-
-libdumpscan.a: $(OBJS_libdumpscan.a)
-       -rm -f libdumpscan.a
-       $(AR) r libdumpscan.a $(OBJS_libdumpscan.a)
-       $(RANLIB) libdumpscan.a
-
-xf_errs.c xf_errs.h: xf_errs.et
-       $(COMPILE_ET) xf_errs.et
-
-dumpscan_errs.c dumpscan_errs.h: dumpscan_errs.et
-       $(COMPILE_ET) dumpscan_errs.et
-
-util.o xfiles.o xf_files.o: xf_errs.h
-backuphdr.o directory.o parsedump.o parsetag.o: dumpscan_errs.h
-parsevnode.o parsevol.o pathname.o stagehdr.o:  dumpscan_errs.h
-util.o:                                         dumpscan_errs.h
-
-# repair addresses the same storage as two different types of structs at the
-# same time.
-CFLAGS_repair.o = @CFLAGS_NOSTRICT@
-repair.o: repair.c dumpscan_errs.h
-
-${TOP_LIBDIR}/libxfiles.a: libxfiles.a
-       ${INSTALL_DATA} $? $@
-
-${TOP_LIBDIR}/libdumpscan.a: libdumpscan.a
-       ${INSTALL_DATA} $? $@
-
 SYS_LIBS       = ${TOP_LIBDIR}/libsys.a ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/util.a
 
 AUTH_LIBS      = ${TOP_LIBDIR}/libauth.a ${SYS_LIBS}
@@ -345,8 +259,8 @@ install:
 uninstall:
 
 clean:
-       -rm -f xf_errs.c xf_errs.h dumpscan_errs.c dumpscan_errs.h *.o \
-       $(TARGETS) run-tests $(TEST_PROGRAMS) OpenAFS/Dirpath.pm OpenAFS/Dirpath.sh
+       -rm -f *.o  run-tests $(TEST_PROGRAMS) OpenAFS/Dirpath.pm \
+       OpenAFS/Dirpath.sh
 
 include ../config/Makefile.version
 
diff --git a/src/tests/TEMPLATE b/src/tests/TEMPLATE
deleted file mode 100644 (file)
index 6448750..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- * 
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
diff --git a/src/tests/afsdump_dirlist.c b/src/tests/afsdump_dirlist.c
deleted file mode 100644 (file)
index 71cde8e..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* afsdump_dirlist.c - List an AFS directory file */
-
-#include <afsconfig.h>
-
-#include <sys/fcntl.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <afs/stds.h>
-#include <afs/com_err.h>
-#include <afs/cellconfig.h>
-#include <afs/vlserver.h>
-#include <afs/volser.h>
-#include <rx/rxkad.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "xf_errs.h"
-
-extern int optind;
-extern char *optarg;
-
-char *argv0;
-static char *input_path;
-static int quiet, verbose, error_count;
-
-static dump_parser dp;
-
-
-/* Print a usage message and exit */
-static void
-usage(int status, char *msg)
-{
-    if (msg)
-       fprintf(stderr, "%s: %s\n", argv0, msg);
-    fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
-    fprintf(stderr, "  -h     Print this help message\n");
-    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
-    fprintf(stderr, "  -v     Verbose mode\n");
-    exit(status);
-}
-
-
-/* Parse the command-line options */
-static void
-parse_options(int argc, char **argv)
-{
-    int c;
-
-    /* Set the program name */
-    if ((argv0 = strrchr(argv[0], '/')) != NULL)
-       argv0++;
-    else
-       argv0 = argv[0];
-
-    /* Initialize options */
-    input_path = 0;
-    quiet = verbose = 0;
-
-    /* Initialize other stuff */
-    error_count = 0;
-
-    /* Parse the options */
-    while ((c = getopt(argc, argv, "hqv")) != EOF) {
-       switch (c) {
-       case 'q':
-           quiet = 1;
-           continue;
-       case 'v':
-           verbose = 1;
-           continue;
-       case 'h':
-           usage(0, 0);
-       default:
-           usage(1, "Invalid option!");
-       }
-    }
-
-    if (quiet && verbose)
-       usage(1, "Can't specify both -q and -v");
-
-    /* Parse non-option arguments */
-    if (argc - optind > 1)
-       usage(1, "Too many arguments!");
-    input_path = (argc == optind) ? "-" : argv[optind];
-}
-
-
-/* A callback to count and print errors */
-static afs_uint32
-my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
-{
-    va_list alist;
-
-    error_count++;
-    if (!quiet) {
-       va_start(alist, msg);
-       afs_com_err_va(argv0, code, msg, alist);
-       va_end(alist);
-    }
-    return 0;
-}
-
-
-/* Main program */
-int
-main(int argc, char **argv)
-{
-    XFILE input_file;
-    afs_uint32 r;
-
-    parse_options(argc, argv);
-    initialize_acfg_error_table();
-    initialize_AVds_error_table();
-    initialize_rxk_error_table();
-    initialize_u_error_table();
-    initialize_vl_error_table();
-    initialize_vols_error_table();
-    initialize_xFil_error_table();
-    r = xfopen(&input_file, O_RDONLY, input_path);
-    if (r) {
-       afs_com_err(argv0, r, "opening %s", input_path);
-       exit(2);
-    }
-
-    memset(&dp, 0, sizeof(dp));
-    dp.cb_error = my_error_cb;
-    dp.print_flags = DSPRINT_DIR;
-    if (input_file.is_seekable)
-       dp.flags |= DSFLAG_SEEK;
-
-    r = ParseDirectory(&input_file, &dp, 0, 1);
-    xfclose(&input_file);
-
-    if (verbose && error_count)
-       fprintf(stderr, "*** %d errors\n", error_count);
-    if (r && !quiet)
-       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
-    return 0;
-}
diff --git a/src/tests/afsdump_extract.c b/src/tests/afsdump_extract.c
deleted file mode 100644 (file)
index 88b6a22..0000000
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* afsdump_extract.c - Extract files from an AFS dump */
-
-#include <afsconfig.h>
-#include <afs/param.h>
-
-#include <sys/fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <afs/com_err.h>
-#include <afs/cellconfig.h>
-#include <afs/vlserver.h>
-#include <afs/volser.h>
-#include <rx/rxkad.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "xf_errs.h"
-
-#define COPYBUFSIZE (256*1024)
-
-extern int optind;
-extern char *optarg;
-
-char *argv0;
-static char **file_names;
-static int *file_vnums, name_count, vnum_count;
-
-static char *input_path, *target;
-static int quiet, verbose, error_count, dirs_done, extract_all;
-static int nomode, use_realpath, use_vnum;
-static int do_acls, do_headers;
-
-static path_hashinfo phi;
-static dump_parser dp;
-
-/* Print a usage message and exit */
-static void
-usage(int status, char *msg)
-{
-    if (msg)
-       fprintf(stderr, "%s: %s\n", argv0, msg);
-    fprintf(stderr, "Usage: %s [options] dumpfile [dest [files...]]\n",
-           argv0);
-    fprintf(stderr, "  -A     Save ACL's\n");
-    fprintf(stderr, "  -H     Save headers\n");
-    fprintf(stderr, "  -h     Print this help message\n");
-    fprintf(stderr, "  -i     Use vnode numbers\n");
-    fprintf(stderr, "  -n     Don't actually create files\n");
-    fprintf(stderr, "  -p     Use real pathnames internally\n");
-    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
-    fprintf(stderr, "  -v     Verbose mode\n");
-    fprintf(stderr, "The destination directory defaults to .\n");
-    fprintf(stderr, "Files may be vnode numbers or volume-relative paths;\n");
-    fprintf(stderr, "If vnode numbers are used, files will be extracted\n");
-    fprintf(stderr,
-           "a name generated from the vnode number and uniqifier.\n");
-    fprintf(stderr, "If paths are used, -p is implied and files will be\n");
-    fprintf(stderr, "into correctly-named files.\n");
-    exit(status);
-}
-
-
-/* Parse the command-line options */
-static void
-parse_options(int argc, char **argv)
-{
-    int c, i, i_name, i_vnum;
-
-    /* Set the program name */
-    if ((argv0 = strrchr(argv[0], '/')))
-       argv0++;
-    else
-       argv0 = argv[0];
-
-    /* Initialize options */
-    input_path = 0;
-    quiet = verbose = nomode = 0;
-    use_realpath = use_vnum = do_acls = do_headers = extract_all = 0;
-
-    /* Initialize other stuff */
-    error_count = 0;
-
-    /* Parse the options */
-    while ((c = getopt(argc, argv, "AHhinpqv")) != EOF) {
-       switch (c) {
-       case 'A':
-           do_acls = 1;
-           continue;
-       case 'H':
-           do_headers = 1;
-           continue;
-       case 'i':
-           use_vnum = 1;
-           continue;
-       case 'n':
-           nomode = 1;
-           continue;
-       case 'p':
-           use_realpath = 1;
-           continue;
-       case 'q':
-           quiet = 1;
-           continue;
-       case 'v':
-           verbose = 1;
-           continue;
-       case 'h':
-           usage(0, 0);
-       default:
-           usage(1, "Invalid option!");
-       }
-    }
-
-    if (quiet && verbose)
-       usage(1, "Can't specify both -q and -v");
-
-    /* Parse non-option arguments */
-    if (argc - optind < 1)
-       usage(1, "Dumpfile name required!");
-    input_path = argv[optind];
-
-    if (argc - optind < 2)
-       target = ".";
-    target = argv[optind + 1];
-
-    vnum_count = name_count = 0;
-    if (argc - optind < 3)
-       extract_all = 1;
-    else {
-       argv += optind + 2;
-       argc -= optind + 2;
-       for (i = 0; i < argc; i++) {
-           if (argv[i][0] == '/')
-               name_count++;
-           else
-               vnum_count++;
-       }
-       file_names = (char **)malloc(name_count + sizeof(char *));
-       file_vnums = (afs_int32 *) malloc(vnum_count + sizeof(afs_uint32));
-       if (name_count)
-           use_realpath = 1;
-
-       i_name = i_vnum = 0;
-       for (i = 0; i < argc; i++) {
-           if (argv[i][0] == '/')
-               file_names[i_name++] = argv[i];
-           else
-               file_vnums[i_vnum++] = strtol(argv[i], 0, 0);
-       }
-    }
-}
-
-
-static int
-mkdirp(char *path)
-{
-    char *x = path, slash;
-    struct stat statbuf;
-
-    for (;;) {
-       while (*x && *x != '/')
-           x++;
-       slash = *x;
-       *x = 0;
-
-       if (stat(path, &statbuf)) {
-           if (errno == ENOENT) {
-               if (verbose)
-                   printf("> mkdir %s\n", path);
-               if (!mkdir(path, 0755))
-                   errno = 0;
-           }
-       }
-       if (!slash)
-           break;
-       *x++ = '/';
-       if (errno)
-           return errno;
-    }
-
-    return 0;
-}
-
-
-static char *
-modestr(int mode)
-{
-    static char str[10];
-    int i;
-
-    strcpy(str, "rwxrwxrwx");
-    for (i = 0; i < 9; i++) {
-       if (!(mode & (1 << i)))
-           str[8 - i] = '-';
-    }
-    if (mode & 01000)
-       str[8] = (str[8] == '-') ? 'T' : 't';
-    if (mode & 02000)
-       str[5] = (str[5] == '-') ? 'S' : 's';
-    if (mode & 04000)
-       str[2] = (str[2] == '-') ? 'S' : 's';
-    return str;
-}
-
-
-static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-static char *
-datestr(time_t date)
-{
-    static char str[13];
-    time_t clock = time(0);
-    struct tm *now, *then;
-    int diff;
-
-    now = localtime(&clock);
-    then = localtime(&date);
-
-    diff = now->tm_mon - then->tm_mon;
-    if (then->tm_year == now->tm_year - 1)
-       diff += 12;
-    if (then->tm_year == now->tm_year + 1)
-       diff -= 12;
-
-    if (diff < 5 || diff > 5)
-       sprintf(str, "%3s %2d  %4d", month[then->tm_mon], then->tm_mday,
-               then->tm_year + 1900);
-    else
-       sprintf(str, "%3s %2d %2d:%2d", month[then->tm_mon], then->tm_mday,
-               then->tm_hour, then->tm_min);
-    return str;
-}
-
-
-/* Should we use this vnode?
- * Return 0 if no, non-0 if yes
- */
-static int
-usevnode(XFILE * X, afs_uint32 vnum, char *vnodepath)
-{
-    int vl, vpl, r, i;
-
-    /* Special case */
-    if (extract_all || !strcmp(vnodepath, "/"))
-       return 1;
-
-    for (i = 0; i < vnum_count; i++)
-       if (vnum == file_vnums[i])
-           return 2;
-
-    vl = strlen(vnodepath);
-/*fprintf(stderr, "++ checking %s\n", vnodepath);*/
-    for (i = 0; i < name_count; i++) {
-       vpl = strlen(file_names[i]);
-/*  fprintf(stderr, "   %s\n", file_names[i]);*/
-
-       if (vl > vpl) {
-           r = !strncmp(file_names[i], vnodepath, vpl)
-               && vnodepath[vpl] == '/';
-       } else if (vl < vpl) {
-           r = !strncmp(file_names[i], vnodepath, vl)
-               && file_names[i][vl] == '/';
-       } else {
-           r = !strcmp(file_names[i], vnodepath);
-       }
-       if (r)
-           return 1;
-    }
-    return 0;
-}
-
-
-static int
-copyfile(XFILE * in, XFILE * out, int size)
-{
-    static char buf[COPYBUFSIZE];
-    int nr, r;
-
-    while (size) {
-       nr = (size > COPYBUFSIZE) ? COPYBUFSIZE : size;
-       if ((r = xfread(in, buf, nr)))
-           return r;
-       if ((r = xfwrite(out, buf, nr)))
-           return r;
-       size -= nr;
-    }
-    return 0;
-}
-
-
-/* A callback to count and print errors */
-static afs_uint32
-my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
-{
-    va_list alist;
-
-    error_count++;
-    if (!quiet) {
-       va_start(alist, msg);
-       afs_com_err_va(argv0, code, msg, alist);
-       va_end(alist);
-    }
-    return 0;
-}
-
-
-static afs_uint32
-dumphdr_cb(afs_dump_header * hdr, XFILE * X, void *refcon)
-{
-    return 0;
-}
-
-
-static afs_uint32
-volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
-{
-    return 0;
-}
-
-
-static afs_uint32
-directory_cb(afs_vnode * v, XFILE * X, void *refcon)
-{
-    char *vnodepath;
-    int r, use = 0;
-
-    /* Should we even use this? */
-    if (!use_vnum) {
-       if ((r = Path_Build(X, &phi, v->vnode, &vnodepath, !use_realpath)))
-           return r;
-       if (!(use = usevnode(X, v->vnode, vnodepath))) {
-           free(vnodepath);
-           return 0;
-       }
-    }
-
-    /* Print it out */
-    if (verbose) {
-       if (use_vnum)
-           printf("d%s %3d %-11d %11d %s #%d:%d\n", modestr(v->mode),
-                  v->nlinks, v->owner, v->size, datestr(v->server_date),
-                  v->vnode, v->vuniq);
-       else
-           printf("d%s %3d %-11d %11d %s %s\n", modestr(v->mode), v->nlinks,
-                  v->owner, v->size, datestr(v->server_date), vnodepath);
-    } else if (!quiet && !use_vnum)
-       printf("%s\n", vnodepath);
-
-    /* Make the directory, if needed */
-    if (!nomode && !use_vnum && use != 2) {
-       if (strcmp(vnodepath, "/")
-           && (r = mkdirp(vnodepath + 1))) {
-           free(vnodepath);
-           return r;
-       }
-       if (do_acls) {
-           /* XXX do ACL's later */
-       }
-    }
-    if (!use_vnum)
-       free(vnodepath);
-    return 0;
-}
-
-
-static afs_uint32
-file_cb(afs_vnode * v, XFILE * X, void *refcon)
-{
-    char *vnodepath, vnpx[30];
-    u_int64 where;
-    XFILE OX;
-    int r, use = 0;
-
-    if (!dirs_done) {
-       dirs_done = 1;
-       if (verbose)
-           printf("* Extracting files...\n");
-    }
-
-    /* Should we even use this? */
-    if (!use_vnum) {
-       if ((r = Path_Build(X, &phi, v->vnode, &vnodepath, !use_realpath)))
-           return r;
-       if (!(use = usevnode(X, v->vnode, vnodepath))) {
-           free(vnodepath);
-           return 0;
-       }
-       if (use == 2) {
-           free(vnodepath);
-           sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
-           vnodepath = vnpx;
-       }
-    } else {
-       sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
-       vnodepath = vnpx;
-    }
-
-    /* Print it out */
-    if (verbose) {
-       printf("-%s %3d %-11d %11d %s %s\n", modestr(v->mode), v->nlinks,
-              v->owner, v->size, datestr(v->server_date), vnodepath);
-    } else if (!quiet) {
-       printf("%s\n", vnodepath);
-    }
-
-    if (!nomode) {
-       if ((r = xftell(X, &where))
-           || (r = xfseek(X, &v->d_offset))
-           || (r =
-               xfopen_path(&OX, O_RDWR | O_CREAT | O_TRUNC, vnodepath + 1,
-                           0644))) {
-           if (!use_vnum)
-               free(vnodepath);
-           return r;
-       }
-       r = copyfile(X, &OX, v->size);
-       xfclose(&OX);
-       xfseek(X, &where);
-    } else
-       r = 0;
-
-    if (!use_vnum && use != 2)
-       free(vnodepath);
-    return r;
-}
-
-
-static afs_uint32
-symlink_cb(afs_vnode * v, XFILE * X, void *refcon)
-{
-    char *vnodepath, *linktarget, vnpx[30];
-    u_int64 where;
-    int r, use = 0;
-
-    if (!dirs_done) {
-       dirs_done = 1;
-       if (verbose)
-           printf("* Extracting files...\n");
-    }
-
-    /* Should we even use this? */
-    if (!use_vnum) {
-       if ((r = Path_Build(X, &phi, v->vnode, &vnodepath, !use_realpath)))
-           return r;
-       if (!(use = usevnode(X, v->vnode, vnodepath))) {
-           free(vnodepath);
-           return 0;
-       }
-       if (use == 2) {
-           free(vnodepath);
-           sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
-           vnodepath = vnpx;
-       }
-    } else {
-       sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
-       vnodepath = vnpx;
-    }
-
-    if (!(linktarget = (char *)malloc(v->size + 1))) {
-       if (!use_vnum && use != 2)
-           free(vnodepath);
-       return DSERR_MEM;
-    }
-    if ((r = xftell(X, &where))
-       || (r = xfseek(X, &v->d_offset))
-       || (r = xfread(X, linktarget, v->size))) {
-       if (!use_vnum && use != 2)
-           free(vnodepath);
-       free(linktarget);
-       return r;
-    }
-    xfseek(X, &where);
-    linktarget[v->size] = 0;
-
-    /* Print it out */
-    if (verbose)
-       printf("l%s %3d %-11d %11d %s %s -> %s\n", modestr(v->mode),
-              v->nlinks, v->owner, v->size, datestr(v->server_date),
-              vnodepath, linktarget);
-    else if (!quiet)
-       printf("%s\n", vnodepath);
-
-    r = 0;
-    if (!nomode) {
-       if (symlink(linktarget, vnodepath + 1))
-           r = errno;
-    }
-
-    free(linktarget);
-    if (!use_vnum && use != 2)
-       free(vnodepath);
-    return r;
-}
-
-
-static afs_uint32
-lose_cb(afs_vnode * v, XFILE * F, void *refcon)
-{
-    if (!dirs_done) {
-       dirs_done = 1;
-       if (verbose)
-           printf("* Extracting files...\n");
-    }
-
-    return 0;
-}
-
-
-/* Main program */
-int
-main(int argc, char **argv)
-{
-    XFILE input_file;
-    afs_uint32 r;
-
-    parse_options(argc, argv);
-    initialize_acfg_error_table();
-    initialize_AVds_error_table();
-    initialize_rxk_error_table();
-    initialize_u_error_table();
-    initialize_vl_error_table();
-    initialize_vols_error_table();
-    initialize_xFil_error_table();
-    r = xfopen(&input_file, O_RDONLY, input_path);
-    if (r) {
-       afs_com_err(argv0, r, "opening %s", input_path);
-       exit(2);
-    }
-
-    memset(&dp, 0, sizeof(dp));
-    dp.cb_error = my_error_cb;
-    if (input_file.is_seekable)
-       dp.flags |= DSFLAG_SEEK;
-    dirs_done = 0;
-
-    if (!use_vnum) {
-       u_int64 where;
-
-       memset(&phi, 0, sizeof(phi));
-       phi.p = &dp;
-
-       if (verbose)
-           printf("* Building pathname info...\n");
-       if ((r = xftell(&input_file, &where))
-           || (r = Path_PreScan(&input_file, &phi, 1))
-           || (r = xfseek(&input_file, &where))) {
-           afs_com_err(argv0, r, "- path initialization failed");
-           xfclose(&input_file);
-           exit(1);
-       }
-    }
-
-    dp.cb_vnode_dir = directory_cb;
-    dp.cb_vnode_file = file_cb;
-    dp.cb_vnode_link = symlink_cb;
-    dp.cb_vnode_empty = lose_cb;
-    dp.cb_vnode_wierd = lose_cb;
-    if (do_headers) {
-       dp.cb_dumphdr = dumphdr_cb;
-       dp.cb_volhdr = volhdr_cb;
-    }
-
-    if (!nomode) {
-       mkdir(target, 0755);
-       if (chdir(target)) {
-           fprintf(stderr, "chdir %s failed: %s\n", target, strerror(errno));
-           exit(1);
-       }
-    }
-    r = ParseDumpFile(&input_file, &dp);
-
-    if (verbose && error_count)
-       fprintf(stderr, "*** %d errors\n", error_count);
-    if (r && !quiet)
-       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
-    exit(0);
-}
diff --git a/src/tests/afsdump_scan.c b/src/tests/afsdump_scan.c
deleted file mode 100644 (file)
index 8bc7f10..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* afsdump_scan.c - General-purpose dump scanner */
-
-#include <afsconfig.h>
-#include <afs/param.h>
-
-#include <sys/fcntl.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <afs/com_err.h>
-#include <afs/pterror.h>
-#include <afs/vlserver.h>
-#include <afs/cellconfig.h>
-#include <rx/rxkad.h>
-#include <afs/volser.h>
-#include <ubik.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "xf_errs.h"
-extern int optind;
-extern char *optarg;
-
-extern XFILE repair_output;
-extern afs_uint32 repair_dumphdr_cb(afs_dump_header *, XFILE *, void *);
-extern afs_uint32 repair_volhdr_cb(afs_vol_header *, XFILE *, void *);
-extern afs_uint32 repair_vnode_cb(afs_vnode *, XFILE *, void *);
-
-char *argv0;
-static char *input_path, *gendump_path;
-static afs_uint32 printflags, repairflags;
-static int quiet, verbose, error_count;
-
-static path_hashinfo phi;
-static dump_parser dp;
-
-
-/* Print a usage message and exit */
-static void
-usage(int status, char *msg)
-{
-    if (msg)
-       fprintf(stderr, "%s: %s\n", argv0, msg);
-    fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
-    fprintf(stderr, "  -Pxxx  Set print options:\n");
-    fprintf(stderr, "          B = Print backup system header (if any)\n");
-    fprintf(stderr, "          H = Print AFS dump header\n");
-    fprintf(stderr, "          V = Print AFS volume header\n");
-    fprintf(stderr, "          v = List vnodes\n");
-    fprintf(stderr, "          p = Include path to each vnode\n");
-    fprintf(stderr, "          i = Include info for each vnode\n");
-    fprintf(stderr, "          d = List directory contents\n");
-    fprintf(stderr, "          a = List access control lists\n");
-    fprintf(stderr, "          g = Print debugging info\n");
-    fprintf(stderr, "  -Rxxx  Set repair options:\n");
-    fprintf(stderr, "          0 = Skip null tags\n");
-    fprintf(stderr, "          b = Seek backward to find skipped tags\n");
-    fprintf(stderr, "          d = Resync after vnode data\n");
-    fprintf(stderr, "          v = Resync after corrupted vnodes\n");
-    fprintf(stderr, "  -h     Print this help message\n");
-    fprintf(stderr, "  -gxxx  Generate a new dump in file xxx\n");
-    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
-    fprintf(stderr, "  -v     Verbose mode\n");
-    exit(status);
-}
-
-
-/* Parse the argument given to the -P option.
- * Returns the resulting * dumpscan print flags (DSPRINT_*).
- * If an unrecognized flag is used, prints an error message and exits.
- */
-static afs_uint32
-parse_printflags(char *flags)
-{
-    afs_uint32 result = 0;
-    char *x;
-
-    for (x = flags; *x; x++)
-       switch (*x) {
-       case 'B':
-           result |= DSPRINT_BCKHDR;
-           continue;
-       case 'H':
-           result |= DSPRINT_DUMPHDR;
-           continue;
-       case 'V':
-           result |= DSPRINT_VOLHDR;
-           continue;
-       case 'v':
-           result |= DSPRINT_ITEM;
-           continue;
-       case 'p':
-           result |= DSPRINT_PATH;
-           continue;
-       case 'i':
-           result |= DSPRINT_VNODE;
-           continue;
-       case 'd':
-           result |= DSPRINT_DIR;
-           continue;
-       case 'a':
-           result |= DSPRINT_ACL;
-           continue;
-       case 'g':
-           result |= DSPRINT_DEBUG;
-           continue;
-       default:
-           usage(1, "Invalid print options!");
-       }
-    return result;
-}
-
-
-/* Parse the argument given to the -R option.
- * Returns the resulting * dumpscan repair flags (DSFIX_*).
- * If an unrecognized flag is used, prints an error message and exits.
- */
-static afs_uint32
-parse_repairflags(char *flags)
-{
-    afs_uint32 result = 0;
-    char *x;
-
-    for (x = flags; *x; x++)
-       switch (*x) {
-       case '0':
-           result |= DSFIX_SKIP;
-           continue;
-       case 'b':
-           result |= DSFIX_RSKIP;
-           continue;
-       case 'd':
-           result |= DSFIX_VDSYNC;
-           continue;
-       case 'v':
-           result |= DSFIX_VFSYNC;
-           continue;
-       default:
-           usage(1, "Invalid repair options!");
-       }
-    return result;
-}
-
-
-/* Parse the command-line options */
-static void
-parse_options(int argc, char **argv)
-{
-    int c;
-
-    /* Set the program name */
-    if ((argv0 = strrchr(argv[0], '/')))
-       argv0++;
-    else
-       argv0 = argv[0];
-
-    /* Initialize options */
-    input_path = gendump_path = 0;
-    printflags = repairflags = 0;
-    quiet = verbose = 0;
-
-    /* Initialize other stuff */
-    error_count = 0;
-
-    /* Parse the options */
-    while ((c = getopt(argc, argv, "P:R:g:hqv")) != EOF) {
-       switch (c) {
-       case 'P':
-           printflags = parse_printflags(optarg);
-           continue;
-       case 'R':
-           repairflags = parse_repairflags(optarg);
-           continue;
-       case 'g':
-           gendump_path = optarg;
-           continue;
-       case 'q':
-           quiet = 1;
-           continue;
-       case 'v':
-           verbose = 1;
-           continue;
-       case 'h':
-           usage(0, 0);
-       default:
-           usage(1, "Invalid option!");
-       }
-    }
-
-    if (quiet && verbose)
-       usage(1, "Can't specify both -q and -v");
-
-    /* Parse non-option arguments */
-    if (argc - optind > 1)
-       usage(1, "Too many arguments!");
-    input_path = (argc == optind) ? "-" : argv[optind];
-}
-
-
-/* A callback to count and print errors */
-static afs_uint32
-my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
-{
-    va_list alist;
-
-    error_count++;
-    if (!quiet) {
-       va_start(alist, msg);
-       afs_com_err_va(argv0, code, msg, alist);
-       va_end(alist);
-    }
-    return 0;
-}
-
-
-/* A callback to print the path of a vnode. */
-static afs_uint32
-print_vnode_path(afs_vnode * v, XFILE * X, void *refcon)
-{
-    afs_uint32 r;
-    char *name = 0;
-
-    /* Do repair, but only for known vnode types */
-    if (gendump_path && (!(v->field_mask & F_VNODE_TYPE)
-                        || ((v->type != vFile) && (v->type != vDirectory)
-                            && (v->type != vSymlink)))) {
-       r = repair_vnode_cb(v, X, refcon);
-       if (r)
-           return r;
-    }
-    r = Path_Build(X, &phi, v->vnode, &name, 0);
-    if (!r && name)
-       printf(" Path: %s\n", name);
-    if (name)
-       free(name);
-    return r;
-}
-
-
-/* Setup for generating a repaired dump */
-static afs_uint32
-setup_repair(void)
-{
-    afs_uint32 r;
-
-    r = xfopen(&repair_output, O_RDWR | O_CREAT | O_TRUNC, gendump_path);
-    if (r)
-       return r;
-
-    dp.cb_dumphdr = repair_dumphdr_cb;
-    dp.cb_volhdr = repair_volhdr_cb;
-    dp.cb_vnode_dir = repair_vnode_cb;
-    dp.cb_vnode_file = repair_vnode_cb;
-    dp.cb_vnode_link = repair_vnode_cb;
-    dp.cb_vnode_empty = repair_vnode_cb;
-    return 0;
-}
-
-extern afs_uint32 DumpDumpEnd(XFILE * OX);
-
-/* Main program */
-int
-main(int argc, char **argv)
-{
-    XFILE input_file;
-    afs_uint32 r;
-
-    parse_options(argc, argv);
-    initialize_acfg_error_table();
-    initialize_AVds_error_table();
-    initialize_rxk_error_table();
-    initialize_u_error_table();
-    initialize_vl_error_table();
-    initialize_vols_error_table();
-    initialize_xFil_error_table();
-    r = xfopen(&input_file, O_RDONLY, input_path);
-    if (r) {
-       afs_com_err(argv0, r, "opening %s", input_path);
-       exit(2);
-    }
-
-    memset(&dp, 0, sizeof(dp));
-    dp.cb_error = my_error_cb;
-    dp.repair_flags = repairflags;
-    if (input_file.is_seekable)
-       dp.flags |= DSFLAG_SEEK;
-    else {
-       if (repairflags)
-           fprintf(stderr,
-                   "Repair modes available only for seekable dumps\n");
-       if (printflags & DSPRINT_PATH)
-           fprintf(stderr,
-                   "Path-printing available only for seekable dumps\n");
-       if (repairflags || (printflags & DSPRINT_PATH))
-           exit(1);
-    }
-
-    if (gendump_path && (r = setup_repair())) {
-       afs_com_err(argv0, r, "setting up repair output");
-       xfclose(&input_file);
-       exit(2);
-    }
-
-    if (printflags & DSPRINT_PATH) {
-       u_int64 where;
-
-       dp.print_flags = printflags & DSPRINT_DEBUG;
-       memset(&phi, 0, sizeof(phi));
-       phi.p = &dp;
-
-       if ((r = xftell(&input_file, &where))
-           || (r = Path_PreScan(&input_file, &phi, 0))
-           || (r = xfseek(&input_file, &where))) {
-           afs_com_err(argv0, r, "- path initialization failed");
-           xfclose(&input_file);
-           exit(2);
-       }
-
-       dp.cb_vnode_dir = print_vnode_path;
-       dp.cb_vnode_file = print_vnode_path;
-       dp.cb_vnode_link = print_vnode_path;
-       dp.cb_vnode_empty = print_vnode_path;
-       dp.cb_vnode_wierd = print_vnode_path;
-    }
-
-    dp.print_flags = printflags;
-    r = ParseDumpFile(&input_file, &dp);
-    xfclose(&input_file);
-    if (gendump_path) {
-       if (!r)
-           r = DumpDumpEnd(&repair_output);
-       if (!r)
-           r = xfclose(&repair_output);
-       else
-           xfclose(&repair_output);
-    }
-
-    if (verbose && error_count)
-       fprintf(stderr, "*** %d errors\n", error_count);
-    if (r && !quiet)
-       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
-    exit(0);
-}
diff --git a/src/tests/afsdump_xsed.c b/src/tests/afsdump_xsed.c
deleted file mode 100644 (file)
index f726ae9..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * COPYRIGHT NOTICE
- * Copyright (c) 1997 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* UB - Unified Backups */
-/* methods/afs/dumpscan/afsdump_scan.c - General-purpose dump scanner */
-
-#include "dumpscan.h"
-#include <sys/fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-extern int opterr, optind;
-extern char *optarg;
-
-extern XFILE repair_output;
-extern afs_uint32 repair_dumphdr_cb(afs_dump_header *, XFILE *, void *);
-extern afs_uint32 repair_volhdr_cb(afs_vol_header *, XFILE *, void *);
-extern afs_uint32 repair_vnode_cb(afs_vnode *, XFILE *, void *);
-
-char *argv0;
-static char *input_path, *gendump_path;
-static afs_uint32 printflags, repairflags, add_admin;
-static int quiet, verbose, error_count;
-
-static path_hashinfo phi;
-static dump_parser dp;
-
-
-/* Print a usage message and exit */
-static void
-usage(int status, char *msg)
-{
-    if (msg)
-       fprintf(stderr, "%s: %s\n", argv0, msg);
-    fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
-    fprintf(stderr, "  -Pxxx  Set print options:\n");
-    fprintf(stderr, "          B = Print backup system header (if any)\n");
-    fprintf(stderr, "          H = Print AFS dump header\n");
-    fprintf(stderr, "          V = Print AFS volume header\n");
-    fprintf(stderr, "          v = List vnodes\n");
-    fprintf(stderr, "          p = Include path to each vnode\n");
-    fprintf(stderr, "          i = Include info for each vnode\n");
-    fprintf(stderr, "          d = List directory contents\n");
-    fprintf(stderr, "          a = List access control lists\n");
-    fprintf(stderr, "          g = Print debugging info\n");
-    fprintf(stderr, "  -Rxxx  Set repair options:\n");
-    fprintf(stderr, "          0 = Skip null tags\n");
-    fprintf(stderr, "          b = Seek backward to find skipped tags\n");
-    fprintf(stderr, "          d = Resync after vnode data\n");
-    fprintf(stderr, "          v = Resync after corrupted vnodes\n");
-    fprintf(stderr,
-           "  -Annn  Add all rights for ID nnn to every directory\n");
-    fprintf(stderr, "  -h     Print this help message\n");
-    fprintf(stderr, "  -gxxx  Generate a new dump in file xxx\n");
-    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
-    fprintf(stderr, "  -v     Verbose mode\n");
-    exit(status);
-}
-
-
-/* Parse the argument given to the -P option.
- * Returns the resulting * dumpscan print flags (DSPRINT_*).
- * If an unrecognized flag is used, prints an error message and exits.
- */
-static afs_uint32
-parse_printflags(char *flags)
-{
-    afs_uint32 result = 0;
-    char *x;
-
-    for (x = flags; *x; x++)
-       switch (*x) {
-       case 'B':
-           result |= DSPRINT_BCKHDR;
-           continue;
-       case 'H':
-           result |= DSPRINT_DUMPHDR;
-           continue;
-       case 'V':
-           result |= DSPRINT_VOLHDR;
-           continue;
-       case 'v':
-           result |= DSPRINT_ITEM;
-           continue;
-       case 'p':
-           result |= DSPRINT_PATH;
-           continue;
-       case 'i':
-           result |= DSPRINT_VNODE;
-           continue;
-       case 'd':
-           result |= DSPRINT_DIR;
-           continue;
-       case 'a':
-           result |= DSPRINT_ACL;
-           continue;
-       case 'g':
-           result |= DSPRINT_DEBUG;
-           continue;
-       default:
-           usage(1, "Invalid print options!");
-       }
-    return result;
-}
-
-
-/* Parse the argument given to the -R option.
- * Returns the resulting * dumpscan repair flags (DSFIX_*).
- * If an unrecognized flag is used, prints an error message and exits.
- */
-static afs_uint32
-parse_repairflags(char *flags)
-{
-    afs_uint32 result = 0;
-    char *x;
-
-    for (x = flags; *x; x++)
-       switch (*x) {
-       case '0':
-           result |= DSFIX_SKIP;
-           continue;
-       case 'b':
-           result |= DSFIX_RSKIP;
-           continue;
-       case 'd':
-           result |= DSFIX_VDSYNC;
-           continue;
-       case 'v':
-           result |= DSFIX_VFSYNC;
-           continue;
-       default:
-           usage(1, "Invalid repair options!");
-       }
-    return result;
-}
-
-
-/* Parse the command-line options */
-static void
-parse_options(int argc, char **argv)
-{
-    int c;
-
-    /* Set the program name */
-    if (argv0 = strrchr(argv[0], '/'))
-       argv0++;
-    else
-       argv0 = argv[0];
-
-    /* Initialize options */
-    input_path = gendump_path = 0;
-    printflags = repairflags = add_admin = 0;
-    quiet = verbose = 0;
-
-    /* Initialize other stuff */
-    error_count = 0;
-
-    /* Parse the options */
-    while ((c = getopt(argc, argv, "A:P:R:g:hv")) != EOF) {
-       switch (c) {
-       case 'A':
-           add_admin = atoi(optarg);
-           continue;
-       case 'P':
-           printflags = parse_printflags(optarg);
-           continue;
-       case 'R':
-           repairflags = parse_repairflags(optarg);
-           continue;
-       case 'g':
-           gendump_path = optarg;
-           continue;
-       case 'q':
-           quiet = 1;
-           continue;
-       case 'v':
-           verbose = 1;
-           continue;
-       case 'h':
-           usage(0, 0);
-       default:
-           usage(1, "Invalid option!");
-       }
-    }
-
-    if (quiet && verbose)
-       usage(1, "Can't specify both -q and -v");
-
-    /* Parse non-option arguments */
-    if (argc - optind > 1)
-       usage(1, "Too many arguments!");
-    input_path = (argc == optind) ? "-" : argv[optind];
-    if (add_admin && !gendump_path)
-       add_admin = 0;
-}
-
-
-/* A callback to count and print errors */
-static afs_uint32
-my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
-{
-    va_list alist;
-
-    error_count++;
-    if (!quiet) {
-       va_start(alist, msg);
-       afs_com_err_va(argv0, code, msg, alist);
-       va_end(alist);
-    }
-}
-
-
-/* A callback to print the path of a vnode. */
-static afs_uint32
-print_vnode_path(afs_vnode * v, XFILE * X, void *refcon)
-{
-    afs_uint32 r;
-    char *name = 0;
-
-    /* Do repair, but only for known vnode types */
-    if (gendump_path && (!(v->field_mask & F_VNODE_TYPE)
-                        || v->type != vFile || v->type != vDirectory
-                        || v->type != vSymlink)) {
-       r = repair_vnode_cb(v, X, refcon);
-       if (r)
-           return r;
-    }
-    r = Path_Build(X, &phi, v->vnode, &name, 0);
-    if (!r && name)
-       printf(" Path: %s\n", name);
-    if (name)
-       free(name);
-    return r;
-}
-
-
-static afs_uint32
-munge_admin_acl(afs_vnode * v, XFILE * X, void *refcon)
-{
-    struct acl_accessList *acl;
-    int add_entry = 1, remove_entry = -1;
-    int i, o, n;
-
-    acl = (struct acl_accessList *)(v->acl);
-    o = n = ntohl(acl->positive);
-    for (i = 0; i < n; i++)
-       if (ntohl(acl->entries[i].id) == add_admin)
-           add_entry = 0;
-    n = ntohl(acl->negative);
-    for (i = o; i < n + o; i++)
-       if (ntohl(acl->entries[i].id) == add_admin)
-           remove_entry = i;
-
-    if (add_entry) {
-       for (i = (remove_entry < 0) ? o + n : remove_entry; i > o; i--) {
-           acl->entries[i].id = acl->entries[i - 1].id;
-           acl->entries[i].rights = acl->entries[i - 1].rights;
-       }
-       acl->entries[o].id = htonl(add_admin);
-       acl->entries[o].rights =
-           htonl((PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
-                  PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER));
-       acl->positive = htonl(o + 1);
-       if (remove_entry < 0)
-           acl->total = htonl(o + n + 1);
-       else
-           acl->negative = htonl(n - 1);
-    } else if (remove_entry >= 0) {
-       for (i = remove_entry; i < o + n - 1; i++) {
-           acl->entries[i].id = acl->entries[i + 1].id;
-           acl->entries[i].rights = acl->entries[i + 1].rights;
-       }
-       acl->negative = htonl(n - 1);
-       acl->total = htonl(o + n - 1);
-    }
-    return repair_vnode_cb(v, X, refcon);
-}
-
-
-/* Setup for generating a repaired dump */
-static afs_uint32
-setup_repair(void)
-{
-    afs_uint32 r;
-
-    r = xfopen(&repair_output, gendump_path, O_RDWR, 0644);
-    if (r)
-       return r;
-
-    dp.cb_dumphdr = repair_dumphdr_cb;
-    dp.cb_volhdr = repair_volhdr_cb;
-    dp.cb_vnode_dir = repair_vnode_cb;
-    dp.cb_vnode_file = repair_vnode_cb;
-    dp.cb_vnode_link = repair_vnode_cb;
-    dp.cb_vnode_empty = repair_vnode_cb;
-    return 0;
-}
-
-
-/* Main program */
-void
-main(int argc, char **argv)
-{
-    XFILE *X;
-    afs_uint32 r;
-
-    parse_options(argc, argv);
-    initialize_UB_error_table();
-    initialize_UBsp_error_table();
-    initialize_AVds_error_table();
-    r = xfopen(&X, input_path, O_RDONLY, 0);
-    if (r) {
-       afs_com_err(argv0, r, "opening %s", input_path);
-       exit(2);
-    }
-
-    bzero(&dp, sizeof(dp));
-    dp.cb_error = my_error_cb;
-    dp.repair_flags = repairflags;
-    if (X->is_seekable)
-       dp.flags |= DSFLAG_SEEK;
-    else {
-       if (repairflags)
-           fprintf(stderr,
-                   "Repair modes available only for seekable dumps\n");
-       if (printflags & DSPRINT_PATH)
-           fprintf(stderr,
-                   "Path-printing available only for seekable dumps\n");
-       if (repairflags || (printflags & DSPRINT_PATH))
-           exit(1);
-    }
-
-    if (gendump_path && (r = setup_repair())) {
-       afs_com_err(argv0, r, "setting up repair output");
-       xfclose(X);
-       exit(2);
-    }
-
-    if (printflags & DSPRINT_PATH) {
-       u_int64 where;
-
-       dp.print_flags = printflags & DSPRINT_DEBUG;
-       bzero(&phi, sizeof(phi));
-       phi.p = &dp;
-
-       if ((r = xftell(X, &where))
-           || (r = Path_PreScan(X, &phi, 0))
-           || (r = xfseek(X, &where))) {
-           afs_com_err(argv0, r, "- path initialization failed");
-           xfclose(X);
-           exit(2);
-       }
-
-       dp.cb_vnode_dir = print_vnode_path;
-       dp.cb_vnode_file = print_vnode_path;
-       dp.cb_vnode_link = print_vnode_path;
-       dp.cb_vnode_empty = print_vnode_path;
-       dp.cb_vnode_wierd = print_vnode_path;
-    }
-
-    if (add_admin) {
-       dp.cb_vnode_dir = munge_admin_acl;
-    }
-
-    dp.print_flags = printflags;
-    r = ParseDumpFile(X, &dp);
-    if (gendump_path) {
-       if (!r)
-           r = DumpDumpEnd(&repair_output);
-       if (!r)
-           r = xfclose(&repair_output);
-       else
-           xfclose(&repair_output);
-    }
-
-    if (verbose && error_count)
-       fprintf(stderr, "*** %d errors\n", error_count);
-    if (r && !quiet)
-       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
-    exit(0);
-}
diff --git a/src/tests/backuphdr.c b/src/tests/backuphdr.c
deleted file mode 100644 (file)
index 68cd6e4..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* backuphdr.c - Parse and print backup system headers */
-
-#include <stdlib.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "stagehdr.h"
-
-afs_uint32
-try_backuphdr(XFILE * X, char *tag, tagged_field * field, afs_uint32 value,
-             tag_parse_info * pi, void *g_refcon, void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    backup_system_header bh;
-    u_int64 where;
-    afs_uint32 r;
-
-    /* Which header should we try (if any)? */
-    switch (*tag) {
-    case STAGE_VERSMIN:
-      r = ParseStageHdr(X, (unsigned char *)tag, &bh);
-       break;
-    default:
-       return DSERR_MAGIC;
-    }
-    if (r)
-       return r;
-
-    /* Do something with it... */
-    if (p->print_flags & DSPRINT_BCKHDR)
-       PrintBackupHdr(&bh);
-    if (p->cb_bckhdr) {
-       r = xftell(X, &where);
-       if (!r && p->cb_bckhdr)
-           r = (p->cb_bckhdr) (&bh, X, p->refcon);
-       if (p->flags & DSFLAG_SEEK) {
-           if (!r)
-               r = xfseek(X, &where);
-           else
-               xfseek(X, &where);
-       }
-    }
-    if (bh.server)
-       free(bh.server);
-    if (bh.part)
-       free(bh.part);
-    if (bh.volname)
-       free(bh.volname);
-    return r;
-}
-
-
-void
-PrintBackupHdr(backup_system_header * hdr)
-{
-    time_t from = hdr->from_date, to = hdr->to_date, dd = hdr->dump_date;
-
-    printf("* BACKUP SYSTEM HEADER\n");
-    printf(" Version:    %d\n", hdr->version);
-    printf(" Volume:     %s (%d)\n", hdr->volname, hdr->volid);
-    printf(" Location:   %s %s\n", hdr->server, hdr->part);
-    printf(" Level:      %d\n", hdr->level);
-    printf(" Range:      %d => %d\n", hdr->from_date, hdr->to_date);
-    printf("          == %s", ctime(&from));
-    printf("          => %s", ctime(&to));
-    printf(" Dump Time:  %d == %s", hdr->dump_date, ctime(&dd));
-    printf(" Dump Flags: 0x%08x\n", hdr->flags);
-#ifdef NATIVE_INT64
-    printf(" Length:     %llu\n", hdr->dumplen);
-#else
-    printf(" Length:     %u,%u\n", hdr->dumplen.hi, hdr->dumplen.lo);
-#endif
-    printf(" File Num:   %d\n", hdr->filenum);
-}
diff --git a/src/tests/directory.c b/src/tests/directory.c
deleted file mode 100644 (file)
index d2f11b4..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998, 2001, 2004 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* directory.c - AFS directory parsing and generation */
-/* See the end of this file for a description of the directory format */
-
-#include <errno.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netinet/in.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "xf_errs.h"
-#include "dumpfmt.h"
-#include "internal.h"
-
-#include <afs/dir.h>
-
-struct dir_state {
-  unsigned char **dirpages;
-  int npages;
-
-  afs_dir_header *dh;        /* Directory header */
-  afs_dir_page *page;        /* Current page */
-  int pageno;                /* Current page # */
-  int entno;                 /* Current (next avail) entry # */
-  int used;                  /* # entries used in this page */
-};
-
-static afs_dir_page page;
-
-#define bmbyte(bm,x) bm[(x)>>3]
-#define bmbit(x) (1 << ((x) & 7))
-
-#define allocbit(x) (bmbyte(page.header.freebitmap,x) & bmbit(x))
-#define setallocbit(bm,x) (bmbyte(bm,x) |= bmbit(x))
-
-#define DPHE (DHE + 1)
-
-/* Hash function used in AFS directories.  */
-static int namehash(char *name, int buckets, int seed)
-{
-  int hval = seed, tval;
-
-  while (*name) hval = (hval * 173) + *name++;
-  tval = hval & (buckets - 1);
-  return tval ? hval < 0 ? buckets - tval : tval : 0;
-}
-
-#if 0
-static void fixup(char *name, int l)
-{
-  name += 16;
-  l -= 15;
-
-  while (l-- > 0) {
-    name[0] = name[4];
-    name++;
-  }
-}
-#endif
-
-afs_uint32 parse_directory(XFILE *X, dump_parser *p, afs_vnode *v,
-                        afs_uint32 size, int toeof)
-{
-  afs_dir_entry de;
-  int pgno, i, l, n;
-  afs_int32 r;
-  u_int64 where;
-
-  if (p->print_flags & DSPRINT_DIR) {
-    printf("  VNode      Uniqifier   Name\n");
-    printf("  ========== ==========  ==============================\n");
-  }
-  if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where))) return r;
-  for (pgno = 0; toeof || size; pgno++, size -= (toeof ? 0 : AFS_PAGESIZE)) {
-    if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where))) return r;
-    if ((r = xfread(X, &page, AFS_PAGESIZE))) {
-      if (toeof && r == ERROR_XFILE_EOF) break;
-      return r;
-    }
-    if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where))) return r;
-    if (page.header.tag != htons(1234)) {
-      if (p->cb_error)
-        (p->cb_error)(DSERR_MAGIC, 1, p->err_refcon,
-                      "Invalid page tag (%d) in page %d",
-                      ntohs(page.header.tag), pgno);
-      return DSERR_MAGIC;
-    }
-    for (i = (pgno ? 1 : DPHE); i < EPP; i++) {
-      if (!allocbit(i)) continue;
-      if (page.entry[i].flag != FFIRST) {
-        if (p->cb_error)
-          (p->cb_error)(DSERR_MAGIC, 0, p->err_refcon,
-                        "Invalid entry flag %d in entry %d/%d; skipping...",
-                        page.entry[i].flag, pgno, i);
-        continue;
-      }
-      n = (EPP - i - 1) * 32 + 16;
-      for (l = 0; n && page.entry[i].name[l]; l++, n--);
-      if (page.entry[i].name[l]) {
-        if (p->cb_error)
-          (p->cb_error)(DSERR_FMT, 0, p->err_refcon,
-                        "Filename too long in entry %d/%d; skipping page",
-                        pgno, i);
-        break;
-      }
-/*    fixup(page.entry[i].name, l); */
-      if (pgno) de.slot = i - 1 + (pgno - 1) * (EPP - 1) + (EPP - DPHE);
-      else de.slot = i - DPHE;
-      de.name  = page.entry[i].name;
-      de.vnode = ntohl(page.entry[i].vnode);
-      de.uniq  = ntohl(page.entry[i].vunique);
-      if (p->print_flags & DSPRINT_DIR)
-        printf("  %10d %10d  %s\n", de.vnode, de.uniq, de.name);
-      if (p->cb_dirent) {
-        r = (p->cb_dirent)(v, &de, X, p->refcon);
-      }
-      if (p->cb_dirent && (r = (p->cb_dirent)(v, &de, X, p->refcon)))
-        return r;
-      i += ((l + 16) >> 5);
-    }
-  }
-  if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where))) return r;
-  return 0;
-}
-
-
-afs_uint32 ParseDirectory(XFILE *X, dump_parser *p, afs_uint32 size, int toeof)
-{
-  afs_uint32 r;
-
-  r = parse_directory(X, p, 0, size, toeof);
-  return r;
-}
-
-
-typedef struct {
-  char **name;
-  afs_uint32 *vnode;
-  afs_uint32 *vuniq;
-} dirlookup_stat;
-
-
-static afs_uint32 dirlookup_cb(afs_vnode *v, afs_dir_entry *de,
-                            XFILE *X, void *refcon)
-{
-  dirlookup_stat *s = (dirlookup_stat *)refcon;
-
-  if (s->name && s->name[0]) {                  /* Search by filename */
-    if (strcmp(de->name, s->name[0])) return 0; /* Not it! */
-    if (s->vnode) s->vnode[0] = de->vnode;
-    if (s->vuniq) s->vuniq[0] = de->uniq;
-  } else if (s->vnode) {                        /* Search by vnode */
-    if (de->vnode != s->vnode[0]) return 0;     /* Not it! */
-    if (s->name) {
-      s->name[0] = (char *)malloc(strlen(de->name) + 1);
-      if (!s->name[0]) return ENOMEM;
-      strcpy(s->name[0], de->name);
-    }
-    if (s->vuniq) s->vuniq[0] = de->uniq;
-  }
-  return DSERR_DONE;
-}
-
-
-/* Look up an entry in a directory, by name or vnode.
- * If *name is NULL, we are looking up by vnode.
- * Otherwise, we are looking for a filename.
- * In any event, any of name, vnode, vuniq that are
- * neither NULL nor the search key are filled in on
- * success.
- *
- * Call this with X pointing to the start of the directory,
- * and size set to the length of the directory.
- * Returns 0 on success, whether or not the entry is found.
- */
-afs_uint32 DirectoryLookup(XFILE *X, dump_parser *p, afs_uint32 size,
-                    char **name, afs_uint32 *vnode, afs_uint32 *vuniq)
-{
-  dump_parser my_p;
-  dirlookup_stat my_s;
-  afs_uint32 r;
-
-  memset(&my_s, 0, sizeof(my_s));
-  my_s.name  = name;
-  my_s.vnode = vnode;
-  my_s.vuniq = vuniq;
-
-  memset(&my_p, 0, sizeof(my_p));
-  my_p.refcon = (void *)&my_s;
-  my_p.err_refcon = p->err_refcon;
-  my_p.cb_error = p->cb_error;
-  my_p.cb_dirent  = dirlookup_cb;
-
-  r = parse_directory(X, &my_p, 0, size, 0);
-  if (!r) r = DSERR_DONE;
-  return handle_return(r, X, 0, p);
-}
-
-
-static int allocpage(struct dir_state *ds, int reserve)
-{
-  unsigned char **dirpages;
-  int i;
-
-  dirpages = malloc((ds->npages + 1) * sizeof(unsigned char *));
-  if (!dirpages) return ENOMEM;
-  if (ds->dirpages) {
-    memcpy(dirpages, ds->dirpages, ds->npages * sizeof(unsigned char *));
-    free(ds->dirpages);
-  }
-  ds->dirpages = dirpages;
-
-  ds->dirpages[ds->npages] = malloc(AFS_PAGESIZE);
-  if (!ds->dirpages[ds->npages]) return ENOMEM;
-  ds->pageno = ds->npages++;
-
-  ds->page = (afs_dir_page *)(ds->dirpages[ds->pageno]);
-  memset(ds->page, 0, AFS_PAGESIZE);
-  ds->page->header.tag = htons(AFS_DIR_MAGIC);
-  ds->entno = ds->used = reserve;
-  for (i = 0; i < reserve; i++)
-    setallocbit(ds->page->header.freebitmap, i);
-  return 0;
-}
-
-
-afs_uint32 Dir_Init(struct dir_state **dsp)
-{
-  afs_uint32 r;
-
-  *dsp = malloc(sizeof(struct dir_state));
-  if (!*dsp) return ENOMEM;
-  memset(*dsp, 0, sizeof(struct dir_state));
-  if ((r = allocpage(*dsp, DPHE))) return r;
-  (*dsp)->dh = (afs_dir_header *)((*dsp)->page);
-  return 0;
-}
-
-
-afs_uint32 Dir_AddEntry(struct dir_state *ds, char *name,
-                        afs_uint32 vnode, afs_uint32 unique)
-{
-  afs_uint32 r;
-  int l = strlen(name) + 1;
-  int ne = l > 16 ? 1 + ((l - 16) / 32) + !!((l - 16) % 32) : 1;
-  int hash = namehash(name, NHASHENT, 0);
-
-  if (ne > EPP - 1) return ENAMETOOLONG;
-  if (ds->entno + ne > EPP) {
-    if (ds->pageno < 128) ds->dh->allomap[ds->pageno] = ds->used;
-    if ((r = allocpage(ds, 1))) return r;
-  }
-  ds->page->entry[ds->entno].flag    = FFIRST;
-  ds->page->entry[ds->entno].next    = ds->dh->hash[hash];
-  ds->page->entry[ds->entno].vnode   = htonl(vnode);
-  ds->page->entry[ds->entno].vunique = htonl(unique);
-  strcpy(ds->page->entry[ds->entno].name, name);
-  ds->dh->hash[hash] = htons((ds->pageno * EPP) + ds->entno);
-  while (ne--) {
-    setallocbit(ds->page->header.freebitmap, ds->entno);
-    ds->used++;
-    ds->entno++;
-  }
-  return 0;
-}
-
-
-afs_uint32 Dir_Finalize(struct dir_state *ds)
-{
-  int pages = ds->pageno + 1;
-
-  if (ds->pageno < 128) ds->dh->allomap[ds->pageno] = ds->used;
-  ds->dh->pagehdr.pgcount = htons(pages);
-  return 0;
-}
-
-
-afs_uint32 Dir_EmitData(struct dir_state *ds, XFILE *X, int dotag)
-{
-  afs_uint32 r, size;
-  int i;
-
-  size = ds->npages * AFS_PAGESIZE;
-  if (dotag && (r = WriteTagInt32(X, VTAG_DATA, size))) return r;
-  for (i = 0; i < ds->npages; i++) {
-    if ((r = xfwrite(X, ds->dirpages[i], AFS_PAGESIZE))) return r;
-  }
-  return 0;
-}
-
-
-afs_uint32 Dir_Free(struct dir_state *ds)
-{
-  int i;
-
-  for (i = 0; i < ds->npages; i++)
-    free(ds->dirpages[i]);
-  free(ds->dirpages);
-  free(ds);
-  return 0;
-}
-
-
-/* AFS directory format:
- * AFS directories are stored in volume dumps in exactly the same format
- * that is used on disk, which makes them relatively easy to dump and restore,
- * but means we have to do some work to interpret them.
- *
- * The ACL for a directory is stored on disk in the last part of a "large"
- * (directory) vnode.  This part of the vnode, which has fixed size
- * SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE, is copied directly into
- * the dump file with a tag of 'A' (VTAG_ACL).  The structure of this
- * section is described in <afs/acl.h>.
- *
- * The name-to-vnode mappings are also stored exactly as they appear on
- * disk, using the file data ('f') attribute.  As usual, this attribute
- * consists of a 32-bit number containing the size, immediately followed
- * by the data itself.  The interesting structures and constants are
- * defined in <afs/dir.h>
- *
- * A directory consists of one or more 'pages', each of which is 2K
- * (AFS_PAGESIZE).  Each page contains EPP (currently 64) 'entries', each
- * of which is 32 bytes.  The first page begins with a DirHeader, which
- * is DHE entries long, and includes a PageHeader.  All other pages begin
- * with just a PageHeader, which is 1 entry long.  Every other entry is
- * a DirEntry, a DirXEntry (name extension), or unused.
- *
- * A Page Header contains the following elements:
- * - pgcount    contains a count of the number of pages in the directory,
- *              if the directory is new-style (>128 pages), or 0 if it is
- *              old-style.  This field is meaningful only in the Dir Header.
- * - tag        a magic number, which must be 1234
- * - freecount  apparently unused
- * - freebitmap A bitmap of free entries.  Each byte corresponds to 8
- *              entries, with the least significant bit referring to the
- *              first of those.  Each bit is set iff the corresponding
- *              entry is allocated.  Entries used by the page and dir
- *              headers are considered allocated.
- *
- * A Dir Header consists of a Page Header, followed by an allocation map
- * and hash table.  The allocation map contains one byte for each of the
- * first 128 pages; that byte contains the number of entries in that page
- * that are allocated.  Every page that actually exists has at peast one
- * entry allocated (the Page Header); if a byte in this map is 0, it means
- * that the page does not yet exist.
- *
- * Each bucket in the hash table is a linked list, using 'blob numbers'
- * as pointers.  A blob number is defined as (page# * EPP) + entry#.
- * The head of each chain is kept in the hash table, and the next pointers
- * are kept in the 'next' entry of each directory.
- *
- * Directory entries themselves contain the following elements:
- * - flag    Set to FFIRST iff this is the first blob in an entry
- *           (otherwise it will be a name continuation).  This is
- *           probably not reliable.
- * - length  Unused
- * - next    Pointer to the next element in this hash chain
- * - fid     FileID (vnode and uniquifier)
- * - name    Filename (null-terminated)
- */
diff --git a/src/tests/dump.c b/src/tests/dump.c
deleted file mode 100644 (file)
index d657f35..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* dump.c - Write out parts of a volume dump */
-
-#include "dumpscan.h"
-#include "dumpfmt.h"
-
-#define COPYBUFSIZE 65536
-
-afs_uint32
-DumpDumpHeader(XFILE * OX, afs_dump_header * hdr)
-{
-    afs_uint32 r;
-
-    if ((r = WriteTagInt32Pair(OX, TAG_DUMPHEADER, hdr->magic, hdr->version)))
-       return r;
-
-    if (hdr->field_mask & F_DUMPHDR_VOLID) {
-       if ((r = WriteTagInt32(OX, DHTAG_VOLID, hdr->volid)))
-           return r;
-    }
-    if (hdr->field_mask & F_DUMPHDR_VOLNAME) {
-       if ((r = WriteByte(OX, DHTAG_VOLNAME)))
-           return r;
-       if ((r = WriteString(OX, hdr->volname)))
-           return r;
-    }
-    if (hdr->field_mask & (F_DUMPHDR_FROM | F_DUMPHDR_TO)) {
-       if ((r = WriteTagInt16(OX, DHTAG_DUMPTIMES, 2)))
-           return r;
-       if ((r = WriteInt32(OX, (hdr->field_mask & F_DUMPHDR_FROM))
-                          ? hdr->from_date : 0))
-           return r;
-       if ((r = WriteInt32(OX, (hdr->field_mask & F_DUMPHDR_TO)
-                           ? hdr->to_date : time(0))))
-           return r;
-    }
-    return 0;
-}
-
-
-afs_uint32
-DumpVolumeHeader(XFILE * OX, afs_vol_header * hdr)
-{
-    afs_uint32 r;
-    int i;
-
-    if ((r = WriteByte(OX, TAG_VOLHEADER)))
-       return r;
-
-    if (hdr->field_mask & F_VOLHDR_VOLID) {
-       if ((r = WriteTagInt32(OX, VHTAG_VOLID, hdr->volid)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_VOLVERS) {
-       if ((r = WriteTagInt32(OX, VHTAG_VERS, hdr->volvers)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_VOLNAME) {
-       if ((r = WriteByte(OX, VHTAG_VOLNAME)))
-           return r;
-       if ((r = WriteString(OX, hdr->volname)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_INSERV) {
-       if ((r = WriteTagByte(OX, VHTAG_INSERV, hdr->flag_inservice)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_BLESSED) {
-       if ((r = WriteTagByte(OX, VHTAG_BLESSED, hdr->flag_blessed)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_VOLUNIQ) {
-       if ((r = WriteTagInt32(OX, VHTAG_VUNIQ, hdr->voluniq)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_VOLTYPE) {
-       if ((r = WriteTagByte(OX, VHTAG_TYPE, hdr->voltype)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_PARENT) {
-       if ((r = WriteTagInt32(OX, VHTAG_PARENT, hdr->parent_volid)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_CLONE) {
-       if ((r = WriteTagInt32(OX, VHTAG_CLONE, hdr->clone_volid)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_MAXQ) {
-       if ((r = WriteTagInt32(OX, VHTAG_MAXQUOTA, hdr->maxquota)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_MINQ) {
-       if ((r = WriteTagInt32(OX, VHTAG_MINQUOTA, hdr->minquota)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_DISKUSED) {
-       if ((r = WriteTagInt32(OX, VHTAG_DISKUSED, hdr->diskused)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_NFILES) {
-       if ((r = WriteTagInt32(OX, VHTAG_FILECNT, hdr->nfiles)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_ACCOUNT) {
-       if ((r = WriteTagInt32(OX, VHTAG_ACCOUNT, hdr->account_no)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_OWNER) {
-       if ((r = WriteTagInt32(OX, VHTAG_OWNER, hdr->owner)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_CREATE_DATE) {
-       if ((r = WriteTagInt32(OX, VHTAG_CREAT, hdr->create_date)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_ACCESS_DATE) {
-       if ((r = WriteTagInt32(OX, VHTAG_ACCESS, hdr->access_date)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_UPDATE_DATE) {
-       if ((r = WriteTagInt32(OX, VHTAG_UPDATE, hdr->update_date)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_EXPIRE_DATE) {
-       if ((r = WriteTagInt32(OX, VHTAG_EXPIRE, hdr->expire_date)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_BACKUP_DATE) {
-       if ((r = WriteTagInt32(OX, VHTAG_BACKUP, hdr->backup_date)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_OFFLINE_MSG) {
-       if ((r = WriteTagInt32(OX, VHTAG_OFFLINE, *hdr->offline_msg)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_MOTD) {
-       if ((r = WriteTagInt32(OX, VHTAG_MOTD, *hdr->motd_msg)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_WEEKUSE) {
-       if ((r = WriteTagInt16(OX, VHTAG_WEEKUSE, 7)))
-           return r;
-       for (i = 0; i < 7; i++)
-           if ((r = WriteInt32(OX, hdr->weekuse[i])))
-               return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_DAYUSE_DATE) {
-       if ((r = WriteTagInt32(OX, VHTAG_DUDATE, hdr->dayuse_date)))
-           return r;
-    }
-    if (hdr->field_mask & F_VOLHDR_DAYUSE) {
-       if ((r = WriteTagInt32(OX, VHTAG_DAYUSE, hdr->dayuse)))
-           return r;
-    }
-    return 0;
-}
-
-
-afs_uint32
-DumpVNode(XFILE * OX, afs_vnode * v)
-{
-    afs_uint32 r;
-
-    if ((r = WriteTagInt32Pair(OX, TAG_VNODE, v->vnode, v->vuniq)))
-       return r;
-
-    if (v->field_mask & F_VNODE_TYPE) {
-       if ((r = WriteTagByte(OX, VTAG_TYPE, v->type)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_NLINKS) {
-       if ((r = WriteTagInt16(OX, VTAG_NLINKS, v->nlinks)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_DVERS) {
-       if ((r = WriteTagInt32(OX, VTAG_DVERS, v->datavers)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_SDATE) {
-       if ((r = WriteTagInt32(OX, VTAG_SERVER_DATE, v->server_date)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_AUTHOR) {
-       if ((r = WriteTagInt32(OX, VTAG_AUTHOR, v->author)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_OWNER) {
-       if ((r = WriteTagInt32(OX, VTAG_OWNER, v->owner)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_GROUP) {
-       if ((r = WriteTagInt32(OX, VTAG_GROUP, v->group)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_MODE) {
-       if ((r = WriteTagInt16(OX, VTAG_MODE, v->mode)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_PARENT) {
-       if ((r = WriteTagInt32(OX, VTAG_PARENT, v->parent)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_CDATE) {
-       if ((r = WriteTagInt32(OX, VTAG_CLIENT_DATE, v->client_date)))
-           return r;
-    }
-    if (v->field_mask & F_VNODE_ACL) {
-       if ((r = WriteByte(OX, VTAG_ACL)))
-           return r;
-       if ((r =
-           xfwrite(OX, v->acl,
-                   SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE)))
-           return r;
-    }
-    return 0;
-}
-
-
-afs_uint32
-DumpVNodeData(XFILE * OX, char *buf, afs_uint32 size)
-{
-    afs_uint32 r;
-
-    if ((r = WriteTagInt32(OX, VTAG_DATA, size)))
-       return r;
-    if ((r = xfwrite(OX, buf, size)))
-       return r;
-    return 0;
-}
-
-
-afs_uint32
-CopyVNodeData(XFILE * OX, XFILE * X, afs_uint32 size)
-{
-    afs_uint32 r, n;
-    static char buf[COPYBUFSIZE];
-
-    if ((r = WriteTagInt32(OX, VTAG_DATA, size)))
-       return r;
-    while (size) {
-       n = (size > COPYBUFSIZE) ? COPYBUFSIZE : size;
-       if ((r = xfread(X, buf, n)))
-           return r;
-       if ((r = xfwrite(OX, buf, n)))
-           return r;
-       size -= n;
-    }
-    return 0;
-}
-
-
-afs_uint32
-DumpDumpEnd(XFILE * OX)
-{
-    afs_uint32 r;
-
-    if ((r = WriteTagInt32(OX, TAG_DUMPEND, DUMPENDMAGIC)))
-       return r;
-    return 0;
-}
diff --git a/src/tests/dumpfmt.h b/src/tests/dumpfmt.h
deleted file mode 100644 (file)
index a6b6d1b..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998, 2001 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* dumpfmt.h - Description of AFS dump format */
-
-#ifndef _DUMPFMT_H_
-#define _DUMPFMT_H_
-
-#include "intNN.h"
-
-/* AFS dump file format:
- * All data in AFS dumps is tagged; that is, each data item is preceeded
- * by a 1-byte tag which identifies what the data item is.  There is no
- * explicit mention of what the data type is, but the type of each possible
- * data item (and thus, each possible tag) is fixed.  Usually this is
- * a relatively simple, fixed amount of data (byte, short, word), but
- * sometimes it is more complex.
- *
- * There is some amount of structure to an AFS volume dump.  Basically,
- * you get a dump header, followed by a volume header, followed by some
- * vnodes, followed by a dump end.  Each of these items (header, vnode,
- * dump end) consists of a tag, a fixed amount of required information,
- * and 0 or more tagged attributes (except dump-end, which has no attributes).
- *
- * Vnodes, in turn, are usually listed in a particular order.  First, we
- * list all the directory vnodes in the volume, in increasing order by
- * vnode.  Then, we list all the file vnodes, again in increasing order.
- * Directory vnodes must have a complete set of attributes and data, but
- * in an incremental dump, file vnodes may have no attributes if the vnode
- * has not changed since the reference date.
- *
- * The primary purpose of this file is to define the tags and some magic
- * numbers.  There is also some information that is defined in the Transarc
- * provided header files.
- */
-
-
-/** MAGIC NUMBERS **/
-#define DUMPVERSION     1
-#define DUMPBEGINMAGIC  0xb3a11322
-#define DUMPENDMAGIC    0x3a214b6e
-
-
-/** TOP-LEVEL TAGS **/
-#define TAG_DUMPHEADER  1
-#define TAG_VOLHEADER   2
-#define TAG_VNODE       3
-#define TAG_DUMPEND     4
-
-
-/** DUMP HEADER TAGS **/
-#define DHTAG_VOLNAME    'n'
-#define DHTAG_VOLID      'v'
-#define DHTAG_DUMPTIMES  't'
-
-
-/** VOLUME HEADER TAGS **/
-#define VHTAG_VOLID      'i'
-#define VHTAG_VERS       'v'
-#define VHTAG_VOLNAME    'n'
-#define VHTAG_INSERV     's'
-#define VHTAG_BLESSED    'b'
-#define VHTAG_VUNIQ      'u'
-#define VHTAG_TYPE       't'
-#define VHTAG_PARENT     'p'
-#define VHTAG_CLONE      'c'
-#define VHTAG_MAXQUOTA   'q'
-#define VHTAG_MINQUOTA   'm'
-#define VHTAG_DISKUSED   'd'
-#define VHTAG_FILECNT    'f'
-#define VHTAG_ACCOUNT    'a'
-#define VHTAG_OWNER      'o'
-#define VHTAG_CREAT      'C'
-#define VHTAG_ACCESS     'A'
-#define VHTAG_UPDATE     'U'
-#define VHTAG_EXPIRE     'E'
-#define VHTAG_BACKUP     'B'
-#define VHTAG_OFFLINE    'O'
-#define VHTAG_MOTD       'M'
-#define VHTAG_WEEKUSE    'W'
-#define VHTAG_DUDATE     'D'
-#define VHTAG_DAYUSE     'Z'
-
-
-/** VNODE TAGS **/
-#define VTAG_TYPE        't'
-#define VTAG_NLINKS      'l'
-#define VTAG_DVERS       'v'
-#define VTAG_CLIENT_DATE 'm'
-#define VTAG_AUTHOR      'a'
-#define VTAG_OWNER       'o'
-#define VTAG_GROUP       'g'
-#define VTAG_MODE        'b'
-#define VTAG_PARENT      'p'
-#define VTAG_SERVER_DATE 's'
-#define VTAG_ACL         'A'
-#define VTAG_DATA        'f'
-
-
-#define AFS_DIR_MAGIC    1234
-#define AFS_DIR_EPP        64
-#define AFS_DIR_MAXPAGES  128
-#define AFS_DIR_NHASH     128
-
-typedef struct {
-  afs_uint16 pgcount;
-  afs_uint16 tag;
-  char freecount;
-  char freebitmap[AFS_DIR_EPP/8];
-  char padding[32 - (5 + AFS_DIR_EPP/8)];
-} afs_dir_pagehdr;
-
-typedef struct {
-  afs_dir_pagehdr pagehdr;
-  char allomap[AFS_DIR_MAXPAGES];
-  afs_uint16 hash[AFS_DIR_NHASH];
-} afs_dir_header;
-
-typedef struct {
-  char flag;
-  char length;
-  afs_uint16 next;
-  afs_uint32 vnode;
-  afs_uint32 vunique;
-  char name[16];
-  char padding[4];
-} afs_dir_direntry;
-
-typedef union {
-  afs_dir_pagehdr header;
-  afs_dir_direntry entry[AFS_DIR_EPP];
-} afs_dir_page;
-
-#endif /* _DUMPFMT_H_ */
diff --git a/src/tests/dumpscan.h b/src/tests/dumpscan.h
deleted file mode 100644 (file)
index a0ebe39..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998, 2001, 2003 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* dumpscan.h - Public interface */
-
-#ifndef _DUMPSCAN_H_
-#define _DUMPSCAN_H_
-
-#include "intNN.h"
-#include "xfiles.h"
-
-#include <lock.h>
-#include <afs/afsint.h>
-#include <afs/nfs.h>
-#include <afs/ihandle.h>
-#include <afs/vnode.h>
-
-/* Random useful types */
-typedef struct tagged_field tagged_field;
-typedef struct tag_parse_info tag_parse_info;
-typedef afs_uint32 (*tag_parser)(XFILE *, unsigned char *, tagged_field *,
-                              afs_uint32, tag_parse_info *, void *, void *);
-typedef struct dir_state dir_state;
-
-/* Error codes used within dumpscan.
- * Any of the routines declared below, or callbacks used by them,
- * may signal a system error by returning the error number, or
- * some other error by returning a com_err code.  Note that
- * ParseTaggedData does _not_ return DSERR_TAG; instead, it returns
- * 0, assuming the tag will be handled at a higher level.
- *
- * In addition, these errors may be reported to the caller of
- * ParseDumpFile using the error callback.  Such reports will be
- * issued whether or not error recovery is possible or attempted.
- *
- * NB: These errors are now in dumpscan_errs.h
- */
-
-
-/* Backup system dump header */
-/* Right now, this looks a lot like an old stage header.  Eventually, it
- * should contain enough fields to fully represent headers from old or
- * new stage, Transarc, or other backup systems, and the appropriate read
- * functions should extract as much data as possible from the actual file
- * to fill this in. */
-typedef struct {
-  afs_uint32 version;
-  afs_uint32 from_date;
-  afs_uint32 to_date;
-  afs_uint32 dump_date;
-  afs_uint32 filenum;
-  unsigned char *server;
-  unsigned char *part;
-  unsigned char *volname;
-  afs_uint32 volid;
-  u_int64 dumplen;
-  afs_uint32 level;
-  afs_uint32 magic;
-  afs_uint32 cksum;
-  afs_uint32 flags;
-} backup_system_header;
-
-
-/** AFS dump header **/
-#define F_DUMPHDR_VOLID       0x00000001
-#define F_DUMPHDR_VOLNAME     0x00000002
-#define F_DUMPHDR_FROM        0x00000004
-#define F_DUMPHDR_TO          0x00000008
-typedef struct {
-  u_int64 offset;              /* Where in the input stream is it? */
-  afs_uint32 field_mask;       /* What fields are present? */
-  afs_uint32 magic;            /* Magic number */
-  afs_uint32 version;          /* Dump format version */
-  afs_uint32 volid;            /* VolID of volume in dump */
-  unsigned char *volname;      /* Name of volume in dump */
-  afs_uint32 from_date;        /* Reference date */
-  afs_uint32 to_date;          /* Date of dump */
-} afs_dump_header;
-
-
-/** AFS volume header **/
-#define F_VOLHDR_VOLID        0x00000001
-#define F_VOLHDR_VOLVERS      0x00000002
-#define F_VOLHDR_VOLNAME      0x00000004
-#define F_VOLHDR_INSERV       0x00000008
-#define F_VOLHDR_BLESSED      0x00000010
-#define F_VOLHDR_VOLUNIQ      0x00000020
-#define F_VOLHDR_VOLTYPE      0x00000040
-#define F_VOLHDR_PARENT       0x00000080
-#define F_VOLHDR_CLONE        0x00000100
-#define F_VOLHDR_MAXQ         0x00000200
-#define F_VOLHDR_MINQ         0x00000400
-#define F_VOLHDR_DISKUSED     0x00000800
-#define F_VOLHDR_NFILES       0x00001000
-#define F_VOLHDR_ACCOUNT      0x00002000
-#define F_VOLHDR_OWNER        0x00004000
-#define F_VOLHDR_CREATE_DATE  0x00008000
-#define F_VOLHDR_ACCESS_DATE  0x00010000
-#define F_VOLHDR_UPDATE_DATE  0x00020000
-#define F_VOLHDR_EXPIRE_DATE  0x00040000
-#define F_VOLHDR_BACKUP_DATE  0x00080000
-#define F_VOLHDR_OFFLINE_MSG  0x00100000
-#define F_VOLHDR_MOTD         0x00200000
-#define F_VOLHDR_WEEKUSE      0x00400000
-#define F_VOLHDR_DAYUSE       0x00800000
-#define F_VOLHDR_DAYUSE_DATE  0x01000000
-typedef struct {
-  u_int64 offset;              /* Where in the input stream is it? */
-  afs_uint32 field_mask;       /* What fields are present? */
-  afs_uint32 volid;            /* Volume ID */
-  afs_uint32 volvers;          /* ?? */
-  unsigned char *volname;      /* Volume Name */
-  int     flag_inservice;      /* Inservice flag (0 or not) */
-  int     flag_blessed;        /* Blessed to come online (0 or not) */
-  afs_uint32 voluniq;          /* Volume uniquifier */
-  int     voltype;             /* Volume type */
-  afs_uint32 parent_volid;     /* Parent volume ID */
-  afs_uint32 clone_volid;      /* Clone volume ID */
-  afs_uint32 maxquota;         /* Max quota */
-  afs_uint32 minquota;         /* Min quota (obsolete) */
-  afs_uint32 diskused;         /* Disk blocks used */
-  afs_uint32 nfiles;           /* Number of files in volume */
-  afs_uint32 account_no;       /* Account number (unused) */
-  afs_uint32 owner;            /* Volume owner */
-  afs_uint32 create_date;      /* Creation date of this copy */
-  afs_uint32 access_date;      /* Last access */
-  afs_uint32 update_date;      /* Last modification */
-  afs_uint32 expire_date;      /* Expiration (unused) */
-  afs_uint32 backup_date;      /* Last backup clone */
-  unsigned char *offline_msg;  /* Offline message */
-  unsigned char *motd_msg;     /* Volume MOTD */
-  afs_uint32 weekuse[7];       /* Weekuse data */
-  afs_uint32 dayuse;           /* # accesses in last day */
-  afs_uint32 dayuse_date;      /* Date for which dayuse is valid */
-} afs_vol_header;
-
-
-/** AFS vnode **/
-#define F_VNODE_TYPE          0x00000001
-#define F_VNODE_NLINKS        0x00000002
-#define F_VNODE_PARENT        0x00000004
-#define F_VNODE_DVERS         0x00000008
-#define F_VNODE_AUTHOR        0x00000010
-#define F_VNODE_OWNER         0x00000020
-#define F_VNODE_GROUP         0x00000040
-#define F_VNODE_MODE          0x00000080
-#define F_VNODE_CDATE         0x00000100
-#define F_VNODE_SDATE         0x00000200
-#define F_VNODE_ACL           0x00000400
-#define F_VNODE_SIZE          0x00000800 /* Set if size is present */
-#define F_VNODE_DATA          0x00001000 /* Set if size nonzero and data present */
-#define F_VNODE_PARTIAL       0x00002000 /* Partial vnode continuation (no header) */
-#define F_VNODE_LINK_TARGET   0x00004000 /* Symlink target present */
-typedef struct {
-  u_int64 offset;              /* Where in the input stream is it? */
-  afs_uint32 field_mask;       /* What fields are present? */
-  afs_uint32 vnode;            /* Vnode number */
-  afs_uint32 vuniq;            /* Uniquifier */
-  int     type;                /* Vnode type */
-  afs_uint16 nlinks;           /* Number of links (should be in 1 dir!) */
-  afs_uint32 parent;           /* Parent vnode */
-  afs_uint32 datavers;         /* Data version */
-  afs_uint32 author;           /* Last writer */
-  afs_uint32 owner;            /* Owner UID */
-  afs_uint32 group;            /* Owning group */
-  afs_uint16 mode;             /* UNIX mode bits */
-  afs_uint32 client_date;      /* Last modified date from client */
-  afs_uint32 server_date;      /* Last modified date on server */
-  afs_uint32 size;             /* Size of data */
-  u_int64 d_offset;            /* Where in the input stream is the data? */
-  char *link_target;           /* Target of symbolic link */
-  unsigned char acl[SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE];
-} afs_vnode;
-
-
-/** AFS directory entry **/
-typedef struct {
-  int  slot;                /* Directory slot # (info only) */
-  char *name;               /* Name of entry */
-  afs_uint32 vnode;            /* Vnode number */
-  afs_uint32 uniq;             /* Uniquifier */
-} afs_dir_entry;
-
-
-/** Tagged field definitions **/
-#define DKIND_NOOP      0x00  /* No data */
-#define DKIND_BYTE      0x10  /* 1 byte  - decimal */
-#define DKIND_HEX8      0x11  /* 1 byte  - hex */
-#define DKIND_CHAR      0x12  /* 1 byte  - character */
-#define DKIND_FLAG      0x13  /* 1 byte  - true/false */
-#define DKIND_INT16     0x20  /* 2 bytes - decimal */
-#define DKIND_HEX16     0x21  /* 2 bytes - hex */
-#define DKIND_OCT16     0x28  /* 2 bytes - octal */
-#define DKIND_INT32     0x30  /* 4 bytes - decimal */
-#define DKIND_HEX32     0x31  /* 4 bytes - hex */
-#define DKIND_TIME      0x32  /* 4 bytes - time */
-#define DKIND_OCT32     0x38  /* 4 bytes - octal */
-#define DKIND_STRING    0x40  /* ASCIIZ string */
-#define DKIND_SPECIAL   0x50  /* Custom parser */
-#define DKIND_MASK     (~0x0f)
-struct tag_parse_info {
-  void *err_refcon;
-  afs_uint32 (*cb_error)(afs_uint32, int, void *, char *, ...);
-  afs_uint32 flags;
-#define TPFLAG_SKIP   0x0001
-#define TPFLAG_RSKIP  0x0002
-  int shift_offset;
-  u_int64 shift_start;
-};
-struct tagged_field {
-  char tag;        /* Tag character */
-  int  kind;       /* Kind of object */
-  char *label;     /* Label to use (for debugging) */
-  tag_parser func; /* Parser function (for DKIND_SPECIAL) */
-  void *refptr;    /* Reference pointer (for parser's use) */
-  int  refarg;     /* Reference argument (for parser's use) */
-};
-
-
-/** Control structure for parsing volume dumps **/
-typedef struct {
-  /* Callback functions:
-   * Whenever a "complex" object is parsed, we call a callback function.
-   * The callback gets a pointer to the complex object, the file pointer
-   * for the dump we're parsing, and the value of refcon in this structure.
-   * Callbacks should return 0 if all is well, non-0 to abort the dump.
-   * By convention, positive numbers should be errno values, and negative
-   * numbers can be used for other things.  It is OK to _try_ to seek anywhere
-   * in the file.  Beware, though, that the input is not always seekable.
-   * Also, note that the structures passed to these callbacks are going to
-   * go away after the callback returns.  There is no way to prevent this;
-   * make a copy if you want one.
-   */
-  void *refcon;
-  afs_uint32 (*cb_bckhdr)(backup_system_header *, XFILE *, void *); /* Backup Header   */
-  afs_uint32 (*cb_dumphdr)(afs_dump_header *, XFILE *, void *);     /* Dump Header     */
-  afs_uint32 (*cb_volhdr)(afs_vol_header *, XFILE *, void *);       /* Volume Header   */
-  afs_uint32 (*cb_vnode_dir)(afs_vnode *, XFILE *, void *);         /* Directory Vnode */
-  afs_uint32 (*cb_vnode_file)(afs_vnode *, XFILE *, void *);        /* File Vnode      */
-  afs_uint32 (*cb_vnode_link)(afs_vnode *, XFILE *, void *);        /* Symlink Vnode   */
-  afs_uint32 (*cb_vnode_empty)(afs_vnode *, XFILE *, void *);       /* vnode+uniq only */
-  afs_uint32 (*cb_vnode_wierd)(afs_vnode *, XFILE *, void *);       /* Unknown type    */
-  afs_uint32 (*cb_file_data)(afs_vnode *, XFILE *, void *);         /* File Data       */
-  afs_uint32 (*cb_dir_data)(afs_vnode *, XFILE *, void *);          /* Directory Data  */
-  afs_uint32 (*cb_link_data)(afs_vnode *, XFILE *, void *);         /* Symlink Data    */
-
-  /* This function is called when there is an error in the dump. */
-  /* (cb_error)(errno, fatal, refcon, msg_fmt, msg_args...) */
-  void *err_refcon; /* If set, use instead of refcon for dir entries */
-  afs_uint32 (*cb_error)(afs_uint32, int, void *, char *, ...);
-
-  /* This function is called for each directory entry, if set */
-  afs_uint32 (*cb_dirent)(afs_vnode *, afs_dir_entry *, XFILE *, void *);
-
-  int flags;            /* Flags and options */
-#define DSFLAG_SEEK     0x0001  /* Input file is seekable */
-
-  int print_flags;      /* Flags to control what is printed */
-#define DSPRINT_BCKHDR  0x0001  /* Print backup system header */
-#define DSPRINT_DUMPHDR 0x0002  /* Print AFS dump header */
-#define DSPRINT_VOLHDR  0x0004  /* Print AFS volume header */
-#define DSPRINT_ITEM    0x0010  /* Print top-level tags */
-#define DSPRINT_VNODE   0x0020  /* Print vnode attributes */
-#define DSPRINT_ACL     0x0040  /* Print directory ACL's */
-#define DSPRINT_DIR     0x0080  /* Print directory contents */
-#define DSPRINT_DEBUG   0x0100  /* Print debugging info */
-#define DSPRINT_PATH    0x0200  /* Print vnode paths */
-
-  int repair_flags;     /* Flags to control what is repaired.
-                         * Most of these _require_ DSFLAG_SEEK */
-#define DSFIX_SKIP      0x0001  /* Try to skip null tags */
-#define DSFIX_RSKIP     0x0002  /* Seek back to fing skipped tags */
-#define DSFIX_VDSYNC    0x0004  /* Resync location after vnode data */
-#define DSFIX_VFSYNC    0x0008  /* Try to resync after bad vnode */
-
-  /** Things below this point for internal use only **/
-  afs_uint32 vol_uniquifier;
-} dump_parser;
-
-
-/** Hash table and control info for pathname manipulation **/
-typedef struct vhash_ent {
-  struct vhash_ent *next;    /* Pointer to next entry */
-  afs_uint32 vnode;             /* VNode number */
-  afs_uint32 parent;            /* Parent VNode number */
-  u_int64 v_offset;          /* Offset to start of vnode */
-  u_int64 d_offset;          /* Offset to data (0 if none) */
-  afs_uint32 d_size;            /* Size of data */
-} vhash_ent;
-typedef struct {
-  afs_uint32 n_vnodes;          /* Number of vnodes in volume */
-  afs_uint32 n_dirs;            /* Number of file vnodes */
-  afs_uint32 n_files;           /* Number of directory vnodes */
-  int hash_size;             /* Hash table size (bits) */
-  vhash_ent **hash_table;    /* Hash table */
-  dump_parser *p;            /* Dump parser to use */
-} path_hashinfo;
-
-
-/** Function prototypes **/
-/** Only the functions declared below are public interfaces **/
-/** Maybe someday, I'll write man pages for these **/
-
-/* primitive.c - I/O primitives */
-extern afs_uint32 ReadByte(XFILE *, unsigned char *);
-extern afs_uint32 ReadInt16(XFILE *, afs_uint16 *);
-extern afs_uint32 ReadInt32(XFILE *, afs_uint32 *);
-extern afs_uint32 ReadString(XFILE *, unsigned char **);
-extern afs_uint32 WriteByte(XFILE *, unsigned char);
-extern afs_uint32 WriteInt16(XFILE *, afs_uint16);
-extern afs_uint32 WriteInt32(XFILE *, afs_uint32);
-extern afs_uint32 WriteString(XFILE *, unsigned char *);
-extern afs_uint32 WriteTagByte(XFILE *, unsigned char, unsigned char);
-extern afs_uint32 WriteTagInt16(XFILE *, unsigned char, afs_uint16);
-extern afs_uint32 WriteTagInt32(XFILE *, unsigned char, afs_uint32);
-extern afs_uint32 WriteTagInt32Pair(XFILE *, unsigned char, afs_uint32, afs_uint32);
-extern afs_uint32 WriteTagString(XFILE *, unsigned char, unsigned char *);
-
-/* parsetag.c - Parse tagged data */
-extern afs_uint32 ParseTaggedData(XFILE *, tagged_field *, unsigned char *,
-                           tag_parse_info *, void *, void *);
-
-/* stagehdr.c - Parse and dump Stage dump headers */
-extern afs_uint32 ParseStageHdr(XFILE *, unsigned char *, backup_system_header *);
-extern afs_uint32 ParseStageV20Hdr(XFILE *, unsigned char *, backup_system_header *);
-extern afs_uint32 DumpStageV20Hdr(XFILE *, backup_system_header *);
-
-/* backuphdr.c - Parse and print backup system headers */
-extern void PrintBackupHdr(backup_system_header *);
-
-/* parsedump.c - Parse all or part of a volume dump */
-extern afs_uint32 ParseDumpFile(XFILE *, dump_parser *);
-extern afs_uint32 ParseDumpHeader(XFILE *, dump_parser *);
-extern afs_uint32 ParseVolumeHeader(XFILE *, dump_parser *);
-extern afs_uint32 ParseVNode(XFILE *, dump_parser *);
-
-
-/* directory.c - Directory parsing, lookup, and generation */
-extern afs_uint32 ParseDirectory(XFILE *, dump_parser *, afs_uint32, int);
-extern afs_uint32 DirectoryLookup(XFILE *, dump_parser *, afs_uint32,
-                           char **, afs_uint32 *, afs_uint32 *);
-extern afs_uint32 Dir_Init(dir_state **);
-extern afs_uint32 Dir_AddEntry(dir_state *, char *, afs_uint32, afs_uint32);
-extern afs_uint32 Dir_Finalize(dir_state *);
-extern afs_uint32 Dir_EmitData(dir_state *, XFILE *, int);
-extern afs_uint32 Dir_Free(dir_state *ds);
-
-
-/* dump.c - Dump parts of a volume dump */
-extern afs_uint32 DumpDumpHeader(XFILE *, afs_dump_header *);
-extern afs_uint32 DumpVolumeHeader(XFILE *, afs_vol_header *);
-extern afs_uint32 DumpVNode(XFILE *, afs_vnode *);
-extern afs_uint32 DumpVnodeData(XFILE *, char *, afs_uint32);
-extern afs_uint32 CopyVnodeData(XFILE *, XFILE *, afs_uint32);
-extern afs_uint32 DumpVNodeData(XFILE *OX, char *buf, afs_uint32 size);
-extern afs_uint32 DumpDumpEnd(XFILE *OX);
-
-/* pathname.c - Follow and construct pathnames */
-extern afs_uint32 Path_PreScan(XFILE *, path_hashinfo *, int);
-extern void Path_FreeHashTable(path_hashinfo *);
-extern afs_uint32 Path_Follow(XFILE *, path_hashinfo *, char *, vhash_ent *);
-extern afs_uint32 Path_Build(XFILE *, path_hashinfo *, afs_uint32, char **, int);
-
-#endif
diff --git a/src/tests/dumpscan_errs.et b/src/tests/dumpscan_errs.et
deleted file mode 100644 (file)
index e15e4c1..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# COPYRIGHT NOTICE
-# Copyright (c) 1997 Carnegie Mellon University
-# All Rights Reserved.
-#
-# Permission to use, copy, modify and distribute this software and its
-# documentation is hereby granted, provided that both the copyright
-# notice and this permission notice appear in all copies of the
-# software, derivative works or modified versions, and any portions
-# thereof, and that both notices appear in supporting documentation.
-#
-# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
-# CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
-# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
-#
-# Carnegie Mellon requests users of this software to return to
-#
-#  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
-#  School of Computer Science
-#  Carnegie Mellon University
-#  Pittsburgh PA 15213-3890
-#
-# any improvements or extensions that they make and grant Carnegie Mellon
-# the rights to redistribute these changes.
-
-# UB - Unified Backups
-# methods/afs/dumpscan/afsdump_errs.et - AFS dump scanner errors
-
-error_table AVds
-  ec DSERR_TAG,            "Unknown tag in AFS volume dump"
-  ec DSERR_MAGIC,          "Bad magic number in AFS volume dump"
-  ec DSERR_BOGUS,          "Bogus value in AFS volume dump"
-  ec DSERR_FMT,            "AFS volume dump format incorrect"
-  ec DSERR_KEEP,           "[AFS dumpscan internal: keep string]"
-  ec DSERR_PANIC,          "[AFS dumpscan internal: panic]"
-  ec DSERR_DONE,           "[AFS dumpscan internal: done]"
-  ec DSERR_MEM,            "[AFS dumpscan internal: out of memory]"
-end
diff --git a/src/tests/dumptool.c b/src/tests/dumptool.c
deleted file mode 100644 (file)
index 79c48cf..0000000
+++ /dev/null
@@ -1,2621 +0,0 @@
-/*
- * $Id$
- *
- * dumptool - A tool to manage MR-AFS dump files
- *
- * The dump file format ought to be documented _somewhere_, and
- * this seems like a good as a place as any ...
- *
- * A AFS dump file is marked off into a series of sections.  Each
- * section marked by a dump tag.  A tag is a single byte who's value
- * corresponds with the next section.  The sections are (in order):
- *
- * DUMPHEADER (tag 0x01)
- * VOLUMEHEADER (tag 0x02)
- * VNODE (tag 0x03)
- * DUMPEND (tag 0x04)
- *
- * Descriptions of the sections follow.  Note that in all cases, data is
- * stored in the dump in network byte order.
- *
- * DUMPHEADER:
- *
- * DUMPHEADER contains two parts: the DUMPMAGIC magic number (32 bits)
- * and the dump header itself.
- *
- * The dump header itself consists of a series of tagged values,
- * each tag marking out members of the DumpHeader structure.  The
- * routine ReadDumpHeader explains the specifics of these tags.
- *
- * VOLUMEHEADER:
- *
- * VOLUMEHEADER is a series of tagged values corresponding to the elements
- * of the VolumeDiskData structure.  See ReadVolumeHeader for more
- * information
- *
- * VNODE:
- *
- * The VNODE section is all vnodes contained in the volume (each vnode
- * itself is marked with the VNODE tag, so it's really a sequence of
- * VNODE tags, unlike other sections).
- *
- * Each vnode consists of three parts: the vnode number (32 bits), the
- * uniqifier (32 bits), and a tagged list of elements corresponding to
- * the elements of the VnodeDiskData structure.  See ScanVnodes for
- * more information.  Note that if file data is associated with a vnode,
- * it will be contained here.
- *
- * DUMPEND:
- *
- * The DUMPEND section consists of one part: the DUMPENDMAGIC magic
- * number (32 bits).
- *
- * Notes:
- *
- * The tagged elements are all ASCII letters, as opposed to the section
- * headers (which are 0x01, 0x02, ...).  Thus, an easy way to tell when
- * you've reached the end of an element sequence is to check to see if
- * the next tag is a printable character (this code tests for < 20).
- *
- * "vos dump" dumps the large vnode index, then the small vnode index,
- * so directories will appear first in the VNODE section.
- */
-
-#include <afsconfig.h>
-#include <afs/param.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <termios.h>
-#include <fnmatch.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include <lock.h>
-#include <afs/afsint.h>
-#include <afs/nfs.h>
-#include <afs/acl.h>
-#if !defined(PRE_AFS_36) && !defined(RESIDENCY)
-#include <afs/ihandle.h>
-#endif /* !defined(PRE_AFS_36) && !defined(RESIDENCY) */
-#include <afs/vnode.h>
-#include <afs/volume.h>
-
-#ifdef AFS_LINUX24_ENV
-#define _LARGEFILE64_SOURCE 1
-#endif
-#ifdef RESIDENCY
-#include <afs/rsdefs.h>
-#include <afs/remioint.h>
-#endif /* RESIDENCY */
-
-#include <afs/dir.h>
-
-#ifndef HAVE_OFF64_T
-typedef off_t off64_t;
-#endif /* !HAVE_OFF64_T */
-#ifndef HAVE_FSEEKO64
-#define fseeko64 fseeko
-#endif /* HAVE_FSEEKO64 */
-#ifndef HAVE_FTELLO64
-#define ftello64 ftello
-#endif /* HAVE_FTELLO64 */
-
-/*
- * Sigh.  Linux blows it again
- */
-
-#ifdef linux
-#include <pty.h>
-#endif
-
-/*
- * Stuff that is in private AFS header files, unfortunately
- */
-
-#define DUMPVERSION    1
-#define DUMPENDMAGIC   0x3A214B6E
-#define DUMPBEGINMAGIC 0xB3A11322
-#define D_DUMPHEADER   1
-#define D_VOLUMEHEADER 2
-#define D_VNODE                3
-#define D_DUMPEND      4
-#define D_MAX          20
-
-#define MAXDUMPTIMES   50
-
-struct DumpHeader {
-    int32_t version;
-    VolumeId volumeId;
-    char volumeName[VNAMESIZE];
-    int nDumpTimes;            /* Number of pairs */
-    struct {
-       int32_t from, to;
-    } dumpTimes[MAXDUMPTIMES];
-};
-
-/*
- * Our command-line arguments
- */
-
-#ifdef RESIDENCY
-struct {
-    int Algorithm;             /* Conversion algorithm */
-    int Size;                  /* Directory hierarchy size */
-    int FSType;                        /* File system type */
-    int DeviceTag;             /* Device Tag */
-} rscmdlineinfo[RS_MAXRESIDENCIES];
-
-/*
- * This stuff comes from ufsname.c (which itself takes it from
- * ufs_interfaces.c)
- */
-
-/* There is an assumption that all of the prefixes will have exactly one '/' */
-static char *Ufs_Prefixes[] = { "/ufs", "/slowufs", "/cdmf", "/sdmf" };
-
-#define MAX_ITERATIONS 10
-#define UFS_SUMMARYTREENAME "Summaries"
-#define UFS_STAGINGTREENAME "Staging"
-#define UFS_VOLUMEHEADERTREENAME "VolHeaders"
-#define UFS_VOLUMETREENAME "Volumes"
-#define UFS_ALGORITHMBASE 'A'
-#define UFS_MOUNTPOINTBASE 'a'
-#define UFS_ALGORITHMS 3
-#define UFS_LINK_MAX 64                /* Arbitrary. */
-#define HARD_LINKED_FILE -2
-#define TAGSTONAME(FileName, MountPoint, Sections, Level1, RWVolume, Vnode, Uniquifier, Algorithm) \
-{ \
-    if (Level1) \
-        sprintf(FileName,"%s/%lu/%lu/%c%lu.%lu.%lu.%lu.%lu", MountPoint, \
-                (Sections)[0], (Sections)[1], UFS_ALGORITHMBASE + Algorithm, \
-                (Sections)[2], (Sections)[3], RWVolume, Vnode, Uniquifier); \
-    else \
-        sprintf(FileName,"%s/%lu/%c%lu.%lu.%lu.%lu.%lu", MountPoint, \
-                (Sections)[0], UFS_ALGORITHMBASE + Algorithm, \
-                (Sections)[1], (Sections)[2], RWVolume, Vnode, Uniquifier); \
-}
-#define TAGSTOSTAGINGNAME(FileName, MountPoint, RWVolume, Vnode, Uniquifier) \
-    sprintf(FileName,"%s/%s/%lu.%lu.%lu", MountPoint, \
-           UFS_STAGINGTREENAME, RWVolume, Vnode, Uniquifier)
-#define TAGSTOVOLUMEHEADERNAME(FileName, MountPoint, FileTag1, FileTag2) \
-    sprintf(FileName,"%s/%s/%lu", MountPoint, UFS_VOLUMEHEADERTREENAME, \
-           FileTag1)
-#define TAGSTOVOLUMEINFONAME(FileName, MountPoint, FileTag1, FileTag2) \
-    sprintf(FileName,"%s/%s/%lu/%lu", MountPoint, \
-           UFS_VOLUMETREENAME, FileTag2, FileTag1)
-#define TAGSTOVOLUMENAME(FileName, MountPoint, FileTag1, FileTag2, RWVolume) \
-    sprintf(FileName,"%s/%s/%lu/%lu.%lu", MountPoint, \
-           UFS_VOLUMETREENAME, FileTag2, FileTag1, RWVolume)
-#define TAGSTOSUMMARYNAME(FileName, MountPoint, FileTag1, FileTag2, SummaryRequestor, Residency) \
-    sprintf(FileName,"%s/%s/%lu.%lu.%lu.%lu", MountPoint, \
-           UFS_SUMMARYTREENAME, FileTag1, FileTag2, SummaryRequestor, \
-           Residency)
-#define DEVICETAGNUMBERTOMOUNTPOINT(MountPoint, DeviceTagNumber, FSType) \
-    sprintf(MountPoint,"%s%c", Ufs_Prefixes[FSType], UFS_MOUNTPOINTBASE + \
-           DeviceTagNumber)
-#define MOUNTPOINTTODEVICETAGNUMBER(MountPoint) \
-    MountPoint[strlen(MountPoint) - 1] - UFS_MOUNTPOINTBASE
-#define DEVICETAGNUMBERTOVOLUMEHEADERTREE(TreeName, MountPoint) \
-    sprintf(TreeName,"%s/%s", MountPoint, UFS_VOLUMEHEADERTREENAME)
-#define UFS_RESIDENCIES_FILE "Residencies"
-
-/* We don't ever want to map to uid/gid -1.  fchown() takes that as a
-   don't change flag.  We know however that volume number range from
-   0x2000000 to 0x20FFFFFF (see VAllocateVolumeId() in vol/vutil.c)
-   so we will use that to insure that -1 never appears. */
-#define RWVolumeToUid(RWVolume) ((RWVolume >> 12) & 0xFFFF)
-#define RWVolumeToGid(RWVolume) ((RWVolume & 0xFFF) | \
-                                (((RWVolume >> 28) & 0xF) << 12))
-#define UidGidToRWVolume(Uid, Gid) ((Gid & 0xFFF) | ((Uid & 0xFFFF) << 12) | \
-                                   ((Gid & 0xF000) << 16))
-
-
-/* These routines generate a file name to correspond to the given tag
-   numbers. */
-
-/* The following entropy array contains the order of bits from highest entropy
-   to lowest in the numbers FileTag1 and FileTag2.  Bit numbers 32 and above
-   correspond to FileTag2.  This ordering was determined by examining all read-
-   write volumes in the psc.edu cell. */
-char UfsEntropy[1][64] = {
-    {1, 2, 3, 4, 33, 5, 6, 7, 44, 45, 46, 36, 8, 34, 42, 35,
-     9, 40, 38, 32, 43, 10, 39, 37, 11, 41, 12, 13, 14, 0,
-     15, 16, 61, 17, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
-     50, 49, 48, 47, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
-     21, 20, 19, 18, 62, 63},
-};
-
-uint32_t Directories[3][2] = { {256, 0}, {256, 16}, {256, 256}, };
-#endif /* RESIDENCY */
-
-static int verbose = 0;
-static int numNoDirData = 0;
-static int termsize = 0;
-int Testing = 0;
-#ifdef RESIDENCY
-extern resid ServerRequestorId;
-#endif /* RESIDENCY */
-
-/*
- * We use this structure to hold vnode data in our hash table.
- * It's indexed by vnode number.
- */
-
-struct vnodeData {
-    struct VnodeDiskObject *vnode;     /* A pointer to the disk vnode */
-    int vnodeNumber;           /* The vnode number */
-    off64_t dumpdata;          /* File offset of dump data (if
-                                * available */
-    unsigned char *filedata;   /* A pointer to the actual file
-                                * data itself (if available) */
-    unsigned int datalength;   /* The length of the data */
-};
-
-/*
- * This contains the current location when we're doing a scan of a
- * directory.
- */
-
-struct DirCursor {
-    int hashbucket;            /* Current hash bucket */
-    int entry;                 /* Entry within hash bucket */
-};
-
-/*
- * Arrays to hold vnode data
- */
-
-struct vnodeData **LargeVnodeIndex;
-struct vnodeData **SmallVnodeIndex;
-int numLargeVnodes = 0;
-int numSmallVnodes = 0;
-
-/*
- * Crap for the libraries
- */
-
-int ShutdownInProgress = 0;
-
-/*
- * Our local function prototypes
- */
-
-static int ReadDumpHeader(FILE *, struct DumpHeader *);
-static int ReadVolumeHeader(FILE *, VolumeDiskData *);
-static int ScanVnodes(FILE *, VolumeDiskData *, int);
-static struct vnodeData *InsertVnode(unsigned int, struct VnodeDiskObject *);
-static struct vnodeData *GetVnode(unsigned int);
-static int CompareVnode(const void *, const void *);
-static void InteractiveRestore(FILE *, VolumeDiskData *);
-static void DirectoryList(int, char **, struct vnodeData *, VolumeDiskData *);
-static void DirListInternal(struct vnodeData *, char *[], int, int, int, int,
-                           int, int, VolumeDiskData *, char *);
-static int CompareDirEntry(const void *, const void *);
-static struct vnodeData *ChangeDirectory(int, char **, struct vnodeData *);
-static void CopyFile(int, char **, struct vnodeData *, FILE *);
-static void CopyVnode(int, char **, FILE *);
-static void DumpAllFiles(int, char **, struct vnodeData *, VolumeDiskData *);
-static struct vnodeData *FindFile(struct vnodeData *, char *);
-static void ResetDirCursor(struct DirCursor *, struct vnodeData *);
-static struct DirEntry *ReadNextDir(struct DirCursor *, struct vnodeData *);
-static void MakeArgv(char *, int *, char ***);
-static char *GetToken(char *, char **, char *, char *[]);
-static int ReadInt16(FILE *, uint16_t *);
-static int ReadInt32(FILE *, uint32_t *);
-static int ReadString(FILE *, char *, int);
-static int ReadByteString(FILE *, void *, int);
-
-#ifdef RESIDENCY
-static int DumpVnodeFile(FILE *, struct VnodeDiskObject *, VolumeDiskData *);
-static void DumpAllResidencies(FILE *, struct vnodeData *, VolumeDiskData *);
-#endif
-
-int
-main(int argc, char *argv[])
-{
-    int c, errflg = 0, force = 0, inode = 0;
-    unsigned int magic;
-    struct DumpHeader dheader;
-    VolumeDiskData vol;
-    off64_t offset;
-#ifdef RESIDENCY
-    int Res, Arg1, Arg2, Arg3, i;
-    int dumpvnodes = 0;
-#endif
-    char *p;
-    struct winsize win;
-    FILE *f;
-    int fd;
-    time_t tmv;
-
-#ifdef RESIDENCY
-    for (i = 0; i < RS_MAXRESIDENCIES; i++) {
-       rscmdlineinfo[i].Algorithm = -1;
-       rscmdlineinfo[i].Size = -1;
-       rscmdlineinfo[i].DeviceTag = -1;
-       rscmdlineinfo[i].FSType = -1;
-    }
-#endif /* RESIDENCY */
-
-    /*
-     * Sigh, this is dumb, but we need the terminal window size
-     * to do intelligent things with "ls" later on.
-     */
-
-    if (isatty(STDOUT_FILENO)) {
-       if ((p = getenv("COLUMNS")) != NULL)
-           termsize = atoi(p);
-       else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0
-                && win.ws_col > 0)
-           termsize = win.ws_col;
-    }
-
-    while ((c = getopt(argc, argv, "difr:t:v")) != EOF)
-       switch (c) {
-       case 't':
-#ifdef RESIDENCY
-           if (sscanf(optarg, "%d/%d", &Res, &Arg1) != 2) {
-               errflg++;
-               break;
-           }
-
-           if (1 << (ffs(Res) - 1) != Res) {
-               fprintf(stderr, "Invalid residency %d\n", Res);
-               errflg++;
-               break;
-           }
-
-           if (Arg1 < 0 || Arg1 > 26) {
-               fprintf(stderr, "Invalid device tag: %d\n", Arg1);
-               errflg++;
-               break;
-           }
-           rscmdlineinfo[ffs(Res) - 1].DeviceTag = Arg1;
-#else /* RESIDENCY */
-           fprintf(stderr, "-t not supported in non-MRAFS " "dumptool.\n");
-           errflg++;
-#endif /* RESIDENCY */
-           break;
-
-       case 'r':
-#ifdef RESIDENCY
-           if (sscanf(optarg, "%d/%d/%d/%d", &Res, &Arg1, &Arg2, &Arg3) != 4) {
-               errflg++;
-               break;
-           }
-
-           if (Arg1 < 0 || Arg1 > 3) {
-               fprintf(stderr, "Invalid fstype: %d\n", Arg1);
-               errflg++;
-               break;
-           }
-
-           if (Arg2 < 0 || Arg2 > 2) {
-               fprintf(stderr, "Invalid size: %d\n", Arg2);
-               errflg++;
-               break;
-           }
-
-           if (Arg3 <= 0 || Arg3 > UFS_ALGORITHMS) {
-               fprintf(stderr, "Invalid algorithm: %d\n", Arg3);
-               errflg++;
-               break;
-           }
-           rscmdlineinfo[ffs(Res) - 1].FSType = Arg1;
-           rscmdlineinfo[ffs(Res) - 1].Size = Arg2;
-           rscmdlineinfo[ffs(Res) - 1].Algorithm = Arg3;
-#else /* RESIDENCY */
-           fprintf(stderr, "-r not supported in non-MRAFS " "dumptool.\n");
-           errflg++;
-#endif /* RESIDENCY */
-           break;
-       case 'd':
-#ifdef RESIDENCY
-           dumpvnodes++;
-#else /* RESIDENCY */
-           fprintf(stderr, "-d not supported in non-MRAFS " "dumptool.\n");
-           errflg++;
-#endif /* RESIDENCY */
-           break;
-       case 'v':
-           verbose++;
-           break;
-       case 'f':
-           force++;
-           break;
-       case 'i':
-           inode++;
-           break;
-       case '?':
-       default:
-           errflg++;
-       }
-
-    if (errflg || optind == argc) {
-       fprintf(stderr, "Usage: %s\n\t[-v] [-f]\n\t"
-#ifdef RESIDENCY
-               "[-t Residency/Tag]\n\t"
-               "[-r Residency/Type/Size/Algorithm]\n\t"
-               "[-d] filename [file_in_dump [file in dump ...]]\n",
-#else /* RESIDENCY */
-               "filename\n",
-#endif /* RESIDENCY */
-               argv[0]);
-       exit(1);
-    }
-
-    /*
-     * Try opening the dump file
-     */
-
-#ifdef O_LARGEFILE
-    if ((fd = open(argv[optind], O_RDONLY | O_LARGEFILE)) < 0) {
-#else
-    if ((fd = open(argv[optind], O_RDONLY)) < 0) {
-#endif
-       fprintf(stderr, "open of dumpfile %s failed: %s\n", argv[optind],
-               strerror(errno));
-       exit(1);
-    }
-
-    if ((f = fdopen(fd, "rb")) == NULL) {
-        fprintf(stderr, "fdopen of dumpfile %s failed: %s\n", argv[optind],
-               strerror(errno));
-       exit(1);
-    }
-
-    if (ReadDumpHeader(f, &dheader)) {
-       fprintf(stderr, "Failed to read dump header!\n");
-       exit(1);
-    }
-
-    if (verbose)
-       printf("Dump is for volume %lu (%s)\n",
-              (unsigned long) dheader.volumeId, dheader.volumeName);
-
-    if (getc(f) != D_VOLUMEHEADER) {
-       fprintf(stderr, "Volume header is missing from dump, aborting\n");
-       exit(1);
-    }
-
-    if (ReadVolumeHeader(f, &vol)) {
-       fprintf(stderr, "Unable to read volume header\n");
-       exit(1);
-    }
-
-    if (verbose) {
-       printf("Volume information:\n");
-       printf("\tid = %lu\n", (unsigned long) vol.id);
-       printf("\tparent id = %lu\n", (unsigned long) vol.parentId);
-       printf("\tname = %s\n", vol.name);
-       printf("\tflags =");
-       if (vol.inUse)
-           printf(" inUse");
-       if (vol.inService)
-           printf(" inService");
-       if (vol.blessed)
-           printf(" blessed");
-       if (vol.needsSalvaged)
-           printf(" needsSalvaged");
-       printf("\n");
-       printf("\tuniquifier = %lu\n", (unsigned long) vol.uniquifier);
-       tmv = vol.creationDate;
-       printf("\tCreation date = %s", ctime(&tmv));
-       tmv = vol.accessDate;
-       printf("\tLast access date = %s", ctime(&tmv));
-       tmv = vol.updateDate;
-       printf("\tLast update date = %s", ctime(&tmv));
-       printf("\tVolume owner = %lu\n", (unsigned long) vol.owner);
-    }
-
-    if (verbose)
-       printf("Scanning vnodes (this may take a while)\n");
-
-    /*
-     * We need to do two vnode scans; one to get the number of
-     * vnodes, the other to actually build the index.
-     */
-
-    offset = ftello64(f);
-
-    if (ScanVnodes(f, &vol, 1)) {
-       fprintf(stderr, "First vnode scan failed, aborting\n");
-       exit(1);
-    }
-
-    fseeko64(f, offset, SEEK_SET);
-
-    if (ScanVnodes(f, &vol, 0)) {
-       fprintf(stderr, "Second vnode scan failed, aborting\n");
-       exit(1);
-    }
-
-    if (getc(f) != D_DUMPEND || ReadInt32(f, &magic) || magic != DUMPENDMAGIC) {
-       fprintf(stderr, "Couldn't find dump postamble, ");
-       if (!force) {
-           fprintf(stderr, "aborting (use -f to override)\n");
-           exit(1);
-       } else {
-           fprintf(stderr, "continuing anyway\n");
-           fprintf(stderr, "WARNING: Dump may not be complete!\n");
-       }
-    }
-
-    /*
-     * If we wanted to simply dump all vnodes, do it now
-     */
-
-#ifdef RESIDENCY
-    if (dumpvnodes) {
-       struct vnodeData *vdata;
-
-       for (i = 0; i < numLargeVnodes; i++) {
-
-           vdata = LargeVnodeIndex[i];
-
-           if (vdata->vnode->type == vFidLookup)
-               if (DumpVnodeFile(stdout, vdata->vnode, &vol)) {
-                   fprintf(stderr, "DumpVnodeFile failed, " "aborting\n");
-                   exit(1);
-               }
-       }
-
-       for (i = 0; i < numSmallVnodes; i++) {
-
-           vdata = SmallVnodeIndex[i];
-
-           if (vdata->vnode->type == vFidLookup)
-               if (DumpVnodeFile(stdout, vdata->vnode, &vol)) {
-                   fprintf(stderr, "DumpVnodeFile failed, " "aborting\n");
-                   exit(1);
-               }
-       }
-
-    } else
-#endif /* RESIDENCY */
-    if (inode) {
-       /*
-        * Dump out all filenames with their corresponding FID
-        */
-
-       struct vnodeData *rootvdata;
-
-       if ((rootvdata = GetVnode(1)) == NULL) {
-           fprintf(stderr,
-                   "Can't get vnode data for root " "vnode!  Aborting\n");
-           exit(1);
-       }
-
-       DirListInternal(rootvdata, NULL, 0, 0, 1, 0, 1, 0, &vol, "");
-
-    } else if (argc > optind + 1) {
-#ifdef RESIDENCY
-       /*
-        * Dump out residencies of files given on the command line.
-        */
-
-       struct vnodeData *vdata, *rootvdata;
-
-       if ((rootvdata = GetVnode(1)) == NULL) {
-           fprintf(stderr,
-                   "Can't get vnode data for root " "vnode!  Aborting\n");
-           exit(1);
-       }
-
-       for (i = optind + 1; i < argc; i++) {
-
-           if ((vdata = FindFile(rootvdata, argv[i])) == NULL) {
-               fprintf(stderr, "Skipping file %s\n", argv[i]);
-               continue;
-           }
-
-           if (verbose)
-               printf("Residency locations for %s:\n", argv[i]);
-
-           while (vdata->vnode->NextVnodeId != 0) {
-
-               vdata = GetVnode(vdata->vnode->NextVnodeId);
-
-               if (vdata == NULL) {
-                   fprintf(stderr,
-                           "We had a vnode chain " "pointer to a vnode that "
-                           "doesn't exist, aborting!\n");
-                   exit(1);
-               }
-               if (vdata->vnode->type == vFidLookup)
-                   DumpVnodeFile(stdout, vdata->vnode, &vol);
-           }
-       }
-#else /* RESIDENCY */
-       fprintf(stderr, "Extra arguments after dump filename: %s\n",
-               argv[optind]);
-       exit(1);
-#endif /* RESIDENCY */
-    } else {
-       /*
-        * Perform an interactive restore
-        */
-
-       InteractiveRestore(f, &vol);
-    }
-
-    exit(0);
-}
-
-/*
- * Read the dump header, which is at the beginning of every dump
- */
-
-static int
-ReadDumpHeader(FILE * f, struct DumpHeader *header)
-{
-    unsigned int magic;
-    int tag, i;
-
-    if (getc(f) != D_DUMPHEADER || ReadInt32(f, &magic)
-       || ReadInt32(f, (unsigned int *)
-                    &header->version) || magic != DUMPBEGINMAGIC) {
-       if (verbose)
-           fprintf(stderr, "Couldn't find dump magic numbers\n");
-       return -1;
-    }
-
-    header->volumeId = 0;
-    header->nDumpTimes = 0;
-
-    while ((tag = getc(f)) > D_MAX && tag != EOF) {
-       unsigned short length;
-       switch (tag) {
-       case 'v':
-           if (ReadInt32(f, &header->volumeId)) {
-               if (verbose)
-                   fprintf(stderr, "Failed to read " "volumeId\n");
-               return -1;
-           }
-           break;
-       case 'n':
-           if (ReadString(f, header->volumeName, sizeof(header->volumeName))) {
-               if (verbose)
-                   fprintf(stderr, "Failed to read " "volume name\n");
-               return -1;
-           }
-           break;
-       case 't':
-           if (ReadInt16(f, &length)) {
-               if (verbose)
-                   fprintf(stderr,
-                           "Failed to read " "dump time array length\n");
-               return -1;
-           }
-           header->nDumpTimes = (length >> 1);
-           for (i = 0; i < header->nDumpTimes; i++)
-               if (ReadInt32(f, (unsigned int *)
-                             &header->dumpTimes[i].from)
-                   || ReadInt32(f, (unsigned int *)
-                                &header->dumpTimes[i].to)) {
-                   if (verbose)
-                       fprintf(stderr, "Failed to " "read dump times\n");
-                   return -1;
-               }
-           break;
-       default:
-           if (verbose)
-               fprintf(stderr, "Unknown dump tag \"%c\"\n", tag);
-           return -1;
-       }
-    }
-
-    if (!header->volumeId || !header->nDumpTimes) {
-       if (verbose)
-           fprintf(stderr,
-                   "We didn't get a volume Id or " "dump times listing\n");
-       return 1;
-    }
-
-    ungetc(tag, f);
-    return 0;
-}
-
-/*
- * Read the volume header; this is the information stored in VolumeDiskData.
- *
- * I'm not sure we need all of this, but read it in just in case.
- */
-
-static int
-ReadVolumeHeader(FILE * f, VolumeDiskData * vol)
-{
-    int tag;
-    unsigned int trash;
-    memset((void *)vol, 0, sizeof(*vol));
-
-    while ((tag = getc(f)) > D_MAX && tag != EOF) {
-       switch (tag) {
-       case 'i':
-           if (ReadInt32(f, &vol->id))
-               return -1;
-           break;
-       case 'v':
-           if (ReadInt32(f, &trash))
-               return -1;
-           break;
-       case 'n':
-           if (ReadString(f, vol->name, sizeof(vol->name)))
-               return -1;
-           break;
-       case 's':
-           vol->inService = getc(f);
-           break;
-       case 'b':
-           vol->blessed = getc(f);
-           break;
-       case 'u':
-           if (ReadInt32(f, &vol->uniquifier))
-               return -1;
-           break;
-       case 't':
-           vol->type = getc(f);
-           break;
-       case 'p':
-           if (ReadInt32(f, &vol->parentId))
-               return -1;
-           break;
-       case 'c':
-           if (ReadInt32(f, &vol->cloneId))
-               return -1;
-           break;
-       case 'q':
-           if (ReadInt32(f, (uint32_t *) & vol->maxquota))
-               return -1;
-           break;
-       case 'm':
-           if (ReadInt32(f, (uint32_t *) & vol->minquota))
-               return -1;
-           break;
-       case 'd':
-           if (ReadInt32(f, (uint32_t *) & vol->diskused))
-               return -1;
-           break;
-       case 'f':
-           if (ReadInt32(f, (uint32_t *) & vol->filecount))
-               return -1;
-           break;
-       case 'a':
-           if (ReadInt32(f, &vol->accountNumber))
-               return -1;
-           break;
-       case 'o':
-           if (ReadInt32(f, &vol->owner))
-               return -1;
-           break;
-       case 'C':
-           if (ReadInt32(f, &vol->creationDate))
-               return -1;
-           break;
-       case 'A':
-           if (ReadInt32(f, &vol->accessDate))
-               return -1;
-           break;
-       case 'U':
-           if (ReadInt32(f, &vol->updateDate))
-               return -1;
-           break;
-       case 'E':
-           if (ReadInt32(f, &vol->expirationDate))
-               return -1;
-           break;
-       case 'B':
-           if (ReadInt32(f, &vol->backupDate))
-               return -1;
-           break;
-       case 'O':
-           if (ReadString
-               (f, vol->offlineMessage, sizeof(vol->offlineMessage)))
-               return -1;
-           break;
-       case 'M':
-           if (ReadString(f, (char *)vol->stat_reads, VMSGSIZE))
-               return -1;
-           break;
-       case 'W':{
-               unsigned short length;
-               int i;
-               unsigned int data;
-               if (ReadInt16(f, &length))
-                   return -1;
-               for (i = 0; i < length; i++) {
-                   if (ReadInt32(f, &data))
-                       return -1;
-                   if (i < sizeof(vol->weekUse) / sizeof(vol->weekUse[0]))
-                       vol->weekUse[i] = data;
-               }
-               break;
-           }
-       case 'D':
-           if (ReadInt32(f, &vol->dayUseDate))
-               return -1;
-           break;
-       case 'Z':
-           if (ReadInt32(f, (uint32_t *) & vol->dayUse))
-               return -1;
-           break;
-#ifdef RESIDENCY
-       case 'R':{
-               unsigned short length;
-               int i;
-               unsigned int data;
-
-               if (ReadInt16(f, &length))
-                   return -1;
-               for (i = 0; i < length; i++) {
-                   if (ReadInt32(f, &data))
-                       return -1;
-                   if (i <
-                       sizeof(vol->DesiredInfo.DesiredResidencyWords) /
-                       sizeof(vol->DesiredInfo.DesiredResidencyWords[0]))
-                       vol->DesiredInfo.DesiredResidencyWords[i] = data;
-               }
-               break;
-           }
-       case 'S':{
-               unsigned short length;
-               int i;
-               unsigned int data;
-
-               if (ReadInt16(f, &length))
-                   return -1;
-               for (i = 0; i < length; i++) {
-                   if (ReadInt32(f, &data))
-                       return -1;
-                   if (i <
-                       sizeof(vol->UnDesiredInfo.UnDesiredResidencyWords) /
-                       sizeof(vol->UnDesiredInfo.UnDesiredResidencyWords[0]))
-                       vol->UnDesiredInfo.UnDesiredResidencyWords[i] = data;
-               }
-               break;
-           }
-#endif
-       default:
-           if (verbose)
-               fprintf(stderr, "Unknown dump tag \"%c\"\n", tag);
-           return -1;
-       }
-    }
-
-    ungetc(tag, f);
-    return 0;
-}
-
-/*
- * Scan all our vnode entries, and build indexing information.
- */
-
-static int
-ScanVnodes(FILE * f, VolumeDiskData * vol, int sizescan)
-{
-    int vnodeNumber;
-    int tag;
-    int numFileVnodes = 0;
-    int numDirVnodes = 0;
-    unsigned char buf[SIZEOF_LARGEDISKVNODE];
-    struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
-    off64_t offset, oldoffset;
-    struct vnodeData *vdata;
-    unsigned int length;
-
-    tag = getc(f);
-
-    while (tag == D_VNODE) {
-
-       offset = 0;
-       length = 0;
-       vnode->type = -1;
-       vnode->length = -1;
-
-       if (ReadInt32(f, (uint32_t *) & vnodeNumber)) {
-           fprintf(stderr, "failed int32 for 'vnodenum'\n");
-           return -1;
-       }
-
-       if (ReadInt32(f, &vnode->uniquifier)) {
-           fprintf(stderr, "failed int32 for 'uniquifier'\n");
-           return -1;
-       }
-
-       if (verbose > 1 && !sizescan)
-           printf("Got vnode %d\n", vnodeNumber);
-
-       while ((tag = getc(f)) > D_MAX && tag != EOF)
-           switch (tag) {
-           case 't':
-               vnode->type = (VnodeType) getc(f);
-               break;
-           case 'l':
-               {
-                   unsigned short tmp;
-                   if (ReadInt16(f, &tmp)) {
-                       fprintf(stderr, "failed int16 for 'l'\n");
-                       return -1;
-                   }
-                   vnode->linkCount = tmp;
-               }
-               break;
-           case 'v':
-               if (ReadInt32(f, &vnode->dataVersion)) {
-                   fprintf(stderr, "failed int32 for 'v'\n");
-                   return -1;
-               }
-               break;
-           case 'm':
-               if (ReadInt32(f, (uint32_t *) & vnode->unixModifyTime)) {
-                   fprintf(stderr, "failed int32 for 'm'\n");
-                   return -1;
-               }
-               break;
-           case 's':
-               if (ReadInt32(f, (uint32_t *) & vnode->serverModifyTime)) {
-                   fprintf(stderr, "failed int32 for 's'\n");
-                   return -1;
-               }
-               break;
-           case 'a':
-               if (ReadInt32(f, &vnode->author)) {
-                   fprintf(stderr, "failed int32 for 'a'\n");
-                   return -1;
-               }
-               break;
-           case 'o':
-               if (ReadInt32(f, &vnode->owner)) {
-                   fprintf(stderr, "failed int32 for 'o'\n");
-                   return -1;
-               }
-               break;
-           case 'g':
-               if (ReadInt32(f, (uint32_t *) & vnode->group)) {
-                   fprintf(stderr, "failed int32 for 'g'\n");
-                   return -1;
-               }
-               break;
-           case 'b':{
-                   unsigned short modeBits;
-                   if (ReadInt16(f, &modeBits))
-                       return -1;
-                   vnode->modeBits = modeBits;
-                   break;
-               }
-           case 'p':
-               if (ReadInt32(f, &vnode->parent)) {
-                   fprintf(stderr, "failed int32 for 'p'\n");
-                   return -1;
-               }
-               break;
-#ifdef RESIDENCY
-           case 'N':
-               if (ReadInt32(f, &vnode->NextVnodeId)) {
-                   fprintf(stderr, "failed int32 for 'N'\n");
-                   return -1;
-               }
-               break;
-           case 'R':
-               if (ReadInt32(f, &VLkp_Residencies(vnode))) {
-                   fprintf(stderr, "failed int32 for 'R'\n");
-                   return -1;
-               }
-               break;
-#endif
-           case 'S':
-               if (ReadInt32(f, &vnode->length)) {
-                   fprintf(stderr, "failed int32 for 'S'\n");
-                   return -1;
-               }
-               break;
-           case 'F':
-               if (ReadInt32(f, (uint32_t *) & vnode->vn_ino_lo))
-                   return -1;
-               break;
-           case 'A':
-               if (ReadByteString
-                   (f, (void *)VVnodeDiskACL(vnode), VAclDiskSize(vnode))) {
-                   fprintf(stderr, "failed readbystring for 'A'\n");
-                   return -1;
-               }
-#if 0
-               acl_NtohACL(VVnodeDiskACL(vnode));
-#endif
-               break;
-#ifdef RESIDENCY
-           case 'h':
-               if (ReadInt32(f, &vnode->length_hi)) {
-                   fprintf(stderr, "failed int32 for 'h'\n");
-                   return -1;
-               }
-#endif
-           case 'f':
-               if (verbose > 1 && !sizescan)
-                   printf("We have file data!\n");
-               if (ReadInt32(f, &length)) {
-                   fprintf(stderr, "failed int32 for 'f'\n");
-                   return -1;
-               }
-               vnode->length = length;
-               offset = ftello64(f);
-               fseeko64(f, length, SEEK_CUR);
-               break;
-           default:
-               if (verbose)
-                   fprintf(stderr, "Unknown dump tag \"%c\"\n", tag);
-               return -1;
-           }
-
-       /*
-        * If we're doing an incremental restore, then vnodes
-        * will be listed in the dump, but won't contain any
-        * vnode information at all (I don't know why they're
-        * included _at all_).  If we get one of these vnodes, then
-        * just skip it (because we can't do anything with it.
-        */
-
-       if (vnode->type == -1)
-           continue;
-
-#ifdef RESIDENCY
-       if (verbose > 1 && vnode->type == vFidLookup && !sizescan) {
-           printf
-               ("This is an auxiliary vnode (lookup) for vnode %d, residency %d\n",
-                VLkp_ParentVnodeId(vnode), VLkp_Residencies(vnode));
-           if (DumpVnodeFile(stdout, vnode, vol))
-               return -1;
-       }
-
-       if (verbose > 1 && vnode->type == vAccessHistory && !sizescan)
-           printf("This is an auxiliary vnode (history) for vnode %d\n",
-                  VLkp_ParentVnodeId(vnode));
-#endif
-
-       if (vnode->type == vDirectory)
-           numDirVnodes++;
-       else
-           numFileVnodes++;
-
-       /*
-        * We know now all we would ever know about the vnode;
-        * insert it into our hash table (but only if we're not
-        * doing a vnode scan).
-        */
-
-       if (!sizescan) {
-
-           vdata = InsertVnode(vnodeNumber, vnode);
-
-           if (vdata == NULL) {
-               if (verbose)
-                   fprintf(stderr,
-                           "Failed to insert " "vnode into hash table");
-               return -1;
-           }
-
-           vdata->dumpdata = offset;
-           vdata->datalength = length;
-
-           /*
-            * Save directory data, since we'll need it later.
-            */
-
-           if (vnode->type == vDirectory && length) {
-
-               vdata->filedata = malloc(length);
-
-               if (!vdata->filedata) {
-                   if (verbose)
-                       fprintf(stderr,
-                               "Unable to " "allocate space for "
-                               "file data (%d)\n", length);
-                   return -1;
-               }
-
-               oldoffset = ftello64(f);
-               fseeko64(f, offset, SEEK_SET);
-
-               if (fread(vdata->filedata, length, 1, f) != 1) {
-                   if (verbose)
-                       fprintf(stderr, "Unable to " "read in file data!\n");
-                   return -1;
-               }
-
-               fseeko64(f, oldoffset, SEEK_SET);
-           } else if (vnode->type == vDirectory)
-               /*
-                * Warn the user we may not have all directory
-                * vnodes
-                */
-               numNoDirData++;
-       }
-    }
-
-    ungetc(tag, f);
-
-    if (!sizescan) {
-
-       numLargeVnodes = numDirVnodes;
-       numSmallVnodes = numFileVnodes;
-
-    } else {
-       LargeVnodeIndex = (struct vnodeData **)
-           malloc(numDirVnodes * sizeof(struct vnodeData));
-       SmallVnodeIndex = (struct vnodeData **)
-           malloc(numFileVnodes * sizeof(struct vnodeData));
-
-       if (LargeVnodeIndex == NULL || SmallVnodeIndex == NULL) {
-           if (verbose)
-               fprintf(stderr,
-                       "Unable to allocate space " "for vnode tables\n");
-           return -1;
-       }
-    }
-
-    if (verbose)
-       fprintf(stderr, "%s vnode scan completed\n",
-               sizescan ? "Primary" : "Secondary");
-
-    return 0;
-}
-
-/*
- * Perform an interactive restore
- *
- * Parsing the directory information is a pain, but other than that
- * we just use the other tools we already have in here.
- */
-#define CMDBUFSIZE     (AFSPATHMAX * 2)
-static void
-InteractiveRestore(FILE * f, VolumeDiskData * vol)
-{
-    struct vnodeData *vdatacwd;        /* Vnode data for our current dir */
-    char cmdbuf[CMDBUFSIZE];
-    int argc;
-    char **argv;
-
-    /*
-     * Let's see if we can at least get the data for our root directory.
-     * If we can't, there's no way we can do an interactive restore.
-     */
-
-    if ((vdatacwd = GetVnode(1)) == NULL) {
-       fprintf(stderr, "No entry for our root vnode!  Aborting\n");
-       return;
-    }
-
-    if (!vdatacwd->filedata) {
-       fprintf(stderr,
-               "There is no directory data for the root "
-               "vnode (1.1).  An interactive\nrestore is not "
-               "possible.\n");
-       return;
-    }
-
-    /*
-     * If you're doing a selective dump correctly, then you should get all
-     * directory vnode data.  But just in case you didn't, let the user
-     * know there may be a problem.
-     */
-
-    if (numNoDirData)
-       fprintf(stderr,
-               "WARNING: %d directory vnodes had no file "
-               "data.  An interactive restore\nmay not be possible\n",
-               numNoDirData);
-
-    printf("> ");
-    while (fgets(cmdbuf, CMDBUFSIZE, stdin)) {
-
-       cmdbuf[strlen(cmdbuf) - 1] = '\0';
-
-       if (strlen(cmdbuf) == 0) {
-           printf("> ");
-           continue;
-       }
-
-       MakeArgv(cmdbuf, &argc, &argv);
-
-       if (strcmp(argv[0], "ls") == 0) {
-           DirectoryList(argc, argv, vdatacwd, vol);
-       } else if (strcmp(argv[0], "cd") == 0) {
-           struct vnodeData *newvdata;
-
-           newvdata = ChangeDirectory(argc, argv, vdatacwd);
-
-           if (newvdata)
-               vdatacwd = newvdata;
-       } else if (strcmp(argv[0], "file") == 0) {
-           DumpAllFiles(argc, argv, vdatacwd, vol);
-       } else if (strcmp(argv[0], "cp") == 0) {
-           CopyFile(argc, argv, vdatacwd, f);
-       } else if (strcmp(argv[0], "vcp") == 0) {
-           CopyVnode(argc, argv, f);
-       } else if (strcmp(argv[0], "quit") == 0
-                  || strcmp(argv[0], "exit") == 0)
-           break;
-       else if (strcmp(argv[0], "?") == 0 || strcmp(argv[0], "help") == 0) {
-           printf("Valid commands are:\n");
-           printf("\tls\t\tList current directory\n");
-           printf("\tcd\t\tChange current directory\n");
-           printf("\tcp\t\tCopy file from dump\n");
-           printf("\tvcp\t\tCopy file from dump (via vnode)\n");
-#ifdef RESIDENCY
-           printf("\tfile\t\tList residency filenames\n");
-#endif /* RESIDENCY */
-           printf("\tquit | exit\tExit program\n");
-           printf("\thelp | ?\tBrief help\n");
-       } else
-           fprintf(stderr,
-                   "Unknown command, \"%s\", enter "
-                   "\"help\" for a list of commands.\n", argv[0]);
-
-       printf("> ");
-    }
-
-    return;
-}
-
-/*
- * Do a listing of all files in a directory.  Sigh, I wish this wasn't
- * so complicated.
- *
- * With the reorganizing, this is just a front-end to DirListInternal()
- */
-
-static void
-DirectoryList(int argc, char **argv, struct vnodeData *vdata,
-             VolumeDiskData * vol)
-{
-    int errflg = 0, lflag = 0, iflag = 0, Fflag = 0, sflag = 0, Rflag = 0;
-    int c;
-
-    optind = 1;
-
-    while ((c = getopt(argc, argv, "liFRs")) != EOF)
-       switch (c) {
-       case 'l':
-           lflag++;
-           break;
-       case 'i':
-           iflag++;
-           break;
-       case 'F':
-           Fflag++;
-           break;
-       case 'R':
-           Rflag++;
-       case 's':
-           sflag++;
-           break;
-       case '?':
-       default:
-           errflg++;
-       }
-
-    if (errflg) {
-       fprintf(stderr, "Usage: %s [-liFs] filename [filename ...]\n",
-               argv[0]);
-       return;
-    }
-
-    DirListInternal(vdata, &(argv[optind]), argc - optind, lflag, iflag,
-                   Fflag, Rflag, 1, vol, NULL);
-
-    return;
-}
-
-/*
- * Function that does the REAL work in terms of directory listing
- */
-
-static void
-DirListInternal(struct vnodeData *vdata, char *pathnames[], int numpathnames,
-               int lflag, int iflag, int Fflag, int Rflag, int verbose,
-               VolumeDiskData * vol, char *path)
-{
-    struct DirEntry *ep, **eplist = NULL, **eprecurse = NULL;
-    struct DirCursor cursor;
-    struct vnodeData *lvdata;
-
-    int i, j, numentries = 0, longestname = 0, numcols, col, numrows;
-    int numrecurse = 0;
-
-    if (!vdata->filedata) {
-       fprintf(stderr, "There is no vnode data for this " "directory!\n");
-       return;
-    }
-
-    ResetDirCursor(&cursor, vdata);
-
-    /*
-     * Scan through the whole directory
-     */
-
-    while ((ep = ReadNextDir(&cursor, vdata)) != NULL) {
-
-       /*
-        * If we didn't get any filenames on the command line,
-        * get them all.
-        */
-
-       if (numpathnames == 0) {
-           eplist =
-               realloc(eplist, sizeof(struct DirEntry *) * ++numentries);
-           eplist[numentries - 1] = ep;
-           if (strlen(ep->name) > longestname)
-               longestname = strlen(ep->name);
-           if (Rflag)
-               if ((lvdata = GetVnode(ntohl(ep->fid.vnode)))
-                   && lvdata->vnode->type == vDirectory
-                   && !(strcmp(ep->name, ".") == 0
-                        || strcmp(ep->name, "..") == 0)) {
-                   eprecurse =
-                       realloc(eprecurse,
-                               sizeof(struct DirEntry *) * ++numrecurse);
-                   eprecurse[numrecurse - 1] = ep;
-               }
-
-       } else {
-           /*
-            * Do glob matching via fnmatch()
-            */
-
-           for (i = 0; i < numpathnames; i++)
-               if (fnmatch(pathnames[i], ep->name, FNM_PATHNAME) == 0) {
-                   eplist =
-                       realloc(eplist,
-                               sizeof(struct DirEntry *) * ++numentries);
-                   eplist[numentries - 1] = ep;
-                   if (strlen(ep->name) > longestname)
-                       longestname = strlen(ep->name);
-                   if (Rflag)
-                       if ((lvdata = GetVnode(ntohl(ep->fid.vnode)))
-                           && lvdata->vnode->type == vDirectory
-                           && !(strcmp(ep->name, ".") == 0
-                                || strcmp(ep->name, "..") == 0)) {
-                           eprecurse =
-                               realloc(eprecurse,
-                                       sizeof(struct DirEntry *) *
-                                       ++numrecurse);
-                           eprecurse[numrecurse - 1] = ep;
-                       }
-                   break;
-               }
-       }
-    }
-
-    qsort((void *)eplist, numentries, sizeof(struct DirEntry *),
-         CompareDirEntry);
-
-    if (Rflag && eprecurse)
-       qsort((void *)eprecurse, numrecurse, sizeof(struct DirEntry *),
-             CompareDirEntry);
-    /*
-     * We don't have to do column printing if we have the -l or the -i
-     * options.  Sigh, column printing is WAY TOO FUCKING COMPLICATED!
-     */
-
-    if (!lflag && !iflag) {
-       char c;
-
-       if (Fflag)
-           longestname++;
-
-       longestname++;
-
-       numcols = termsize / longestname ? termsize / longestname : 1;
-       numrows = numentries / numcols + (numentries % numcols ? 1 : 0);
-
-       for (i = 0; i < numrows; i++) {
-           col = 0;
-           while (col < numcols && (i + col * numrows) < numentries) {
-               ep = eplist[i + col++ * numrows];
-               if (Fflag) {
-                   if (!(lvdata = GetVnode(ntohl(ep->fid.vnode))))
-                       c = ' ';
-                   else if (lvdata->vnode->type == vDirectory)
-                       c = '/';
-                   else if (lvdata->vnode->type == vSymlink)
-                       c = '@';
-                   else if ((lvdata->vnode->modeBits & 0111) != 0)
-                       c = '*';
-                   else
-                       c = ' ';
-                   printf("%s%-*c", ep->name, (int)(longestname -
-                                                    strlen(ep->name)), c);
-               } else
-                   printf("%-*s", longestname, ep->name);
-           }
-
-           printf("\n");
-       }
-    } else if (iflag)
-       for (i = 0; i < numentries; i++)
-           if (!(lvdata = GetVnode(ntohl(eplist[i]->fid.vnode))))
-               printf("%d.0.0\t%s\n",
-                      vol->parentId ? vol->parentId : vol->id,
-                      eplist[i]->name);
-           else if (path)
-               printf("%d.%d.%d\t%s/%s\n", vol->id,
-                      ntohl(eplist[i]->fid.vnode),
-                      ntohl(eplist[i]->fid.vunique), path, eplist[i]->name);
-           else
-               printf("%d.%d.%d\t%s\n", vol->id, ntohl(eplist[i]->fid.vnode),
-                      ntohl(eplist[i]->fid.vunique), eplist[i]->name);
-    else if (lflag) {
-       for (i = 0; i < numentries; i++)
-           if (!(lvdata = GetVnode(ntohl(eplist[i]->fid.vnode))))
-               printf("----------   0 0        " "0                 0 %s\n",
-                      eplist[i]->name);
-           else {
-               switch (lvdata->vnode->type) {
-               case vDirectory:
-                   printf("d");
-                   break;
-               case vSymlink:
-                   printf("l");
-                   break;
-               default:
-                   printf("-");
-               }
-
-               for (j = 8; j >= 0; j--) {
-                   if (lvdata->vnode->modeBits & (1 << j))
-                       switch (j % 3) {
-                       case 2:
-                           printf("r");
-                           break;
-                       case 1:
-                           printf("w");
-                           break;
-                       case 0:
-                           printf("x");
-                   } else
-                       printf("-");
-               }
-
-               printf(" %-3d %-8d %-8d %10d %s\n", lvdata->vnode->linkCount,
-                      lvdata->vnode->owner, lvdata->vnode->group,
-                      lvdata->vnode->length, eplist[i]->name);
-           }
-    }
-
-    free(eplist);
-
-    if (Rflag && eprecurse) {
-       char *lpath;
-       lpath = NULL;
-       for (i = 0; i < numrecurse; i++) {
-           if (verbose)
-               printf("\n%s:\n", eprecurse[i]->name);
-           if (path) {
-               lpath = malloc(strlen(path) + strlen(eprecurse[i]->name) + 2);
-               if (lpath)
-                   sprintf(lpath, "%s/%s", path, eprecurse[i]->name);
-           }
-           DirListInternal(GetVnode(ntohl(eprecurse[i]->fid.vnode)), NULL, 0,
-                           lflag, iflag, Fflag, Rflag, verbose, vol, lpath);
-           if (lpath) {
-               free(lpath);
-               lpath = NULL;
-           }
-       }
-    }
-
-    if (eprecurse)
-       free(eprecurse);
-
-    return;
-}
-
-
-/*
- * Directory name comparison function, used by qsort
- */
-
-static int
-CompareDirEntry(const void *e1, const void *e2)
-{
-    struct DirEntry **ep1 = (struct DirEntry **)e1;
-    struct DirEntry **ep2 = (struct DirEntry **)e2;
-
-    return strcmp((*ep1)->name, (*ep2)->name);
-}
-
-/*
- * Change a directory.  Return a pointer to our new vdata structure for
- * this directory.
- */
-
-static struct vnodeData *
-ChangeDirectory(int argc, char **argv, struct vnodeData *vdatacwd)
-{
-    struct vnodeData *newvdatacwd;
-
-    if (argc != 2) {
-       fprintf(stderr, "Usage: %s directory\n", argv[0]);
-       return NULL;
-    }
-
-    if ((newvdatacwd = FindFile(vdatacwd, argv[1])) == NULL)
-       return NULL;
-
-    if (newvdatacwd->vnode->type != vDirectory) {
-       fprintf(stderr, "%s: Not a directory\n", argv[1]);
-       return NULL;
-    }
-
-    if (newvdatacwd->filedata == NULL) {
-       fprintf(stderr, "%s: No directory data found.\n", argv[1]);
-       return NULL;
-    }
-
-    return newvdatacwd;
-}
-
-/*
- * Copy a file from out of the dump file
- */
-
-#define COPYBUFSIZE 8192
-
-static void
-CopyFile(int argc, char **argv, struct vnodeData *vdatacwd, FILE * f)
-{
-    struct vnodeData *vdata;
-    FILE *out;
-    off64_t cur = 0;
-    int bytes, ret;
-    char buffer[COPYBUFSIZE];
-
-    if (argc != 3) {
-       fprintf(stderr, "Usage: %s dumpfile destfile\n", argv[0]);
-       return;
-    }
-
-    if ((vdata = FindFile(vdatacwd, argv[1])) == NULL)
-       return;
-
-    if (vdata->dumpdata == 0) {
-       fprintf(stderr, "File %s has no data in dump file\n", argv[1]);
-       return;
-    }
-
-    if ((out = fopen(argv[2], "wb")) == NULL) {
-       fprintf(stderr, "Open of %s failed: %s\n", argv[2], strerror(errno));
-       return;
-    }
-
-    if (fseeko64(f, vdata->dumpdata, SEEK_SET)) {
-       fprintf(stderr, "Seek failed: %s\n", strerror(errno));
-       fclose(out);
-       return;
-    }
-
-    while (cur < vdata->datalength) {
-
-       bytes =
-           cur + COPYBUFSIZE <
-           vdata->datalength ? COPYBUFSIZE : vdata->datalength - cur;
-
-       ret = fread(buffer, sizeof(char), bytes, f);
-       if (ret != bytes) {
-           if (ret != 0)
-               fprintf(stderr, "Short read (expected %d, " "got %d)\n",
-                       bytes, ret);
-           else
-               fprintf(stderr, "Error during read: %s\n", strerror(errno));
-           fclose(out);
-           return;
-       }
-
-       ret = fwrite(buffer, sizeof(char), bytes, out);
-       if (ret != bytes) {
-           if (ret != 0)
-               fprintf(stderr, "Short write (expected %d, " "got %d)\n",
-                       bytes, ret);
-           else
-               fprintf(stderr, "Error during write: %s\n", strerror(errno));
-           fclose(out);
-           return;
-       }
-
-       cur += bytes;
-    }
-
-    fclose(out);
-}
-
-/*
- * Copy a file from out of the dump file, by using the vnode
- */
-
-static void
-CopyVnode(int argc, char *argv[], FILE * f)
-{
-    struct vnodeData *vdata;
-    FILE *out;
-    off64_t cur = 0;
-    int bytes, ret;
-    char buffer[COPYBUFSIZE];
-    unsigned int vnode, uniquifier = 0;
-
-    if (argc != 3) {
-       fprintf(stderr, "Usage: %s vnode[.uniqifier] destfile\n", argv[0]);
-       return;
-    }
-
-    ret = sscanf(argv[1], "%d.%d", &vnode, &uniquifier);
-
-    if (ret < 1) {
-       fprintf(stderr, "Invalid file identifier: %s\n", argv[1]);
-       return;
-    }
-
-    if (!(vdata = GetVnode(vnode))) {
-       fprintf(stderr, "Vnode %d not in dump file\n", vnode);
-       return;
-    }
-
-    if (ret == 2 && vdata->vnode->uniquifier != uniquifier) {
-       fprintf(stderr,
-               "Specified uniquifier %d did not match "
-               "uniquifier %d found in dump file!\n", uniquifier,
-               vdata->vnode->uniquifier);
-       return;
-    }
-
-    if (vdata->dumpdata == 0) {
-       fprintf(stderr, "File %s has no data in dump file\n", argv[1]);
-       return;
-    }
-
-    if ((out = fopen(argv[2], "wb")) == NULL) {
-       fprintf(stderr, "Open of %s failed: %s\n", argv[2], strerror(errno));
-       return;
-    }
-
-    if (fseeko64(f, vdata->dumpdata, SEEK_SET)) {
-       fprintf(stderr, "Seek failed: %s\n", strerror(errno));
-       fclose(out);
-       return;
-    }
-
-    while (cur < vdata->datalength) {
-
-       bytes =
-           cur + COPYBUFSIZE <
-           vdata->datalength ? COPYBUFSIZE : vdata->datalength - cur;
-
-       ret = fread(buffer, sizeof(char), bytes, f);
-       if (ret != bytes) {
-           if (ret != 0)
-               fprintf(stderr, "Short read (expected %d, " "got %d)\n",
-                       bytes, ret);
-           else
-               fprintf(stderr, "Error during read: %s\n", strerror(errno));
-           fclose(out);
-           return;
-       }
-
-       ret = fwrite(buffer, sizeof(char), bytes, out);
-       if (ret != bytes) {
-           if (ret != 0)
-               fprintf(stderr, "Short write (expected %d, " "got %d)\n",
-                       bytes, ret);
-           else
-               fprintf(stderr, "Error during write: %s\n", strerror(errno));
-           fclose(out);
-           return;
-       }
-
-       cur += bytes;
-    }
-
-    fclose(out);
-}
-
-/*
- * Dump all residency filenames associated with a file, or all files
- * within a directory.
- */
-
-static void
-DumpAllFiles(int argc, char **argv, struct vnodeData *vdatacwd,
-            VolumeDiskData * vol)
-{
-#ifdef RESIDENCY
-    struct vnodeData *vdata, *nvdata;
-    struct DirCursor cursor;
-    struct DirEntry *ep;
-    FILE *f = stdout;
-    int c, i;
-    int dflag = 0, fflag = 0, errflg = 0;
-
-    optind = 1;
-
-    while ((c = getopt(argc, argv, "df:")) != EOF)
-       switch (c) {
-       case 'd':
-           dflag++;
-           break;
-       case 'f':
-           if ((f = fopen(optarg, "a")) == NULL) {
-               fprintf(stderr, "Cannot open \"%s\": %s\n", optarg,
-                       strerror(errno));
-               return;
-           }
-           fflag++;
-           break;
-       case 'h':
-       case '?':
-       default:
-           errflg++;
-       }
-
-    if (errflg || argc == optind) {
-       fprintf(stderr, "Usage: %s [-d] [-f filename] file " "[file ...]\n",
-               argv[0]);
-       if (fflag)
-           fclose(f);
-       return;
-    }
-
-    for (i = optind; i < argc; i++) {
-
-       if ((vdata = FindFile(vdatacwd, argv[i])) == NULL)
-           continue;
-
-       if (vdata->vnode->type == vDirectory && !dflag) {
-
-           ResetDirCursor(&cursor, vdata);
-
-           while ((ep = ReadNextDir(&cursor, vdata)) != NULL) {
-
-               if (!(nvdata = GetVnode(ntohl(ep->fid.vnode)))) {
-                   fprintf(stderr,
-                           "Cannot find vnode " "entry for %s (%d)\n",
-                           ep->name, ntohl(ep->fid.vnode));
-                   continue;
-               }
-
-
-               if (!fflag) {
-                   printf("Residency locations for %s:\n", ep->name);
-
-                   if (nvdata->dumpdata)
-                       printf("Local disk (in dump " "file)\n");
-               }
-
-               DumpAllResidencies(f, nvdata, vol);
-
-           }
-
-       } else {
-           if (!fflag) {
-               printf("Residency locations for %s:\n", argv[i]);
-
-               if (vdata->dumpdata)
-                   printf("Local disk (in dump file)\n");
-           }
-
-           DumpAllResidencies(f, vdata, vol);
-       }
-    }
-
-    if (fflag)
-       fclose(f);
-#else /* RESIDENCY */
-    fprintf(stderr,
-           "The \"file\" command is not available in the non-"
-           "MRAFS version of dumptool.\n");
-#endif /* RESIDENCY */
-    return;
-}
-
-/*
- * Take a vnode, traverse the vnode chain, and dump out all files on
- * all residencies corresponding to that parent vnode.
- */
-
-#ifdef RESIDENCY
-static void
-DumpAllResidencies(FILE * f, struct vnodeData *vdata,
-                  struct VolumeDiskData *vol)
-{
-    unsigned int nextVnodeNum;
-
-    while (nextVnodeNum = vdata->vnode->NextVnodeId) {
-       if ((vdata = GetVnode(nextVnodeNum)) == NULL) {
-           fprintf(stderr,
-                   "We had a pointer to %lu in it's "
-                   "vnode chain, but there\nisn't a record of "
-                   "it!  The dump might be corrupt.\n", nextVnodeNum);
-           return;
-       }
-
-       if (vdata->vnode->type == vFidLookup)
-           DumpVnodeFile(f, vdata->vnode, vol);
-    }
-
-    return;
-}
-#endif
-
-
-/*
- * Given a directory vnode and a filename, return the vnode corresponding
- * to the file in that directory.
- *
- * We now handle pathnames with directories in them.
- */
-
-static struct vnodeData *
-FindFile(struct vnodeData *vdatacwd, char *filename)
-{
-    struct DirHeader *dhp;
-    struct DirEntry *ep;
-    int i, num;
-    struct vnodeData *vdata;
-    char *c, newstr[MAXPATHLEN];
-
-    if (!vdatacwd->filedata) {
-       fprintf(stderr, "There is no vnode data for this " "directory!\n");
-       return NULL;
-    }
-
-    /*
-     * If we have a "/" in here, look up the vnode data for the
-     * directory (everything before the "/") and use that as our
-     * current directory.  We automagically handle multiple directories
-     * by using FindFile recursively.
-     */
-
-    if ((c = strrchr(filename, '/')) != NULL) {
-
-       strncpy(newstr, filename, c - filename);
-       newstr[c - filename] = '\0';
-
-       if ((vdatacwd = FindFile(vdatacwd, newstr)) == NULL)
-           return NULL;
-
-       if (vdatacwd->vnode->type != vDirectory) {
-           fprintf(stderr, "%s: Not a directory\n", newstr);
-           return NULL;
-       }
-
-       filename = c + 1;
-    }
-
-    dhp = (struct DirHeader *)vdatacwd->filedata;
-
-    i = DirHash(filename);
-
-    num = ntohs(dhp->hashTable[i]);
-
-    while (num) {
-       ep = (struct DirEntry *)(vdatacwd->filedata + (num * 32));
-       if (strcmp(ep->name, filename) == 0)
-           break;
-       num = ntohs(ep->next);
-    }
-
-    if (!num) {
-       fprintf(stderr, "%s: No such file or directory\n", filename);
-       return NULL;
-    }
-
-    if ((vdata = GetVnode(ntohl(ep->fid.vnode))) == NULL) {
-       fprintf(stderr, "%s: No vnode information for %u found\n", filename,
-               ntohl(ep->fid.vnode));
-       return NULL;
-    }
-
-    return vdata;
-}
-
-/*
- * Reset a structure containing the current directory scan location
- */
-
-static void
-ResetDirCursor(struct DirCursor *cursor, struct vnodeData *vdata)
-{
-    struct DirHeader *dhp;
-
-    cursor->hashbucket = 0;
-
-    dhp = (struct DirHeader *)vdata->filedata;
-
-    cursor->entry = ntohs(dhp->hashTable[0]);
-}
-
-/*
- * Given a cursor and a directory entry, return the next entry in the
- * directory.
- */
-
-static struct DirEntry *
-ReadNextDir(struct DirCursor *cursor, struct vnodeData *vdata)
-{
-    struct DirHeader *dhp;
-    struct DirEntry *ep;
-
-    dhp = (struct DirHeader *)vdata->filedata;
-
-    if (cursor->entry) {
-       ep = (struct DirEntry *)(vdata->filedata + (cursor->entry * 32));
-       cursor->entry = ntohs(ep->next);
-       return ep;
-    } else {
-       while (++(cursor->hashbucket) < NHASHENT) {
-           cursor->entry = ntohs(dhp->hashTable[cursor->hashbucket]);
-           if (cursor->entry) {
-               ep = (struct DirEntry *)(vdata->filedata +
-                                        (cursor->entry * 32));
-               cursor->entry = ntohs(ep->next);
-               return ep;
-           }
-       }
-    }
-
-    return NULL;
-}
-
-/*
- * Given a string, split it up into components a la Unix argc/argv.
- *
- * This code is most stolen from ftp.
- */
-
-static void
-MakeArgv(char *string, int *argc, char ***argv)
-{
-    static char *largv[64];
-    char **la = largv;
-    char *s = string;
-    static char argbuf[CMDBUFSIZE];
-    char *ap = argbuf;
-
-    *argc = 0;
-    *argv = largv;
-
-    while ((*la++ = GetToken(s, &s, ap, &ap)) != NULL)
-       (*argc)++;
-}
-
-/*
- * Return a pointer to the next token, and update the current string
- * position.
- */
-
-static char *
-GetToken(char *string, char **nexttoken, char argbuf[], char *nextargbuf[])
-{
-    char *sp = string;
-    char *ap = argbuf;
-    int got_one = 0;
-
-  S0:
-    switch (*sp) {
-
-    case '\0':
-       goto OUTTOKEN;
-
-    case ' ':
-    case '\t':
-       sp++;
-       goto S0;
-
-    default:
-       goto S1;
-    }
-
-  S1:
-    switch (*sp) {
-
-    case ' ':
-    case '\t':
-    case '\0':
-       goto OUTTOKEN;          /* End of our token */
-
-    case '\\':
-       sp++;
-       goto S2;                /* Get next character */
-
-    case '"':
-       sp++;
-       goto S3;                /* Get quoted string */
-
-    default:
-       *ap++ = *sp++;          /* Add a character to our token */
-       got_one = 1;
-       goto S1;
-    }
-
-  S2:
-    switch (*sp) {
-
-    case '\0':
-       goto OUTTOKEN;
-
-    default:
-       *ap++ = *sp++;
-       got_one = 1;
-       goto S1;
-    }
-
-  S3:
-    switch (*sp) {
-
-    case '\0':
-       goto OUTTOKEN;
-
-    case '"':
-       sp++;
-       goto S1;
-
-    default:
-       *ap++ = *sp++;
-       got_one = 1;
-       goto S3;
-    }
-
-  OUTTOKEN:
-    if (got_one)
-       *ap++ = '\0';
-    *nextargbuf = ap;          /* Update storage pointer */
-    *nexttoken = sp;           /* Update token pointer */
-
-    return got_one ? argbuf : NULL;
-}
-
-/*
- * Insert vnodes into our hash table.
- */
-
-static struct vnodeData *
-InsertVnode(unsigned int vnodeNumber, struct VnodeDiskObject *vnode)
-{
-    struct VnodeDiskObject *nvnode;
-    struct vnodeData *vdata;
-    static int curSmallVnodeIndex = 0;
-    static int curLargeVnodeIndex = 0;
-    struct vnodeData ***vnodeIndex;
-    int *curIndex;
-
-    nvnode = (struct VnodeDiskObject *)malloc(sizeof(struct VnodeDiskObject));
-
-    if (!nvnode) {
-       if (verbose)
-           fprintf(stderr, "Unable to allocate space for vnode\n");
-       return NULL;
-    }
-
-    memcpy((void *)nvnode, (void *)vnode, sizeof(struct VnodeDiskObject));
-
-    if (vnodeNumber & 1) {
-       vnodeIndex = &LargeVnodeIndex;
-       curIndex = &curLargeVnodeIndex;
-    } else {
-       vnodeIndex = &SmallVnodeIndex;
-       curIndex = &curSmallVnodeIndex;
-    }
-
-    vdata = (struct vnodeData *)malloc(sizeof(struct vnodeData));
-
-    vdata->vnode = nvnode;
-    vdata->vnodeNumber = vnodeNumber;
-    vdata->dumpdata = 0;
-    vdata->filedata = 0;
-    vdata->datalength = 0;
-
-    (*vnodeIndex)[(*curIndex)++] = vdata;
-
-    return vdata;
-}
-
-/*
- * Routine to retrieve a vnode from the hash table.
- */
-
-static struct vnodeData *
-GetVnode(unsigned int vnodeNumber)
-{
-    struct vnodeData vnode, *vnodep, **tmp;
-
-    vnode.vnodeNumber = vnodeNumber;
-    vnodep = &vnode;
-
-    tmp = (struct vnodeData **)
-       bsearch((void *)&vnodep,
-               vnodeNumber & 1 ? LargeVnodeIndex : SmallVnodeIndex,
-               vnodeNumber & 1 ? numLargeVnodes : numSmallVnodes,
-               sizeof(struct vnodeData *), CompareVnode);
-
-    return tmp ? *tmp : NULL;
-}
-
-/*
- * Our comparator function for bsearch
- */
-
-static int
-CompareVnode(const void *node1, const void *node2)
-{
-    struct vnodeData **vnode1 = (struct vnodeData **)node1;
-    struct vnodeData **vnode2 = (struct vnodeData **)node2;
-
-    if ((*vnode1)->vnodeNumber == (*vnode2)->vnodeNumber)
-       return 0;
-    else if ((*vnode1)->vnodeNumber > (*vnode2)->vnodeNumber)
-       return 1;
-    else
-       return -1;
-}
-
-#ifdef RESIDENCY
-/*
- * Dump out the filename corresponding to a particular vnode.
- *
- * This routine has the following dependancies:
- *
- * - Only will work on UFS filesystems at this point
- * - Has to talk to the rsserver.
- * - Can only determine UFS algorithm type when run on the same machine
- *   as the residency (unless you manually specify algorithm information)
- */
-
-static int
-DumpVnodeFile(FILE * f, struct VnodeDiskObject *vnode, VolumeDiskData * vol)
-{
-    static int rscache = 0;
-    static rsaccessinfoList rsnlist = { 0, 0 };
-    char MountPoint[MAXPATHLEN + 1];
-    char FileName[MAXPATHLEN + 1];
-    unsigned int Size, Level[4];
-    unsigned int DeviceTag, Algorithm;
-    FileSystems *FSInfo;
-    int i, found, FSType, rsindex;
-
-    /*
-     * Maybe we found out something about this residency via the
-     * command-line; check that first.
-     */
-
-    rsindex = ffs(VLkp_Residencies(vnode)) - 1;
-
-    /*
-     * We need to get information from the rsserver (so we can
-     * find out the device tag for a given residency).  If we
-     * haven't cached that, talk to the rsserver to get it.
-     * If we have info about this already, then don't talk to
-     * the rsserver (this lets us still do disaster recovery if
-     * MR-AFS is completely hosed).
-     */
-
-    if (!rscache && rscmdlineinfo[rsindex].DeviceTag == -1) {
-       int code;
-
-       code = ServerInitResidencyConnection();
-
-       if (code) {
-           fprintf(stderr,
-                   "ServerInitResidencyConnection failed " "with code %d\n",
-                   code);
-           return -1;
-       }
-
-       code = rs_GetResidencySummary(ServerRequestorId, &rsnlist);
-
-       if (code) {
-           fprintf(stderr, "rs_GetResidencySummary failed " "with code %d\n",
-                   code);
-           return -1;
-       }
-
-       rscache = 1;
-    }
-
-    /*
-     * For a given residency (as specified in the vnode),
-     * find out it's device tag number, either via the rsserver
-     * or via the command line.
-     */
-
-    if (rscmdlineinfo[rsindex].DeviceTag != -1) {
-       DeviceTag = rscmdlineinfo[rsindex].DeviceTag;
-       found = 1;
-    } else
-       for (i = 0, found = 0; (i < rsnlist.rsaccessinfoList_len) && (!found);
-            i++) {
-           if (rsnlist.rsaccessinfoList_val[i].id.residency ==
-               VLkp_Residencies(vnode)) {
-               found = 1;
-               DeviceTag = rsnlist.rsaccessinfoList_val[i].devicetagnumber;
-               break;
-           }
-       }
-
-    if (!found) {
-       if (verbose)
-           fprintf(stderr,
-                   "Unable to find residency %d in "
-                   "rsserver database, aborting\n", VLkp_Residencies(vnode));
-       return -1;
-    }
-
-    /*
-     * Okay, now we've got the DeviceTag ... which we can use to
-     * lookup the on-disk configuration information (which we
-     * assume is locally stored).  We also need the DeviceTag to
-     * print out which partition we're using (but that comes later).
-     *
-     * We lookup the on-disk configuration information by calling
-     * Ufs_GetFSInfo() to get the configuration information on the
-     * filesystems specified by the given DeviceTag.
-     *
-     * Before we call Ufs_GetFSInfo, check the command-line cache;
-     * if we got something via the command-line, don't go to disk.
-     */
-
-    if (rscmdlineinfo[rsindex].FSType == -1
-       && Ufs_GetFSInfo(&FSInfo, DeviceTag)) {
-       if (verbose)
-           fprintf(stderr,
-                   "Ufs_GetFSInfo failed for DeviceTag "
-                   "%d, Residency %d\n", DeviceTag, VLkp_Residencies(vnode));
-       return -1;
-    }
-
-    /*
-     * The FSInfo structure has the last two things we need: the
-     * FSType (ufs, slowufs, etc etc), and the usage algorithm (which
-     * ends up being how many directories are being used on the
-     * residency filesystem).
-     *
-     * With these last two parameters, use routines stolen from
-     * ufsname to generate the filename.
-     *
-     * (Actually, I lied - we also need the "Size" parameter, which
-     * we can also get from FSInfo);
-     */
-
-    if (rscmdlineinfo[rsindex].FSType != -1) {
-       FSType = rscmdlineinfo[rsindex].FSType;
-       Algorithm = rscmdlineinfo[rsindex].Algorithm;
-       Size = rscmdlineinfo[rsindex].Size;
-    } else {
-       FSType = FSInfo->FileSystems_u.UfsInterface.FSType;
-       Algorithm = FSInfo->FileSystems_u.UfsInterface.Algorithm;
-       if (FSInfo->FileSystems_u.UfsInterface.Directories[1] == 0)
-           Size = 0;
-       else if (FSInfo->FileSystems_u.UfsInterface.Directories[1] == 16)
-           Size = 1;
-       else if (FSInfo->FileSystems_u.UfsInterface.Directories[1] == 256)
-           Size = 2;
-       else {
-           if (verbose)
-               fprintf(stderr, "Unknown directory size %d, " "aborting\n",
-                       FSInfo->FileSystems_u.UfsInterface.Directories[1]);
-           return -1;
-       }
-    }
-
-    /*
-     * First, generate our mount point from the DeviceTag and
-     * FSType.
-     */
-
-    DEVICETAGNUMBERTOMOUNTPOINT(MountPoint, DeviceTag, FSType);
-
-    /*
-     * Then, generate the "level" (directory bitmasks) from the
-     * file tags, size, and algorithm
-     */
-
-    UfsTagsToLevel(VLkp_FileTag1(vnode), VLkp_FileTag2(vnode), Algorithm,
-                  Size, Level, VLkp_ParentVnodeId(vnode),
-                  VLkp_ParentUniquifierId(vnode));
-
-    /*
-     * Finally, take the above information and generate the
-     * corresponding filename (this macro ends up being a
-     * sprintf() call)
-     */
-
-    TAGSTONAME(FileName, MountPoint, Level, Directories[Size][1],
-              vol->parentId, VLkp_ParentVnodeId(vnode),
-              VLkp_ParentUniquifierId(vnode), Algorithm);
-
-    fprintf(f, "%s\n", FileName);
-
-    return 0;
-}
-#endif
-
-/*
- * Read a 16 bit integer in network order
- */
-
-static int
-ReadInt16(FILE * f, unsigned short *s)
-{
-    unsigned short in;
-
-    if (fread((void *)&in, sizeof(in), 1, f) != 1) {
-       if (verbose)
-           fprintf(stderr, "ReadInt16 failed!\n");
-       return -1;
-    }
-
-    *s = ntohs(in);
-
-    return 0;
-}
-
-
-/*
- * Read a 32 bit integer in network order
- */
-
-static int
-ReadInt32(FILE * f, unsigned int *i)
-{
-    unsigned int in;
-
-    if (fread((void *)&in, sizeof(in), 1, f) != 1) {
-       if (verbose)
-           fprintf(stderr, "ReadInt32 failed!\n");
-       return -1;
-    }
-
-    *i = ntohl((unsigned long)in);
-
-    return 0;
-}
-
-/*
- * Read a string from a dump file
- */
-
-static int
-ReadString(FILE * f, char *string, int maxlen)
-{
-    int c;
-
-    while (maxlen--) {
-       if ((*string++ = getc(f)) == 0)
-           break;
-    }
-
-    /*
-     * I'm not sure what the _hell_ this is supposed to do ...
-     * but it was in the original dump code
-     */
-
-    if (string[-1]) {
-       while ((c = getc(f)) && c != EOF);
-       string[-1] = 0;
-    }
-
-    return 0;
-}
-
-static int
-ReadByteString(FILE * f, void *s, int size)
-{
-    unsigned char *c = (unsigned char *)s;
-
-    while (size--)
-       *c++ = getc(f);
-
-    return 0;
-}
-
-/*
- * The directory hashing algorithm used by AFS
- */
-
-int
-DirHash(char *string)
-{
-    /* Hash a string to a number between 0 and NHASHENT. */
-    unsigned char tc;
-    int hval;
-    int tval;
-    hval = 0;
-    while ((tc = (*string++)) != '\0') {
-       hval *= 173;
-       hval += tc;
-    }
-    tval = hval & (NHASHENT - 1);
-#ifdef AFS_CRAY_ENV            /* actually, any > 32 bit environment */
-    if (tval == 0)
-       return tval;
-    else if (hval & 0x80000000)
-       tval = NHASHENT - tval;
-#else /* AFS_CRAY_ENV */
-    if (tval == 0)
-       return tval;
-    else if (hval < 0)
-       tval = NHASHENT - tval;
-#endif /* AFS_CRAY_ENV */
-    return tval;
-}
-
-#ifdef RESIDENCY
-/*
- * Sigh, we need this for the AFS libraries
- */
-
-int
-LogErrors(int level, char *a, char *b, char *c, char *d, char *e, char *f,
-         char *g, char *h, char *i, char *j, char *k)
-{
-    if (level <= 0) {
-       fprintf(stderr, a, b, c, d, e, f, g, h, i, j, k);
-    }
-    return 0;
-}
-
-/*
- * These are routines taken from AFS libraries and programs.  Most of
- * them are from ufsname.c, but a few are from the dir library (the dir
- * library has a bunch of hidden dependancies, so it's not suitable to
- * include it outright).
- */
-
-UfsEntropiesToTags(HighEntropy, LowEntropy, Algorithm, FileTag1, FileTag2)
-     uint32_t HighEntropy;
-     uint32_t LowEntropy;
-     uint32_t Algorithm;
-     uint32_t *FileTag1;
-     uint32_t *FileTag2;
-{
-    int i;
-
-    if ((Algorithm > UFS_ALGORITHMS) || (Algorithm <= 0))
-       return -1;
-    *FileTag1 = 0;
-    *FileTag2 = 0;
-    for (i = 0; i < 32; ++i) {
-       if (UfsEntropy[Algorithm - 1][i] < 32)
-           *FileTag1 |=
-               ((HighEntropy & (1 << i)) ==
-                0) ? 0 : 1 << UfsEntropy[Algorithm - 1][i];
-       else
-           *FileTag2 |=
-               ((HighEntropy & (1 << i)) ==
-                0) ? 0 : 1 << (UfsEntropy[Algorithm - 1][i] - 32);
-    }
-    for (i = 32; i < 64; ++i) {
-       if (UfsEntropy[Algorithm - 1][i] < 32)
-           *FileTag1 |=
-               ((LowEntropy & (1 << (i - 32))) ==
-                0) ? 0 : 1 << UfsEntropy[Algorithm - 1][i];
-       else
-           *FileTag2 |=
-               ((LowEntropy & (1 << (i - 32))) ==
-                0) ? 0 : 1 << (UfsEntropy[Algorithm - 1][i] - 32);
-    }
-    return 0;
-}
-
-uint32_t
-UfsTagsToHighEntropy(FileTag1, FileTag2, Algorithm)
-     uint32_t FileTag1;
-     uint32_t FileTag2;
-     uint32_t Algorithm;
-{
-    int i;
-    uint32_t Value;
-
-    Value = 0;
-    for (i = 0; i < 32; ++i) {
-       if (UfsEntropy[Algorithm - 1][i] < 32)
-           Value |= ((FileTag1 & (1 << UfsEntropy[Algorithm - 1][i]))
-                     == 0) ? 0 : 1 << i;
-       else
-           Value |=
-               ((FileTag2 & (1 << (UfsEntropy[Algorithm - 1][i] - 32))) ==
-                0) ? 0 : 1 << i;
-    }
-    return Value;
-}
-
-uint32_t
-UfsTagsToLowEntropy(FileTag1, FileTag2, Algorithm)
-     uint32_t FileTag1;
-     uint32_t FileTag2;
-     uint32_t Algorithm;
-{
-    int i;
-    uint32_t Value;
-
-    Value = 0;
-    for (i = 32; i < 64; ++i) {
-       if (UfsEntropy[Algorithm - 1][i] < 32)
-           Value |= ((FileTag1 & (1 << UfsEntropy[Algorithm - 1][i]))
-                     == 0) ? 0 : 1 << (i - 32);
-       else
-           Value |=
-               ((FileTag2 & (1 << (UfsEntropy[Algorithm - 1][i] - 32))) ==
-                0) ? 0 : 1 << (i - 32);
-    }
-    return Value;
-}
-
-UfsTagsToLevel(FileTag1, FileTag2, Algorithm, Size, Sections, vnode,
-              Uniquifier)
-     uint32_t FileTag1;
-     uint32_t FileTag2;
-     uint32_t Algorithm;
-     uint32_t Size;
-     uint32_t Sections[4];
-     uint32_t vnode;
-     uint32_t Uniquifier;
-{
-    uint32_t HighEntropy;
-    uint32_t LowEntropy;
-
-    switch (Algorithm) {
-    case 1:
-       LowEntropy = UfsTagsToLowEntropy(FileTag1, FileTag2, Algorithm);
-       HighEntropy = UfsTagsToHighEntropy(FileTag1, FileTag2, Algorithm);
-       Sections[0] = HighEntropy % Directories[Size][0];
-       HighEntropy /= Directories[Size][0];
-       if (Directories[Size][1]) {
-           Sections[1] = HighEntropy % Directories[Size][1];
-           HighEntropy /= Directories[Size][1];
-           Sections[2] = HighEntropy;
-           Sections[3] = LowEntropy;
-       } else {
-           Sections[1] = HighEntropy;
-           Sections[2] = LowEntropy;
-       }
-       break;
-    case 2:
-       Sections[0] = FileTag1 & 0xff;
-       if (Directories[Size][1]) {
-           Sections[1] = Uniquifier & 0xff;
-           if (Directories[Size][1] == 16)
-               Sections[1] &= 0xf;
-           Sections[2] = FileTag1;
-           Sections[3] = FileTag2;
-       } else {
-           Sections[1] = FileTag1;
-           Sections[2] = FileTag2;
-       }
-       break;
-    case 3:
-       Sections[0] = FileTag1 & 0xff;
-       if (Directories[Size][1]) {
-           Sections[1] = (vnode >> 1) & 0xff;
-           if (Directories[Size][1] == 16)
-               Sections[1] &= 0xf;
-           Sections[2] = FileTag1;
-           Sections[3] = FileTag2;
-       } else {
-           Sections[1] = FileTag1;
-           Sections[2] = FileTag2;
-       }
-       break;
-    default:
-       fprintf(stderr, "UfsTagsToLevel: bad algorithm %lu!\n", Algorithm);
-       return -1;
-    }
-    return 0;
-}
-
-#include <afs/afscbdummies.h>
-#endif /* RESIDENCY */
diff --git a/src/tests/int64.c b/src/tests/int64.c
deleted file mode 100644 (file)
index de3396b..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* int64.c - Support for 64-bit integers */
-
-#include <stdio.h>
-#include <string.h>
-#include "intNN.h"
-
-char *
-hexify_int64(u_int64 * X, char *buf)
-{
-    static char mybuf[17];
-
-#ifdef NATIVE_INT64
-    char c, *p;
-    u_int64 x = *X;
-
-    if (!buf)
-       buf = mybuf;
-    p = buf + 16;
-    *p-- = 0;
-    while (x && p >= buf) {
-       c = x & 0xf;
-       c += ((c < 10) ? '0' : 'a' - 10);
-       *p-- = c;
-       x >>= 4;
-    }
-    while (p >= buf)
-       *p-- = '0';
-
-#else
-    if (!buf)
-       buf = mybuf;
-    sprintf(buf, "%08lx%08lx", (unsigned long)X->hi, (unsigned long)X->lo);
-#endif
-
-    return buf;
-}
-
-
-#ifdef NATIVE_INT64
-char *
-decimate_int64(u_int64 * X, char *buf)
-{
-    static char mybuf[21];
-    char *p;
-    u_int64 x = *X;
-
-    if (!buf)
-       buf = mybuf;
-    p = buf + 21;
-    *--p = 0;
-    while (x && p > buf) {
-       *--p = ((x % 10) + '0');
-       x /= 10;
-    }
-    if (!*p)
-       *--p = '0';
-    return p;
-}
-
-#else
-static char bitvals[64][21] = {
-/*                1 */ "00000000000000000001",
-/*                2 */ "00000000000000000002",
-/*                4 */ "00000000000000000004",
-/*                8 */ "00000000000000000008",
-/*               10 */ "00000000000000000016",
-/*               20 */ "00000000000000000032",
-/*               40 */ "00000000000000000064",
-/*               80 */ "00000000000000000128",
-/*              100 */ "00000000000000000256",
-/*              200 */ "00000000000000000512",
-/*              400 */ "00000000000000001024",
-/*              800 */ "00000000000000002048",
-/*             1000 */ "00000000000000004096",
-/*             2000 */ "00000000000000008192",
-/*             4000 */ "00000000000000016384",
-/*             8000 */ "00000000000000032768",
-/*            10000 */ "00000000000000065536",
-/*            20000 */ "00000000000000131072",
-/*            40000 */ "00000000000000262144",
-/*            80000 */ "00000000000000524288",
-/*           100000 */ "00000000000001048576",
-/*           200000 */ "00000000000002097152",
-/*           400000 */ "00000000000004194304",
-/*           800000 */ "00000000000008388608",
-/*          1000000 */ "00000000000016777216",
-/*          2000000 */ "00000000000033554432",
-/*          4000000 */ "00000000000067108864",
-/*          8000000 */ "00000000000134217728",
-/*         10000000 */ "00000000000268435456",
-/*         20000000 */ "00000000000536870912",
-/*         40000000 */ "00000000001073741824",
-/*         80000000 */ "00000000002147483648",
-/*        100000000 */ "00000000004294967296",
-/*        200000000 */ "00000000008589934592",
-/*        400000000 */ "00000000017179869184",
-/*        800000000 */ "00000000034359738368",
-/*       1000000000 */ "00000000068719476736",
-/*       2000000000 */ "00000000137438953472",
-/*       4000000000 */ "00000000274877906944",
-/*       8000000000 */ "00000000549755813888",
-/*      10000000000 */ "00000001099511627776",
-/*      20000000000 */ "00000002199023255552",
-/*      40000000000 */ "00000004398046511104",
-/*      80000000000 */ "00000008796093022208",
-/*     100000000000 */ "00000017592186044416",
-/*     200000000000 */ "00000035184372088832",
-/*     400000000000 */ "00000070368744177664",
-/*     800000000000 */ "00000140737488355328",
-/*    1000000000000 */ "00000281474976710656",
-/*    2000000000000 */ "00000562949953421312",
-/*    4000000000000 */ "00001125899906842624",
-/*    8000000000000 */ "00002251799813685248",
-/*   10000000000000 */ "00004503599627370496",
-/*   20000000000000 */ "00009007199254740992",
-/*   40000000000000 */ "00018014398509481984",
-/*   80000000000000 */ "00036028797018963968",
-/*  100000000000000 */ "00072057594037927936",
-/*  200000000000000 */ "00144115188075855872",
-/*  400000000000000 */ "00288230376151711744",
-/*  800000000000000 */ "00576460752303423488",
-/* 1000000000000000 */ "01152921504606846976",
-/* 2000000000000000 */ "02305843009213693952",
-/* 4000000000000000 */ "04611686018427387904",
-/* 8000000000000000 */ "09223372036854775808"
-};
-
-
-static void
-prep_table(void)
-{
-    int bit, digit;
-
-    if (bitvals[0][0] < '0')
-       return;
-    for (bit = 0; bit < 64; bit++)
-       for (digit = 0; digit < 20; digit++)
-           bitvals[bit][digit] -= '0';
-}
-
-
-static void
-add_bit(int bit, char *answer)
-{
-    int digit;
-
-    for (digit = 19; digit >= 0; digit--) {
-       answer[digit] += bitvals[bit][digit];
-       if (!digit)
-           break;
-       while (answer[digit] > 9) {
-           answer[digit] -= 10;
-           answer[digit - 1]++;
-       }
-    }
-}
-
-
-static void
-decimate(unsigned long hi, unsigned long lo, char *answer)
-{
-    unsigned long mask;
-    int bit, digit;
-
-    memset(answer, 0, 21);
-    for (bit = 0, mask = 1; bit < 32; bit++, mask <<= 1)
-       if (lo & mask)
-           add_bit(bit, answer);
-    for (bit = 0, mask = 1; bit < 32; bit++, mask <<= 1)
-       if (hi & mask)
-           add_bit(bit + 32, answer);
-
-    for (digit = 0; digit < 20; digit++)
-       answer[digit] += '0';
-}
-
-char *
-decimate_int64(u_int64 * X, char *buf)
-{
-    static char mybuf[21];
-    char *p;
-
-    prep_table();
-    if (!buf)
-       buf = mybuf;
-    decimate(X->hi, X->lo, buf);
-    for (p = buf; *p == '0'; p++);
-    return (*p) ? p : p - 1;
-}
-
-#endif /* NATIVE_INT64 */
-
-
-void
-shift_int64(u_int64 * X, int bits)
-{
-#ifdef NATIVE_INT64
-    if (bits < 0)
-       *X >>= (-bits);
-    else
-       *X <<= bits;
-#else
-    if (bits < 0) {
-       bits = -bits;
-       if (bits >= 32) {
-           X->lo = ((X->hi & 0xffffffffL) >> (bits - 32));
-           X->hi = 0;
-       } else {
-           X->lo = ((X->lo & 0xffffffffL) >> bits)
-               | ((X->hi & ((1 << (32 - bits)) - 1)) << (32 - bits));
-           X->hi = ((X->hi & 0xffffffffL) >> bits);
-       }
-    } else {
-       if (bits >= 32) {
-           X->hi = ((X->lo & 0xffffffffL) << (bits - 32));
-           X->lo = 0;
-       } else {
-           X->hi = ((X->hi & 0xffffffffL) << bits)
-               | ((X->lo & (((1 << bits) - 1) << (32 - bits))) >>
-                  (32 - bits));
-           X->lo = ((X->lo & 0xffffffffL) << bits);
-       }
-    }
-#endif
-}
-
-
-#ifdef TEST_INT64
-
-/** the rest of this is for testing the int64 suite **/
-
-#ifdef NATIVE_INT64
-
-#define xize(x) #x
-#define stringize(x) xize(x)
-#define INT64_NAME stringize(unsigned NATIVE_INT64)
-
-
-#endif /* NATIVE_INT64 */
-
-
-void
-verify_int64_size()
-{
-#ifdef NATIVE_INT64
-    signed char testchar = -1;
-    unsigned int testint = (unsigned char)testchar;
-
-    printf("We think '%s' is a native 64-bit type\n", INT64_NAME);
-
-    if (testint != 0xff) {
-       printf("testint = 0x%x; should be 0xff\n", testint);
-       fprintf(stderr, "Hmm...  char's are not 8 bits.  That sucks!\n");
-       exit(-1);
-    }
-    printf("Looks like a char is 8 bits...\n");
-
-    if (sizeof(unsigned NATIVE_INT64) != 8) {
-       printf("sizeof(%s) = %d; should be 8\n", INT64_NAME,
-              sizeof(unsigned NATIVE_INT64));
-       fprintf(stderr, "Hey!  You said a %s was 64-bits wide!\n",
-               INT64_NAME);
-       exit(-1);
-    }
-    printf("Yippee!  We have a native 64-bit type (%s)\n\n", INT64_NAME);
-
-#else /* !NATIVE_INT64 */
-
-    printf("Using fake 64-bit integers...\n\n");
-#endif /* NATIVE_INT64 */
-}
-
-
-void
-test_int64_constructs(void)
-{
-    u_int64 x, y;
-    afs_uint32 hi, lo;
-    int failures = 0, pass;
-    char buf[17];
-
-    printf("Constructor/accessor tests:\n");
-    printf("Setting x := %s\n", INT64_TEST_STR);
-    mk64(x, INT64_TEST_HI, INT64_TEST_LO);
-
-#ifdef NATIVE_INT64
-    pass = (x == INT64_TEST_CONST);
-    hexify_int64(&x, buf);
-    printf("NATIVE mk64: x       = 0x%16s                %s\n", buf,
-          pass ? "PASSED" : "FAILED");
-    if (!pass)
-       failures++;
-#else
-    pass = (x.hi == INT64_TEST_HI && x.lo == INT64_TEST_LO);
-    printf("FAKE mk64:   x.hi    = 0x%08lx  x.lo    = 0x%08lx  %s\n", x.hi,
-          x.lo, pass ? "PASSED" : "FAILED");
-    if (!pass)
-       failures++;
-#endif
-
-    pass = (hi64(x) == INT64_TEST_HI && lo64(x) == INT64_TEST_LO);
-    printf("hi64/lo64:   hi64(x) = 0x%08lx  lo64(x) = 0x%08lx  %s\n", hi64(x),
-          lo64(x), pass ? "PASSED" : "FAILED");
-    if (!pass)
-       failures++;
-
-    ex64(x, hi, lo);
-    pass = (hi == INT64_TEST_HI && lo == INT64_TEST_LO);
-    printf("ex64:        hi      = 0x%08lx  lo      = 0x%08lx  %s\n", hi, lo,
-          pass ? "PASSED" : "FAILED");
-    if (!pass)
-       failures++;
-
-    cp64(y, x);
-    pass = (hi64(y) == INT64_TEST_HI && lo64(y) == INT64_TEST_LO);
-    printf("cp64:        hi64(y) = 0x%08lx  lo64(y) = 0x%08lx  %s\n", hi64(y),
-          lo64(y), pass ? "PASSED" : "FAILED");
-    if (!pass)
-       failures++;
-
-    if (failures)
-       printf("%d/4 tests FAILED\n\n", failures);
-    else
-       printf("All 4 tests PASSED\n\n");
-}
-
-
-void
-test_int64_compares()
-{
-#define NCOMPARE 9
-    u_int64 control, test[NCOMPARE];
-    char cbuf[17], tbuf[17];
-    int i, r, result[NCOMPARE];
-    int pass, failures, FAILURES = 0;
-
-    printf("Comparison tests:\n");
-
-    mk64(control, 0x12345678, 0xabcdabcd);
-    mk64(test[0], 0x12340000, 0xabcd0000);
-    result[0] = +1;
-    mk64(test[1], 0x12340000, 0xabcdabcd);
-    result[1] = +1;
-    mk64(test[2], 0x12340000, 0xabcdffff);
-    result[2] = +1;
-    mk64(test[3], 0x12345678, 0xabcd0000);
-    result[3] = +1;
-    mk64(test[4], 0x12345678, 0xabcdabcd);
-    result[4] = 0;
-    mk64(test[5], 0x12345678, 0xabcdffff);
-    result[5] = -1;
-    mk64(test[6], 0x1234ffff, 0xabcd0000);
-    result[6] = -1;
-    mk64(test[7], 0x1234ffff, 0xabcdabcd);
-    result[7] = -1;
-    mk64(test[8], 0x1234ffff, 0xabcdffff);
-    result[8] = -1;
-
-    for (i = 0; i < NCOMPARE; i++) {
-       failures = 0;
-       hexify_int64(&control, cbuf);
-       hexify_int64(&test[i], tbuf);
-
-       r = eq64(control, test[i]);
-       pass = (r == (result[i] == 0));
-       if (!pass)
-           failures++;
-       printf("0x%s == 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
-
-       r = ne64(control, test[i]);
-       pass = (r == (result[i] != 0));
-       if (!pass)
-           failures++;
-       printf("0x%s != 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
-
-       r = lt64(control, test[i]);
-       pass = (r == (result[i] < 0));
-       if (!pass)
-           failures++;
-       printf("0x%s <  0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
-
-       r = le64(control, test[i]);
-       pass = (r == (result[i] <= 0));
-       if (!pass)
-           failures++;
-       printf("0x%s <= 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
-
-       r = gt64(control, test[i]);
-       pass = (r == (result[i] > 0));
-       if (!pass)
-           failures++;
-       printf("0x%s >  0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
-
-       r = ge64(control, test[i]);
-       pass = (r == (result[i] >= 0));
-       if (!pass)
-           failures++;
-       printf("0x%s >= 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
-
-       r = zero64(test[i]);
-       pass = !r;
-       if (!pass)
-           failures++;
-       printf("0x%s is nonzero            %s\n", tbuf,
-              pass ? "PASSED" : "FAILED");
-
-       if (failures)
-           printf("%d/7 tests on this pair FAILED\n\n", failures);
-       else
-           printf("All 7 tests on this pair PASSED\n\n");
-    }
-
-    mk64(control, 0, 0);
-    pass = zero64(control);
-    if (!pass)
-       FAILURES++;
-    printf("0x0000000000000000 is zero               %s\n",
-          pass ? "PASSED" : "FAILED");
-
-    if (FAILURES)
-       printf("%d/%d comparison tests FAILED\n\n", FAILURES,
-              7 * NCOMPARE + 1);
-    else
-       printf("All %d comparison tests PASSED\n\n", 7 * NCOMPARE + 1);
-}
-
-
-void
-test_int64_arith()
-{
-    printf("No arithmetic tests yet!!!\n");
-}
-
-
-void
-main()
-{
-    verify_int64_size();
-    test_int64_constructs();
-    test_int64_compares();
-    test_int64_arith();
-    exit(0);
-}
-#endif
diff --git a/src/tests/intNN.h b/src/tests/intNN.h
deleted file mode 100644 (file)
index bc56bfe..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-#ifndef _INTNN_H_
-#define _INTNN_H_
-
-/* intNN.h - Sized integer types */
-#include <afs/stds.h>
-#if 0
-typedef short afs_int16;
-typedef unsigned short afs_uint16;
-
-typedef long afs_int32;
-typedef unsigned long afs_uint32;
-#endif
-
-
-/* Support for 64-bit integers.
- * Presently, only unsigned 64-bit numbers are supported.
- */
-#define INT64_TEST_STR "0x12345678fedcba98"
-#define INT64_TEST_HI  0x12345678
-#define INT64_TEST_LO  0xfedcba98
-
-
-#ifdef NATIVE_INT64
-typedef unsigned NATIVE_INT64 u_int64;
-
-/* construct/extract/assign */
-#define mk64(X,H,L) ((X) = ( ((u_int64)(H) << 32) \
-                           | ((u_int64)(L) & 0xffffffff)))
-#define hi64(Y)     ((afs_uint32)(((Y) >> 32) & 0xffffffff))
-#define lo64(Y)     ((afs_uint32)((Y) & 0xffffffff))
-#define ex64(Y,H,L) ((H) = hi64(Y), (L) = lo64(Y))
-#define cp64(X,Y)   ((X) = (Y))
-#define get64(X)    (X)
-#define set64(X,V)  ((X) = (V))
-
-/* Comparison */
-#define eq64(X,Y)   ((X) == (Y))
-#define ne64(X,Y)   ((X) != (Y))
-#define lt64(X,Y)   ((X) <  (Y))
-#define le64(X,Y)   ((X) <= (Y))
-#define gt64(X,Y)   ((X) >  (Y))
-#define ge64(X,Y)   ((X) >= (Y))
-#define zero64(X)   (!(X))
-
-/* Arithmetic */
-#define add64_32(X,A,B) ((X) = (A) + (u_int64)(B))
-#define add64_64(X,A,B) ((X) = (A) + (B))
-#define sub64_32(X,A,B) ((X) = (A) - (u_int64)(B))
-#define sub64_64(X,A,B) ((X) = (A) - (B))
-
-/* Byte-order */
-#ifdef WORDS_BIGENDIAN
-#define hton64(X,Y) cp64(X,Y)
-#define ntoh64(X,Y) cp64(X,Y)
-#else
-#define hton64(X,Y) mk64(X,htonl(lo64(Y)),htonl(hi64(Y)))
-#define ntoh64(X,Y) mk64(X,ntohl(lo64(Y)),ntohl(hi64(Y)))
-#endif
-
-#else /* !NATIVE_INT64 */
-/** We have to provide our own 64-bit integers **/
-typedef struct {
-    afs_uint32 hi, lo;
-} u_int64;
-
-/* construct/extract/assign */
-#define mk64(X,H,L) ((X).hi = (H), (X).lo = (L))
-#define ex64(Y,H,L) ((H) = (Y).hi, (L) = (Y).lo)
-#define hi64(Y)     ((Y).hi)
-#define lo64(Y)     ((Y).lo)
-#define cp64(X,Y)   ((X).hi = (Y).hi, (X).lo = (Y).lo)
-#define get64(X)    ((X).lo)
-#define set64(X,V)  ((X).hi = 0, (X).lo = (V))
-
-/* Comparison */
-#define eq64(A,B) ((A).hi == (B).hi && (A).lo == (B).lo)
-#define ne64(A,B) ((A).hi != (B).hi || (A).lo != (B).lo)
-#define lt64(A,B) ((A).hi <  (B).hi || ((A).hi == (B).hi && (A).lo <  (B).lo))
-#define le64(A,B) ((A).hi <  (B).hi || ((A).hi == (B).hi && (A).lo <= (B).lo))
-#define gt64(A,B) ((A).hi >  (B).hi || ((A).hi == (B).hi && (A).lo >  (B).lo))
-#define ge64(A,B) ((A).hi >  (B).hi || ((A).hi == (B).hi && (A).lo >= (B).lo))
-#define zero64(X) ((X).hi == 0 && (X).lo == 0)
-
-/* Arithmetic */
-#define add64_32(X,A,B) (                                              \
-  (X).lo = (A).lo + (B),                                               \
-  (X).hi = (A).hi +                                                    \
-   (((((A).lo & 0x80000000) ^  ((B) & 0x80000000)) && !((X).lo & 0x80000000)) \
-  || (((A).lo & 0x80000000) && ((B) & 0x80000000)))                     \
-  )
-#define add64_64(X,A,B) (add64_32(X,A,(B).lo), (X).hi += (B).hi)
-
-#define sub64_32(X,A,B) ((X).lo = (A).lo - (B), \
-                         (X).hi = (A).hi - ((A).lo < (B)))
-#define sub64_64(X,A,B) (sub64_32(X,A,(B).lo), (X).hi -= (B).hi)
-
-/* Byte-order */
-#define hton64(X,Y) mk64(X,htonl(hi64(Y)),htonl(lo64(Y)))
-#define ntoh64(X,Y) mk64(X,ntohl(hi64(Y)),ntohl(lo64(Y)))
-
-#endif /* NATIVE_INT64 */
-
-
-/* The following are too complex to be macros: */
-
-/* char *hexify_int64(u_int64 a, char *buf)
- * Produces an ASCII representation of a in hexadecimal, and returns
- * a pointer to the resulting string.  If buf is non-NULL, it is taken
- * to be a pointer to the buffer to be used, which must be at least 17
- * bytes long.  This function is thread-safe iff buf is provided.
- */
-extern char *hexify_int64(u_int64 *, char *);
-
-/* char *decimate_int64(u_int64 a, char *buf)
- * Produces an ASCII representation of a in decimal, and returns
- * a pointer to the resulting string.  If buf is non-NULL, it is taken
- * to be a pointer to the buffer to be used, which must be at least 21
- * bytes long.  This function is thread-safe iff buf is provided.
- */
-extern char *decimate_int64(u_int64 *, char *);
-
-/* void shift_int64(u_int64 a, int bits)
- * Shifts the 64-bit integer in a by the specified number of bits.
- * If bits is positive, the shift is to the left; if negative, the
- * shift is to the right.
- */
-extern void shift_int64(u_int64 *, int);
-
-#endif /* _INTNN_H_ */
diff --git a/src/tests/internal.h b/src/tests/internal.h
deleted file mode 100644 (file)
index 276767a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* internal.h - Routines for internal use only */
-
-#include "xfiles.h"
-#include "dumpscan.h"
-
-
-/* parsevol.c - Routines to parse volume headers */
-extern afs_uint32 parse_volhdr(XFILE *, unsigned char *, tagged_field *,
-                              afs_uint32, tag_parse_info *, void *, void *);
-
-/* parsevnode.c - Routines to parse vnodes and their fields */
-extern afs_uint32 parse_vnode(XFILE *, unsigned char *, tagged_field *,
-                             afs_uint32, tag_parse_info *, void *, void *);
-
-/* directory.c - Routines for parsing AFS directories */
-extern afs_uint32 parse_directory(XFILE *, dump_parser *, afs_vnode *,
-                                 afs_uint32, int);
-
-/* backuphdr.c - Generic support for backup system headers */
-extern afs_uint32 try_backuphdr(XFILE * X, unsigned char *tag,
-                               tagged_field * field, afs_uint32 value,
-                               tag_parse_info * pi, void *g_refcon,
-                               void *l_refcon);
-
-/* util.c - Random utilities */
-extern afs_uint32 handle_return(int, XFILE *, unsigned char, dump_parser *);
-extern void prep_pi(dump_parser *, tag_parse_info *);
-extern afs_uint32 match_next_vnode(XFILE *, dump_parser *, u_int64 *,
-                                  afs_uint32);
diff --git a/src/tests/parsedump.c b/src/tests/parsedump.c
deleted file mode 100644 (file)
index bbb48e8..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* parsedump.c - Parse a volume dump file */
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "dumpfmt.h"
-#include "internal.h"
-#include "stagehdr.h"
-
-static afs_uint32 parse_dumphdr(XFILE *, unsigned char *, tagged_field *,
-                               afs_uint32, tag_parse_info *, void *, void *);
-static afs_uint32 parse_dumpend(XFILE *, unsigned char *, tagged_field *,
-                               afs_uint32, tag_parse_info *, void *, void *);
-static afs_uint32 store_dumphdr(XFILE *, unsigned char *, tagged_field *,
-                               afs_uint32, tag_parse_info *, void *, void *);
-static afs_uint32 parse_dumptimes(XFILE *, unsigned char *, tagged_field *,
-                                 afs_uint32, tag_parse_info *, void *,
-                                 void *);
-
-/** Field list for top-level objects **/
-static tagged_field top_fields[] = {
-    {TAG_DUMPHEADER, DKIND_SPECIAL, "* DUMP HEADER", parse_dumphdr, 0, 0},
-    {TAG_VOLHEADER, DKIND_SPECIAL, "* VOLUME HEADER", parse_volhdr, 0, 0},
-    {TAG_VNODE, DKIND_SPECIAL, "* VNODE ", parse_vnode, 0, 0},
-    {TAG_DUMPEND, DKIND_INT32, "* DUMP END", parse_dumpend, 0, 0},
-    {STAGE_VERSMIN, DKIND_SPECIAL, "* STAGE HEADER", try_backuphdr, 0, 0},
-    {0, 0, 0, 0, 0, 0}
-};
-
-
-/** Field list for dump headers **/
-static tagged_field dumphdr_fields[] = {
-    {DHTAG_VOLNAME, DKIND_STRING, " Volume name:  ", store_dumphdr, 0, 0},
-    {DHTAG_VOLID, DKIND_INT32, " Volume ID:    ", store_dumphdr, 0, 0},
-    {DHTAG_DUMPTIMES, DKIND_SPECIAL, " Dump Range:   ", parse_dumptimes, 0,
-     0},
-    {0, 0, 0, 0, 0, 0}
-};
-
-
-/* Parse a dump header, including its tagged attributes, and call the
- * dump-header callback, if one is defined.
- */
-static afs_uint32
-parse_dumphdr(XFILE * X, unsigned char *tag, tagged_field * field,
-             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-             void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_dump_header hdr;
-    u_int64 where;
-    afs_uint32 r;
-
-    memset(&hdr, 0, sizeof(hdr));
-    if ((r = xftell(X, &where)))
-       return r;
-    sub64_32(hdr.offset, where, 1);
-
-    if ((r = ReadInt32(X, &hdr.magic)))
-       return r;
-    if ((r = ReadInt32(X, &hdr.version)))
-       return r;
-
-    if (hdr.magic != DUMPBEGINMAGIC) {
-       if (p->cb_error)
-           (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
-                          "Invalid magic number (0x%08x) in dump header",
-                          hdr.magic);
-       return DSERR_MAGIC;
-    }
-    if (hdr.version != DUMPVERSION) {
-       if (p->cb_error)
-           (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
-                          "Unknown dump format version (%d) in dump header",
-                          hdr.version);
-       return DSERR_MAGIC;
-    }
-
-    if (p->print_flags & DSPRINT_DUMPHDR)
-       printf("%s [%s = 0x%s]\n", field->label,
-              decimate_int64(&hdr.offset, 0), hexify_int64(&hdr.offset, 0));
-    if (p->print_flags & DSPRINT_DUMPHDR) {
-       printf(" Magic number: 0x%08x\n", hdr.magic);
-       printf(" Version:      %d\n", hdr.version);
-    }
-    r = ParseTaggedData(X, dumphdr_fields, tag, pi, g_refcon, (void *)&hdr);
-
-    if (!r && p->cb_dumphdr) {
-       r = xftell(X, &where);
-       if (!r)
-           r = (p->cb_dumphdr) (&hdr, X, p->refcon);
-       if (p->flags & DSFLAG_SEEK) {
-           if (!r)
-               r = xfseek(X, &where);
-           else
-               xfseek(X, &where);
-       }
-    }
-    if (hdr.field_mask & F_DUMPHDR_VOLNAME)
-       free(hdr.volname);
-    return r;
-}
-
-
-/* Store tagged attributes into a dump header */
-static afs_uint32
-store_dumphdr(XFILE * X, unsigned char *tag, tagged_field * field,
-             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-             void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_dump_header *hdr = (afs_dump_header *) l_refcon;
-
-    switch (field->tag) {
-    case DHTAG_VOLID:
-       hdr->field_mask |= F_DUMPHDR_VOLID;
-       hdr->volid = value;
-       if (p->print_flags & DSPRINT_DUMPHDR)
-           printf("%s%d\n", field->label, hdr->volid);
-       return 0;
-
-    case DHTAG_VOLNAME:
-       if (tag && tag[0]) {
-           hdr->field_mask |= F_DUMPHDR_VOLNAME;
-           hdr->volname = tag;
-           if (p->print_flags & DSPRINT_DUMPHDR)
-               printf("%s%s\n", field->label, hdr->volname);
-           return DSERR_KEEP;
-       } else
-           return 0;
-
-    default:
-       if (p->print_flags & DSPRINT_DUMPHDR)
-           printf("%s<<< UNKNOWN FIELD >>>\n", field->label);
-       return 0;
-    }
-}
-
-
-/* Parse and store the dump time range from a dump header */
-static afs_uint32
-parse_dumptimes(XFILE * X, unsigned char *tag, tagged_field * field,
-               afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-               void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_dump_header *hdr = (afs_dump_header *) l_refcon;
-    afs_uint16 count;
-    afs_uint32 r;
-
-    if ((r = ReadInt16(X, &count)))
-       return r;
-    if (count != 2) {
-       if (p->cb_error)
-           (p->cb_error) (DSERR_FMT, 1, p->err_refcon,
-                          "Incorrect array count (%d) in dump times", count);
-       return DSERR_FMT;
-    }
-    if ((r = ReadInt32(X, &hdr->from_date)))
-       return r;
-    if ((r = ReadInt32(X, &hdr->to_date)))
-       return r;
-    hdr->field_mask |= (F_DUMPHDR_FROM | F_DUMPHDR_TO);
-    if (p->print_flags & DSPRINT_DUMPHDR)
-       printf("%s%d => %d\n", field->label, hdr->from_date, hdr->to_date);
-
-    return ReadByte(X, tag);
-}
-
-
-/* Parse a dump_end record */
-static afs_uint32
-parse_dumpend(XFILE * X, unsigned char *tag, tagged_field * field,
-             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-             void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-
-    if (value != DUMPENDMAGIC) {
-       if (p->cb_error)
-           (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
-                          "Invalid magic number (0x%08x) in dump trailer",
-                          value);
-       return DSERR_MAGIC;
-    }
-    if (p->print_flags & (DSPRINT_DUMPHDR | DSPRINT_ITEM))
-       printf("%s\n", field->label);
-    return DSERR_DONE;
-}
-
-
-
-afs_uint32
-ParseDumpFile(XFILE * X, dump_parser * p)
-{
-    tag_parse_info pi;
-    unsigned char tag;
-    afs_uint32 r;
-
-    prep_pi(p, &pi);
-    r = ParseTaggedData(X, top_fields, &tag, &pi, (void *)p, 0);
-    return handle_return(r, X, tag, p);
-}
-
-
-afs_uint32
-ParseDumpHeader(XFILE * X, dump_parser * p)
-{
-    tag_parse_info pi;
-    unsigned char tag;
-    afs_uint32 r;
-
-    prep_pi(p, &pi);
-    if ((r = ReadByte(X, &tag)))
-       return handle_return(r, X, tag, p);
-    if (tag != TAG_DUMPHEADER)
-       return handle_return(0, X, tag, p);
-    r = parse_dumphdr(X, &tag, &top_fields[0], 0, &pi, (void *)p, 0);
-    if (!r && tag >= 1 && tag <= 4)
-       r = DSERR_DONE;
-    return handle_return(r, X, tag, p);
-}
-
-
-afs_uint32
-ParseVolumeHeader(XFILE * X, dump_parser * p)
-{
-    tag_parse_info pi;
-    unsigned char tag;
-    afs_uint32 r;
-
-    prep_pi(p, &pi);
-    if ((r = ReadByte(X, &tag)))
-       return handle_return(r, X, tag, p);
-    if (tag != TAG_VOLHEADER)
-       return handle_return(0, X, tag, p);
-    r = parse_volhdr(X, &tag, &top_fields[1], 0, &pi, (void *)p, 0);
-    if (!r && tag >= 1 && tag <= 4)
-       r = DSERR_DONE;
-    return handle_return(r, X, tag, p);
-}
-
-
-afs_uint32
-ParseVNode(XFILE * X, dump_parser * p)
-{
-    tag_parse_info pi;
-    unsigned char tag;
-    afs_uint32 r;
-
-    prep_pi(p, &pi);
-    if ((r = ReadByte(X, &tag)))
-       return handle_return(r, X, tag, p);
-    if (tag != TAG_VNODE)
-       return handle_return(0, X, tag, p);
-    r = parse_vnode(X, &tag, &top_fields[2], 0, &pi, (void *)p, 0);
-    if (!r && tag >= 1 && tag <= 4)
-       r = DSERR_DONE;
-    return handle_return(r, X, tag, p);
-}
diff --git a/src/tests/parsetag.c b/src/tests/parsetag.c
deleted file mode 100644 (file)
index 67e8a2c..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* parsetag.c - Parse a tagged data stream */
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-
-/* If a parser function is defined, it will be called after the data value
- * (if any) is read.  The parser is called as follows:
- *
- *   parser(input_file, &tag, &field_rec, value, g_refcon, l_refcon);
- *
- * - input_file is the FILE * for the input stream
- * - field_rec is a pointer to the field record for the field just read
- * - g_refcon and l_refcon are as passed in to ParseTaggedData
- * - For integer types, value is the integer value
- * - For DKIND_STRING, tag is a pointer to the string just read
- * - For DKIND_SPEACH, tag is a pointer to the place to put the next tag.
- *
- * If the field type is DKIND_SPECIAL, the parser is expected to read its
- * own data from the input stream, and return when ParseTaggedData is supposed
- * to take over, with the next tag to process in *tag.  At no other time
- * should the parser read, write, or reposition the input stream.
- *
- * The parser routine should return 0 on success, non-0 on failure.  If the
- * data type is DKIND_STRING, the parser may return DSERR_KEEP to indicate
- * that the memory allocated for the value should not be freed.
- */
-
-/* Parse a file containing tagged data and attributes **/
-afs_uint32
-ParseTaggedData(XFILE * X, tagged_field * fields, unsigned char *tag,
-               tag_parse_info * pi, void *g_refcon, void *l_refcon)
-{
-    int i = -1;
-    afs_uint32 r, val;
-    afs_uint16 val16;
-    unsigned char val8;
-    unsigned char *strval;
-
-    for (;;) {
-       if (i < 0 || (fields[i].kind & DKIND_MASK) != DKIND_SPECIAL) {
-           /* Need to read in a tag */
-           if ((r = ReadByte(X, tag)))
-               return r;
-       }
-
-       /* Simple error recovery - if we encounter a 0, it can never be
-        * a valid tag.  If TPFLAG_SKIP is set, we can skip over any
-        * such null bytes, and process whatever tag we find beyond.
-        * In addition, if TPFLAG_RSKIP is set, then the next time
-        * we encounter a 0, try skipping backwards.  That seems to
-        * work much of the time.
-        */
-       if (!*tag && pi->shift_offset && (pi->flags & TPFLAG_RSKIP)) {
-           u_int64 where, tmp64a, tmp64b;
-           char buf1[21], buf2[21], buf3[21];
-           char *p1, *p2, *p3;
-
-           if ((r = xftell(X, &tmp64a)))
-               return r;
-           sub64_32(where, tmp64a, pi->shift_offset + 1);
-           if ((r = xfseek(X, &where)))
-               return r;
-           if (pi->cb_error) {
-               (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
-                               "Inserted %d bytes before offset %d",
-                               pi->shift_offset, decimate_int64(&where, 0));
-               add64_32(tmp64a, pi->shift_start, pi->shift_offset);
-               p1 = decimate_int64(&tmp64a, buf1);
-               sub64_64(tmp64b, where, tmp64a);
-               p2 = decimate_int64(&tmp64b, buf2);
-               p3 = decimate_int64(&pi->shift_start, buf3);
-               (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
-                               ">>> SHIFT start=%s length=%s target=%s", p1,
-                               p2, p3);
-           }
-           pi->shift_offset = 0;
-           if ((r = ReadByte(X, tag)))
-               return r;
-       }
-       if (!*tag && (pi->flags & TPFLAG_SKIP)) {
-           int count = 0;
-           u_int64 where, tmp64a;
-
-           if ((r = xftell(X, &where)))
-               return r;
-
-           while (!*tag) {
-               if ((r = ReadByte(X, tag)))
-                   return r;
-               count++;
-           }
-           pi->shift_offset += count;
-           cp64(pi->shift_start, where);
-           if (pi->cb_error) {
-               sub64_32(tmp64a, where, 1);
-               (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
-                               "Skipped %d bytes at offset %s", count,
-                               decimate_int64(&tmp64a, 0));
-           }
-       }
-
-       for (i = 0; fields[i].tag && fields[i].tag != *tag; i++);
-       if (!fields[i].tag)
-           return 0;
-
-       switch (fields[i].kind & DKIND_MASK) {
-       case DKIND_NOOP:
-           if (fields[i].func) {
-               r = (fields[i].func) (X, 0, fields + i, 0, pi, g_refcon,
-                                     l_refcon);
-               if (r)
-                   return r;
-           }
-           break;
-
-       case DKIND_BYTE:
-           if ((r = ReadByte(X, &val8)))
-               return r;
-           if (fields[i].func) {
-               r = (fields[i].func) (X, 0, fields + i, val8, pi, g_refcon,
-                                     l_refcon);
-               if (r)
-                   return r;
-           }
-           break;
-
-       case DKIND_INT16:
-           if ((r = ReadInt16(X, &val16)))
-               return r;
-           if (fields[i].func) {
-               r = (fields[i].func) (X, 0, fields + i, val16, pi, g_refcon,
-                                     l_refcon);
-               if (r)
-                   return r;
-           }
-           break;
-
-       case DKIND_INT32:
-           if ((r = ReadInt32(X, &val)))
-               return r;
-           if (fields[i].func) {
-               r = (fields[i].func) (X, 0, fields + i, val, pi, g_refcon,
-                                     l_refcon);
-               if (r)
-                   return r;
-           }
-           break;
-
-       case DKIND_STRING:
-           if ((r = ReadString(X, &strval)))
-               return r;
-           if (fields[i].func) {
-               r = (fields[i].func) (X, strval, fields + i, 0, pi, g_refcon,
-                                     l_refcon);
-               if (r != DSERR_KEEP)
-                   free(strval);
-               if (r && r != DSERR_KEEP)
-                   return r;
-           } else
-               free(strval);
-           break;
-
-       case DKIND_SPECIAL:
-           if (fields[i].func) {
-               r = (fields[i].func) (X, tag, fields + i, 0, pi, g_refcon,
-                                     l_refcon);
-               if (r)
-                   return r;
-           } else
-               i = -1;
-       }
-    }
-}
diff --git a/src/tests/parsevnode.c b/src/tests/parsevnode.c
deleted file mode 100644 (file)
index 8f09fd1..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* parsevnode.c - Parse a VNode */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <errno.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "dumpfmt.h"
-#include "internal.h"
-
-#include <afs/acl.h>
-#include <afs/prs_fs.h>
-
-static afs_uint32 LastGoodVNode = 0;
-static afs_uint32 store_vnode(XFILE *, unsigned char *, tagged_field *,
-                             afs_uint32, tag_parse_info *, void *, void *);
-static afs_uint32 parse_acl(XFILE *, unsigned char *, tagged_field *,
-                           afs_uint32, tag_parse_info *, void *, void *);
-static afs_uint32 parse_vdata(XFILE *, unsigned char *, tagged_field *,
-                             afs_uint32, tag_parse_info *, void *, void *);
-
-/** Field list for vnodes **/
-static tagged_field vnode_fields[] = {
-    {VTAG_TYPE, DKIND_BYTE, " VNode type:   ", store_vnode, 0, 0},
-    {VTAG_NLINKS, DKIND_INT16, " Link count:   ", store_vnode, 0, 0},
-    {VTAG_DVERS, DKIND_INT32, " Version:      ", store_vnode, 0, 0},
-    {VTAG_CLIENT_DATE, DKIND_TIME, " Server Date:  ", store_vnode, 0, 0},
-    {VTAG_AUTHOR, DKIND_INT32, " Author:       ", store_vnode, 0, 0},
-    {VTAG_OWNER, DKIND_INT32, " Owner:        ", store_vnode, 0, 0},
-    {VTAG_GROUP, DKIND_INT32, " Group:        ", store_vnode, 0, 0},
-    {VTAG_MODE, DKIND_INT16, " UNIX mode:    ", store_vnode, 0, 0},
-    {VTAG_PARENT, DKIND_INT32, " Parent:       ", store_vnode, 0, 0},
-    {VTAG_SERVER_DATE, DKIND_TIME, " Client Date:  ", store_vnode, 0, 0},
-    {VTAG_ACL, DKIND_SPECIAL, " xxxxxxxx ACL: ", parse_acl, 0, 0},
-    {VTAG_DATA, DKIND_SPECIAL, " Contents:     ", parse_vdata, 0, 0},
-    {0, 0, 0, 0, 0, 0}
-};
-
-
-static afs_uint32
-resync_vnode(XFILE * X, dump_parser * p, afs_vnode * v, int start, int limit)
-{
-    u_int64 where, expected_where;
-    afs_uint32 r;
-    int i;
-
-    if ((r = xftell(X, &expected_where)))
-       return r;
-    cp64(where, expected_where);
-
-    r = match_next_vnode(X, p, &where, v->vnode);
-    if (r && r != DSERR_FMT)
-       return r;
-    if (r)
-       for (i = -start; i < limit; i++) {
-           add64_32(where, expected_where, i);
-           r = match_next_vnode(X, p, &where, v->vnode);
-           if (!r)
-               break;
-           if (r != DSERR_FMT)
-               return r;
-       }
-    if (r) {
-       if (p->cb_error)
-           (p->cb_error) (r, 1, p->err_refcon,
-                          "Unable to resync after vnode %d [%s = 0x%s]",
-                          v->vnode, decimate_int64(&expected_where, 0),
-                          hexify_int64(&expected_where, 0));
-       return r;
-    }
-    if (ne64(where, expected_where) && p->cb_error) {
-       (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
-                      "Vnode after %d not in expected location", v->vnode);
-       (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
-                      "Expected location: %s = 0x%s",
-                      decimate_int64(&expected_where, 0),
-                      hexify_int64(&expected_where, 0));
-       (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
-                      "Actual location: %s = 0x%s", decimate_int64(&where,
-                                                                   0),
-                      hexify_int64(&where, 0));
-    }
-    return xfseek(X, &where);
-}
-
-
-/* Parse a VNode, including any tagged attributes and data, and call the
- * appropriate callback, if one is defined.
- */
-afs_uint32
-parse_vnode(XFILE * X, unsigned char *tag, tagged_field * field,
-           afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-           void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_uint32(*cb) (afs_vnode *, XFILE *, void *);
-    u_int64 where, offset2k;
-    afs_vnode v;
-    afs_uint32 r;
-
-
-    if ((r = xftell(X, &where)))
-       return r;
-    memset(&v, 0, sizeof(v));
-    sub64_32(v.offset, where, 1);
-    if ((r = ReadInt32(X, &v.vnode)))
-       return r;
-    if ((r = ReadInt32(X, &v.vuniq)))
-       return r;
-
-    mk64(offset2k, 0, 2048);
-    if (!LastGoodVNode
-       || ((p->flags & DSFLAG_SEEK) && v.vnode == 1
-           && lt64(v.offset, offset2k)))
-       LastGoodVNode = -1;
-
-    if (p->print_flags & DSPRINT_ITEM) {
-       printf("%s %d/%d [%s = 0x%s]\n", field->label, v.vnode, v.vuniq,
-              decimate_int64(&where, 0), hexify_int64(&where, 0));
-    }
-
-    r = ParseTaggedData(X, vnode_fields, tag, pi, g_refcon, (void *)&v);
-
-    /* Try to resync, if requested */
-    if (!r && (p->repair_flags & DSFIX_VFSYNC)) {
-       afs_uint32 drop;
-       u_int64 xwhere;
-
-       if ((r = xftell(X, &where)))
-           return r;
-       sub64_32(xwhere, where, 1);
-
-       /* Are we at the start of a valid vnode (or dump end)? */
-       r = match_next_vnode(X, p, &xwhere, v.vnode);
-       if (r && r != DSERR_FMT)
-           return r;
-       if (r) {                /* Nope. */
-           /* Was _this_ a valid vnode?  If so, we can keep it and search for
-            * the next one.  Otherwise, we throw it out, and start the search
-            * at the starting point of this vnode.
-            */
-           drop = r = match_next_vnode(X, p, &v.offset, LastGoodVNode);
-           if (r && r != DSERR_FMT)
-               return r;
-           if (!r) {
-               add64_32(where, v.offset, 1);
-               if ((r = xfseek(X, &v.offset)))
-                   return r;
-           } else {
-               if ((r = xfseek(X, &xwhere)))
-                   return r;
-           }
-           if ((r = resync_vnode(X, p, &v, 0, 1024)))
-               return r;
-           if ((r = ReadByte(X, tag)))
-               return r;
-           if (drop) {
-               if (p->cb_error)
-                   (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
-                                  "Dropping vnode %d", v.vnode);
-               return 0;
-           }
-       } else {
-           if ((r = xfseek(X, &where)))
-               return r;
-       }
-    }
-    LastGoodVNode = v.vnode;
-
-    if (!r) {
-       if (v.field_mask & F_VNODE_TYPE)
-           switch (v.type) {
-           case vFile:
-               cb = p->cb_vnode_file;
-               break;
-           case vDirectory:
-               cb = p->cb_vnode_dir;
-               break;
-           case vSymlink:
-               cb = p->cb_vnode_link;
-               break;
-           default:
-               cb = p->cb_vnode_wierd;
-               break;
-       } else
-           cb = p->cb_vnode_empty;
-       if (cb) {
-           u_int64 where;
-
-           if ((r = xftell(X, &where)))
-               return r;
-           r = (cb) (&v, X, p->refcon);
-           if (p->flags & DSFLAG_SEEK) {
-               if (!r)
-                   r = xfseek(X, &where);
-               else
-                   xfseek(X, &where);
-           }
-       }
-    }
-    return r;
-}
-
-
-/* Store data in a vnode */
-static afs_uint32
-store_vnode(XFILE * X, unsigned char *tag, tagged_field * field,
-           afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-           void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_vnode *v = (afs_vnode *) l_refcon;
-    time_t when;
-    afs_uint32 r = 0;
-
-    switch (field->tag) {
-    case VTAG_TYPE:
-       v->field_mask |= F_VNODE_TYPE;
-       v->type = value;
-       if (p->print_flags & DSPRINT_VNODE) {
-           switch (value) {
-           case vFile:
-               printf("%sFile (%d)\n", field->label, value);
-               break;
-           case vDirectory:
-               printf("%sDirectory (%d)\n", field->label, value);
-               break;
-           case vSymlink:
-               printf("%sSymbolic Link (%d)\n", field->label, value);
-               break;
-           default:
-               printf("%s??? (%d)\n", field->label, value);
-           }
-           return r;
-       }
-       break;
-
-    case VTAG_NLINKS:
-       v->field_mask |= F_VNODE_NLINKS;
-       v->nlinks = value;
-       break;
-
-    case VTAG_DVERS:
-       v->field_mask |= F_VNODE_DVERS;
-       v->datavers = value;
-       break;
-
-    case VTAG_CLIENT_DATE:
-       v->field_mask |= F_VNODE_CDATE;
-       v->client_date = value;
-       break;
-
-    case VTAG_SERVER_DATE:
-       v->field_mask |= F_VNODE_SDATE;
-       v->server_date = value;
-       break;
-
-    case VTAG_AUTHOR:
-       v->field_mask |= F_VNODE_AUTHOR;
-       v->author = value;
-       break;
-
-    case VTAG_OWNER:
-       v->field_mask |= F_VNODE_OWNER;
-       v->owner = value;
-       break;
-
-    case VTAG_GROUP:
-       v->field_mask |= F_VNODE_GROUP;
-       v->group = value;
-       break;
-
-    case VTAG_MODE:
-       v->field_mask |= F_VNODE_MODE;
-       v->mode = value;
-       break;
-
-    case VTAG_PARENT:
-       v->field_mask |= F_VNODE_PARENT;
-       v->parent = value;
-       break;
-    }
-
-    if (p->print_flags & DSPRINT_VNODE)
-       switch (field->kind) {
-       case DKIND_BYTE:
-       case DKIND_INT16:
-       case DKIND_INT32:
-           printf("%s%d\n", field->label, value);
-           break;
-       case DKIND_HEX8:
-           printf("%s0x%02x\n", field->label, value);
-           break;
-       case DKIND_HEX16:
-           printf("%s0x%04x\n", field->label, value);
-           break;
-       case DKIND_HEX32:
-           printf("%s0x%08x\n", field->label, value);
-           break;
-       case DKIND_CHAR:
-           printf("%s%c\n", field->label, value);
-           break;
-       case DKIND_STRING:
-           printf("%s%s\n", field->label, tag);
-           break;
-       case DKIND_FLAG:
-           printf("%s%s\n", field->label, value ? "true" : "false");
-           break;
-       case DKIND_TIME:
-           when = value;
-           printf("%s%s", field->label, ctime(&when));
-           break;
-       }
-    return r;
-}
-
-
-static char *
-rights2str(afs_uint32 rights)
-{
-    static char str[16];
-    char *p = str;
-
-    if (rights & PRSFS_READ)
-       *p++ = 'r';
-    if (rights & PRSFS_LOOKUP)
-       *p++ = 'l';
-    if (rights & PRSFS_INSERT)
-       *p++ = 'i';
-    if (rights & PRSFS_DELETE)
-       *p++ = 'd';
-    if (rights & PRSFS_WRITE)
-       *p++ = 'w';
-    if (rights & PRSFS_LOCK)
-       *p++ = 'k';
-    if (rights & PRSFS_ADMINISTER)
-       *p++ = 'a';
-    if (rights & PRSFS_USR0)
-       *p++ = 'A';
-    if (rights & PRSFS_USR1)
-       *p++ = 'B';
-    if (rights & PRSFS_USR2)
-       *p++ = 'C';
-    if (rights & PRSFS_USR3)
-       *p++ = 'D';
-    if (rights & PRSFS_USR4)
-       *p++ = 'E';
-    if (rights & PRSFS_USR5)
-       *p++ = 'F';
-    if (rights & PRSFS_USR6)
-       *p++ = 'G';
-    if (rights & PRSFS_USR7)
-       *p++ = 'H';
-
-    *p = 0;
-    if (!str[0])
-       strcpy(str, "none");
-    return str;
-}
-
-
-/* Parse and store the ACL data from a directory vnode */
-static afs_uint32
-parse_acl(XFILE * X, unsigned char *tag, tagged_field * field,
-         afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-         void *l_refcon)
-{
-    struct acl_accessList *acl;
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_vnode *v = (afs_vnode *) l_refcon;
-    afs_uint32 r, i, n;
-
-    if ((r = xfread(X, v->acl, SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE)))
-       return r;
-
-    v->field_mask |= F_VNODE_ACL;
-    if (p->print_flags & DSPRINT_ACL) {
-       acl = (struct acl_accessList *)(v->acl);
-       n = ntohl(acl->positive);
-       if (n) {
-           printf(" Positive ACL: %d entries\n", n);
-           for (i = 0; i < n; i++)
-               printf("              %9d  %s\n", ntohl(acl->entries[i].id),
-                      rights2str(ntohl(acl->entries[i].rights)));
-       }
-       n = ntohl(acl->negative);
-       if (n) {
-           printf(" Negative ACL: %d entries\n", n);
-           for (i = ntohl(acl->positive); i < ntohl(acl->total); i++)
-               printf("              %9d  %s\n", ntohl(acl->entries[i].id),
-                      rights2str(ntohl(acl->entries[i].rights)));
-       }
-    }
-    return ReadByte(X, tag);
-}
-
-
-/* Parse or skip over the vnode data */
-static afs_uint32
-parse_vdata(XFILE * X, unsigned char *tag, tagged_field * field,
-           afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-           void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_vnode *v = (afs_vnode *) l_refcon;
-    static char *symlink_buf = 0;
-    static int symlink_size = 0;
-    afs_uint32 r;
-
-    if ((r = ReadInt32(X, &v->size)))
-       return r;
-    v->field_mask |= F_VNODE_SIZE;
-
-    if (v->size) {
-       v->field_mask |= F_VNODE_DATA;
-       if ((r = xftell(X, &v->d_offset)))
-           return r;
-       if (p->print_flags & DSPRINT_VNODE)
-           printf("%s%d (0x%08x) bytes at %s (0x%s)\n", field->label,
-                  v->size, v->size, decimate_int64(&v->d_offset, 0),
-                  hexify_int64(&v->d_offset, 0));
-
-       switch (v->type) {
-       case vSymlink:
-           if (v->size > symlink_size) {
-               if (symlink_buf)
-                   symlink_buf = (char *)realloc(symlink_buf, v->size + 1);
-               else
-                   symlink_buf = (char *)malloc(v->size + 1);
-               symlink_size = symlink_buf ? v->size : 0;
-           }
-           if (symlink_buf) {
-               if ((r = xfread(X, symlink_buf, v->size)))
-                   return r;
-               symlink_buf[v->size] = 0;
-               if (p->print_flags & DSPRINT_VNODE)
-                   printf(" Target:       %s\n", symlink_buf);
-           } else {
-               /* Call the callback here, because it's non-fatal */
-               if (p->cb_error)
-                   (p->cb_error) (ENOMEM, 0, p->err_refcon,
-                                  "Out of memory reading symlink");
-               if ((r = xfskip(X, v->size)))
-                   return r;
-           }
-           break;
-
-       case vDirectory:
-           if (p->cb_dirent || (p->print_flags & DSPRINT_DIR)) {
-               if ((r = parse_directory(X, p, v, v->size, 0)))
-                   return r;
-               break;
-           }
-
-       default:
-           if ((r = xfskip(X, v->size)))
-               return r;
-       }
-    } else if (p->print_flags & DSPRINT_VNODE) {
-       printf("%sEmpty\n", field->label);
-    }
-    if (p->repair_flags & DSFIX_VDSYNC) {
-       r = resync_vnode(X, p, v, 10, 15);
-       if (r)
-           return r;
-    }
-    return ReadByte(X, tag);
-}
diff --git a/src/tests/parsevol.c b/src/tests/parsevol.c
deleted file mode 100644 (file)
index 9b95368..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* parsevol.c - Parse a volume header */
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "dumpfmt.h"
-
-static afs_uint32 store_volhdr(XFILE *, unsigned char *, tagged_field *,
-                              afs_uint32, tag_parse_info *, void *, void *);
-static afs_uint32 parse_weekuse(XFILE *, unsigned char *, tagged_field *,
-                               afs_uint32, tag_parse_info *, void *, void *);
-
-/** Field list for volume headers **/
-static tagged_field volhdr_fields[] = {
-    {VHTAG_VOLID, DKIND_INT32, " Volume ID:   ", store_volhdr, 0, 0},
-    {VHTAG_VERS, DKIND_INT32, " Version:     ", store_volhdr, 0, 0},
-    {VHTAG_VOLNAME, DKIND_STRING, " Volume name: ", store_volhdr, 0, 0},
-    {VHTAG_INSERV, DKIND_FLAG, " In service?  ", store_volhdr, 0, 0},
-    {VHTAG_BLESSED, DKIND_FLAG, " Blessed?     ", store_volhdr, 0, 0},
-    {VHTAG_VUNIQ, DKIND_INT32, " Uniquifier:  ", store_volhdr, 0, 0},
-    {VHTAG_TYPE, DKIND_BYTE, " Type:        ", store_volhdr, 0, 0},
-    {VHTAG_PARENT, DKIND_INT32, " Parent ID:   ", store_volhdr, 0, 0},
-    {VHTAG_CLONE, DKIND_INT32, " Clone ID:    ", store_volhdr, 0, 0},
-    {VHTAG_MAXQUOTA, DKIND_INT32, " Max quota:   ", store_volhdr, 0, 0},
-    {VHTAG_MINQUOTA, DKIND_INT32, " Min quota:   ", store_volhdr, 0, 0},
-    {VHTAG_DISKUSED, DKIND_INT32, " Disk used:   ", store_volhdr, 0, 0},
-    {VHTAG_FILECNT, DKIND_INT32, " File count:  ", store_volhdr, 0, 0},
-    {VHTAG_ACCOUNT, DKIND_INT32, " Account:     ", store_volhdr, 0, 0},
-    {VHTAG_OWNER, DKIND_INT32, " Owner:       ", store_volhdr, 0, 0},
-    {VHTAG_CREAT, DKIND_TIME, " Created:     ", store_volhdr, 0, 0},
-    {VHTAG_ACCESS, DKIND_TIME, " Accessed:    ", store_volhdr, 0, 0},
-    {VHTAG_UPDATE, DKIND_TIME, " Updated:     ", store_volhdr, 0, 0},
-    {VHTAG_EXPIRE, DKIND_TIME, " Expires:     ", store_volhdr, 0, 0},
-    {VHTAG_BACKUP, DKIND_TIME, " Backed up:   ", store_volhdr, 0, 0},
-    {VHTAG_OFFLINE, DKIND_STRING, " Offine Msg:  ", store_volhdr, 0, 0},
-    {VHTAG_MOTD, DKIND_STRING, " MOTD:        ", store_volhdr, 0, 0},
-    {VHTAG_WEEKUSE, DKIND_SPECIAL, " Weekuse:     ", parse_weekuse, 0, 0},
-    {VHTAG_DUDATE, DKIND_TIME, " Dayuse Date: ", store_volhdr, 0, 0},
-    {VHTAG_DAYUSE, DKIND_INT32, " Daily usage: ", store_volhdr, 0, 0},
-    {0, 0, 0, 0, 0, 0}
-};
-
-
-/* Parse a volume header, including any tagged attributes, and call the
- * volume-header callback, if one is defined.
- */
-afs_uint32
-parse_volhdr(XFILE * X, unsigned char *tag, tagged_field * field,
-            afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-            void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_vol_header hdr;
-    u_int64 where;
-    afs_uint32 r;
-
-    memset(&hdr, 0, sizeof(hdr));
-    if ((r = xftell(X, &where)))
-       return r;
-    sub64_32(hdr.offset, where, 1);
-    if (p->print_flags & DSPRINT_VOLHDR)
-       printf("%s [%s = 0x%s]\n", field->label,
-              decimate_int64(&hdr.offset, 0), hexify_int64(&hdr.offset, 0));
-
-    r = ParseTaggedData(X, volhdr_fields, tag, pi, g_refcon, (void *)&hdr);
-
-    if (!r && p->cb_volhdr) {
-      if ((r = xftell(X, &where)))
-           return r;
-       r = (p->cb_volhdr) (&hdr, X, p->refcon);
-       if (p->flags & DSFLAG_SEEK) {
-           if (!r)
-               r = xfseek(X, &where);
-           else
-               xfseek(X, &where);
-       }
-    }
-    if (hdr.field_mask & F_VOLHDR_VOLUNIQ)
-       p->vol_uniquifier = hdr.voluniq;
-    if (hdr.field_mask & F_VOLHDR_VOLNAME)
-       free(hdr.volname);
-    if (hdr.field_mask & F_VOLHDR_OFFLINE_MSG)
-       free(hdr.offline_msg);
-    if (hdr.field_mask & F_VOLHDR_MOTD)
-       free(hdr.motd_msg);
-    return r;
-}
-
-
-/* Store data in a volume header */
-static afs_uint32
-store_volhdr(XFILE * X, unsigned char *tag, tagged_field * field,
-            afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-            void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_vol_header *hdr = (afs_vol_header *) l_refcon;
-    time_t when;
-    afs_uint32 r = 0;
-
-    switch (field->tag) {
-    case VHTAG_VOLID:
-       hdr->field_mask |= F_VOLHDR_VOLID;
-       hdr->volid = value;
-       break;
-
-    case VHTAG_VERS:
-       hdr->field_mask |= F_VOLHDR_VOLVERS;
-       hdr->volvers = value;
-       break;
-
-    case VHTAG_VOLNAME:
-       if (tag && tag[0]) {
-           hdr->field_mask |= F_VOLHDR_VOLNAME;
-           hdr->volname = tag;
-           r = DSERR_KEEP;
-       }
-       break;
-
-    case VHTAG_INSERV:
-       hdr->field_mask |= F_VOLHDR_INSERV;
-       hdr->flag_inservice = value;
-       break;
-
-    case VHTAG_BLESSED:
-       hdr->field_mask |= F_VOLHDR_BLESSED;
-       hdr->flag_blessed = value;
-       break;
-
-    case VHTAG_VUNIQ:
-       hdr->field_mask |= F_VOLHDR_VOLUNIQ;
-       hdr->voluniq = value;
-       break;
-
-    case VHTAG_TYPE:
-       hdr->field_mask |= F_VOLHDR_VOLTYPE;
-       hdr->voltype = value;
-       break;
-
-    case VHTAG_PARENT:
-       hdr->field_mask |= F_VOLHDR_PARENT;
-       hdr->parent_volid = value;
-       break;
-
-    case VHTAG_CLONE:
-       hdr->field_mask |= F_VOLHDR_CLONE;
-       hdr->clone_volid = value;
-       break;
-
-    case VHTAG_MAXQUOTA:
-       hdr->field_mask |= F_VOLHDR_MAXQ;
-       hdr->maxquota = value;
-       break;
-
-    case VHTAG_MINQUOTA:
-       hdr->field_mask |= F_VOLHDR_MINQ;
-       hdr->minquota = value;
-       break;
-
-    case VHTAG_DISKUSED:
-       hdr->field_mask |= F_VOLHDR_DISKUSED;
-       hdr->diskused = value;
-       break;
-
-    case VHTAG_FILECNT:
-       hdr->field_mask |= F_VOLHDR_NFILES;
-       hdr->nfiles = value;
-       break;
-
-    case VHTAG_ACCOUNT:
-       hdr->field_mask |= F_VOLHDR_ACCOUNT;
-       hdr->account_no = value;
-       break;
-
-    case VHTAG_OWNER:
-       hdr->field_mask |= F_VOLHDR_OWNER;
-       hdr->owner = value;
-       break;
-
-    case VHTAG_CREAT:
-       hdr->field_mask |= F_VOLHDR_CREATE_DATE;
-       hdr->create_date = value;
-       break;
-
-    case VHTAG_ACCESS:
-       hdr->field_mask |= F_VOLHDR_ACCESS_DATE;
-       hdr->access_date = value;
-       break;
-
-    case VHTAG_UPDATE:
-       hdr->field_mask |= F_VOLHDR_UPDATE_DATE;
-       hdr->update_date = value;
-       break;
-
-    case VHTAG_EXPIRE:
-       hdr->field_mask |= F_VOLHDR_EXPIRE_DATE;
-       hdr->expire_date = value;
-       break;
-
-    case VHTAG_BACKUP:
-       hdr->field_mask |= F_VOLHDR_BACKUP_DATE;
-       hdr->backup_date = value;
-       break;
-
-    case VHTAG_OFFLINE:
-       if (tag && tag[0]) {
-           hdr->field_mask |= F_VOLHDR_OFFLINE_MSG;
-           hdr->offline_msg = tag;
-           r = DSERR_KEEP;
-       }
-       break;
-
-    case VHTAG_MOTD:
-       if (tag && tag[0]) {
-           hdr->field_mask |= F_VOLHDR_MOTD;
-           hdr->motd_msg = tag;
-           r = DSERR_KEEP;
-       }
-       break;
-
-    case VHTAG_DUDATE:
-       hdr->field_mask |= F_VOLHDR_DAYUSE_DATE;
-       hdr->dayuse_date = value;
-       break;
-
-    case VHTAG_DAYUSE:
-       hdr->field_mask |= F_VOLHDR_DAYUSE;
-       hdr->dayuse = value;
-       break;
-    }
-
-    if (p->print_flags & DSPRINT_VOLHDR)
-       switch (field->kind) {
-       case DKIND_BYTE:
-       case DKIND_INT16:
-       case DKIND_INT32:
-           printf("%s%d\n", field->label, value);
-           break;
-       case DKIND_HEX8:
-           printf("%s0x%02x\n", field->label, value);
-           break;
-       case DKIND_HEX16:
-           printf("%s0x%04x\n", field->label, value);
-           break;
-       case DKIND_HEX32:
-           printf("%s0x%08x\n", field->label, value);
-           break;
-       case DKIND_CHAR:
-           printf("%s%c\n", field->label, value);
-           break;
-       case DKIND_STRING:
-           printf("%s%s\n", field->label, tag);
-           break;
-       case DKIND_FLAG:
-           printf("%s%s\n", field->label, value ? "true" : "false");
-           break;
-       case DKIND_TIME:
-           when = value;
-           printf("%s%s", field->label, ctime(&when));
-           break;
-       }
-    return r;
-}
-
-
-/* Parse and store the week use data from a volume header */
-static afs_uint32
-parse_weekuse(XFILE * X, unsigned char *tag, tagged_field * field,
-             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
-             void *l_refcon)
-{
-    dump_parser *p = (dump_parser *) g_refcon;
-    afs_vol_header *hdr = (afs_vol_header *) l_refcon;
-    afs_uint16 count;
-    afs_uint32 r;
-    unsigned int i;
-
-    if ((r = ReadInt16(X, &count)))
-       return r;
-    if (count != 7) {
-       if (p->cb_error)
-           (p->cb_error) (DSERR_FMT, 1, p->err_refcon,
-                          "Incorrect array count (%d) in weekuse data",
-                          count);
-       return DSERR_FMT;
-    }
-    for (i = 0; i < count; i++)
-       if ((r = ReadInt32(X, hdr->weekuse + i)))
-           return r;
-    hdr->field_mask |= F_VOLHDR_WEEKUSE;
-    if (p->print_flags & DSPRINT_VOLHDR) {
-       printf("%s%10d %10d %10d %10d\n", field->label, hdr->weekuse[0],
-              hdr->weekuse[1], hdr->weekuse[2], hdr->weekuse[3]);
-       printf("%s%10d %10d %10d\n", field->label, hdr->weekuse[4],
-              hdr->weekuse[5], hdr->weekuse[6]);
-    }
-    return ReadByte(X, tag);
-}
diff --git a/src/tests/pathname.c b/src/tests/pathname.c
deleted file mode 100644 (file)
index 0057df8..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* pathname.c - Pathname lookup and traversal */
-
-#include <errno.h>
-#include <string.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-
-/* Hash function for a vnode */
-#define BUCKET_SIZE 32
-#define vnode_hash(phi,vnode) ((vnode) & ((1 << (phi)->hash_size) - 1))
-
-
-static vhash_ent *
-get_vhash_ent(path_hashinfo * phi, afs_uint32 vnode, int make)
-{
-    int key = vnode_hash(phi, vnode);
-    vhash_ent *vhe;
-
-    for (vhe = phi->hash_table[key]; vhe && vhe->vnode != vnode;
-        vhe = vhe->next);
-    if (make && !vhe) {
-       vhe = (vhash_ent *) malloc(sizeof(vhash_ent));
-       if (vhe) {
-           memset(vhe, 0, sizeof(vhash_ent));
-           vhe->vnode = vnode;
-           vhe->next = phi->hash_table[key];
-           phi->hash_table[key] = vhe;
-       }
-    }
-    return vhe;
-}
-
-
-static afs_uint32
-volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
-{
-    path_hashinfo *phi = (path_hashinfo *) refcon;
-    int nfiles, hsize;
-
-    if (hdr->field_mask & F_VOLHDR_NFILES) {
-       nfiles = phi->n_vnodes = hdr->nfiles;
-       for (phi->hash_size = 1; nfiles > BUCKET_SIZE;
-            phi->hash_size++, nfiles >>= 1);
-       hsize = (1 << phi->hash_size);
-       phi->hash_table = (vhash_ent **) malloc(hsize * sizeof(vhash_ent *));
-       if (!phi->hash_table)
-           return ENOMEM;
-       memset(phi->hash_table, 0, hsize * sizeof(vhash_ent *));
-       return 0;
-    } else {
-       if (phi->p->cb_error)
-           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                               "File count missing from volume header");
-       return DSERR_FMT;
-    }
-}
-
-
-static afs_uint32
-vnode_keep(afs_vnode * v, XFILE * X, void *refcon)
-{
-    path_hashinfo *phi = (path_hashinfo *) refcon;
-    vhash_ent *vhe;
-
-    if (!phi->hash_table) {
-       if (phi->p->cb_error)
-           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->refcon,
-                               "No volume header in dump???");
-       return DSERR_FMT;
-    }
-    vhe = get_vhash_ent(phi, v->vnode, 1);
-    if (!vhe)
-       return ENOMEM;
-    cp64(vhe->v_offset, v->offset);
-    if (v->field_mask & F_VNODE_PARENT)
-       vhe->parent = v->parent;
-    if (v->field_mask & F_VNODE_DATA) {
-       cp64(vhe->d_offset, v->d_offset);
-       vhe->d_size = v->size;
-    }
-    if ((v->field_mask & F_VNODE_TYPE) && v->type == vDirectory)
-       phi->n_dirs++;
-    else
-       phi->n_files++;
-    return 0;
-}
-
-
-static afs_uint32
-vnode_stop(afs_vnode * v, XFILE * X, void *refcon)
-{
-    path_hashinfo *phi = (path_hashinfo *) refcon;
-    int r;
-
-    /* If the file is seekable, try to position so we can pick up later... */
-    if (phi->p->flags & DSFLAG_SEEK)
-      if ((r = xfseek(X, &v->offset)))
-           return r;
-    return DSERR_DONE;
-}
-
-
-static afs_uint32
-dirent_cb(afs_vnode * v, afs_dir_entry * de, XFILE * X, void *refcon)
-{
-    path_hashinfo *phi = (path_hashinfo *) refcon;
-    vhash_ent *vhe;
-
-    if (!phi->hash_table) {
-       if (phi->p->cb_error)
-           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->refcon,
-                               "No volume header in dump???");
-       return DSERR_FMT;
-    }
-    if (!strcmp(de->name, ".") || !strcmp(de->name, ".."))
-       return 0;
-    vhe = get_vhash_ent(phi, de->vnode, 1);
-    if (!vhe)
-       return ENOMEM;
-    vhe->parent = v->vnode;
-    return 0;
-}
-
-
-/* Prescan the vnodes in a dump file, collecting information that will
- * be useful in generating and following pathnames.
- */
-afs_uint32
-Path_PreScan(XFILE * X, path_hashinfo * phi, int full)
-{
-    dump_parser my_p, *p = phi->p;
-
-    memset(phi, 0, sizeof(path_hashinfo));
-    phi->p = p;
-    memset(&my_p, 0, sizeof(my_p));
-    my_p.refcon = (void *)phi;
-    my_p.cb_volhdr = volhdr_cb;
-    my_p.cb_vnode_dir = vnode_keep;
-    if (full) {
-       my_p.cb_vnode_file = vnode_keep;
-       my_p.cb_vnode_link = vnode_keep;
-       my_p.cb_vnode_empty = vnode_keep;
-       my_p.cb_vnode_wierd = vnode_keep;
-    } else {
-       my_p.cb_vnode_file = vnode_stop;
-       my_p.cb_vnode_link = vnode_stop;
-       my_p.cb_vnode_empty = vnode_stop;
-       my_p.cb_vnode_wierd = vnode_stop;
-    }
-    my_p.err_refcon = p->err_refcon;
-    my_p.cb_error = p->cb_error;
-    my_p.cb_dirent = dirent_cb;
-    my_p.flags = p->flags;
-    my_p.print_flags = p->print_flags;
-    my_p.repair_flags = p->repair_flags;
-
-    return ParseDumpFile(X, &my_p);
-}
-
-
-/* Free the hash table in a path_hashinfo */
-void
-Path_FreeHashTable(path_hashinfo * phi)
-{
-    int i, size;
-    vhash_ent *vhe, *next_vhe;
-
-    if (phi->hash_table) {
-       size = (1 << phi->hash_size);
-       for (i = 0; i < size; i++)
-           for (vhe = phi->hash_table[i]; vhe; vhe = next_vhe) {
-               next_vhe = vhe->next;
-               free(vhe);
-           }
-       free(phi->hash_table);
-    }
-}
-
-
-/* Follow a pathname to the vnode it represents */
-afs_uint32
-Path_Follow(XFILE * X, path_hashinfo * phi, char *path, vhash_ent * his_vhe)
-{
-    vhash_ent *vhe;
-    char *name;
-    afs_uint32 r, vnum = 1;
-
-    if (*path == '/')
-       path++;
-    name = strtok(path, "/");
-
-    for (name = strtok(path, "/"); name; name = strtok(0, "/")) {
-       if (!(vnum & 1)) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (ENOTDIR, 1, phi->p->err_refcon,
-                                   "Not a directory vnode");
-           return ENOTDIR;
-       }
-       vhe = get_vhash_ent(phi, vnum, 0);
-       if (!vhe) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                                   "Vnode %d not found in hash table", vnum);
-           return DSERR_FMT;
-       }
-       if (zero64(vhe->d_offset)) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                                   "Directory vnode %d is incomplete", vnum);
-           return DSERR_FMT;
-       }
-       if ((r = xfseek(X, &vhe->d_offset))) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (r, 1, phi->p->err_refcon,
-                                   "Unable to seek to directory %d", vnum);
-           return r;
-       }
-       vnum = 0;
-       r = DirectoryLookup(X, phi->p, vhe->d_size, &name, &vnum, 0);
-       if (r)
-           return r;
-       if (!vnum) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (ENOENT, 1, phi->p->err_refcon,
-                                   "No such vnode");
-           return ENOENT;
-       }
-    }
-    vhe = get_vhash_ent(phi, vnum, 0);
-    if (!vhe) {
-       if (phi->p->cb_error)
-           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                               "Vnode %d not found in hash table", vnum);
-       return DSERR_FMT;
-    }
-    if (his_vhe)
-       *his_vhe = *vhe;
-    return 0;
-}
-
-
-afs_uint32
-Path_Build(XFILE * X, path_hashinfo * phi, afs_uint32 vnode, char **his_path,
-          int fast)
-{
-    vhash_ent *vhe;
-    char *name, *path = 0, fastbuf[12];
-    char *x, *y;
-    afs_uint32 parent, r;
-    int nl, pl = 0;
-
-    if (vnode == 1) {
-       *his_path = (char *)malloc(2);
-       if (!his_path) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
-                                   "No memory for pathname of vnode 1");
-           return ENOMEM;
-       }
-       strcpy(*his_path, "/");
-       return 0;
-    }
-
-    *his_path = 0;
-    vhe = get_vhash_ent(phi, vnode, 0);
-    if (!vhe) {
-       if (phi->p->cb_error)
-           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                               "Vnode %d not found in hash table", vnode);
-       return DSERR_FMT;
-    }
-    while (vnode != 1) {
-       /* Find the parent */
-       if (!vhe->parent) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                                   "Vnode %d has no parent?", vnode);
-           if (path)
-               free(path);
-           return DSERR_FMT;
-       }
-       parent = vhe->parent;
-       vhe = get_vhash_ent(phi, parent, 0);
-       if (phi->p->print_flags & DSPRINT_DEBUG)
-           fprintf(stderr, "Searching for vnode %d in parent %d\n", vnode,
-                   parent);
-       if (!vhe) {
-           if (phi->p->cb_error)
-               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                                   "Vnode %d not found in hash table",
-                                   parent);
-           if (path)
-               free(path);
-           return DSERR_FMT;
-       }
-
-       if (fast) {
-           /* Make up a path component from the vnode number */
-           sprintf(fastbuf, "%d", vnode);
-           name = fastbuf;
-       } else {
-           /* Do a reverse-lookup in the parent directory */
-           if (zero64(vhe->d_offset)) {
-               if (phi->p->cb_error)
-                   (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                                       "Directory vnode %d is incomplete",
-                                       parent);
-               if (path)
-                   free(path);
-               return DSERR_FMT;
-           }
-           if ((r = xfseek(X, &vhe->d_offset))) {
-               if (phi->p->cb_error)
-                   (phi->p->cb_error) (errno, 1, phi->p->err_refcon,
-                                       "Unable to seek to directory %d",
-                                       parent);
-               if (path)
-                   free(path);
-               return r;
-           }
-
-           name = 0;
-           r = DirectoryLookup(X, phi->p, vhe->d_size, &name, &vnode, 0);
-           if (r)
-               return r;
-           if (!name) {
-               if (phi->p->cb_error)
-                   (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
-                                       "No entry for vnode %d in directory %d",
-                                       vnode, parent);
-               if (path)
-                   free(path);
-               return ENOENT;
-           }
-       }
-
-       nl = strlen(name);
-       if (path) {
-           path = (char *)realloc(path, nl + pl + 2);
-           if (!path) {
-               if (phi->p->cb_error)
-                   (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
-                                       "No memory for pathname of vnode 1");
-               return ENOMEM;
-           }
-           x = path + pl;
-           y = x + nl + 1;
-           while (x >= path)
-               *y-- = *x--;
-           path[0] = '/';
-           for (x = name, y = path + 1; *x;)
-               *y++ = *x++;
-           pl += nl + 1;
-       } else {
-           path = (char *)malloc(nl + 2);
-           if (!path) {
-               if (phi->p->cb_error)
-                   (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
-                                       "No memory for pathname of vnode 1");
-               return ENOMEM;
-           }
-           path[0] = '/';
-           strcpy(path + 1, name);
-           pl = nl + 1;
-       }
-       if (!fast)
-           free(name);
-       vnode = parent;
-    }
-    *his_path = path;
-    return 0;
-}
diff --git a/src/tests/primitive.c b/src/tests/primitive.c
deleted file mode 100644 (file)
index 80e5dbd..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* primitive.c - Routines for reading and writing low-level things */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dumpscan.h"
-
-#define BUFSIZE 256
-
-
-afs_uint32
-ReadByte(XFILE * X, unsigned char *val)
-{
-    return xfread(X, val, 1);
-}
-
-afs_uint32
-ReadInt16(XFILE * X, afs_uint16 * val)
-{
-    afs_uint32 r;
-
-    if ((r = xfread(X, val, 2)))
-       return r;
-    *val = ntohs(*val);
-    return 0;
-}
-
-afs_uint32
-ReadInt32(XFILE * X, afs_uint32 * val)
-{
-    afs_uint32 r;
-
-    if ((r = xfread(X, val, 4)))
-       return r;
-    *val = ntohl(*val);
-    return 0;
-}
-
-/* Read in a NUL-terminated string.  This method is kind of messy, but
- * has the advantage that it reads the data stream only once, doesn't
- * read anything extra, and never has to seek on the data stream.
- */
-afs_uint32
-ReadString(XFILE * X, unsigned char **val)
-{
-    static unsigned char buf[BUFSIZE];
-    unsigned char *result = 0;
-    afs_uint32 r;
-    int i, l = 0;
-
-    *val = 0;
-    for (;;) {
-       for (i = 0; i < BUFSIZE; i++) {
-           r = ReadByte(X, buf + i);
-           if (r) {
-               if (result)
-                   free(result);
-               return r;
-           }
-           if (!buf[i])
-               break;
-       }
-       /* iff we found a null, i < BUFSIZE and buf[i] holds the NUL */
-       if (result)
-           result = (unsigned char *)realloc(result, l + i + 1);
-       else
-           result = (unsigned char *)malloc(i + 1);
-       if (!result)
-           return ENOMEM;
-       memcpy(result + l, buf, i);
-       result[l + i] = 0;
-       l += i;
-       if (i < BUFSIZE)
-           break;
-    }
-    *val = result;
-    return 0;
-}
-
-
-afs_uint32
-WriteByte(XFILE * X, unsigned char val)
-{
-    return xfwrite(X, &val, 1);
-}
-
-afs_uint32
-WriteInt16(XFILE * X, afs_uint16 val)
-{
-    val = htons(val);
-    return xfwrite(X, &val, 2);
-}
-
-afs_uint32
-WriteInt32(XFILE * X, afs_uint32 val)
-{
-    val = htonl(val);
-    return xfwrite(X, &val, 4);
-}
-
-afs_uint32
-WriteString(XFILE * X, unsigned char *str)
-{
-    int len = strlen((char *)str) + 1;
-    return xfwrite(X, str, len);
-}
-
-afs_uint32
-WriteTagByte(XFILE * X, unsigned char tag, unsigned char val)
-{
-    char buffer[2];
-    buffer[0] = tag;
-    buffer[1] = val;
-    return xfwrite(X, buffer, 2);
-}
-
-afs_uint32
-WriteTagInt16(XFILE * X, unsigned char tag, afs_uint16 val)
-{
-    char buffer[3];
-    buffer[0] = tag;
-    buffer[1] = (val & 0xff00) >> 8;
-    buffer[2] = val & 0xff;
-    return xfwrite(X, buffer, 3);
-}
-
-afs_uint32
-WriteTagInt32(XFILE * X, unsigned char tag, afs_uint32 val)
-{
-    char buffer[5];
-    buffer[0] = tag;
-    buffer[1] = (val & 0xff000000) >> 24;
-    buffer[2] = (val & 0xff0000) >> 16;
-    buffer[3] = (val & 0xff00) >> 8;
-    buffer[4] = val & 0xff;
-    return xfwrite(X, buffer, 5);
-}
-
-afs_uint32
-WriteTagInt32Pair(XFILE * X, unsigned char tag, afs_uint32 val1,
-                 afs_uint32 val2)
-{
-    char buffer[9];
-    buffer[0] = tag;
-    buffer[1] = (val1 & 0xff000000) >> 24;
-    buffer[2] = (val1 & 0xff0000) >> 16;
-    buffer[3] = (val1 & 0xff00) >> 8;
-    buffer[4] = val1 & 0xff;
-    buffer[5] = (val2 & 0xff000000) >> 24;
-    buffer[6] = (val2 & 0xff0000) >> 16;
-    buffer[7] = (val2 & 0xff00) >> 8;
-    buffer[8] = val2 & 0xff;
-    return xfwrite(X, buffer, 9);
-}
diff --git a/src/tests/repair.c b/src/tests/repair.c
deleted file mode 100644 (file)
index e4d80d5..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* repair.c - Routines to generate a repaired dump */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "dumpfmt.h"
-
-#include <afs/acl.h>
-#include <afs/dir.h>
-#include <afs/prs_fs.h>
-
-XFILE repair_output;
-int repair_verbose;
-#define RV repair_verbose
-
-extern afs_uint32 CopyVNodeData(XFILE * OX, XFILE * X, afs_uint32 size);
-extern afs_uint32 DumpVNodeData(XFILE * OX, char *buf, afs_uint32 size);
-
-/* Try to dump a dump header.  Generate missing fields, if neccessary */
-afs_uint32
-repair_dumphdr_cb(afs_dump_header * hdr, XFILE * X, void *refcon)
-{
-    afs_uint32 field_mask = hdr->field_mask;
-    char volname[22];
-
-    if (!(field_mask & F_DUMPHDR_VOLID)) {
-       if (RV)
-           fprintf(stderr, ">>> DUMP HEADER missing volume ID\n");
-       return DSERR_FMT;
-    }
-    if (!(field_mask & F_DUMPHDR_VOLNAME)) {
-       if (RV) {
-           fprintf(stderr, ">>> DUMP HEADER missing volume name\n");
-           fprintf(stderr, ">>> Will use RESTORED.%d\n", hdr->volid);
-       }
-       sprintf(volname, "RESTORED.%d", hdr->volid);
-       hdr->volname = (unsigned char *)malloc(strlen(volname) + 1);
-       if (!hdr->volname)
-           return ENOMEM;
-       strcpy((char *)hdr->volname, volname);
-       hdr->field_mask |= F_DUMPHDR_VOLNAME;
-    }
-    if (!(field_mask & F_DUMPHDR_FROM)) {
-       if (RV)
-           fprintf(stderr, ">>> DUMP HEADER missing from time (using 0)\n");
-       hdr->from_date = 0;
-       hdr->field_mask |= F_DUMPHDR_FROM;
-    }
-    if (!(field_mask & F_DUMPHDR_TO)) {
-       hdr->to_date = time(0);
-       if (RV)
-           fprintf(stderr, ">>> DUMP HEADER missing from time (using %d)\n",
-                   hdr->to_date);
-       hdr->field_mask |= F_DUMPHDR_TO;
-    }
-
-    return DumpDumpHeader(&repair_output, hdr);
-}
-
-
-/* Try to dump a volume header.  Generate missing fields, if necessary */
-afs_uint32
-repair_volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
-{
-    afs_uint32 field_mask = hdr->field_mask;
-    char volname[22];
-
-    if (!(field_mask & F_VOLHDR_VOLID)) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing volume ID\n");
-       return DSERR_FMT;
-    }
-    if (!(field_mask & F_VOLHDR_VOLVERS)) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing version (using 1)\n");
-       hdr->volvers = 1;
-       hdr->field_mask |= F_VOLHDR_VOLVERS;
-    } else if (hdr->volvers != 1) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER bogus version %d (using 1)\n",
-                   hdr->volvers);
-       hdr->volvers = 1;
-    }
-    if (!(field_mask & F_VOLHDR_VOLNAME)) {
-       if (RV) {
-           fprintf(stderr, ">>> VOL HEADER missing volume name\n");
-           fprintf(stderr, ">>> Will use RESTORED.%d\n", hdr->volid);
-       }
-       sprintf(volname, "RESTORED.%d", hdr->volid);
-       hdr->volname = (unsigned char *)malloc(strlen(volname) + 1);
-       if (!hdr->volname)
-           return ENOMEM;
-       strcpy((char *)hdr->volname, volname);
-       hdr->field_mask |= F_VOLHDR_VOLNAME;
-    }
-    if (!(field_mask & F_VOLHDR_INSERV)) {
-       if (RV)
-           fprintf(stderr,
-                   ">>> VOL HEADER missing in-service flag (using 1)\n");
-       hdr->flag_inservice = 1;
-       hdr->field_mask |= F_VOLHDR_INSERV;
-    }
-    if (!(field_mask & F_VOLHDR_BLESSED)) {
-       if (RV)
-           fprintf(stderr,
-                   ">>> VOL HEADER missing blessed flag (using 1)\n");
-       hdr->flag_blessed = 1;
-       hdr->field_mask |= F_VOLHDR_BLESSED;
-    }
-    if (!(field_mask & F_VOLHDR_VOLUNIQ)) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing uniquifier (using 1)\n");
-       hdr->voluniq = 1;
-       hdr->field_mask |= F_VOLHDR_VOLUNIQ;
-    }
-    if (!(field_mask & F_VOLHDR_VOLTYPE)) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing type (using 0: RW)\n");
-       hdr->voltype = 0;
-       hdr->field_mask |= F_VOLHDR_VOLTYPE;
-    } else if (hdr->voltype < 0 || hdr->voltype > 2) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER bogus type %d (using 0: RW)\n",
-                   hdr->voltype);
-       hdr->voltype = 0;
-    }
-    if (!(field_mask & F_VOLHDR_PARENT)) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER parent (using %d)\n", hdr->volid);
-       hdr->parent_volid = hdr->volid;
-       hdr->field_mask |= F_VOLHDR_PARENT;
-    }
-    if (!(field_mask & F_VOLHDR_MAXQ)) {
-       if (field_mask & F_VOLHDR_DISKUSED)
-           hdr->maxquota = hdr->diskused;
-       else
-           hdr->maxquota = 1;
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing max quota (using %d)\n",
-                   hdr->maxquota);
-       hdr->field_mask |= F_VOLHDR_MAXQ;
-    }
-    if (!(field_mask & F_VOLHDR_DISKUSED)) {
-       if (RV)
-           fprintf(stderr,
-                   ">>> VOL HEADER missing disk used (using 2048)\n");
-       hdr->diskused = 2048;
-       hdr->field_mask |= F_VOLHDR_DISKUSED;
-    }
-    if (!(field_mask & F_VOLHDR_NFILES)) {
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing file count (using 1)\n");
-       hdr->nfiles = 1;
-       hdr->field_mask |= F_VOLHDR_NFILES;
-    }
-    if (!(field_mask & F_VOLHDR_CREATE_DATE)) {
-       hdr->create_date = 0;
-       if ((field_mask & F_VOLHDR_ACCESS_DATE)
-           && (!hdr->create_date || hdr->access_date < hdr->create_date))
-           hdr->create_date = hdr->access_date;
-       if ((field_mask & F_VOLHDR_UPDATE_DATE)
-           && (!hdr->create_date || hdr->update_date < hdr->create_date))
-           hdr->create_date = hdr->update_date;
-       if ((field_mask & F_VOLHDR_BACKUP_DATE)
-           && (!hdr->create_date || hdr->backup_date < hdr->create_date))
-           hdr->create_date = hdr->backup_date;
-
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing create date (using %d)\n",
-                   hdr->create_date);
-       hdr->field_mask |= F_VOLHDR_CREATE_DATE;
-    }
-    if (!(field_mask & F_VOLHDR_ACCESS_DATE)) {
-       hdr->access_date = 0;
-       if ((field_mask & F_VOLHDR_CREATE_DATE)
-           && (!hdr->access_date || hdr->create_date > hdr->access_date))
-           hdr->access_date = hdr->create_date;
-       if ((field_mask & F_VOLHDR_UPDATE_DATE)
-           && (!hdr->access_date || hdr->update_date > hdr->access_date))
-           hdr->access_date = hdr->update_date;
-       if ((field_mask & F_VOLHDR_BACKUP_DATE)
-           && (!hdr->access_date || hdr->backup_date > hdr->access_date))
-           hdr->access_date = hdr->backup_date;
-
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing access date (using %d)\n",
-                   hdr->access_date);
-       hdr->field_mask |= F_VOLHDR_ACCESS_DATE;
-    }
-    if (!(field_mask & F_VOLHDR_UPDATE_DATE)) {
-       hdr->update_date = 0;
-       if ((field_mask & F_VOLHDR_CREATE_DATE)
-           && (!hdr->update_date || hdr->create_date > hdr->update_date))
-           hdr->update_date = hdr->create_date;
-       if ((field_mask & F_VOLHDR_ACCESS_DATE) && !hdr->update_date)
-           hdr->update_date = hdr->access_date;
-       if ((field_mask & F_VOLHDR_BACKUP_DATE) && !hdr->update_date)
-           hdr->update_date = hdr->backup_date;
-
-       if (RV)
-           fprintf(stderr, ">>> VOL HEADER missing update date (using %d)\n",
-                   hdr->update_date);
-       hdr->field_mask |= F_VOLHDR_UPDATE_DATE;
-    }
-
-    return DumpVolumeHeader(&repair_output, hdr);
-}
-
-
-/* Try to dump a vnode.  Generate missing fields, if necessary */
-afs_uint32
-repair_vnode_cb(afs_vnode * v, XFILE * X, void *refcon)
-{
-    afs_uint32 r, field_mask = v->field_mask;
-
-    if ((v->vnode & 1) && !field_mask) {
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d is directory but has no fields?\n", v->vnode);
-       v->type = vDirectory;
-       v->field_mask |= F_VNODE_TYPE;
-       field_mask = F_VNODE_TYPE;      /* Messy! */
-    }
-    if (field_mask && !(field_mask & F_VNODE_TYPE)) {
-       v->type = (v->vnode & 1) ? vDirectory : vFile;
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing type (using %d)\n",
-                   v->vnode, v->type);
-       v->field_mask |= F_VNODE_TYPE;
-    }
-    if (field_mask && !(field_mask & F_VNODE_NLINKS)) {
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing link count (using 1)\n",
-                   v->vnode);
-       v->nlinks = 1;
-       v->field_mask |= F_VNODE_NLINKS;
-    }
-    if (field_mask && !(field_mask & F_VNODE_PARENT)) {
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing parent (using 1)\n",
-                   v->vnode);
-       v->parent = 1;
-       v->field_mask |= F_VNODE_PARENT;
-    }
-    if (field_mask && !(field_mask & F_VNODE_DVERS)) {
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing data version (using 1)\n",
-                   v->vnode);
-       v->datavers = 1;
-       v->field_mask |= F_VNODE_DVERS;
-    }
-    if (field_mask && !(field_mask & F_VNODE_AUTHOR)) {
-       if (field_mask & F_VNODE_OWNER)
-           v->author = v->owner;
-       else
-           v->author = 0;
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing author (using %d)\n",
-                   v->vnode, v->author);
-       v->field_mask |= F_VNODE_AUTHOR;
-    }
-    if (field_mask && !(field_mask & F_VNODE_OWNER)) {
-       if (field_mask & F_VNODE_AUTHOR)
-           v->owner = v->author;
-       else
-           v->owner = 0;
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing owner (using %d)\n",
-                   v->vnode, v->owner);
-       v->field_mask |= F_VNODE_OWNER;
-    }
-    if (field_mask && !(field_mask & F_VNODE_MODE)) {
-       v->mode = (v->vnode & 1) ? 0755 : 0644;
-       if (RV)
-           fprintf(stderr, ">>> VNODE missing mode (using %d)\n", v->mode);
-       v->field_mask |= F_VNODE_MODE;
-    }
-    if (field_mask && !(field_mask & F_VNODE_CDATE)) {
-       if (field_mask & F_VNODE_SDATE)
-           v->client_date = v->server_date;
-       else
-           v->client_date = 0;
-
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing client date (using %d)\n",
-                   v->vnode, v->client_date);
-       v->field_mask |= F_VNODE_CDATE;
-    }
-    if (field_mask && !(field_mask & F_VNODE_SDATE)) {
-       if (field_mask & F_VNODE_CDATE)
-           v->server_date = v->client_date;
-       else
-           v->server_date = 0;
-
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d missing server date (using %d)\n",
-                   v->vnode, v->server_date);
-       v->field_mask |= F_VNODE_SDATE;
-    }
-    if (field_mask && !(field_mask & F_VNODE_SIZE)) {
-       if (RV)
-           fprintf(stderr, ">>> VNODE %d has no data size (using 0)\n", v->vnode);
-       v->size = 0;
-       v->field_mask |= F_VNODE_SIZE;
-    }
-    if ((field_mask & F_VNODE_DATA) && !v->size) {
-       if (RV)
-           fprintf(stderr,
-                   ">>> VNODE %d has data, but size == 0 (ignoring)\n",
-                   v->vnode);
-       v->field_mask &= ~F_VNODE_DATA;
-    }
-    if (field_mask && v->type == vDirectory && !(field_mask & F_VNODE_ACL)) {
-       struct acl_accessList *acl = (struct acl_accessList *)v->acl;
-       if (RV) {
-           fprintf(stderr, ">>> VNODE %d is directory but has no ACL\n", v->vnode);
-           fprintf(stderr, ">>> Will generate default ACL\n");
-       }
-       memset(v->acl, 0, SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE);
-       acl->size = htonl(SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE);
-       acl->version = htonl(ACL_ACLVERSION);
-       acl->total = htonl(v->owner ? 0 : 1);
-       acl->positive = acl->total;
-       acl->negative = 0;
-       if (v->owner) {
-           acl->entries[0].id = htonl(v->owner);
-           acl->entries[0].rights =
-               htonl((PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP
-                      | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER));
-       }
-       v->field_mask |= F_VNODE_ACL;
-    }
-
-    r = DumpVNode(&repair_output, v);
-    if (r)
-       return r;
-
-    if (v->size) {
-       if ((r = xfseek(X, &v->d_offset)))
-           return r;
-       r = CopyVNodeData(&repair_output, X, v->size);
-    } else if (v->type == vDirectory) {
-       afs_dir_page page;
-       struct DirHeader *dhp = (struct DirHeader *)&page;
-       int i;
-
-       if (RV) {
-           fprintf(stderr,
-                   ">>> VNODE %d is directory but has no contents\n", v->vnode);
-           fprintf(stderr, ">>> Will generate deafult directory entries\n");
-       }
-       memset(&page, 0, sizeof(page));
-
-       /* Page and Directory Headers */
-       page.header.tag = htons(1234);
-       page.header.freecount = (EPP - DHE - 3);
-       page.header.freebitmap[0] = 0xff;
-       page.header.freebitmap[1] = 0x7f;
-       dhp->alloMap[0] = EPP - DHE - 3;
-       for (i = 1; i < MAXPAGES; i++)
-           dhp->alloMap[i] = EPP;
-
-       /* Entry for . */
-       page.entry[DHE + 1].flag = FFIRST;
-       page.entry[DHE + 1].length = 1;
-       page.entry[DHE + 1].vnode = v->vnode;
-       page.entry[DHE + 1].vunique = v->vuniq;
-       strcpy(page.entry[DHE + 1].name, ".");
-       dhp->hashTable[0x2e] = DHE + 1;
-
-       /* Entry for .. */
-       page.entry[DHE + 2].flag = FFIRST;
-       page.entry[DHE + 2].length = 1;
-       page.entry[DHE + 2].vnode = v->parent;
-       page.entry[DHE + 2].vunique = 1;        /* Can't have everything! */
-       strcpy(page.entry[DHE + 2].name, "..");
-       dhp->hashTable[0x44] = DHE + 2;
-
-       r = DumpVNodeData(&repair_output, (char *)&page, 2048);
-    } else if (field_mask) {
-       /* We wrote out attributes, so we should also write the 0-length data */
-       r = DumpVNodeData(&repair_output, "", 0);
-    }
-
-    return r;
-}
diff --git a/src/tests/stagehdr.c b/src/tests/stagehdr.c
deleted file mode 100644 (file)
index ecdd2c2..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* stagehdr.c - Parse and dump stage backup headers */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "xf_errs.h"
-#include "stagehdr.h"
-
-static afs_uint32
-hdr_checksum(char *buf, int size)
-{
-    afs_uint32 sum = 0, n = size / sizeof(afs_uint32), *words =
-       (afs_uint32 *) buf;
-
-    while (--n)
-       sum += ntohl(*words++);
-    return sum;
-}
-
-
-/* Parse a stage backup header.
- * If tag is non-NULL, *tag should contain the first byte (already read),
- * and will be filled in with the first byte after the header, if one exists.
- * On success, returns 0 and leaves us positioned after the header
- * On failure, returns an error and position is undefined
- * Iff there is no header, returns DSERR_MAGIC and leaves us
- * positioned where we started.
- */
-afs_uint32
-ParseStageHdr(XFILE * X, unsigned char *tag, backup_system_header * hdr)
-{
-    char buf[STAGE_HDRLEN];
-    struct stage_header *bckhdr = (struct stage_header *)buf;
-    u_int64 where;
-    afs_int32 r;
-
-    if ((r = xftell(X, &where)))
-       return r;
-    if (hdr)
-       memset(hdr, 0, sizeof(*hdr));
-    if (tag) {
-       if (*tag != STAGE_VERSMIN)
-           return DSERR_MAGIC;
-       buf[0] = *tag;
-       r = xfread(X, buf + 1, STAGE_HDRLEN - 1);
-    } else {
-       r = xfread(X, buf, STAGE_HDRLEN);
-    }
-
-    if (r == ERROR_XFILE_EOF) {
-       r = xfseek(X, &where);
-       return r ? r : DSERR_MAGIC;
-    } else if (r)
-       return r;
-
-    if (bckhdr->c_vers < STAGE_VERSMIN
-       || ntohl(bckhdr->c_magic) != STAGE_MAGIC
-       || hdr_checksum(buf, STAGE_HDRLEN) != STAGE_CHECKSUM) {
-       r = xfseek(X, &where);
-       return r ? r : DSERR_MAGIC;
-    }
-
-    if (hdr) {
-       hdr->version = bckhdr->c_vers;
-       hdr->from_date = ntohl(bckhdr->c_fdate);
-       hdr->to_date = ntohl(bckhdr->c_tdate);
-       hdr->dump_date = ntohl(bckhdr->c_time);
-       hdr->filenum = ntohl(bckhdr->c_filenum);
-       hdr->volid = ntohl(bckhdr->c_id);
-#ifdef NATIVE_INT64
-       hdr->dumplen = ntohl(bckhdr->c_length);
-#else
-        hdr->dumplen.hi = 0;
-        hdr->dumplen.lo = ntohl(bckhdr->c_length);
-#endif
-       hdr->level = ntohl(bckhdr->c_level);
-       hdr->magic = ntohl(bckhdr->c_magic);
-       hdr->cksum = ntohl(bckhdr->c_checksum);
-       hdr->flags = ntohl(bckhdr->c_flags);
-       hdr->server = malloc(strlen(bckhdr->c_host) + 1);
-       hdr->part = malloc(strlen(bckhdr->c_disk) + 1);
-       hdr->volname = malloc(strlen(bckhdr->c_name) + 1);
-
-       if (!hdr->server || !hdr->part || !hdr->volname) {
-           if (hdr->server)
-               free(hdr->server);
-           if (hdr->part)
-               free(hdr->part);
-           if (hdr->volname)
-               free(hdr->volname);
-           return ENOMEM;
-       }
-       strcpy((char *)hdr->server, bckhdr->c_host);
-       strcpy((char *)hdr->part, bckhdr->c_disk);
-       strcpy((char *)hdr->volname, bckhdr->c_name);
-    }
-
-    if (tag)
-       return ReadByte(X, tag);
-    else
-       return 0;
-}
-
-
-/* Dump a stage backup header */
-afs_uint32
-DumpStageHdr(XFILE * OX, backup_system_header * hdr)
-{
-    char buf[STAGE_HDRLEN];
-    struct stage_header *bckhdr = (struct stage_header *)buf;
-    afs_uint32 checksum;
-    afs_uint32 r;
-
-    memset(buf, 0, STAGE_HDRLEN);
-    bckhdr->c_vers = hdr->version;
-    bckhdr->c_fdate = htonl(hdr->from_date);
-    bckhdr->c_tdate = htonl(hdr->to_date);
-    bckhdr->c_filenum = htonl(hdr->filenum);
-    bckhdr->c_time = htonl(hdr->dump_date);
-    bckhdr->c_id = htonl(hdr->volid);
-#ifdef NATIVE_INT64
-    bckhdr->c_length = htonl((afs_uint32) hdr->dumplen);
-#else
-    bckhdr->c_length = htonl(hdr->dumplen.lo);
-#endif
-    bckhdr->c_level = htonl(hdr->level);
-    bckhdr->c_magic = htonl(STAGE_MAGIC);
-    bckhdr->c_flags = htonl(hdr->flags);
-
-    strcpy(bckhdr->c_host, (char *)hdr->server);
-    strcpy(bckhdr->c_disk, (char *)hdr->part);
-    strcpy(bckhdr->c_name, (char *)hdr->volname);
-
-    /* Now, compute the checksum */
-    checksum = hdr_checksum(buf, STAGE_HDRLEN);
-    bckhdr->c_checksum = htonl(STAGE_CHECKSUM - checksum);
-
-    if ((r = xfwrite(OX, buf, STAGE_HDRLEN)))
-       return r;
-    return 0;
-}
diff --git a/src/tests/stagehdr.h b/src/tests/stagehdr.h
deleted file mode 100644 (file)
index b8e4ef3..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* stagehdr.h - (old) Stage backup header format */
-
-#ifndef _STAGEHDR_H_
-#define _STAGEHDR_H_
-
-#include "intNN.h"
-
-/* Stage-related constants */
-#define STAGE_MAGIC    0x00adf8bc      /* magic number for stage header */
-#define STAGE_CHECKSUM 84446   /* checksum (same as 4.2bsd dump) */
-#define STAGE_VERSMIN  20      /* minimum version */
-#define STAGE_NAMLEN   64      /* length of host/part/vol names */
-#define STAGE_HDRLEN   1024    /* size of the header */
-
-struct stage_header {
-    unsigned char c_vers;      /* header version (starts at 20) */
-    unsigned char c_notused[3];
-    afs_uint32 c_fdate;                /* dump "from" date */
-    afs_uint32 c_tdate;                /* dump "to" date */
-    afs_uint32 c_filenum;      /* tape file number */
-    afs_uint32 c_time;         /* time dump was done */
-    char c_host[STAGE_NAMLEN]; /* hostname volume came from */
-    char c_disk[STAGE_NAMLEN]; /* partition volume came from */
-    char c_name[STAGE_NAMLEN]; /* volume name */
-    afs_uint32 c_id;           /* volume ID */
-    afs_uint32 c_length;       /* length of the dump */
-    afs_uint32 c_level;                /* dump level */
-    afs_uint32 c_magic;                /* magic number */
-    afs_uint32 c_checksum;     /* checksum of backup header */
-    afs_uint32 c_flags;                /* feature flags */
-};
-
-#endif /* _STAGEHDR_H_ */
diff --git a/src/tests/util.c b/src/tests/util.c
deleted file mode 100644 (file)
index badf07e..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* util.c - Useful utilities */
-
-#include <errno.h>
-
-#include "xf_errs.h"
-#include "dumpscan.h"
-#include "dumpscan_errs.h"
-#include "dumpfmt.h"
-
-
-/* Take care of errno, ERROR_XFILE_EOF, and ENOMEM return codes.
- * Call whatever callbacks are necessary, and return the code to
- * actually use.  If you don't want '0' to result in a DSERR_TAG,
- * then you must translate it to DSERR_DONE before calling this.
- */
-/*** THIS FUNCTION INTENDED FOR INTERNAL USE ONLY ***/
-int
-handle_return(int r, XFILE * X, unsigned char tag, dump_parser * p)
-{
-    u_int64 where, xwhere;
-
-    switch (r) {
-    case 0:
-       if (p->cb_error) {
-           xftell(X, &where);
-           sub64_32(xwhere, where, 1);
-           (p->cb_error) (DSERR_TAG, 1, p->err_refcon,
-                          (tag > 0x20 && tag < 0x7f)
-                          ? "Unexpected tag '%c' at %s = 0x%s" :
-                          "Unexpected tag 0x%02x at %s = 0x%s", tag,
-                          decimate_int64(&xwhere, 0), hexify_int64(&xwhere,
-                                                                   0));
-       }
-       return DSERR_TAG;
-
-    case ERROR_XFILE_EOF:
-       if (p->cb_error) {
-           xftell(X, &where);
-           (p->cb_error) (ERROR_XFILE_EOF, 1, p->err_refcon,
-                          "Unexpected EOF at %s = 0x%s",
-                          decimate_int64(&where, 0), hexify_int64(&where,
-                                                                  0));
-       }
-       return ERROR_XFILE_EOF;
-
-    case ENOMEM:
-       if (p->cb_error) {
-           xftell(X, &where);
-           (p->cb_error) (ENOMEM, 1, p->err_refcon,
-                          "Out of memory at %s = 0x%s",
-                          decimate_int64(&where, 0), hexify_int64(&where,
-                                                                  0));
-       }
-       return ENOMEM;
-
-    case DSERR_DONE:
-       return 0;
-
-    default:
-       /* For other negative valuees, the callback was already done */
-       if (r > 0 && p->cb_error)
-           (p->cb_error) (r, 1, p->err_refcon,
-                          "System error %d reading dump file", r);
-       return r;
-    }
-}
-
-
-/* Prepare a tag_parse_info for use by the dump parser. */
-/* ** THIS FUNCTION INTENDED FOR INTERNAL USE ONLY ** */
-void
-prep_pi(dump_parser * p, tag_parse_info * pi)
-{
-    memset(pi, 0, sizeof(tag_parse_info));
-    pi->err_refcon = p->err_refcon;
-    pi->cb_error = p->cb_error;
-
-    if (p->repair_flags & DSFIX_SKIP)
-       pi->flags |= TPFLAG_SKIP;
-    if ((p->flags & DSFLAG_SEEK) && (p->repair_flags & DSFIX_RSKIP))
-       pi->flags |= TPFLAG_RSKIP;
-}
-
-
-/* Does the designated location match a vnode?
- * Returns 0 if yes, DSERR_FMT if no, something else on error
- */
-/*** THIS FUNCTION INTENDED FOR INTERNAL USE ONLY ***/
-int
-match_next_vnode(XFILE * X, dump_parser * p, u_int64 * where,
-                afs_uint32 vnode)
-{
-    afs_uint32 r, x, y, z;
-    unsigned char tag;
-
-    if ((r = xfseek(X, where)))
-       return r;
-    if ((r = ReadByte(X, &tag)))
-       return r;
-    switch (tag) {
-    case 3:                    /* A vnode? */
-       if ((r = ReadInt32(X, &x)))
-           return r;
-       if ((r = ReadInt32(X, &y)))
-           return r;
-       if ((r = ReadByte(X, &tag)))
-         return r;
-       if (!((vnode & 1) && !(x & 1) && x < vnode)
-           && !((vnode & 1) == (x & 1) && x > vnode))
-           return DSERR_FMT;
-       if (x > vnode && x - vnode > 10000)
-           return DSERR_FMT;
-       if (y < 0 || y > p->vol_uniquifier)
-           return DSERR_FMT;
-
-       /* Now, what follows the vnode/uniquifier? */
-       switch (tag) {
-       case 3:         /* Another vnode? - Only if this is a non-directory */
-           if (x & 1)
-               return DSERR_FMT;
-           if ((r = ReadInt32(X, &z)))
-               return r;
-           if (!((x & 1) && !(z & 1) && z < x)
-               && !((x & 1) == (z & 1) && z > x))
-               return DSERR_FMT;
-           return 0;
-
-       case 4:         /* Dump end - Only if this is a non-directory */
-           if (x & 1)
-               return DSERR_FMT;
-           if ((r = ReadInt32(X, &z)))
-               return r;
-           if (z != DUMPENDMAGIC)
-               return DSERR_FMT;
-           return 0;
-
-       case 't':               /* Vnode type byte */
-           if ((r = ReadByte(X, &tag)))
-               return r;
-           if ((tag == vFile || tag == vSymlink) && !(x & 1))
-               return 0;
-           if (tag == vDirectory && (x & 1))
-               return 0;
-           return DSERR_FMT;
-
-       default:
-           return DSERR_FMT;
-       }
-
-    case 4:                    /* A dump end? */
-       if ((r = ReadInt32(X, &x)))
-           return r;
-       if (x != DUMPENDMAGIC)
-           return DSERR_FMT;
-       return 0;
-
-    default:
-       return DSERR_FMT;
-    }
-}
diff --git a/src/tests/xf_errs.et b/src/tests/xf_errs.et
deleted file mode 100644 (file)
index 76c71d7..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-# CMUCS AFStools
-# dumpscan - routines for scanning and manipulating AFS volume dumps
-#
-# Copyright (c) 1998 Carnegie Mellon University
-# All Rights Reserved.
-#
-# Permission to use, copy, modify and distribute this software and its
-# documentation is hereby granted, provided that both the copyright
-# notice and this permission notice appear in all copies of the
-# software, derivative works or modified versions, and any portions
-# thereof, and that both notices appear in supporting documentation.
-#
-# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
-# CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
-# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
-#
-# Carnegie Mellon requests users of this software to return to
-#
-#  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
-#  School of Computer Science
-#  Carnegie Mellon University
-#  Pittsburgh PA 15213-3890
-#
-# any improvements or extensions that they make and grant Carnegie Mellon
-# the rights to redistribute these changes.
-
-# xf_errs.et - Error table for xfiles
-
-error_table xFil
-  ec ERROR_XFILE_EOF,            "EOF while reading XFILE"
-  ec ERROR_XFILE_WRONLY,         "XFILE may not be opened write-only"
-  ec ERROR_XFILE_RDONLY,         "XFILE is read-only"
-  ec ERROR_XFILE_NOSEEK,         "XFILE is not seekable"
-  ec ERROR_XFILE_ISPASS,         "XFILE passthru already set"
-  ec ERROR_XFILE_NOPASS,         "XFILE passthru not set"
-  ec ERROR_XFILE_TYPE,           "unknown XFILE type"
-end
diff --git a/src/tests/xf_files.c b/src/tests/xf_files.c
deleted file mode 100644 (file)
index 719d3a2..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* xf_files.c - XFILE routines for accessing UNIX files */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "xfiles.h"
-#include "xf_errs.h"
-
-#define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
-
-
-/* do_read for stdio xfiles */
-static afs_uint32
-xf_FILE_do_read(XFILE * X, void *buf, afs_uint32 count)
-{
-    FILE *F = X->refcon;
-
-    /* XXX: handle short and interrupted reads */
-    if (fread(buf, count, 1, F) != 1)
-       return ferror(F) ? errno : ERROR_XFILE_EOF;
-    return 0;
-}
-
-
-/* do_write for stdio xfiles */
-static afs_uint32
-xf_FILE_do_write(XFILE * X, void *buf, afs_uint32 count)
-{
-    FILE *F = X->refcon;
-
-    /* XXX: handle interrupted writes */
-    if (fwrite(buf, count, 1, F) != 1)
-       return errno;
-    return 0;
-}
-
-
-/* do_tell for stdio xfiles */
-static afs_uint32
-xf_FILE_do_tell(XFILE * X, u_int64 * offset)
-{
-    FILE *F = X->refcon;
-    off_t where;
-
-    where = ftell(F);
-    if (where == -1)
-       return errno;
-    set64(*offset, where);
-    return 0;
-}
-
-
-/* do_seek for stdio xfiles */
-static afs_uint32
-xf_FILE_do_seek(XFILE * X, u_int64 * offset)
-{
-    FILE *F = X->refcon;
-    off_t where = get64(*offset);
-
-    if (fseek(F, where, SEEK_SET) == -1)
-       return errno;
-    return 0;
-}
-
-
-/* do_skip for stdio xfiles */
-static afs_uint32
-xf_FILE_do_skip(XFILE * X, afs_uint32 count)
-{
-    FILE *F = X->refcon;
-
-    if (fseek(F, count, SEEK_CUR) == -1)
-       return errno;
-    return 0;
-}
-
-
-/* do_close for stdio xfiles */
-static afs_uint32
-xf_FILE_do_close(XFILE * X)
-{
-    FILE *F = X->refcon;
-
-    X->refcon = 0;
-    if (fclose(F))
-       return errno;
-    return 0;
-}
-
-
-/* Prepare a stdio XFILE */
-static void
-prepare(XFILE * X, FILE * F, int xflag)
-{
-    struct stat st;
-
-    memset(X, 0, sizeof(*X));
-    X->do_read = xf_FILE_do_read;
-    X->do_write = xf_FILE_do_write;
-    X->do_tell = xf_FILE_do_tell;
-    X->do_close = xf_FILE_do_close;
-    X->refcon = F;
-    if (xflag == O_RDWR)
-       X->is_writable = 1;
-
-    if (!fstat(fileno(F), &st)
-       && ((st.st_mode & S_IFMT) == S_IFREG
-           || (st.st_mode & S_IFMT) == S_IFBLK)) {
-       X->is_seekable = 1;
-       X->do_seek = xf_FILE_do_seek;
-       X->do_skip = xf_FILE_do_skip;
-    }
-}
-
-
-/* Open an XFILE by path */
-afs_uint32
-xfopen_path(XFILE * X, int flag, char *path, int mode)
-{
-    FILE *F = 0;
-    int fd = -1, xflag;
-    afs_uint32 code;
-
-    xflag = flag & O_MODE_MASK;
-    if (xflag == O_WRONLY)
-       return ERROR_XFILE_WRONLY;
-
-    if ((fd = open(path, flag, mode)) < 0)
-       return errno;
-    if (!(F = fdopen(fd, (xflag == O_RDONLY) ? "r" : "r+"))) {
-       code = errno;
-       close(fd);
-       return code;
-    }
-
-    prepare(X, F, xflag);
-    return 0;
-}
-
-
-/* Open an XFILE by FILE * */
-afs_uint32
-xfopen_FILE(XFILE * X, int flag, FILE * F)
-{
-    flag &= O_MODE_MASK;
-    if (flag == O_WRONLY)
-       return ERROR_XFILE_WRONLY;
-    prepare(X, F, flag);
-    return 0;
-}
-
-
-/* Open an XFILE by file descriptor */
-afs_uint32
-xfopen_fd(XFILE * X, int flag, int fd)
-{
-    FILE *F;
-
-    flag &= O_MODE_MASK;
-    if (flag == O_WRONLY)
-       return ERROR_XFILE_WRONLY;
-    if (!(F = fdopen(fd, (flag == O_RDONLY) ? "r" : "r+")))
-       return errno;
-    prepare(X, F, flag);
-    return 0;
-}
-
-
-/* open-by-name support for filenames */
-afs_uint32
-xfon_path(XFILE * X, int flag, char *name)
-{
-    return xfopen_path(X, flag, name, 0644);
-}
-
-
-/* open-by-name support for file descriptors */
-afs_uint32
-xfon_fd(XFILE * X, int flag, char *name)
-{
-    int fd = atoi(name);
-    return xfopen_fd(X, flag, fd);
-}
-
-
-/* open-by-name support for standard I/O */
-afs_uint32
-xfon_stdio(XFILE * X, int flag)
-{
-    flag &= O_MODE_MASK;
-    if (flag == O_WRONLY)
-       flag = O_RDWR;
-    return xfopen_FILE(X, flag, (flag == O_RDONLY) ? stdin : stdout);
-}
diff --git a/src/tests/xf_printf.c b/src/tests/xf_printf.c
deleted file mode 100644 (file)
index 6c5c9aa..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "xfiles.h"
-#include "xf_errs.h"
-
-#define SPBUFLEN 40
-static char spbuf[SPBUFLEN + 1] = "";
-
-
-#define MAXPREC 100
-
-/* Generate an ASCII representation of an integer <val>, as follows:
- * <base> indicates the base to be used (2-36)
- * <uc> is nonzero if letter digits should be uppercase
- * <prec> is the minimum number of digits
- * The resulting number is stored in <buf>, which must be long enough
- * to receive it.  The minimum length is <prec> or ceil(log{base}(val)),
- * whichever is larger, plus room for a trailing NUL.
- */
-static void
-mkint(char *buf, unsigned long val, int base, int uc, int prec)
-{
-    int len = 0, dig, i;
-
-    while (val) {
-       dig = val % base;
-       val = (val - dig) / base;
-       if (dig < 10)
-           dig = dig + '0';
-       else if (uc)
-           dig = dig + 'A' - 10;
-       else
-           dig = dig + 'a' - 10;
-       buf[len++] = dig;
-    }
-    while (len < prec)
-       buf[len++] = '0';
-    for (i = 0; i < (len + 1) / 2; i++) {
-       dig = buf[i];
-       buf[i] = buf[len - i - 1];
-       buf[len - i - 1] = dig;
-    }
-    buf[len] = 0;
-}
-
-
-/* Write spaces faster than one at a time */
-static afs_uint32
-wsp(XFILE * X, int count)
-{
-    char *x;
-    afs_uint32 err;
-    int i;
-
-    if (!spbuf[0]) {
-       for (x = spbuf, i = SPBUFLEN; i; x++, i--)
-           *x = ' ';
-    }
-
-    while (count > SPBUFLEN) {
-       err = xfwrite(X, spbuf, SPBUFLEN);
-       if (err)
-           return err;
-       count -= SPBUFLEN;
-    }
-    if (count > 0)
-       return xfwrite(X, spbuf, count);
-    return 0;
-}
-
-
-/* This function is a mostly-complete implementation of snprintf,
- * with the following features:
- *
- *   - Actually obeys the length limit, which (unfortunately) many
- *     implementations of snprintf do not.
- *
- *   - Supports all the standard format specifiers for integers
- *     (d, i, o, u, x, X), floating-point values (f, e, E, g, G),
- *     and strings and characters (c, s, %), plus a few unusual
- *     but useful ones described below.
- *
- *   - Supports all the standard flags (-, 0, +, space, #).  These
- *     flags are ignored if used when they are not appropriate.
- *
- *   - Supports the standard size modifiers for short (h), long (h),
- *     and double (L) arguments.  These modifiers are ignored if used
- *     when they are not appropriate.
- *
- *   - Supports minimum field width and precision, where appropriate,
- *     including the use of '*' to specify a value given as an argument
- *     instead of in the format string.  There is a maximum precision
- *     of 100 digits.
- *
- *   - At present, the 'p' specifier for printing pointers is not
- *     implemented, because it is inherently non-portable and thus
- *     can be implemented correctly only by the compiler's run-time
- *     library.
- *
- *   - Floating-point specifier (%e, %f, %g) are implemented by
- *     calling the standard sprintf, and thus may be unsafe.
- *
- *   - The '%...$' notation is used primarily when the format string
- *     is specified by the user, who knows but cannot change the order
- *     of the arguments.  Such usage is inherently dangerous and
- *     insecure; thus, it is not supported.
- *
- * The custom format specifier '%I' is supported.  This specifier
- * takes as its argument an unsigned long integer containing an
- * IPv4 address in network byte order.  The address is rendered
- * either as a hostname or as a dotted quad, as follows:
- *
- *   - If precision is nonzero or unspecified, a hostname lookup
- *     is attempted; if it is successful, the hostname is printed.
- *     If the hostname lookup fails, the address is printed in
- *     dotted-quad notation.
- *
- *   - If precision is explicitly specified as 0, then the hostname
- *     lookup is skipped, and dotted-quad notation is always used.
- *
- *   - If a hostname is to be printed:
- *     + The precision controls the maximum number of characters
- *       printed, as with %s.
- *     + If the '#' flag is specified, any letters in the hostname
- *       will be forced to lower case before printing.
- *     + If the '+' flag is specified, any letters in the hostname
- *       will be forced to upper case before printing.  If both
- *       '#' and '+' are given, the '+' flag will be ignored.
- *     + The '0' and ' ' flags have no effect.
- *
- *   - If a dotted quad is to be printed:
- *     + The precision has no effect; dotted quads are always
- *       7 to 12 characters in length, depending on the value
- *       to be printed and the format flags used.
- *     + If the '0' flag is given, each field (byte) of the address
- *       will be padded with '0' on the left to three digits.
- *     + If the ' ' flag is given, each field (byte) of the address
- *       will be padded with spaces on the left to three digits.  If
- *       both '0' and ' ' are given, the ' ' flag will be ignored.
- *     + The '#' and '+' flags have no effect.
- */
-
-afs_uint32
-vxfprintf(XFILE * X, char *fmt, va_list ap)
-{
-    unsigned int width, precision, haveprec, len;
-    int ljust, plsign, spsign, altform, zfill;
-    int hflag, lflag, count, *countp, j;
-    char *x, *y, *lit = 0, xbuf[MAXPREC + 21], fbuf[20];
-    struct hostent *he;
-    struct in_addr ia;
-    unsigned long UVAL;
-    long SVAL, *lcountp;
-    double FVAL;
-    short *hcountp;
-    afs_uint32 err;
-
-    count = 0;
-    while (*fmt) {
-       if (*fmt != '%') {
-           if (!lit)
-               lit = fmt;
-           fmt++;
-           count++;
-           continue;
-       }
-       if (lit) {
-           if ((err = xfwrite(X, lit, fmt - lit)))
-               return err;
-           lit = 0;
-       }
-
-    /** Found a format specifier **/
-       ljust = plsign = spsign = altform = zfill = 0;
-       width = precision = haveprec = 0;
-       hflag = lflag = 0;
-       fmt++;
-
-       /* parse format flags */
-       while (*fmt) {
-           switch (*fmt) {
-           case '-':
-               ljust = 1;
-               fmt++;
-               continue;       /* left justify */
-           case '+':
-               plsign = 1;
-               fmt++;
-               continue;       /* use + or - */
-           case ' ':
-               spsign = 1;
-               fmt++;
-               continue;       /* use space or - */
-           case '#':
-               altform = 1;
-               fmt++;
-               continue;       /* alternate form */
-           case '0':
-               zfill = 1;
-               fmt++;
-               continue;       /* pad with 0 */
-           default:
-               break;
-           }
-           break;
-       }
-
-       /* parse minimum width */
-       if (*fmt == '*') {
-           width = va_arg(ap, int);
-           fmt++;
-       } else
-           while (isdigit(*fmt)) {
-               width = (width * 10) + (*fmt - '0');
-               fmt++;
-           }
-
-       /* parse precision */
-       if (*fmt == '.') {
-           fmt++;
-           haveprec = 1;
-           if (*fmt == '*') {
-               precision = va_arg(ap, int);
-               fmt++;
-           } else
-               while (isdigit(*fmt)) {
-                   precision = (precision * 10) + (*fmt - '0');
-                   fmt++;
-               }
-       }
-
-       /* parse size flags */
-       while (*fmt) {
-           switch (*fmt) {
-           case 'h':
-               hflag = 1;
-               fmt++;
-               continue;       /* short argument */
-           case 'l':
-               lflag = 1;
-               fmt++;
-               continue;       /* long argument */
-           default:
-               break;
-           }
-           break;
-       }
-
-       /* parse format specifier */
-       if (!*fmt)
-           break;
-       switch (*fmt++) {
-       case 'e':
-       case 'E':
-       case 'f':
-       case 'g':
-       case 'G':
-           FVAL = va_arg(ap, double);
-           sprintf(fbuf, "%%%s%s.*L%c", plsign ? "+" : (spsign ? " " : ""),
-                   altform ? "#" : "", fmt[-1]);
-           if (!haveprec)
-               precision = 6;
-           if (precision > MAXPREC)
-               precision = MAXPREC;
-           sprintf(xbuf, fbuf, precision, FVAL);
-           x = xbuf;
-           len = strlen(x);
-           break;
-
-       case 'i':
-       case 'd':               /* signed decimal integer */
-           if (lflag)
-               SVAL = va_arg(ap, long);
-           else if (hflag)
-               SVAL = va_arg(ap, int);
-           else
-               SVAL = va_arg(ap, int);
-           UVAL = (SVAL < 0) ? -SVAL : SVAL;
-
-           if (SVAL < 0)
-               xbuf[0] = '-';
-           else if (plsign)
-               xbuf[0] = '+';
-           else if (spsign)
-               xbuf[0] = ' ';
-           else
-               xbuf[0] = 0;
-
-           if (!haveprec) {
-               if (zfill && !ljust)
-                   precision = width - !!xbuf[0];
-               else
-                   precision = 1;
-               if (precision < 1 + !!xbuf[0])
-                   precision = 1 + !!xbuf[0];
-           }
-           if (precision > MAXPREC)
-               precision = MAXPREC;
-
-           mkint(xbuf + 1, UVAL, 10, 0, precision);
-           x = xbuf + !xbuf[0];
-           len = strlen(x);
-           break;
-
-
-       case 'o':               /* unsigned octal integer */
-           if (lflag)
-               UVAL = va_arg(ap, unsigned long);
-           else if (hflag)
-               UVAL = va_arg(ap, unsigned int);
-           else
-               UVAL = va_arg(ap, unsigned int);
-
-           xbuf[0] = '0';
-
-           if (!haveprec) {
-               if (zfill && !ljust)
-                   precision = width;
-               else
-                   precision = 1;
-           }
-           if (precision > MAXPREC)
-               precision = MAXPREC;
-
-           mkint(xbuf + 1, UVAL, 8, 0, precision);
-           x = xbuf + (xbuf[1] == '0' || !altform);
-           len = strlen(x);
-           break;
-
-       case 'u':               /* unsigned decimal integer */
-           if (lflag)
-               UVAL = va_arg(ap, unsigned long);
-           else if (hflag)
-               UVAL = va_arg(ap, unsigned int);
-           else
-               UVAL = va_arg(ap, unsigned int);
-
-           if (!haveprec) {
-               if (zfill && !ljust)
-                   precision = width;
-               else
-                   precision = 1;
-           }
-           if (precision > MAXPREC)
-               precision = MAXPREC;
-
-           mkint(xbuf, UVAL, 10, 0, precision);
-           x = xbuf;
-           len = strlen(x);
-           break;
-
-       case 'x':
-       case 'X':               /* unsigned hexadecimal integer */
-           if (lflag)
-               UVAL = va_arg(ap, unsigned long);
-           else if (hflag)
-               UVAL = va_arg(ap, unsigned int);
-           else
-               UVAL = va_arg(ap, unsigned int);
-
-           xbuf[0] = '0';
-           xbuf[1] = 'x';
-
-           if (!haveprec) {
-               if (zfill && !ljust)
-                   precision = width;
-               else
-                   precision = 1;
-           }
-           if (precision > MAXPREC)
-               precision = MAXPREC;
-
-           mkint(xbuf + 2, UVAL, 16, 0, precision);
-           x = xbuf + ((altform && UVAL) ? 0 : 2);
-           len = strlen(x);
-           break;
-
-       case '%':               /* literal % */
-           xbuf[0] = '%';
-           xbuf[1] = 0;
-           x = xbuf;
-           len = 1;
-           break;
-
-       case 'c':               /* character */
-           xbuf[0] = va_arg(ap, int);
-           xbuf[1] = 0;
-           x = xbuf;
-           len = 1;
-           break;
-
-       case 's':               /* string */
-           x = va_arg(ap, char *);
-           if (!x)
-               x = "<null>";
-           len = strlen(x);
-           if (haveprec && precision < len)
-               len = precision;
-           break;
-
-       case 'I':               /* IP address:
-                                * value is provided as a network-order unsigned long integer
-                                * precision specifies max hostname length, as for %s
-                                * if precision is explicitly 0, no hostname lookup is done
-                                * if 0fill specified, IPaddr fields are 0-filled to 3 digits
-                                * if spsign specified, IPaddr fields are space-filled to 3 digits
-                                */
-           UVAL = va_arg(ap, unsigned long);
-           ia.s_addr = UVAL;
-           /* XXX: add support for an application-provided function
-            * for doing hostname lookups.  We don't do it automatically
-            * because on some platforms that would prevent us from
-            * being fully statically linked.
-            */
-           if (haveprec && !precision)
-               he = 0;
-           else
-               he = gethostbyaddr((char *)&ia, 4, AF_INET);
-           if (he) {
-               x = he->h_name;
-               len = strlen(x);
-               if (haveprec && precision < len)
-                   len = precision;
-               if (altform)
-                   for (y = x; *y; y++)
-                       if (isupper(*y))
-                           *y = tolower(*y);
-                       else if (plsign)
-                           for (y = x; *y; y++)
-                               if (islower(*y))
-                                   *y = toupper(*y);
-           } else {
-               UVAL = ntohl(UVAL);
-               if (zfill)
-                   x = "%03u.%03u.%03u.%03u";
-               else if (spsign)
-                   x = "%3u.%3u.%3u.%3u";
-               else
-                   x = "%u.%u.%u.%u";
-               sprintf(xbuf, x, (UVAL & 0xff000000) >> 24,
-                       (UVAL & 0x00ff0000) >> 16, (UVAL & 0x0000ff00) >> 8,
-                       (UVAL & 0x000000ff));
-               x = xbuf;
-               len = strlen(xbuf);
-           }
-           break;
-
-       case 'n':               /* report count so far */
-           if (lflag) {
-               lcountp = va_arg(ap, long *);
-               *lcountp = count;
-           } else if (hflag) {
-               hcountp = va_arg(ap, short *);
-               *hcountp = count;
-           } else {
-               countp = va_arg(ap, int *);
-               *countp = count;
-           }
-           continue;
-
-       default:                /* unknown specifier */
-           continue;
-       }
-
-       /* render the results */
-       if (!width)
-           width = len;
-       j = width - len;
-       if (j > 0)
-           count += j;
-       count += len;
-
-       if (!ljust && (err = wsp(X, j)))
-           return err;
-       if ((err = xfwrite(X, x, len)))
-           return err;
-       if (ljust && (err = wsp(X, j)))
-           return err;
-    }
-    if (lit && (err = xfwrite(X, lit, fmt - lit)))
-       return err;
-    return 0;
-}
-
-
-afs_uint32
-xfprintf(XFILE * X, char *fmt, ...)
-{
-    va_list ap;
-    afs_uint32 err;
-
-    va_start(ap, fmt);
-    err = vxfprintf(X, fmt, ap);
-    va_end(ap);
-    return err;
-}
diff --git a/src/tests/xf_profile.c b/src/tests/xf_profile.c
deleted file mode 100644 (file)
index f043849..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* xf_profile.c - XFILE routines for read/write profiling */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "xfiles.h"
-#include "xf_errs.h"
-
-#define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
-
-typedef struct {
-    XFILE content;
-    XFILE profile;
-} PFILE;
-
-
-/* do_read for profiled xfiles */
-static afs_uint32
-xf_PROFILE_do_read(XFILE * X, void *buf, afs_uint32 count)
-{
-    PFILE *PF = X->refcon;
-    afs_uint32 err;
-
-    err = xfread(&PF->content, buf, count);
-    xfprintf(&PF->profile, "R %ld =%ld\n", (long)count, (long)err);
-    return err;
-}
-
-
-/* do_write for profiled xfiles */
-static afs_uint32
-xf_PROFILE_do_write(XFILE * X, void *buf, afs_uint32 count)
-{
-    PFILE *PF = X->refcon;
-    afs_uint32 err;
-
-    err = xfwrite(&PF->content, buf, count);
-    xfprintf(&PF->profile, "W %ld =%ld\n", (long)count, (long)err);
-    return err;
-}
-
-
-/* do_tell for profiled xfiles */
-static afs_uint32
-xf_PROFILE_do_tell(XFILE * X, u_int64 * offset)
-{
-    PFILE *PF = X->refcon;
-    afs_uint32 err;
-
-    err = xftell(&PF->content, offset);
-    if (err)
-       xfprintf(&PF->profile, "TELL ERR =%ld\n", (long)err);
-    else
-       xfprintf(&PF->profile, "TELL %s =0\n", hexify_int64(offset, 0));
-    return err;
-}
-
-
-/* do_seek for profiled xfiles */
-static afs_uint32
-xf_PROFILE_do_seek(XFILE * X, u_int64 * offset)
-{
-    PFILE *PF = X->refcon;
-    afs_uint32 err;
-
-    err = xfseek(&PF->content, offset);
-    xfprintf(&PF->profile, "SEEK %s =%ld\n", hexify_int64(offset, 0),
-            (long)err);
-    return err;
-}
-
-
-/* do_skip for profiled xfiles */
-static afs_uint32
-xf_PROFILE_do_skip(XFILE * X, afs_uint32 count)
-{
-    PFILE *PF = X->refcon;
-    afs_uint32 err;
-
-    err = xfskip(&PF->content, count);
-    xfprintf(&PF->profile, "SKIP %ld =%ld\n", (long)count, (long)err);
-    return err;
-}
-
-
-/* do_close for profiled xfiles */
-static afs_uint32
-xf_PROFILE_do_close(XFILE * X)
-{
-    PFILE *PF = X->refcon;
-    afs_uint32 err, err2;
-
-    err = xfclose(&PF->content);
-    err2 = xfclose(&PF->profile);
-    free(PF);
-    return err ? err : err2;
-}
-
-
-/* Open a profiled XFILE */
-afs_uint32
-xfopen_profile(XFILE * X, int flag, char *xname, char *profile)
-{
-    PFILE *PF;
-    afs_uint32 err;
-
-    PF = malloc(sizeof(*PF));
-    if (!PF)
-       return ENOMEM;
-    memset(PF, 0, sizeof(*PF));
-
-    err = xfopen(&PF->profile, O_RDWR | O_CREAT | O_TRUNC, profile);
-    if (err) {
-       free(PF);
-       return err;
-    }
-
-    err = xfopen(&PF->content, flag, xname);
-    if (err) {
-       xfclose(&PF->profile);
-       free(PF);
-       return err;
-    }
-
-    memset(X, 0, sizeof(*X));
-    X->refcon = PF;
-    X->do_read = xf_PROFILE_do_read;
-    X->do_write = xf_PROFILE_do_write;
-    X->do_tell = xf_PROFILE_do_tell;
-    X->do_close = xf_PROFILE_do_close;
-    X->is_writable = PF->content.is_writable;
-    if (PF->content.is_seekable) {
-       X->is_seekable = 1;
-       X->do_seek = xf_PROFILE_do_seek;
-       X->do_skip = xf_PROFILE_do_skip;
-    }
-    xfprintf(&PF->profile, "OPEN %s\n", xname);
-    return 0;
-}
-
-
-afs_uint32
-xfon_profile(XFILE * X, int flag, char *name)
-{
-    char *x, *profile, *xname;
-    afs_uint32 err;
-
-    if (!(name = strdup(name)))
-       return ENOMEM;
-
-    profile = "-";
-    xname = name;
-    for (x = name; *x; x++) {
-       if (x[0] == ':' && x[1] == ':') {
-           *x = 0;
-           profile = name;
-           xname = x + 2;
-           break;
-       }
-    }
-    if (!*name)
-       profile = "-";
-    err = xfopen_profile(X, flag, xname, profile);
-    free(name);
-    return err;
-}
diff --git a/src/tests/xf_rxcall.c b/src/tests/xf_rxcall.c
deleted file mode 100644 (file)
index e74eef4..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* xf_rxcall.c - XFILE routines for Rx bulk data transfers */
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <netdb.h>
-
-#include "xfiles.h"
-#include "xf_errs.h"
-
-#include <rx/xdr.h>
-#include <rx/rx.h>
-#include <rx/rx_null.h>
-#include <rx/rxkad.h>
-#include <afs/auth.h>
-#include <afs/cellconfig.h>
-#include <afs/vlserver.h>
-#include <afs/volser.h>
-#include <afs/volint.h>
-
-#ifndef AFSCONF_CLIENTNAME
-#include <afs/dirpath.h>
-#define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
-#endif
-
-#define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
-
-struct rxinfo {
-    struct rx_connection *conn;        /* connection */
-    struct rx_call *call;      /* call */
-    afs_int32 tid;             /* volser transaction ID */
-    afs_uint32 code;           /* result code */
-};
-
-static afs_uint32
-xf_rxcall_do_read(XFILE * X, void *buf, afs_uint32 count)
-{
-    struct rxinfo *i = X->refcon;
-    afs_uint32 xcount;
-
-    xcount = rx_Read(i->call, buf, count);
-    if (xcount == count)
-       return 0;
-    i->code = rx_EndCall(i->call, 0);
-    i->call = 0;
-    return i->code ? i->code : ERROR_XFILE_RDONLY;
-}
-
-
-static afs_uint32
-xf_rxcall_do_write(XFILE * X, void *buf, afs_uint32 count)
-{
-    struct rxinfo *i = X->refcon;
-    afs_uint32 xcount;
-
-    xcount = rx_Write(i->call, buf, count);
-    if (xcount == count)
-       return 0;
-    i->code = rx_EndCall(i->call, 0);
-    i->call = 0;
-    return i->code;
-}
-
-
-static afs_uint32
-xf_rxcall_do_close(XFILE * X)
-{
-    struct rxinfo *i = X->refcon;
-    afs_uint32 code;
-
-    if (i->call) {
-       code = rx_EndCall(i->call, i->code);
-       i->call = 0;
-    } else {
-       code = i->code;
-    }
-    free(i);
-    return code;
-}
-
-
-static afs_uint32
-xf_voldump_do_close(XFILE * X)
-{
-    struct rxinfo *i = X->refcon;
-    struct rx_connection *conn = i->conn;
-    afs_int32 code, rcode, xcode;
-    afs_int32 tid = i->tid;
-
-    code = xf_rxcall_do_close(X);
-    xcode = AFSVolEndTrans(conn, tid, &rcode);
-    if (!code)
-       code = xcode ? xcode : rcode;
-    return code;
-}
-
-
-afs_uint32
-xfopen_rxcall(XFILE * X, int flag, struct rx_call * call)
-{
-    struct rxinfo *i;
-
-    flag &= O_MODE_MASK;
-    if (flag == O_WRONLY)
-       return ERROR_XFILE_WRONLY;
-    memset(X, 0, sizeof(*X));
-    if (!(i = (struct rxinfo *)malloc(sizeof(struct rxinfo))))
-       return ENOMEM;
-    i->call = call;
-    i->code = 0;
-    X->do_read = xf_rxcall_do_read;
-    X->do_write = xf_rxcall_do_write;
-    X->do_close = xf_rxcall_do_close;
-    X->is_writable = (flag == O_RDWR);
-    X->refcon = i;
-    return 0;
-}
-
-
-afs_uint32
-xfopen_voldump(XFILE * X, struct rx_connection * conn, afs_int32 part,
-              afs_int32 volid, afs_int32 date)
-{
-    struct rx_call *call;
-    struct rxinfo *i;
-    afs_int32 code, rcode;
-    afs_int32 tid;
-
-    if ((code = AFSVolTransCreate(conn, volid, part, ITBusy, &tid)))
-       return code;
-    call = rx_NewCall(conn);
-    if ((code = StartAFSVolDump(call, tid, date))
-       || (code = xfopen_rxcall(X, O_RDONLY, call))) {
-       rx_EndCall(call, 0);
-       AFSVolEndTrans(conn, tid, &rcode);
-       return code;
-    }
-
-    i = X->refcon;
-    i->conn = conn;
-    i->tid = tid;
-    X->do_close = xf_voldump_do_close;
-    return 0;
-}
-
-
-afs_uint32
-xfon_voldump(XFILE * X, int flag, char *name)
-{
-    struct hostent *he;
-    struct rx_securityClass *class;
-    struct rx_connection *conn;
-    struct ktc_principal sname;
-    struct ktc_token token;
-    struct afsconf_dir *confdir;
-    afs_uint32 code, server_addr = 0;
-    afs_int32 volid, date, partid = 0;
-    int isnum, index;
-    char *x, *y;
-
-    /* Parse out the optional date and server location */
-    if ((code = rx_Init(0)))
-       return code;
-    if (!(name = strdup(name)))
-       return ENOMEM;
-    if ((x = strrchr(name, ','))) {
-       *x++ = 0;
-       date = atoi(x);
-    } else {
-       date = 0;
-    }
-    if ((x = strrchr(name, '@'))) {
-       int a, b, c, d;
-
-       *x++ = 0;
-       if (!(y = strchr(x, '/'))) {
-           free(name);
-           return VL_BADPARTITION;
-       }
-       *y++ = 0;
-       if (sscanf(x, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 && a >= 0
-           && a <= 255 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0
-           && d <= 255) {
-           server_addr = (a << 24) | (b << 16) | (c << 8) | d;
-           server_addr = htonl(server_addr);
-       } else {
-           he = gethostbyname(x);
-           if (!he) {
-               free(name);
-               return VL_BADSERVER;
-           }
-           memcpy(&server_addr, he->h_addr, sizeof(server_addr));
-       }
-       partid = volutil_GetPartitionID(y);
-       if (partid < 0) {
-           free(name);
-           return VL_BADPARTITION;
-       }
-    }
-
-    /* Get tokens and set up a security object */
-    confdir = afsconf_Open(AFSCONF_CLIENTNAME);
-    if (!confdir) {
-       free(name);
-       return AFSCONF_NODB;
-    }
-    if ((code = afsconf_GetLocalCell(confdir, sname.cell, MAXKTCNAMELEN))) {
-       free(name);
-       return code;
-    }
-    afsconf_Close(confdir);
-    strcpy(sname.name, "afs");
-    sname.instance[0] = 0;
-    code = ktc_GetToken(&sname, &token, sizeof(token), 0);
-    if (code) {
-       class = rxnull_NewClientSecurityObject();
-       index = 0;
-    } else {
-       class =
-           rxkad_NewClientSecurityObject(rxkad_clear, &token.sessionKey,
-                                         token.kvno, token.ticketLen,
-                                         token.ticket);
-       index = 2;
-    }
-
-    /* Figure out the volume ID, looking it up in the VLDB if neccessary.
-     * Also look up the server and partition, if they were not specified.
-     */
-    for (isnum = 1, y = name; *y; y++)
-       if (*y < '0' || *y > '9')
-           isnum = 0;
-    if (isnum) {
-       volid = atoi(name);
-       if (!x) {
-           fprintf(stderr, "XXX: need to lookup volume by ID!\n");
-           exit(-1);
-       }
-    } else {
-       fprintf(stderr, "XXX: need to lookup volume by name!\n");
-       exit(-1);
-    }
-    free(name);
-
-    /* Establish a connection and start the call */
-    conn =
-       rx_NewConnection(server_addr, htons(AFSCONF_VOLUMEPORT),
-                        VOLSERVICE_ID, class, index);
-    return xfopen_voldump(X, conn, partid, volid, date);
-}
diff --git a/src/tests/xfiles.c b/src/tests/xfiles.c
deleted file mode 100644 (file)
index 08898fb..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* xfiles.c - General support routines for xfiles */
-#include <sys/types.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "xfiles.h"
-#include "xf_errs.h"
-
-#define SKIP_SIZE 65536
-
-extern afs_uint32 xfon_path(XFILE *, int, char *);
-extern afs_uint32 xfon_fd(XFILE *, int, char *);
-extern afs_uint32 xfon_voldump(XFILE *, int, char *);
-extern afs_uint32 xfon_profile(XFILE *, int, char *);
-extern afs_uint32 xfon_stdio(XFILE *, int);
-
-struct xftype {
-    struct xftype *next;
-    char *name;
-      afs_uint32(*do_on) (XFILE *, int, char *);
-};
-
-
-static struct xftype *xftypes = 0;
-static int did_register_defaults = 0;
-
-
-afs_uint32
-xfread(XFILE * X, void *buf, afs_uint32 count)
-{
-    afs_uint32 code;
-    u_int64 tmp64;
-
-    code = (X->do_read) (X, buf, count);
-    if (code)
-       return code;
-
-    add64_32(tmp64, X->filepos, count);
-    cp64(X->filepos, tmp64);
-    if (X->passthru)
-       return xfwrite(X->passthru, buf, count);
-    return 0;
-}
-
-
-afs_uint32
-xfwrite(XFILE * X, void *buf, afs_uint32 count)
-{
-    afs_uint32 code;
-    u_int64 tmp64;
-
-    if (!X->is_writable)
-       return ERROR_XFILE_RDONLY;
-    code = (X->do_write) (X, buf, count);
-    if (code)
-       return code;
-
-    add64_32(tmp64, X->filepos, count);
-    cp64(X->filepos, tmp64);
-    return 0;
-}
-
-
-afs_uint32
-xftell(XFILE * X, u_int64 * offset)
-{
-    if (X->do_tell)
-       return (X->do_tell) (X, offset);
-    cp64(*offset, X->filepos);
-    return 0;
-}
-
-
-afs_uint32
-xfseek(XFILE * X, u_int64 * offset)
-{
-    afs_uint32 code;
-
-    if (!X->do_seek)
-       return ERROR_XFILE_NOSEEK;
-    code = (X->do_seek) (X, offset);
-    if (code)
-       return code;
-    cp64(X->filepos, *offset);
-    return 0;
-}
-
-
-afs_uint32
-xfskip(XFILE * X, afs_uint32 count)
-{
-    afs_uint32 code;
-    u_int64 tmp64;
-
-    /* Use the skip method, if there is one */
-    if (X->do_skip && !X->passthru) {
-       code = (X->do_skip) (X, count);
-       if (code)
-           return code;
-       add64_32(tmp64, X->filepos, count);
-       cp64(X->filepos, tmp64);
-       return 0;
-    }
-
-    /* Simulate using absolute seek, if available */
-    if (X->do_seek && !X->passthru) {
-       if ((code = xftell(X, &tmp64)))
-           return code;
-       add64_32(X->filepos, tmp64, count);
-       cp64(tmp64, X->filepos);
-       return xfseek(X, &tmp64);
-    }
-
-    /* Do it the hard/slow way - read all the data to be skipped.
-     * This is done if no other method is available, or if we are
-     * supposed to be copying all the data to another XFILE
-     */
-    {
-       char buf[SKIP_SIZE];
-       afs_uint32 n;
-
-       while (count) {
-           n = (count > SKIP_SIZE) ? SKIP_SIZE : count;
-           if ((code = xfread(X, buf, n)))
-               return code;
-           count -= n;
-       }
-       return 0;
-    }
-}
-
-
-afs_uint32
-xfpass(XFILE * X, XFILE * Y)
-{
-    if (X->passthru)
-       return ERROR_XFILE_ISPASS;
-    if (!Y->is_writable)
-       return ERROR_XFILE_RDONLY;
-    X->passthru = Y;
-    return 0;
-}
-
-
-afs_uint32
-xfunpass(XFILE * X)
-{
-    if (!X->passthru)
-       return ERROR_XFILE_NOPASS;
-    X->passthru = 0;
-    return 0;
-}
-
-
-afs_uint32
-xfclose(XFILE * X)
-{
-    int code = 0;
-
-    if (X->do_close)
-       code = (X->do_close) (X);
-    memset(X, 0, sizeof(*X));
-    return 0;
-}
-
-
-afs_uint32
-xfregister(char *name, afs_uint32(*do_on) (XFILE *, int, char *))
-{
-    struct xftype *x;
-
-    if (!(x = (struct xftype *)malloc(sizeof(struct xftype))))
-       return ENOMEM;
-    memset(x, 0, sizeof(*x));
-    x->next = xftypes;
-    x->name = name;
-    x->do_on = do_on;
-    xftypes = x;
-    return 0;
-}
-
-
-static void
-register_default_types(void)
-{
-    xfregister("FILE", xfon_path);
-    xfregister("FD", xfon_fd);
-    xfregister("AFSDUMP", xfon_voldump);
-    xfregister("PROFILE", xfon_profile);
-    did_register_defaults = 1;
-}
-
-
-afs_uint32
-xfopen(XFILE * X, int flag, char *name)
-{
-    struct xftype *x;
-    char *type, *sep;
-
-    if (!did_register_defaults)
-       register_default_types();
-    if (!strcmp(name, "-"))
-       return xfon_stdio(X, flag);
-
-    for (type = name; *name && *name != ':'; name++);
-    if (*name) {
-       sep = name;
-       *name++ = 0;
-    } else {
-       sep = 0;
-       name = type;
-       type = "FILE";
-    }
-
-    for (x = xftypes; x; x = x->next)
-       if (!strcmp(type, x->name))
-           break;
-    if (sep)
-       *sep = ':';
-    if (x)
-       return (x->do_on) (X, flag, name);
-    return ERROR_XFILE_TYPE;
-}
diff --git a/src/tests/xfiles.h b/src/tests/xfiles.h
deleted file mode 100644 (file)
index 83d3b7e..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * CMUCS AFStools
- * dumpscan - routines for scanning and manipulating AFS volume dumps
- *
- * Copyright (c) 1998 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
- *  School of Computer Science
- *  Carnegie Mellon University
- *  Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-
-/* xfiles.h - Type, constant, and function declarations for
- * extensible file-like things */
-
-#ifndef _XFILES_H_
-#define _XFILES_H_
-
-#include <stdio.h>
-#include <stdarg.h>
-#include "intNN.h"
-
-struct rx_call;
-struct rx_connection;
-
-/* The XFILE structure */
-typedef struct XFILE XFILE;
-struct XFILE {
-    afs_uint32(*do_read) (XFILE *, void *, afs_uint32);        /* read data */
-    afs_uint32(*do_write) (XFILE *, void *, afs_uint32);       /* write data */
-    afs_uint32(*do_tell) (XFILE *, u_int64 *); /* find position */
-    afs_uint32(*do_seek) (XFILE *, u_int64 *); /* set position */
-    afs_uint32(*do_skip) (XFILE *, afs_uint32);        /* skip forward */
-    afs_uint32(*do_close) (XFILE *);   /* close */
-    u_int64 filepos;           /* position (counted) */
-    int is_seekable;           /* 1 if seek works */
-    int is_writable;           /* 1 if write works */
-    XFILE *passthru;           /* XFILE to pass thru to */
-    void *refcon;              /* type-specific data */
-};
-
-
-/* Functions for opening XFILEs.  For these, the first two arguments are
- * always a pointer to an XFILE to fill in, and the mode in which to
- * open the file.  O_RDONLY and O_RDWR are permitted; O_WRONLY is not.
- * Other open modes may or may not be used, depending on the object type.
- * Remaining arguments are a function of the object type
- */
-extern afs_uint32 xfopen(XFILE *, int, char *);        /* open by TYPE:name */
-extern afs_uint32 xfopen_path(XFILE *, int, char *, int);      /* open by path   */
-extern afs_uint32 xfopen_FILE(XFILE *, int, FILE *);   /* open by FILE * */
-extern afs_uint32 xfopen_fd(XFILE *, int, int);        /* open by fd     */
-extern afs_uint32 xfopen_rxcall(XFILE *, int, struct rx_call *);
-extern afs_uint32 xfopen_voldump(XFILE *, struct rx_connection *, afs_int32,
-                                afs_int32, afs_int32);
-extern afs_uint32 xfopen_profile(XFILE *, int, char *, char *);
-
-extern afs_uint32 xfregister(char *, afs_uint32(*)(XFILE *, int, char *));
-
-/* Standard operations on XFILEs */
-extern afs_uint32 xfread(XFILE *, void *, afs_uint32); /* read data */
-extern afs_uint32 xfwrite(XFILE *, void *, afs_uint32);        /* write data */
-extern afs_uint32 xfprintf(XFILE *, char *, ...);      /* formatted */
-extern afs_uint32 vxfprintf(XFILE *, char *, va_list); /* formatted VA */
-extern afs_uint32 xftell(XFILE *, u_int64 *);  /* get position */
-extern afs_uint32 xfseek(XFILE *, u_int64 *);  /* set position */
-extern afs_uint32 xfskip(XFILE *, afs_uint32); /* skip forward */
-extern afs_uint32 xfpass(XFILE *, XFILE *);    /* set passthru */
-extern afs_uint32 xfunpass(XFILE *);   /* unset passthru */
-extern afs_uint32 xfclose(XFILE *);    /* close */
-
-#endif /* _XFILES_H_ */
diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in
new file mode 100644 (file)
index 0000000..3f3e620
--- /dev/null
@@ -0,0 +1,107 @@
+srcdir         = @srcdir@
+include @TOP_OBJDIR@/src/config/Makefile.config
+include @TOP_OBJDIR@/src/config/Makefile.lwp
+
+
+SHELL          = /bin/sh
+
+INCDIRS=-I${TOP_OBJDIR}/src/config -I${TOP_INCDIR}/afs -I${TOP_INCDIR}
+INCLIBS=-L${SRCDIR}/lib/afs -L${TOP_LIBDIR}
+
+LIBS=\
+       libdumpscan.a \
+       libxfiles.a \
+       ${TOP_LIBDIR}/libauth.a \
+       ${TOP_LIBDIR}/libaudit.a \
+       ${TOP_LIBDIR}/libvolser.a \
+       ${TOP_LIBDIR}/libvldb.a \
+       ${TOP_LIBDIR}/libubik.a \
+       ${TOP_LIBDIR}/librxkad.a \
+       ${TOP_LIBDIR}/libsys.a \
+       ${TOP_LIBDIR}/librx.a \
+       ${TOP_LIBDIR}/liblwp.a \
+       ${TOP_LIBDIR}/util.a \
+       $(TOP_LIBDIR)/libopr.a \
+       ${TOP_LIBDIR}/libafscom_err.a \
+       $(LIB_roken) \
+       ${XLIBS}
+
+OBJS_afsdump_scan    = afsdump_scan.o repair.o
+OBJS_afsdump_xsed    = afsdump_xsed.o repair.o
+OBJS_libxfiles.a     = xfiles.o xf_errs.o xf_printf.o int64.o \
+                       xf_files.o xf_rxcall.o xf_profile.o
+OBJS_libdumpscan.a   = primitive.o util.o dumpscan_errs.o parsetag.o \
+                       parsedump.o parsevol.o parsevnode.o dump.o \
+                       directory.o pathname.o backuphdr.o stagehdr.o
+
+TARGETS = libxfiles.a libdumpscan.a \
+          afsdump_scan afsdump_dirlist afsdump_extract dumptool
+
+all: libxfiles.a libdumpscan.a \
+       afsdump_scan afsdump_dirlist afsdump_extract dumptool
+
+generated: xf_errs.c xf_errs.h dumpscan_errs.c dumpscan_errs.h
+
+afsdump_scan: libxfiles.a libdumpscan.a $(OBJS_afsdump_scan)
+       $(AFS_LDRULE) $(OBJS_afsdump_scan) $(LIBS)
+
+afsdump_xsed: libxfiles.a libdumpscan.a $(OBJS_afsdump_xsed)
+       $(AFS_LDRULE) $(OBJS_afsdump_xsed) $(LIBS)
+
+afsdump_dirlist: libxfiles.a libdumpscan.a afsdump_dirlist.o
+       $(AFS_LDRULE) afsdump_dirlist.o $(LIBS)
+
+afsdump_extract: libxfiles.a libdumpscan.a afsdump_extract.o
+       $(AFS_LDRULE) afsdump_extract.o $(LIBS)
+
+null-search: libxfiles.a libdumpscan.a null-search.c
+       $(AFS_LDRULE) null-search.c $(LIBS)
+
+dumptool: dumptool.c
+       $(AFS_LDRULE) dumptool.c
+
+libxfiles.a: $(OBJS_libxfiles.a)
+       -rm -f libxfiles.a
+       $(AR) r libxfiles.a $(OBJS_libxfiles.a)
+       $(RANLIB) libxfiles.a
+
+libdumpscan.a: $(OBJS_libdumpscan.a)
+       -rm -f libdumpscan.a
+       $(AR) r libdumpscan.a $(OBJS_libdumpscan.a)
+       $(RANLIB) libdumpscan.a
+
+xf_errs.c xf_errs.h: xf_errs.et
+       $(COMPILE_ET) xf_errs.et
+
+dumpscan_errs.c dumpscan_errs.h: dumpscan_errs.et
+       $(COMPILE_ET) dumpscan_errs.et
+
+util.o xfiles.o xf_files.o: xf_errs.h
+backuphdr.o directory.o parsedump.o parsetag.o: dumpscan_errs.h
+parsevnode.o parsevol.o pathname.o stagehdr.o:  dumpscan_errs.h
+util.o:                                         dumpscan_errs.h
+
+# repair addresses the same storage as two different types of structs at the
+# same time.
+CFLAGS_repair.o = @CFLAGS_NOSTRICT@
+repair.o: repair.c dumpscan_errs.h
+
+${TOP_LIBDIR}/libxfiles.a: libxfiles.a
+       ${INSTALL_DATA} $? $@
+
+${TOP_LIBDIR}/libdumpscan.a: libdumpscan.a
+       ${INSTALL_DATA} $? $@
+
+dest:
+
+install:
+
+uninstall:
+
+clean:
+       -rm -f xf_errs.c xf_errs.h dumpscan_errs.c dumpscan_errs.h *.o \
+       $(TARGETS)
+
+include ../config/Makefile.version
+
+.PHONY:                all install clean realclean distclean mostlyclean install uninstall
diff --git a/src/tools/TEMPLATE b/src/tools/TEMPLATE
new file mode 100644 (file)
index 0000000..6448750
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
diff --git a/src/tools/afsdump_dirlist.c b/src/tools/afsdump_dirlist.c
new file mode 100644 (file)
index 0000000..71cde8e
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* afsdump_dirlist.c - List an AFS directory file */
+
+#include <afsconfig.h>
+
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <afs/stds.h>
+#include <afs/com_err.h>
+#include <afs/cellconfig.h>
+#include <afs/vlserver.h>
+#include <afs/volser.h>
+#include <rx/rxkad.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "xf_errs.h"
+
+extern int optind;
+extern char *optarg;
+
+char *argv0;
+static char *input_path;
+static int quiet, verbose, error_count;
+
+static dump_parser dp;
+
+
+/* Print a usage message and exit */
+static void
+usage(int status, char *msg)
+{
+    if (msg)
+       fprintf(stderr, "%s: %s\n", argv0, msg);
+    fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
+    fprintf(stderr, "  -h     Print this help message\n");
+    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
+    fprintf(stderr, "  -v     Verbose mode\n");
+    exit(status);
+}
+
+
+/* Parse the command-line options */
+static void
+parse_options(int argc, char **argv)
+{
+    int c;
+
+    /* Set the program name */
+    if ((argv0 = strrchr(argv[0], '/')) != NULL)
+       argv0++;
+    else
+       argv0 = argv[0];
+
+    /* Initialize options */
+    input_path = 0;
+    quiet = verbose = 0;
+
+    /* Initialize other stuff */
+    error_count = 0;
+
+    /* Parse the options */
+    while ((c = getopt(argc, argv, "hqv")) != EOF) {
+       switch (c) {
+       case 'q':
+           quiet = 1;
+           continue;
+       case 'v':
+           verbose = 1;
+           continue;
+       case 'h':
+           usage(0, 0);
+       default:
+           usage(1, "Invalid option!");
+       }
+    }
+
+    if (quiet && verbose)
+       usage(1, "Can't specify both -q and -v");
+
+    /* Parse non-option arguments */
+    if (argc - optind > 1)
+       usage(1, "Too many arguments!");
+    input_path = (argc == optind) ? "-" : argv[optind];
+}
+
+
+/* A callback to count and print errors */
+static afs_uint32
+my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
+{
+    va_list alist;
+
+    error_count++;
+    if (!quiet) {
+       va_start(alist, msg);
+       afs_com_err_va(argv0, code, msg, alist);
+       va_end(alist);
+    }
+    return 0;
+}
+
+
+/* Main program */
+int
+main(int argc, char **argv)
+{
+    XFILE input_file;
+    afs_uint32 r;
+
+    parse_options(argc, argv);
+    initialize_acfg_error_table();
+    initialize_AVds_error_table();
+    initialize_rxk_error_table();
+    initialize_u_error_table();
+    initialize_vl_error_table();
+    initialize_vols_error_table();
+    initialize_xFil_error_table();
+    r = xfopen(&input_file, O_RDONLY, input_path);
+    if (r) {
+       afs_com_err(argv0, r, "opening %s", input_path);
+       exit(2);
+    }
+
+    memset(&dp, 0, sizeof(dp));
+    dp.cb_error = my_error_cb;
+    dp.print_flags = DSPRINT_DIR;
+    if (input_file.is_seekable)
+       dp.flags |= DSFLAG_SEEK;
+
+    r = ParseDirectory(&input_file, &dp, 0, 1);
+    xfclose(&input_file);
+
+    if (verbose && error_count)
+       fprintf(stderr, "*** %d errors\n", error_count);
+    if (r && !quiet)
+       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
+    return 0;
+}
diff --git a/src/tools/afsdump_extract.c b/src/tools/afsdump_extract.c
new file mode 100644 (file)
index 0000000..88b6a22
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* afsdump_extract.c - Extract files from an AFS dump */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <afs/com_err.h>
+#include <afs/cellconfig.h>
+#include <afs/vlserver.h>
+#include <afs/volser.h>
+#include <rx/rxkad.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "xf_errs.h"
+
+#define COPYBUFSIZE (256*1024)
+
+extern int optind;
+extern char *optarg;
+
+char *argv0;
+static char **file_names;
+static int *file_vnums, name_count, vnum_count;
+
+static char *input_path, *target;
+static int quiet, verbose, error_count, dirs_done, extract_all;
+static int nomode, use_realpath, use_vnum;
+static int do_acls, do_headers;
+
+static path_hashinfo phi;
+static dump_parser dp;
+
+/* Print a usage message and exit */
+static void
+usage(int status, char *msg)
+{
+    if (msg)
+       fprintf(stderr, "%s: %s\n", argv0, msg);
+    fprintf(stderr, "Usage: %s [options] dumpfile [dest [files...]]\n",
+           argv0);
+    fprintf(stderr, "  -A     Save ACL's\n");
+    fprintf(stderr, "  -H     Save headers\n");
+    fprintf(stderr, "  -h     Print this help message\n");
+    fprintf(stderr, "  -i     Use vnode numbers\n");
+    fprintf(stderr, "  -n     Don't actually create files\n");
+    fprintf(stderr, "  -p     Use real pathnames internally\n");
+    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
+    fprintf(stderr, "  -v     Verbose mode\n");
+    fprintf(stderr, "The destination directory defaults to .\n");
+    fprintf(stderr, "Files may be vnode numbers or volume-relative paths;\n");
+    fprintf(stderr, "If vnode numbers are used, files will be extracted\n");
+    fprintf(stderr,
+           "a name generated from the vnode number and uniqifier.\n");
+    fprintf(stderr, "If paths are used, -p is implied and files will be\n");
+    fprintf(stderr, "into correctly-named files.\n");
+    exit(status);
+}
+
+
+/* Parse the command-line options */
+static void
+parse_options(int argc, char **argv)
+{
+    int c, i, i_name, i_vnum;
+
+    /* Set the program name */
+    if ((argv0 = strrchr(argv[0], '/')))
+       argv0++;
+    else
+       argv0 = argv[0];
+
+    /* Initialize options */
+    input_path = 0;
+    quiet = verbose = nomode = 0;
+    use_realpath = use_vnum = do_acls = do_headers = extract_all = 0;
+
+    /* Initialize other stuff */
+    error_count = 0;
+
+    /* Parse the options */
+    while ((c = getopt(argc, argv, "AHhinpqv")) != EOF) {
+       switch (c) {
+       case 'A':
+           do_acls = 1;
+           continue;
+       case 'H':
+           do_headers = 1;
+           continue;
+       case 'i':
+           use_vnum = 1;
+           continue;
+       case 'n':
+           nomode = 1;
+           continue;
+       case 'p':
+           use_realpath = 1;
+           continue;
+       case 'q':
+           quiet = 1;
+           continue;
+       case 'v':
+           verbose = 1;
+           continue;
+       case 'h':
+           usage(0, 0);
+       default:
+           usage(1, "Invalid option!");
+       }
+    }
+
+    if (quiet && verbose)
+       usage(1, "Can't specify both -q and -v");
+
+    /* Parse non-option arguments */
+    if (argc - optind < 1)
+       usage(1, "Dumpfile name required!");
+    input_path = argv[optind];
+
+    if (argc - optind < 2)
+       target = ".";
+    target = argv[optind + 1];
+
+    vnum_count = name_count = 0;
+    if (argc - optind < 3)
+       extract_all = 1;
+    else {
+       argv += optind + 2;
+       argc -= optind + 2;
+       for (i = 0; i < argc; i++) {
+           if (argv[i][0] == '/')
+               name_count++;
+           else
+               vnum_count++;
+       }
+       file_names = (char **)malloc(name_count + sizeof(char *));
+       file_vnums = (afs_int32 *) malloc(vnum_count + sizeof(afs_uint32));
+       if (name_count)
+           use_realpath = 1;
+
+       i_name = i_vnum = 0;
+       for (i = 0; i < argc; i++) {
+           if (argv[i][0] == '/')
+               file_names[i_name++] = argv[i];
+           else
+               file_vnums[i_vnum++] = strtol(argv[i], 0, 0);
+       }
+    }
+}
+
+
+static int
+mkdirp(char *path)
+{
+    char *x = path, slash;
+    struct stat statbuf;
+
+    for (;;) {
+       while (*x && *x != '/')
+           x++;
+       slash = *x;
+       *x = 0;
+
+       if (stat(path, &statbuf)) {
+           if (errno == ENOENT) {
+               if (verbose)
+                   printf("> mkdir %s\n", path);
+               if (!mkdir(path, 0755))
+                   errno = 0;
+           }
+       }
+       if (!slash)
+           break;
+       *x++ = '/';
+       if (errno)
+           return errno;
+    }
+
+    return 0;
+}
+
+
+static char *
+modestr(int mode)
+{
+    static char str[10];
+    int i;
+
+    strcpy(str, "rwxrwxrwx");
+    for (i = 0; i < 9; i++) {
+       if (!(mode & (1 << i)))
+           str[8 - i] = '-';
+    }
+    if (mode & 01000)
+       str[8] = (str[8] == '-') ? 'T' : 't';
+    if (mode & 02000)
+       str[5] = (str[5] == '-') ? 'S' : 's';
+    if (mode & 04000)
+       str[2] = (str[2] == '-') ? 'S' : 's';
+    return str;
+}
+
+
+static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+static char *
+datestr(time_t date)
+{
+    static char str[13];
+    time_t clock = time(0);
+    struct tm *now, *then;
+    int diff;
+
+    now = localtime(&clock);
+    then = localtime(&date);
+
+    diff = now->tm_mon - then->tm_mon;
+    if (then->tm_year == now->tm_year - 1)
+       diff += 12;
+    if (then->tm_year == now->tm_year + 1)
+       diff -= 12;
+
+    if (diff < 5 || diff > 5)
+       sprintf(str, "%3s %2d  %4d", month[then->tm_mon], then->tm_mday,
+               then->tm_year + 1900);
+    else
+       sprintf(str, "%3s %2d %2d:%2d", month[then->tm_mon], then->tm_mday,
+               then->tm_hour, then->tm_min);
+    return str;
+}
+
+
+/* Should we use this vnode?
+ * Return 0 if no, non-0 if yes
+ */
+static int
+usevnode(XFILE * X, afs_uint32 vnum, char *vnodepath)
+{
+    int vl, vpl, r, i;
+
+    /* Special case */
+    if (extract_all || !strcmp(vnodepath, "/"))
+       return 1;
+
+    for (i = 0; i < vnum_count; i++)
+       if (vnum == file_vnums[i])
+           return 2;
+
+    vl = strlen(vnodepath);
+/*fprintf(stderr, "++ checking %s\n", vnodepath);*/
+    for (i = 0; i < name_count; i++) {
+       vpl = strlen(file_names[i]);
+/*  fprintf(stderr, "   %s\n", file_names[i]);*/
+
+       if (vl > vpl) {
+           r = !strncmp(file_names[i], vnodepath, vpl)
+               && vnodepath[vpl] == '/';
+       } else if (vl < vpl) {
+           r = !strncmp(file_names[i], vnodepath, vl)
+               && file_names[i][vl] == '/';
+       } else {
+           r = !strcmp(file_names[i], vnodepath);
+       }
+       if (r)
+           return 1;
+    }
+    return 0;
+}
+
+
+static int
+copyfile(XFILE * in, XFILE * out, int size)
+{
+    static char buf[COPYBUFSIZE];
+    int nr, r;
+
+    while (size) {
+       nr = (size > COPYBUFSIZE) ? COPYBUFSIZE : size;
+       if ((r = xfread(in, buf, nr)))
+           return r;
+       if ((r = xfwrite(out, buf, nr)))
+           return r;
+       size -= nr;
+    }
+    return 0;
+}
+
+
+/* A callback to count and print errors */
+static afs_uint32
+my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
+{
+    va_list alist;
+
+    error_count++;
+    if (!quiet) {
+       va_start(alist, msg);
+       afs_com_err_va(argv0, code, msg, alist);
+       va_end(alist);
+    }
+    return 0;
+}
+
+
+static afs_uint32
+dumphdr_cb(afs_dump_header * hdr, XFILE * X, void *refcon)
+{
+    return 0;
+}
+
+
+static afs_uint32
+volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
+{
+    return 0;
+}
+
+
+static afs_uint32
+directory_cb(afs_vnode * v, XFILE * X, void *refcon)
+{
+    char *vnodepath;
+    int r, use = 0;
+
+    /* Should we even use this? */
+    if (!use_vnum) {
+       if ((r = Path_Build(X, &phi, v->vnode, &vnodepath, !use_realpath)))
+           return r;
+       if (!(use = usevnode(X, v->vnode, vnodepath))) {
+           free(vnodepath);
+           return 0;
+       }
+    }
+
+    /* Print it out */
+    if (verbose) {
+       if (use_vnum)
+           printf("d%s %3d %-11d %11d %s #%d:%d\n", modestr(v->mode),
+                  v->nlinks, v->owner, v->size, datestr(v->server_date),
+                  v->vnode, v->vuniq);
+       else
+           printf("d%s %3d %-11d %11d %s %s\n", modestr(v->mode), v->nlinks,
+                  v->owner, v->size, datestr(v->server_date), vnodepath);
+    } else if (!quiet && !use_vnum)
+       printf("%s\n", vnodepath);
+
+    /* Make the directory, if needed */
+    if (!nomode && !use_vnum && use != 2) {
+       if (strcmp(vnodepath, "/")
+           && (r = mkdirp(vnodepath + 1))) {
+           free(vnodepath);
+           return r;
+       }
+       if (do_acls) {
+           /* XXX do ACL's later */
+       }
+    }
+    if (!use_vnum)
+       free(vnodepath);
+    return 0;
+}
+
+
+static afs_uint32
+file_cb(afs_vnode * v, XFILE * X, void *refcon)
+{
+    char *vnodepath, vnpx[30];
+    u_int64 where;
+    XFILE OX;
+    int r, use = 0;
+
+    if (!dirs_done) {
+       dirs_done = 1;
+       if (verbose)
+           printf("* Extracting files...\n");
+    }
+
+    /* Should we even use this? */
+    if (!use_vnum) {
+       if ((r = Path_Build(X, &phi, v->vnode, &vnodepath, !use_realpath)))
+           return r;
+       if (!(use = usevnode(X, v->vnode, vnodepath))) {
+           free(vnodepath);
+           return 0;
+       }
+       if (use == 2) {
+           free(vnodepath);
+           sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
+           vnodepath = vnpx;
+       }
+    } else {
+       sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
+       vnodepath = vnpx;
+    }
+
+    /* Print it out */
+    if (verbose) {
+       printf("-%s %3d %-11d %11d %s %s\n", modestr(v->mode), v->nlinks,
+              v->owner, v->size, datestr(v->server_date), vnodepath);
+    } else if (!quiet) {
+       printf("%s\n", vnodepath);
+    }
+
+    if (!nomode) {
+       if ((r = xftell(X, &where))
+           || (r = xfseek(X, &v->d_offset))
+           || (r =
+               xfopen_path(&OX, O_RDWR | O_CREAT | O_TRUNC, vnodepath + 1,
+                           0644))) {
+           if (!use_vnum)
+               free(vnodepath);
+           return r;
+       }
+       r = copyfile(X, &OX, v->size);
+       xfclose(&OX);
+       xfseek(X, &where);
+    } else
+       r = 0;
+
+    if (!use_vnum && use != 2)
+       free(vnodepath);
+    return r;
+}
+
+
+static afs_uint32
+symlink_cb(afs_vnode * v, XFILE * X, void *refcon)
+{
+    char *vnodepath, *linktarget, vnpx[30];
+    u_int64 where;
+    int r, use = 0;
+
+    if (!dirs_done) {
+       dirs_done = 1;
+       if (verbose)
+           printf("* Extracting files...\n");
+    }
+
+    /* Should we even use this? */
+    if (!use_vnum) {
+       if ((r = Path_Build(X, &phi, v->vnode, &vnodepath, !use_realpath)))
+           return r;
+       if (!(use = usevnode(X, v->vnode, vnodepath))) {
+           free(vnodepath);
+           return 0;
+       }
+       if (use == 2) {
+           free(vnodepath);
+           sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
+           vnodepath = vnpx;
+       }
+    } else {
+       sprintf(vnpx, "#%d:%d", v->vnode, v->vuniq);
+       vnodepath = vnpx;
+    }
+
+    if (!(linktarget = (char *)malloc(v->size + 1))) {
+       if (!use_vnum && use != 2)
+           free(vnodepath);
+       return DSERR_MEM;
+    }
+    if ((r = xftell(X, &where))
+       || (r = xfseek(X, &v->d_offset))
+       || (r = xfread(X, linktarget, v->size))) {
+       if (!use_vnum && use != 2)
+           free(vnodepath);
+       free(linktarget);
+       return r;
+    }
+    xfseek(X, &where);
+    linktarget[v->size] = 0;
+
+    /* Print it out */
+    if (verbose)
+       printf("l%s %3d %-11d %11d %s %s -> %s\n", modestr(v->mode),
+              v->nlinks, v->owner, v->size, datestr(v->server_date),
+              vnodepath, linktarget);
+    else if (!quiet)
+       printf("%s\n", vnodepath);
+
+    r = 0;
+    if (!nomode) {
+       if (symlink(linktarget, vnodepath + 1))
+           r = errno;
+    }
+
+    free(linktarget);
+    if (!use_vnum && use != 2)
+       free(vnodepath);
+    return r;
+}
+
+
+static afs_uint32
+lose_cb(afs_vnode * v, XFILE * F, void *refcon)
+{
+    if (!dirs_done) {
+       dirs_done = 1;
+       if (verbose)
+           printf("* Extracting files...\n");
+    }
+
+    return 0;
+}
+
+
+/* Main program */
+int
+main(int argc, char **argv)
+{
+    XFILE input_file;
+    afs_uint32 r;
+
+    parse_options(argc, argv);
+    initialize_acfg_error_table();
+    initialize_AVds_error_table();
+    initialize_rxk_error_table();
+    initialize_u_error_table();
+    initialize_vl_error_table();
+    initialize_vols_error_table();
+    initialize_xFil_error_table();
+    r = xfopen(&input_file, O_RDONLY, input_path);
+    if (r) {
+       afs_com_err(argv0, r, "opening %s", input_path);
+       exit(2);
+    }
+
+    memset(&dp, 0, sizeof(dp));
+    dp.cb_error = my_error_cb;
+    if (input_file.is_seekable)
+       dp.flags |= DSFLAG_SEEK;
+    dirs_done = 0;
+
+    if (!use_vnum) {
+       u_int64 where;
+
+       memset(&phi, 0, sizeof(phi));
+       phi.p = &dp;
+
+       if (verbose)
+           printf("* Building pathname info...\n");
+       if ((r = xftell(&input_file, &where))
+           || (r = Path_PreScan(&input_file, &phi, 1))
+           || (r = xfseek(&input_file, &where))) {
+           afs_com_err(argv0, r, "- path initialization failed");
+           xfclose(&input_file);
+           exit(1);
+       }
+    }
+
+    dp.cb_vnode_dir = directory_cb;
+    dp.cb_vnode_file = file_cb;
+    dp.cb_vnode_link = symlink_cb;
+    dp.cb_vnode_empty = lose_cb;
+    dp.cb_vnode_wierd = lose_cb;
+    if (do_headers) {
+       dp.cb_dumphdr = dumphdr_cb;
+       dp.cb_volhdr = volhdr_cb;
+    }
+
+    if (!nomode) {
+       mkdir(target, 0755);
+       if (chdir(target)) {
+           fprintf(stderr, "chdir %s failed: %s\n", target, strerror(errno));
+           exit(1);
+       }
+    }
+    r = ParseDumpFile(&input_file, &dp);
+
+    if (verbose && error_count)
+       fprintf(stderr, "*** %d errors\n", error_count);
+    if (r && !quiet)
+       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
+    exit(0);
+}
diff --git a/src/tools/afsdump_scan.c b/src/tools/afsdump_scan.c
new file mode 100644 (file)
index 0000000..8bc7f10
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* afsdump_scan.c - General-purpose dump scanner */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <afs/com_err.h>
+#include <afs/pterror.h>
+#include <afs/vlserver.h>
+#include <afs/cellconfig.h>
+#include <rx/rxkad.h>
+#include <afs/volser.h>
+#include <ubik.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "xf_errs.h"
+extern int optind;
+extern char *optarg;
+
+extern XFILE repair_output;
+extern afs_uint32 repair_dumphdr_cb(afs_dump_header *, XFILE *, void *);
+extern afs_uint32 repair_volhdr_cb(afs_vol_header *, XFILE *, void *);
+extern afs_uint32 repair_vnode_cb(afs_vnode *, XFILE *, void *);
+
+char *argv0;
+static char *input_path, *gendump_path;
+static afs_uint32 printflags, repairflags;
+static int quiet, verbose, error_count;
+
+static path_hashinfo phi;
+static dump_parser dp;
+
+
+/* Print a usage message and exit */
+static void
+usage(int status, char *msg)
+{
+    if (msg)
+       fprintf(stderr, "%s: %s\n", argv0, msg);
+    fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
+    fprintf(stderr, "  -Pxxx  Set print options:\n");
+    fprintf(stderr, "          B = Print backup system header (if any)\n");
+    fprintf(stderr, "          H = Print AFS dump header\n");
+    fprintf(stderr, "          V = Print AFS volume header\n");
+    fprintf(stderr, "          v = List vnodes\n");
+    fprintf(stderr, "          p = Include path to each vnode\n");
+    fprintf(stderr, "          i = Include info for each vnode\n");
+    fprintf(stderr, "          d = List directory contents\n");
+    fprintf(stderr, "          a = List access control lists\n");
+    fprintf(stderr, "          g = Print debugging info\n");
+    fprintf(stderr, "  -Rxxx  Set repair options:\n");
+    fprintf(stderr, "          0 = Skip null tags\n");
+    fprintf(stderr, "          b = Seek backward to find skipped tags\n");
+    fprintf(stderr, "          d = Resync after vnode data\n");
+    fprintf(stderr, "          v = Resync after corrupted vnodes\n");
+    fprintf(stderr, "  -h     Print this help message\n");
+    fprintf(stderr, "  -gxxx  Generate a new dump in file xxx\n");
+    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
+    fprintf(stderr, "  -v     Verbose mode\n");
+    exit(status);
+}
+
+
+/* Parse the argument given to the -P option.
+ * Returns the resulting * dumpscan print flags (DSPRINT_*).
+ * If an unrecognized flag is used, prints an error message and exits.
+ */
+static afs_uint32
+parse_printflags(char *flags)
+{
+    afs_uint32 result = 0;
+    char *x;
+
+    for (x = flags; *x; x++)
+       switch (*x) {
+       case 'B':
+           result |= DSPRINT_BCKHDR;
+           continue;
+       case 'H':
+           result |= DSPRINT_DUMPHDR;
+           continue;
+       case 'V':
+           result |= DSPRINT_VOLHDR;
+           continue;
+       case 'v':
+           result |= DSPRINT_ITEM;
+           continue;
+       case 'p':
+           result |= DSPRINT_PATH;
+           continue;
+       case 'i':
+           result |= DSPRINT_VNODE;
+           continue;
+       case 'd':
+           result |= DSPRINT_DIR;
+           continue;
+       case 'a':
+           result |= DSPRINT_ACL;
+           continue;
+       case 'g':
+           result |= DSPRINT_DEBUG;
+           continue;
+       default:
+           usage(1, "Invalid print options!");
+       }
+    return result;
+}
+
+
+/* Parse the argument given to the -R option.
+ * Returns the resulting * dumpscan repair flags (DSFIX_*).
+ * If an unrecognized flag is used, prints an error message and exits.
+ */
+static afs_uint32
+parse_repairflags(char *flags)
+{
+    afs_uint32 result = 0;
+    char *x;
+
+    for (x = flags; *x; x++)
+       switch (*x) {
+       case '0':
+           result |= DSFIX_SKIP;
+           continue;
+       case 'b':
+           result |= DSFIX_RSKIP;
+           continue;
+       case 'd':
+           result |= DSFIX_VDSYNC;
+           continue;
+       case 'v':
+           result |= DSFIX_VFSYNC;
+           continue;
+       default:
+           usage(1, "Invalid repair options!");
+       }
+    return result;
+}
+
+
+/* Parse the command-line options */
+static void
+parse_options(int argc, char **argv)
+{
+    int c;
+
+    /* Set the program name */
+    if ((argv0 = strrchr(argv[0], '/')))
+       argv0++;
+    else
+       argv0 = argv[0];
+
+    /* Initialize options */
+    input_path = gendump_path = 0;
+    printflags = repairflags = 0;
+    quiet = verbose = 0;
+
+    /* Initialize other stuff */
+    error_count = 0;
+
+    /* Parse the options */
+    while ((c = getopt(argc, argv, "P:R:g:hqv")) != EOF) {
+       switch (c) {
+       case 'P':
+           printflags = parse_printflags(optarg);
+           continue;
+       case 'R':
+           repairflags = parse_repairflags(optarg);
+           continue;
+       case 'g':
+           gendump_path = optarg;
+           continue;
+       case 'q':
+           quiet = 1;
+           continue;
+       case 'v':
+           verbose = 1;
+           continue;
+       case 'h':
+           usage(0, 0);
+       default:
+           usage(1, "Invalid option!");
+       }
+    }
+
+    if (quiet && verbose)
+       usage(1, "Can't specify both -q and -v");
+
+    /* Parse non-option arguments */
+    if (argc - optind > 1)
+       usage(1, "Too many arguments!");
+    input_path = (argc == optind) ? "-" : argv[optind];
+}
+
+
+/* A callback to count and print errors */
+static afs_uint32
+my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
+{
+    va_list alist;
+
+    error_count++;
+    if (!quiet) {
+       va_start(alist, msg);
+       afs_com_err_va(argv0, code, msg, alist);
+       va_end(alist);
+    }
+    return 0;
+}
+
+
+/* A callback to print the path of a vnode. */
+static afs_uint32
+print_vnode_path(afs_vnode * v, XFILE * X, void *refcon)
+{
+    afs_uint32 r;
+    char *name = 0;
+
+    /* Do repair, but only for known vnode types */
+    if (gendump_path && (!(v->field_mask & F_VNODE_TYPE)
+                        || ((v->type != vFile) && (v->type != vDirectory)
+                            && (v->type != vSymlink)))) {
+       r = repair_vnode_cb(v, X, refcon);
+       if (r)
+           return r;
+    }
+    r = Path_Build(X, &phi, v->vnode, &name, 0);
+    if (!r && name)
+       printf(" Path: %s\n", name);
+    if (name)
+       free(name);
+    return r;
+}
+
+
+/* Setup for generating a repaired dump */
+static afs_uint32
+setup_repair(void)
+{
+    afs_uint32 r;
+
+    r = xfopen(&repair_output, O_RDWR | O_CREAT | O_TRUNC, gendump_path);
+    if (r)
+       return r;
+
+    dp.cb_dumphdr = repair_dumphdr_cb;
+    dp.cb_volhdr = repair_volhdr_cb;
+    dp.cb_vnode_dir = repair_vnode_cb;
+    dp.cb_vnode_file = repair_vnode_cb;
+    dp.cb_vnode_link = repair_vnode_cb;
+    dp.cb_vnode_empty = repair_vnode_cb;
+    return 0;
+}
+
+extern afs_uint32 DumpDumpEnd(XFILE * OX);
+
+/* Main program */
+int
+main(int argc, char **argv)
+{
+    XFILE input_file;
+    afs_uint32 r;
+
+    parse_options(argc, argv);
+    initialize_acfg_error_table();
+    initialize_AVds_error_table();
+    initialize_rxk_error_table();
+    initialize_u_error_table();
+    initialize_vl_error_table();
+    initialize_vols_error_table();
+    initialize_xFil_error_table();
+    r = xfopen(&input_file, O_RDONLY, input_path);
+    if (r) {
+       afs_com_err(argv0, r, "opening %s", input_path);
+       exit(2);
+    }
+
+    memset(&dp, 0, sizeof(dp));
+    dp.cb_error = my_error_cb;
+    dp.repair_flags = repairflags;
+    if (input_file.is_seekable)
+       dp.flags |= DSFLAG_SEEK;
+    else {
+       if (repairflags)
+           fprintf(stderr,
+                   "Repair modes available only for seekable dumps\n");
+       if (printflags & DSPRINT_PATH)
+           fprintf(stderr,
+                   "Path-printing available only for seekable dumps\n");
+       if (repairflags || (printflags & DSPRINT_PATH))
+           exit(1);
+    }
+
+    if (gendump_path && (r = setup_repair())) {
+       afs_com_err(argv0, r, "setting up repair output");
+       xfclose(&input_file);
+       exit(2);
+    }
+
+    if (printflags & DSPRINT_PATH) {
+       u_int64 where;
+
+       dp.print_flags = printflags & DSPRINT_DEBUG;
+       memset(&phi, 0, sizeof(phi));
+       phi.p = &dp;
+
+       if ((r = xftell(&input_file, &where))
+           || (r = Path_PreScan(&input_file, &phi, 0))
+           || (r = xfseek(&input_file, &where))) {
+           afs_com_err(argv0, r, "- path initialization failed");
+           xfclose(&input_file);
+           exit(2);
+       }
+
+       dp.cb_vnode_dir = print_vnode_path;
+       dp.cb_vnode_file = print_vnode_path;
+       dp.cb_vnode_link = print_vnode_path;
+       dp.cb_vnode_empty = print_vnode_path;
+       dp.cb_vnode_wierd = print_vnode_path;
+    }
+
+    dp.print_flags = printflags;
+    r = ParseDumpFile(&input_file, &dp);
+    xfclose(&input_file);
+    if (gendump_path) {
+       if (!r)
+           r = DumpDumpEnd(&repair_output);
+       if (!r)
+           r = xfclose(&repair_output);
+       else
+           xfclose(&repair_output);
+    }
+
+    if (verbose && error_count)
+       fprintf(stderr, "*** %d errors\n", error_count);
+    if (r && !quiet)
+       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
+    exit(0);
+}
diff --git a/src/tools/afsdump_xsed.c b/src/tools/afsdump_xsed.c
new file mode 100644 (file)
index 0000000..f726ae9
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * COPYRIGHT NOTICE
+ * Copyright (c) 1997 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* UB - Unified Backups */
+/* methods/afs/dumpscan/afsdump_scan.c - General-purpose dump scanner */
+
+#include "dumpscan.h"
+#include <sys/fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+extern int opterr, optind;
+extern char *optarg;
+
+extern XFILE repair_output;
+extern afs_uint32 repair_dumphdr_cb(afs_dump_header *, XFILE *, void *);
+extern afs_uint32 repair_volhdr_cb(afs_vol_header *, XFILE *, void *);
+extern afs_uint32 repair_vnode_cb(afs_vnode *, XFILE *, void *);
+
+char *argv0;
+static char *input_path, *gendump_path;
+static afs_uint32 printflags, repairflags, add_admin;
+static int quiet, verbose, error_count;
+
+static path_hashinfo phi;
+static dump_parser dp;
+
+
+/* Print a usage message and exit */
+static void
+usage(int status, char *msg)
+{
+    if (msg)
+       fprintf(stderr, "%s: %s\n", argv0, msg);
+    fprintf(stderr, "Usage: %s [options] [file]\n", argv0);
+    fprintf(stderr, "  -Pxxx  Set print options:\n");
+    fprintf(stderr, "          B = Print backup system header (if any)\n");
+    fprintf(stderr, "          H = Print AFS dump header\n");
+    fprintf(stderr, "          V = Print AFS volume header\n");
+    fprintf(stderr, "          v = List vnodes\n");
+    fprintf(stderr, "          p = Include path to each vnode\n");
+    fprintf(stderr, "          i = Include info for each vnode\n");
+    fprintf(stderr, "          d = List directory contents\n");
+    fprintf(stderr, "          a = List access control lists\n");
+    fprintf(stderr, "          g = Print debugging info\n");
+    fprintf(stderr, "  -Rxxx  Set repair options:\n");
+    fprintf(stderr, "          0 = Skip null tags\n");
+    fprintf(stderr, "          b = Seek backward to find skipped tags\n");
+    fprintf(stderr, "          d = Resync after vnode data\n");
+    fprintf(stderr, "          v = Resync after corrupted vnodes\n");
+    fprintf(stderr,
+           "  -Annn  Add all rights for ID nnn to every directory\n");
+    fprintf(stderr, "  -h     Print this help message\n");
+    fprintf(stderr, "  -gxxx  Generate a new dump in file xxx\n");
+    fprintf(stderr, "  -q     Quiet mode (don't print errors)\n");
+    fprintf(stderr, "  -v     Verbose mode\n");
+    exit(status);
+}
+
+
+/* Parse the argument given to the -P option.
+ * Returns the resulting * dumpscan print flags (DSPRINT_*).
+ * If an unrecognized flag is used, prints an error message and exits.
+ */
+static afs_uint32
+parse_printflags(char *flags)
+{
+    afs_uint32 result = 0;
+    char *x;
+
+    for (x = flags; *x; x++)
+       switch (*x) {
+       case 'B':
+           result |= DSPRINT_BCKHDR;
+           continue;
+       case 'H':
+           result |= DSPRINT_DUMPHDR;
+           continue;
+       case 'V':
+           result |= DSPRINT_VOLHDR;
+           continue;
+       case 'v':
+           result |= DSPRINT_ITEM;
+           continue;
+       case 'p':
+           result |= DSPRINT_PATH;
+           continue;
+       case 'i':
+           result |= DSPRINT_VNODE;
+           continue;
+       case 'd':
+           result |= DSPRINT_DIR;
+           continue;
+       case 'a':
+           result |= DSPRINT_ACL;
+           continue;
+       case 'g':
+           result |= DSPRINT_DEBUG;
+           continue;
+       default:
+           usage(1, "Invalid print options!");
+       }
+    return result;
+}
+
+
+/* Parse the argument given to the -R option.
+ * Returns the resulting * dumpscan repair flags (DSFIX_*).
+ * If an unrecognized flag is used, prints an error message and exits.
+ */
+static afs_uint32
+parse_repairflags(char *flags)
+{
+    afs_uint32 result = 0;
+    char *x;
+
+    for (x = flags; *x; x++)
+       switch (*x) {
+       case '0':
+           result |= DSFIX_SKIP;
+           continue;
+       case 'b':
+           result |= DSFIX_RSKIP;
+           continue;
+       case 'd':
+           result |= DSFIX_VDSYNC;
+           continue;
+       case 'v':
+           result |= DSFIX_VFSYNC;
+           continue;
+       default:
+           usage(1, "Invalid repair options!");
+       }
+    return result;
+}
+
+
+/* Parse the command-line options */
+static void
+parse_options(int argc, char **argv)
+{
+    int c;
+
+    /* Set the program name */
+    if (argv0 = strrchr(argv[0], '/'))
+       argv0++;
+    else
+       argv0 = argv[0];
+
+    /* Initialize options */
+    input_path = gendump_path = 0;
+    printflags = repairflags = add_admin = 0;
+    quiet = verbose = 0;
+
+    /* Initialize other stuff */
+    error_count = 0;
+
+    /* Parse the options */
+    while ((c = getopt(argc, argv, "A:P:R:g:hv")) != EOF) {
+       switch (c) {
+       case 'A':
+           add_admin = atoi(optarg);
+           continue;
+       case 'P':
+           printflags = parse_printflags(optarg);
+           continue;
+       case 'R':
+           repairflags = parse_repairflags(optarg);
+           continue;
+       case 'g':
+           gendump_path = optarg;
+           continue;
+       case 'q':
+           quiet = 1;
+           continue;
+       case 'v':
+           verbose = 1;
+           continue;
+       case 'h':
+           usage(0, 0);
+       default:
+           usage(1, "Invalid option!");
+       }
+    }
+
+    if (quiet && verbose)
+       usage(1, "Can't specify both -q and -v");
+
+    /* Parse non-option arguments */
+    if (argc - optind > 1)
+       usage(1, "Too many arguments!");
+    input_path = (argc == optind) ? "-" : argv[optind];
+    if (add_admin && !gendump_path)
+       add_admin = 0;
+}
+
+
+/* A callback to count and print errors */
+static afs_uint32
+my_error_cb(afs_uint32 code, int fatal, void *ref, char *msg, ...)
+{
+    va_list alist;
+
+    error_count++;
+    if (!quiet) {
+       va_start(alist, msg);
+       afs_com_err_va(argv0, code, msg, alist);
+       va_end(alist);
+    }
+}
+
+
+/* A callback to print the path of a vnode. */
+static afs_uint32
+print_vnode_path(afs_vnode * v, XFILE * X, void *refcon)
+{
+    afs_uint32 r;
+    char *name = 0;
+
+    /* Do repair, but only for known vnode types */
+    if (gendump_path && (!(v->field_mask & F_VNODE_TYPE)
+                        || v->type != vFile || v->type != vDirectory
+                        || v->type != vSymlink)) {
+       r = repair_vnode_cb(v, X, refcon);
+       if (r)
+           return r;
+    }
+    r = Path_Build(X, &phi, v->vnode, &name, 0);
+    if (!r && name)
+       printf(" Path: %s\n", name);
+    if (name)
+       free(name);
+    return r;
+}
+
+
+static afs_uint32
+munge_admin_acl(afs_vnode * v, XFILE * X, void *refcon)
+{
+    struct acl_accessList *acl;
+    int add_entry = 1, remove_entry = -1;
+    int i, o, n;
+
+    acl = (struct acl_accessList *)(v->acl);
+    o = n = ntohl(acl->positive);
+    for (i = 0; i < n; i++)
+       if (ntohl(acl->entries[i].id) == add_admin)
+           add_entry = 0;
+    n = ntohl(acl->negative);
+    for (i = o; i < n + o; i++)
+       if (ntohl(acl->entries[i].id) == add_admin)
+           remove_entry = i;
+
+    if (add_entry) {
+       for (i = (remove_entry < 0) ? o + n : remove_entry; i > o; i--) {
+           acl->entries[i].id = acl->entries[i - 1].id;
+           acl->entries[i].rights = acl->entries[i - 1].rights;
+       }
+       acl->entries[o].id = htonl(add_admin);
+       acl->entries[o].rights =
+           htonl((PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
+                  PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER));
+       acl->positive = htonl(o + 1);
+       if (remove_entry < 0)
+           acl->total = htonl(o + n + 1);
+       else
+           acl->negative = htonl(n - 1);
+    } else if (remove_entry >= 0) {
+       for (i = remove_entry; i < o + n - 1; i++) {
+           acl->entries[i].id = acl->entries[i + 1].id;
+           acl->entries[i].rights = acl->entries[i + 1].rights;
+       }
+       acl->negative = htonl(n - 1);
+       acl->total = htonl(o + n - 1);
+    }
+    return repair_vnode_cb(v, X, refcon);
+}
+
+
+/* Setup for generating a repaired dump */
+static afs_uint32
+setup_repair(void)
+{
+    afs_uint32 r;
+
+    r = xfopen(&repair_output, gendump_path, O_RDWR, 0644);
+    if (r)
+       return r;
+
+    dp.cb_dumphdr = repair_dumphdr_cb;
+    dp.cb_volhdr = repair_volhdr_cb;
+    dp.cb_vnode_dir = repair_vnode_cb;
+    dp.cb_vnode_file = repair_vnode_cb;
+    dp.cb_vnode_link = repair_vnode_cb;
+    dp.cb_vnode_empty = repair_vnode_cb;
+    return 0;
+}
+
+
+/* Main program */
+void
+main(int argc, char **argv)
+{
+    XFILE *X;
+    afs_uint32 r;
+
+    parse_options(argc, argv);
+    initialize_UB_error_table();
+    initialize_UBsp_error_table();
+    initialize_AVds_error_table();
+    r = xfopen(&X, input_path, O_RDONLY, 0);
+    if (r) {
+       afs_com_err(argv0, r, "opening %s", input_path);
+       exit(2);
+    }
+
+    bzero(&dp, sizeof(dp));
+    dp.cb_error = my_error_cb;
+    dp.repair_flags = repairflags;
+    if (X->is_seekable)
+       dp.flags |= DSFLAG_SEEK;
+    else {
+       if (repairflags)
+           fprintf(stderr,
+                   "Repair modes available only for seekable dumps\n");
+       if (printflags & DSPRINT_PATH)
+           fprintf(stderr,
+                   "Path-printing available only for seekable dumps\n");
+       if (repairflags || (printflags & DSPRINT_PATH))
+           exit(1);
+    }
+
+    if (gendump_path && (r = setup_repair())) {
+       afs_com_err(argv0, r, "setting up repair output");
+       xfclose(X);
+       exit(2);
+    }
+
+    if (printflags & DSPRINT_PATH) {
+       u_int64 where;
+
+       dp.print_flags = printflags & DSPRINT_DEBUG;
+       bzero(&phi, sizeof(phi));
+       phi.p = &dp;
+
+       if ((r = xftell(X, &where))
+           || (r = Path_PreScan(X, &phi, 0))
+           || (r = xfseek(X, &where))) {
+           afs_com_err(argv0, r, "- path initialization failed");
+           xfclose(X);
+           exit(2);
+       }
+
+       dp.cb_vnode_dir = print_vnode_path;
+       dp.cb_vnode_file = print_vnode_path;
+       dp.cb_vnode_link = print_vnode_path;
+       dp.cb_vnode_empty = print_vnode_path;
+       dp.cb_vnode_wierd = print_vnode_path;
+    }
+
+    if (add_admin) {
+       dp.cb_vnode_dir = munge_admin_acl;
+    }
+
+    dp.print_flags = printflags;
+    r = ParseDumpFile(X, &dp);
+    if (gendump_path) {
+       if (!r)
+           r = DumpDumpEnd(&repair_output);
+       if (!r)
+           r = xfclose(&repair_output);
+       else
+           xfclose(&repair_output);
+    }
+
+    if (verbose && error_count)
+       fprintf(stderr, "*** %d errors\n", error_count);
+    if (r && !quiet)
+       fprintf(stderr, "*** FAILED: %s\n", afs_error_message(r));
+    exit(0);
+}
diff --git a/src/tools/backuphdr.c b/src/tools/backuphdr.c
new file mode 100644 (file)
index 0000000..68cd6e4
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* backuphdr.c - Parse and print backup system headers */
+
+#include <stdlib.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "stagehdr.h"
+
+afs_uint32
+try_backuphdr(XFILE * X, char *tag, tagged_field * field, afs_uint32 value,
+             tag_parse_info * pi, void *g_refcon, void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    backup_system_header bh;
+    u_int64 where;
+    afs_uint32 r;
+
+    /* Which header should we try (if any)? */
+    switch (*tag) {
+    case STAGE_VERSMIN:
+      r = ParseStageHdr(X, (unsigned char *)tag, &bh);
+       break;
+    default:
+       return DSERR_MAGIC;
+    }
+    if (r)
+       return r;
+
+    /* Do something with it... */
+    if (p->print_flags & DSPRINT_BCKHDR)
+       PrintBackupHdr(&bh);
+    if (p->cb_bckhdr) {
+       r = xftell(X, &where);
+       if (!r && p->cb_bckhdr)
+           r = (p->cb_bckhdr) (&bh, X, p->refcon);
+       if (p->flags & DSFLAG_SEEK) {
+           if (!r)
+               r = xfseek(X, &where);
+           else
+               xfseek(X, &where);
+       }
+    }
+    if (bh.server)
+       free(bh.server);
+    if (bh.part)
+       free(bh.part);
+    if (bh.volname)
+       free(bh.volname);
+    return r;
+}
+
+
+void
+PrintBackupHdr(backup_system_header * hdr)
+{
+    time_t from = hdr->from_date, to = hdr->to_date, dd = hdr->dump_date;
+
+    printf("* BACKUP SYSTEM HEADER\n");
+    printf(" Version:    %d\n", hdr->version);
+    printf(" Volume:     %s (%d)\n", hdr->volname, hdr->volid);
+    printf(" Location:   %s %s\n", hdr->server, hdr->part);
+    printf(" Level:      %d\n", hdr->level);
+    printf(" Range:      %d => %d\n", hdr->from_date, hdr->to_date);
+    printf("          == %s", ctime(&from));
+    printf("          => %s", ctime(&to));
+    printf(" Dump Time:  %d == %s", hdr->dump_date, ctime(&dd));
+    printf(" Dump Flags: 0x%08x\n", hdr->flags);
+#ifdef NATIVE_INT64
+    printf(" Length:     %llu\n", hdr->dumplen);
+#else
+    printf(" Length:     %u,%u\n", hdr->dumplen.hi, hdr->dumplen.lo);
+#endif
+    printf(" File Num:   %d\n", hdr->filenum);
+}
diff --git a/src/tools/directory.c b/src/tools/directory.c
new file mode 100644 (file)
index 0000000..d2f11b4
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998, 2001, 2004 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* directory.c - AFS directory parsing and generation */
+/* See the end of this file for a description of the directory format */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "xf_errs.h"
+#include "dumpfmt.h"
+#include "internal.h"
+
+#include <afs/dir.h>
+
+struct dir_state {
+  unsigned char **dirpages;
+  int npages;
+
+  afs_dir_header *dh;        /* Directory header */
+  afs_dir_page *page;        /* Current page */
+  int pageno;                /* Current page # */
+  int entno;                 /* Current (next avail) entry # */
+  int used;                  /* # entries used in this page */
+};
+
+static afs_dir_page page;
+
+#define bmbyte(bm,x) bm[(x)>>3]
+#define bmbit(x) (1 << ((x) & 7))
+
+#define allocbit(x) (bmbyte(page.header.freebitmap,x) & bmbit(x))
+#define setallocbit(bm,x) (bmbyte(bm,x) |= bmbit(x))
+
+#define DPHE (DHE + 1)
+
+/* Hash function used in AFS directories.  */
+static int namehash(char *name, int buckets, int seed)
+{
+  int hval = seed, tval;
+
+  while (*name) hval = (hval * 173) + *name++;
+  tval = hval & (buckets - 1);
+  return tval ? hval < 0 ? buckets - tval : tval : 0;
+}
+
+#if 0
+static void fixup(char *name, int l)
+{
+  name += 16;
+  l -= 15;
+
+  while (l-- > 0) {
+    name[0] = name[4];
+    name++;
+  }
+}
+#endif
+
+afs_uint32 parse_directory(XFILE *X, dump_parser *p, afs_vnode *v,
+                        afs_uint32 size, int toeof)
+{
+  afs_dir_entry de;
+  int pgno, i, l, n;
+  afs_int32 r;
+  u_int64 where;
+
+  if (p->print_flags & DSPRINT_DIR) {
+    printf("  VNode      Uniqifier   Name\n");
+    printf("  ========== ==========  ==============================\n");
+  }
+  if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where))) return r;
+  for (pgno = 0; toeof || size; pgno++, size -= (toeof ? 0 : AFS_PAGESIZE)) {
+    if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where))) return r;
+    if ((r = xfread(X, &page, AFS_PAGESIZE))) {
+      if (toeof && r == ERROR_XFILE_EOF) break;
+      return r;
+    }
+    if ((p->flags & DSFLAG_SEEK) && (r = xftell(X, &where))) return r;
+    if (page.header.tag != htons(1234)) {
+      if (p->cb_error)
+        (p->cb_error)(DSERR_MAGIC, 1, p->err_refcon,
+                      "Invalid page tag (%d) in page %d",
+                      ntohs(page.header.tag), pgno);
+      return DSERR_MAGIC;
+    }
+    for (i = (pgno ? 1 : DPHE); i < EPP; i++) {
+      if (!allocbit(i)) continue;
+      if (page.entry[i].flag != FFIRST) {
+        if (p->cb_error)
+          (p->cb_error)(DSERR_MAGIC, 0, p->err_refcon,
+                        "Invalid entry flag %d in entry %d/%d; skipping...",
+                        page.entry[i].flag, pgno, i);
+        continue;
+      }
+      n = (EPP - i - 1) * 32 + 16;
+      for (l = 0; n && page.entry[i].name[l]; l++, n--);
+      if (page.entry[i].name[l]) {
+        if (p->cb_error)
+          (p->cb_error)(DSERR_FMT, 0, p->err_refcon,
+                        "Filename too long in entry %d/%d; skipping page",
+                        pgno, i);
+        break;
+      }
+/*    fixup(page.entry[i].name, l); */
+      if (pgno) de.slot = i - 1 + (pgno - 1) * (EPP - 1) + (EPP - DPHE);
+      else de.slot = i - DPHE;
+      de.name  = page.entry[i].name;
+      de.vnode = ntohl(page.entry[i].vnode);
+      de.uniq  = ntohl(page.entry[i].vunique);
+      if (p->print_flags & DSPRINT_DIR)
+        printf("  %10d %10d  %s\n", de.vnode, de.uniq, de.name);
+      if (p->cb_dirent) {
+        r = (p->cb_dirent)(v, &de, X, p->refcon);
+      }
+      if (p->cb_dirent && (r = (p->cb_dirent)(v, &de, X, p->refcon)))
+        return r;
+      i += ((l + 16) >> 5);
+    }
+  }
+  if ((p->flags & DSFLAG_SEEK) && (r = xfseek(X, &where))) return r;
+  return 0;
+}
+
+
+afs_uint32 ParseDirectory(XFILE *X, dump_parser *p, afs_uint32 size, int toeof)
+{
+  afs_uint32 r;
+
+  r = parse_directory(X, p, 0, size, toeof);
+  return r;
+}
+
+
+typedef struct {
+  char **name;
+  afs_uint32 *vnode;
+  afs_uint32 *vuniq;
+} dirlookup_stat;
+
+
+static afs_uint32 dirlookup_cb(afs_vnode *v, afs_dir_entry *de,
+                            XFILE *X, void *refcon)
+{
+  dirlookup_stat *s = (dirlookup_stat *)refcon;
+
+  if (s->name && s->name[0]) {                  /* Search by filename */
+    if (strcmp(de->name, s->name[0])) return 0; /* Not it! */
+    if (s->vnode) s->vnode[0] = de->vnode;
+    if (s->vuniq) s->vuniq[0] = de->uniq;
+  } else if (s->vnode) {                        /* Search by vnode */
+    if (de->vnode != s->vnode[0]) return 0;     /* Not it! */
+    if (s->name) {
+      s->name[0] = (char *)malloc(strlen(de->name) + 1);
+      if (!s->name[0]) return ENOMEM;
+      strcpy(s->name[0], de->name);
+    }
+    if (s->vuniq) s->vuniq[0] = de->uniq;
+  }
+  return DSERR_DONE;
+}
+
+
+/* Look up an entry in a directory, by name or vnode.
+ * If *name is NULL, we are looking up by vnode.
+ * Otherwise, we are looking for a filename.
+ * In any event, any of name, vnode, vuniq that are
+ * neither NULL nor the search key are filled in on
+ * success.
+ *
+ * Call this with X pointing to the start of the directory,
+ * and size set to the length of the directory.
+ * Returns 0 on success, whether or not the entry is found.
+ */
+afs_uint32 DirectoryLookup(XFILE *X, dump_parser *p, afs_uint32 size,
+                    char **name, afs_uint32 *vnode, afs_uint32 *vuniq)
+{
+  dump_parser my_p;
+  dirlookup_stat my_s;
+  afs_uint32 r;
+
+  memset(&my_s, 0, sizeof(my_s));
+  my_s.name  = name;
+  my_s.vnode = vnode;
+  my_s.vuniq = vuniq;
+
+  memset(&my_p, 0, sizeof(my_p));
+  my_p.refcon = (void *)&my_s;
+  my_p.err_refcon = p->err_refcon;
+  my_p.cb_error = p->cb_error;
+  my_p.cb_dirent  = dirlookup_cb;
+
+  r = parse_directory(X, &my_p, 0, size, 0);
+  if (!r) r = DSERR_DONE;
+  return handle_return(r, X, 0, p);
+}
+
+
+static int allocpage(struct dir_state *ds, int reserve)
+{
+  unsigned char **dirpages;
+  int i;
+
+  dirpages = malloc((ds->npages + 1) * sizeof(unsigned char *));
+  if (!dirpages) return ENOMEM;
+  if (ds->dirpages) {
+    memcpy(dirpages, ds->dirpages, ds->npages * sizeof(unsigned char *));
+    free(ds->dirpages);
+  }
+  ds->dirpages = dirpages;
+
+  ds->dirpages[ds->npages] = malloc(AFS_PAGESIZE);
+  if (!ds->dirpages[ds->npages]) return ENOMEM;
+  ds->pageno = ds->npages++;
+
+  ds->page = (afs_dir_page *)(ds->dirpages[ds->pageno]);
+  memset(ds->page, 0, AFS_PAGESIZE);
+  ds->page->header.tag = htons(AFS_DIR_MAGIC);
+  ds->entno = ds->used = reserve;
+  for (i = 0; i < reserve; i++)
+    setallocbit(ds->page->header.freebitmap, i);
+  return 0;
+}
+
+
+afs_uint32 Dir_Init(struct dir_state **dsp)
+{
+  afs_uint32 r;
+
+  *dsp = malloc(sizeof(struct dir_state));
+  if (!*dsp) return ENOMEM;
+  memset(*dsp, 0, sizeof(struct dir_state));
+  if ((r = allocpage(*dsp, DPHE))) return r;
+  (*dsp)->dh = (afs_dir_header *)((*dsp)->page);
+  return 0;
+}
+
+
+afs_uint32 Dir_AddEntry(struct dir_state *ds, char *name,
+                        afs_uint32 vnode, afs_uint32 unique)
+{
+  afs_uint32 r;
+  int l = strlen(name) + 1;
+  int ne = l > 16 ? 1 + ((l - 16) / 32) + !!((l - 16) % 32) : 1;
+  int hash = namehash(name, NHASHENT, 0);
+
+  if (ne > EPP - 1) return ENAMETOOLONG;
+  if (ds->entno + ne > EPP) {
+    if (ds->pageno < 128) ds->dh->allomap[ds->pageno] = ds->used;
+    if ((r = allocpage(ds, 1))) return r;
+  }
+  ds->page->entry[ds->entno].flag    = FFIRST;
+  ds->page->entry[ds->entno].next    = ds->dh->hash[hash];
+  ds->page->entry[ds->entno].vnode   = htonl(vnode);
+  ds->page->entry[ds->entno].vunique = htonl(unique);
+  strcpy(ds->page->entry[ds->entno].name, name);
+  ds->dh->hash[hash] = htons((ds->pageno * EPP) + ds->entno);
+  while (ne--) {
+    setallocbit(ds->page->header.freebitmap, ds->entno);
+    ds->used++;
+    ds->entno++;
+  }
+  return 0;
+}
+
+
+afs_uint32 Dir_Finalize(struct dir_state *ds)
+{
+  int pages = ds->pageno + 1;
+
+  if (ds->pageno < 128) ds->dh->allomap[ds->pageno] = ds->used;
+  ds->dh->pagehdr.pgcount = htons(pages);
+  return 0;
+}
+
+
+afs_uint32 Dir_EmitData(struct dir_state *ds, XFILE *X, int dotag)
+{
+  afs_uint32 r, size;
+  int i;
+
+  size = ds->npages * AFS_PAGESIZE;
+  if (dotag && (r = WriteTagInt32(X, VTAG_DATA, size))) return r;
+  for (i = 0; i < ds->npages; i++) {
+    if ((r = xfwrite(X, ds->dirpages[i], AFS_PAGESIZE))) return r;
+  }
+  return 0;
+}
+
+
+afs_uint32 Dir_Free(struct dir_state *ds)
+{
+  int i;
+
+  for (i = 0; i < ds->npages; i++)
+    free(ds->dirpages[i]);
+  free(ds->dirpages);
+  free(ds);
+  return 0;
+}
+
+
+/* AFS directory format:
+ * AFS directories are stored in volume dumps in exactly the same format
+ * that is used on disk, which makes them relatively easy to dump and restore,
+ * but means we have to do some work to interpret them.
+ *
+ * The ACL for a directory is stored on disk in the last part of a "large"
+ * (directory) vnode.  This part of the vnode, which has fixed size
+ * SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE, is copied directly into
+ * the dump file with a tag of 'A' (VTAG_ACL).  The structure of this
+ * section is described in <afs/acl.h>.
+ *
+ * The name-to-vnode mappings are also stored exactly as they appear on
+ * disk, using the file data ('f') attribute.  As usual, this attribute
+ * consists of a 32-bit number containing the size, immediately followed
+ * by the data itself.  The interesting structures and constants are
+ * defined in <afs/dir.h>
+ *
+ * A directory consists of one or more 'pages', each of which is 2K
+ * (AFS_PAGESIZE).  Each page contains EPP (currently 64) 'entries', each
+ * of which is 32 bytes.  The first page begins with a DirHeader, which
+ * is DHE entries long, and includes a PageHeader.  All other pages begin
+ * with just a PageHeader, which is 1 entry long.  Every other entry is
+ * a DirEntry, a DirXEntry (name extension), or unused.
+ *
+ * A Page Header contains the following elements:
+ * - pgcount    contains a count of the number of pages in the directory,
+ *              if the directory is new-style (>128 pages), or 0 if it is
+ *              old-style.  This field is meaningful only in the Dir Header.
+ * - tag        a magic number, which must be 1234
+ * - freecount  apparently unused
+ * - freebitmap A bitmap of free entries.  Each byte corresponds to 8
+ *              entries, with the least significant bit referring to the
+ *              first of those.  Each bit is set iff the corresponding
+ *              entry is allocated.  Entries used by the page and dir
+ *              headers are considered allocated.
+ *
+ * A Dir Header consists of a Page Header, followed by an allocation map
+ * and hash table.  The allocation map contains one byte for each of the
+ * first 128 pages; that byte contains the number of entries in that page
+ * that are allocated.  Every page that actually exists has at peast one
+ * entry allocated (the Page Header); if a byte in this map is 0, it means
+ * that the page does not yet exist.
+ *
+ * Each bucket in the hash table is a linked list, using 'blob numbers'
+ * as pointers.  A blob number is defined as (page# * EPP) + entry#.
+ * The head of each chain is kept in the hash table, and the next pointers
+ * are kept in the 'next' entry of each directory.
+ *
+ * Directory entries themselves contain the following elements:
+ * - flag    Set to FFIRST iff this is the first blob in an entry
+ *           (otherwise it will be a name continuation).  This is
+ *           probably not reliable.
+ * - length  Unused
+ * - next    Pointer to the next element in this hash chain
+ * - fid     FileID (vnode and uniquifier)
+ * - name    Filename (null-terminated)
+ */
diff --git a/src/tools/dump.c b/src/tools/dump.c
new file mode 100644 (file)
index 0000000..d657f35
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* dump.c - Write out parts of a volume dump */
+
+#include "dumpscan.h"
+#include "dumpfmt.h"
+
+#define COPYBUFSIZE 65536
+
+afs_uint32
+DumpDumpHeader(XFILE * OX, afs_dump_header * hdr)
+{
+    afs_uint32 r;
+
+    if ((r = WriteTagInt32Pair(OX, TAG_DUMPHEADER, hdr->magic, hdr->version)))
+       return r;
+
+    if (hdr->field_mask & F_DUMPHDR_VOLID) {
+       if ((r = WriteTagInt32(OX, DHTAG_VOLID, hdr->volid)))
+           return r;
+    }
+    if (hdr->field_mask & F_DUMPHDR_VOLNAME) {
+       if ((r = WriteByte(OX, DHTAG_VOLNAME)))
+           return r;
+       if ((r = WriteString(OX, hdr->volname)))
+           return r;
+    }
+    if (hdr->field_mask & (F_DUMPHDR_FROM | F_DUMPHDR_TO)) {
+       if ((r = WriteTagInt16(OX, DHTAG_DUMPTIMES, 2)))
+           return r;
+       if ((r = WriteInt32(OX, (hdr->field_mask & F_DUMPHDR_FROM))
+                          ? hdr->from_date : 0))
+           return r;
+       if ((r = WriteInt32(OX, (hdr->field_mask & F_DUMPHDR_TO)
+                           ? hdr->to_date : time(0))))
+           return r;
+    }
+    return 0;
+}
+
+
+afs_uint32
+DumpVolumeHeader(XFILE * OX, afs_vol_header * hdr)
+{
+    afs_uint32 r;
+    int i;
+
+    if ((r = WriteByte(OX, TAG_VOLHEADER)))
+       return r;
+
+    if (hdr->field_mask & F_VOLHDR_VOLID) {
+       if ((r = WriteTagInt32(OX, VHTAG_VOLID, hdr->volid)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_VOLVERS) {
+       if ((r = WriteTagInt32(OX, VHTAG_VERS, hdr->volvers)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_VOLNAME) {
+       if ((r = WriteByte(OX, VHTAG_VOLNAME)))
+           return r;
+       if ((r = WriteString(OX, hdr->volname)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_INSERV) {
+       if ((r = WriteTagByte(OX, VHTAG_INSERV, hdr->flag_inservice)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_BLESSED) {
+       if ((r = WriteTagByte(OX, VHTAG_BLESSED, hdr->flag_blessed)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_VOLUNIQ) {
+       if ((r = WriteTagInt32(OX, VHTAG_VUNIQ, hdr->voluniq)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_VOLTYPE) {
+       if ((r = WriteTagByte(OX, VHTAG_TYPE, hdr->voltype)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_PARENT) {
+       if ((r = WriteTagInt32(OX, VHTAG_PARENT, hdr->parent_volid)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_CLONE) {
+       if ((r = WriteTagInt32(OX, VHTAG_CLONE, hdr->clone_volid)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_MAXQ) {
+       if ((r = WriteTagInt32(OX, VHTAG_MAXQUOTA, hdr->maxquota)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_MINQ) {
+       if ((r = WriteTagInt32(OX, VHTAG_MINQUOTA, hdr->minquota)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_DISKUSED) {
+       if ((r = WriteTagInt32(OX, VHTAG_DISKUSED, hdr->diskused)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_NFILES) {
+       if ((r = WriteTagInt32(OX, VHTAG_FILECNT, hdr->nfiles)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_ACCOUNT) {
+       if ((r = WriteTagInt32(OX, VHTAG_ACCOUNT, hdr->account_no)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_OWNER) {
+       if ((r = WriteTagInt32(OX, VHTAG_OWNER, hdr->owner)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_CREATE_DATE) {
+       if ((r = WriteTagInt32(OX, VHTAG_CREAT, hdr->create_date)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_ACCESS_DATE) {
+       if ((r = WriteTagInt32(OX, VHTAG_ACCESS, hdr->access_date)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_UPDATE_DATE) {
+       if ((r = WriteTagInt32(OX, VHTAG_UPDATE, hdr->update_date)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_EXPIRE_DATE) {
+       if ((r = WriteTagInt32(OX, VHTAG_EXPIRE, hdr->expire_date)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_BACKUP_DATE) {
+       if ((r = WriteTagInt32(OX, VHTAG_BACKUP, hdr->backup_date)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_OFFLINE_MSG) {
+       if ((r = WriteTagInt32(OX, VHTAG_OFFLINE, *hdr->offline_msg)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_MOTD) {
+       if ((r = WriteTagInt32(OX, VHTAG_MOTD, *hdr->motd_msg)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_WEEKUSE) {
+       if ((r = WriteTagInt16(OX, VHTAG_WEEKUSE, 7)))
+           return r;
+       for (i = 0; i < 7; i++)
+           if ((r = WriteInt32(OX, hdr->weekuse[i])))
+               return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_DAYUSE_DATE) {
+       if ((r = WriteTagInt32(OX, VHTAG_DUDATE, hdr->dayuse_date)))
+           return r;
+    }
+    if (hdr->field_mask & F_VOLHDR_DAYUSE) {
+       if ((r = WriteTagInt32(OX, VHTAG_DAYUSE, hdr->dayuse)))
+           return r;
+    }
+    return 0;
+}
+
+
+afs_uint32
+DumpVNode(XFILE * OX, afs_vnode * v)
+{
+    afs_uint32 r;
+
+    if ((r = WriteTagInt32Pair(OX, TAG_VNODE, v->vnode, v->vuniq)))
+       return r;
+
+    if (v->field_mask & F_VNODE_TYPE) {
+       if ((r = WriteTagByte(OX, VTAG_TYPE, v->type)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_NLINKS) {
+       if ((r = WriteTagInt16(OX, VTAG_NLINKS, v->nlinks)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_DVERS) {
+       if ((r = WriteTagInt32(OX, VTAG_DVERS, v->datavers)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_SDATE) {
+       if ((r = WriteTagInt32(OX, VTAG_SERVER_DATE, v->server_date)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_AUTHOR) {
+       if ((r = WriteTagInt32(OX, VTAG_AUTHOR, v->author)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_OWNER) {
+       if ((r = WriteTagInt32(OX, VTAG_OWNER, v->owner)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_GROUP) {
+       if ((r = WriteTagInt32(OX, VTAG_GROUP, v->group)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_MODE) {
+       if ((r = WriteTagInt16(OX, VTAG_MODE, v->mode)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_PARENT) {
+       if ((r = WriteTagInt32(OX, VTAG_PARENT, v->parent)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_CDATE) {
+       if ((r = WriteTagInt32(OX, VTAG_CLIENT_DATE, v->client_date)))
+           return r;
+    }
+    if (v->field_mask & F_VNODE_ACL) {
+       if ((r = WriteByte(OX, VTAG_ACL)))
+           return r;
+       if ((r =
+           xfwrite(OX, v->acl,
+                   SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE)))
+           return r;
+    }
+    return 0;
+}
+
+
+afs_uint32
+DumpVNodeData(XFILE * OX, char *buf, afs_uint32 size)
+{
+    afs_uint32 r;
+
+    if ((r = WriteTagInt32(OX, VTAG_DATA, size)))
+       return r;
+    if ((r = xfwrite(OX, buf, size)))
+       return r;
+    return 0;
+}
+
+
+afs_uint32
+CopyVNodeData(XFILE * OX, XFILE * X, afs_uint32 size)
+{
+    afs_uint32 r, n;
+    static char buf[COPYBUFSIZE];
+
+    if ((r = WriteTagInt32(OX, VTAG_DATA, size)))
+       return r;
+    while (size) {
+       n = (size > COPYBUFSIZE) ? COPYBUFSIZE : size;
+       if ((r = xfread(X, buf, n)))
+           return r;
+       if ((r = xfwrite(OX, buf, n)))
+           return r;
+       size -= n;
+    }
+    return 0;
+}
+
+
+afs_uint32
+DumpDumpEnd(XFILE * OX)
+{
+    afs_uint32 r;
+
+    if ((r = WriteTagInt32(OX, TAG_DUMPEND, DUMPENDMAGIC)))
+       return r;
+    return 0;
+}
diff --git a/src/tools/dumpfmt.h b/src/tools/dumpfmt.h
new file mode 100644 (file)
index 0000000..a6b6d1b
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998, 2001 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* dumpfmt.h - Description of AFS dump format */
+
+#ifndef _DUMPFMT_H_
+#define _DUMPFMT_H_
+
+#include "intNN.h"
+
+/* AFS dump file format:
+ * All data in AFS dumps is tagged; that is, each data item is preceeded
+ * by a 1-byte tag which identifies what the data item is.  There is no
+ * explicit mention of what the data type is, but the type of each possible
+ * data item (and thus, each possible tag) is fixed.  Usually this is
+ * a relatively simple, fixed amount of data (byte, short, word), but
+ * sometimes it is more complex.
+ *
+ * There is some amount of structure to an AFS volume dump.  Basically,
+ * you get a dump header, followed by a volume header, followed by some
+ * vnodes, followed by a dump end.  Each of these items (header, vnode,
+ * dump end) consists of a tag, a fixed amount of required information,
+ * and 0 or more tagged attributes (except dump-end, which has no attributes).
+ *
+ * Vnodes, in turn, are usually listed in a particular order.  First, we
+ * list all the directory vnodes in the volume, in increasing order by
+ * vnode.  Then, we list all the file vnodes, again in increasing order.
+ * Directory vnodes must have a complete set of attributes and data, but
+ * in an incremental dump, file vnodes may have no attributes if the vnode
+ * has not changed since the reference date.
+ *
+ * The primary purpose of this file is to define the tags and some magic
+ * numbers.  There is also some information that is defined in the Transarc
+ * provided header files.
+ */
+
+
+/** MAGIC NUMBERS **/
+#define DUMPVERSION     1
+#define DUMPBEGINMAGIC  0xb3a11322
+#define DUMPENDMAGIC    0x3a214b6e
+
+
+/** TOP-LEVEL TAGS **/
+#define TAG_DUMPHEADER  1
+#define TAG_VOLHEADER   2
+#define TAG_VNODE       3
+#define TAG_DUMPEND     4
+
+
+/** DUMP HEADER TAGS **/
+#define DHTAG_VOLNAME    'n'
+#define DHTAG_VOLID      'v'
+#define DHTAG_DUMPTIMES  't'
+
+
+/** VOLUME HEADER TAGS **/
+#define VHTAG_VOLID      'i'
+#define VHTAG_VERS       'v'
+#define VHTAG_VOLNAME    'n'
+#define VHTAG_INSERV     's'
+#define VHTAG_BLESSED    'b'
+#define VHTAG_VUNIQ      'u'
+#define VHTAG_TYPE       't'
+#define VHTAG_PARENT     'p'
+#define VHTAG_CLONE      'c'
+#define VHTAG_MAXQUOTA   'q'
+#define VHTAG_MINQUOTA   'm'
+#define VHTAG_DISKUSED   'd'
+#define VHTAG_FILECNT    'f'
+#define VHTAG_ACCOUNT    'a'
+#define VHTAG_OWNER      'o'
+#define VHTAG_CREAT      'C'
+#define VHTAG_ACCESS     'A'
+#define VHTAG_UPDATE     'U'
+#define VHTAG_EXPIRE     'E'
+#define VHTAG_BACKUP     'B'
+#define VHTAG_OFFLINE    'O'
+#define VHTAG_MOTD       'M'
+#define VHTAG_WEEKUSE    'W'
+#define VHTAG_DUDATE     'D'
+#define VHTAG_DAYUSE     'Z'
+
+
+/** VNODE TAGS **/
+#define VTAG_TYPE        't'
+#define VTAG_NLINKS      'l'
+#define VTAG_DVERS       'v'
+#define VTAG_CLIENT_DATE 'm'
+#define VTAG_AUTHOR      'a'
+#define VTAG_OWNER       'o'
+#define VTAG_GROUP       'g'
+#define VTAG_MODE        'b'
+#define VTAG_PARENT      'p'
+#define VTAG_SERVER_DATE 's'
+#define VTAG_ACL         'A'
+#define VTAG_DATA        'f'
+
+
+#define AFS_DIR_MAGIC    1234
+#define AFS_DIR_EPP        64
+#define AFS_DIR_MAXPAGES  128
+#define AFS_DIR_NHASH     128
+
+typedef struct {
+  afs_uint16 pgcount;
+  afs_uint16 tag;
+  char freecount;
+  char freebitmap[AFS_DIR_EPP/8];
+  char padding[32 - (5 + AFS_DIR_EPP/8)];
+} afs_dir_pagehdr;
+
+typedef struct {
+  afs_dir_pagehdr pagehdr;
+  char allomap[AFS_DIR_MAXPAGES];
+  afs_uint16 hash[AFS_DIR_NHASH];
+} afs_dir_header;
+
+typedef struct {
+  char flag;
+  char length;
+  afs_uint16 next;
+  afs_uint32 vnode;
+  afs_uint32 vunique;
+  char name[16];
+  char padding[4];
+} afs_dir_direntry;
+
+typedef union {
+  afs_dir_pagehdr header;
+  afs_dir_direntry entry[AFS_DIR_EPP];
+} afs_dir_page;
+
+#endif /* _DUMPFMT_H_ */
diff --git a/src/tools/dumpscan.h b/src/tools/dumpscan.h
new file mode 100644 (file)
index 0000000..a0ebe39
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998, 2001, 2003 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* dumpscan.h - Public interface */
+
+#ifndef _DUMPSCAN_H_
+#define _DUMPSCAN_H_
+
+#include "intNN.h"
+#include "xfiles.h"
+
+#include <lock.h>
+#include <afs/afsint.h>
+#include <afs/nfs.h>
+#include <afs/ihandle.h>
+#include <afs/vnode.h>
+
+/* Random useful types */
+typedef struct tagged_field tagged_field;
+typedef struct tag_parse_info tag_parse_info;
+typedef afs_uint32 (*tag_parser)(XFILE *, unsigned char *, tagged_field *,
+                              afs_uint32, tag_parse_info *, void *, void *);
+typedef struct dir_state dir_state;
+
+/* Error codes used within dumpscan.
+ * Any of the routines declared below, or callbacks used by them,
+ * may signal a system error by returning the error number, or
+ * some other error by returning a com_err code.  Note that
+ * ParseTaggedData does _not_ return DSERR_TAG; instead, it returns
+ * 0, assuming the tag will be handled at a higher level.
+ *
+ * In addition, these errors may be reported to the caller of
+ * ParseDumpFile using the error callback.  Such reports will be
+ * issued whether or not error recovery is possible or attempted.
+ *
+ * NB: These errors are now in dumpscan_errs.h
+ */
+
+
+/* Backup system dump header */
+/* Right now, this looks a lot like an old stage header.  Eventually, it
+ * should contain enough fields to fully represent headers from old or
+ * new stage, Transarc, or other backup systems, and the appropriate read
+ * functions should extract as much data as possible from the actual file
+ * to fill this in. */
+typedef struct {
+  afs_uint32 version;
+  afs_uint32 from_date;
+  afs_uint32 to_date;
+  afs_uint32 dump_date;
+  afs_uint32 filenum;
+  unsigned char *server;
+  unsigned char *part;
+  unsigned char *volname;
+  afs_uint32 volid;
+  u_int64 dumplen;
+  afs_uint32 level;
+  afs_uint32 magic;
+  afs_uint32 cksum;
+  afs_uint32 flags;
+} backup_system_header;
+
+
+/** AFS dump header **/
+#define F_DUMPHDR_VOLID       0x00000001
+#define F_DUMPHDR_VOLNAME     0x00000002
+#define F_DUMPHDR_FROM        0x00000004
+#define F_DUMPHDR_TO          0x00000008
+typedef struct {
+  u_int64 offset;              /* Where in the input stream is it? */
+  afs_uint32 field_mask;       /* What fields are present? */
+  afs_uint32 magic;            /* Magic number */
+  afs_uint32 version;          /* Dump format version */
+  afs_uint32 volid;            /* VolID of volume in dump */
+  unsigned char *volname;      /* Name of volume in dump */
+  afs_uint32 from_date;        /* Reference date */
+  afs_uint32 to_date;          /* Date of dump */
+} afs_dump_header;
+
+
+/** AFS volume header **/
+#define F_VOLHDR_VOLID        0x00000001
+#define F_VOLHDR_VOLVERS      0x00000002
+#define F_VOLHDR_VOLNAME      0x00000004
+#define F_VOLHDR_INSERV       0x00000008
+#define F_VOLHDR_BLESSED      0x00000010
+#define F_VOLHDR_VOLUNIQ      0x00000020
+#define F_VOLHDR_VOLTYPE      0x00000040
+#define F_VOLHDR_PARENT       0x00000080
+#define F_VOLHDR_CLONE        0x00000100
+#define F_VOLHDR_MAXQ         0x00000200
+#define F_VOLHDR_MINQ         0x00000400
+#define F_VOLHDR_DISKUSED     0x00000800
+#define F_VOLHDR_NFILES       0x00001000
+#define F_VOLHDR_ACCOUNT      0x00002000
+#define F_VOLHDR_OWNER        0x00004000
+#define F_VOLHDR_CREATE_DATE  0x00008000
+#define F_VOLHDR_ACCESS_DATE  0x00010000
+#define F_VOLHDR_UPDATE_DATE  0x00020000
+#define F_VOLHDR_EXPIRE_DATE  0x00040000
+#define F_VOLHDR_BACKUP_DATE  0x00080000
+#define F_VOLHDR_OFFLINE_MSG  0x00100000
+#define F_VOLHDR_MOTD         0x00200000
+#define F_VOLHDR_WEEKUSE      0x00400000
+#define F_VOLHDR_DAYUSE       0x00800000
+#define F_VOLHDR_DAYUSE_DATE  0x01000000
+typedef struct {
+  u_int64 offset;              /* Where in the input stream is it? */
+  afs_uint32 field_mask;       /* What fields are present? */
+  afs_uint32 volid;            /* Volume ID */
+  afs_uint32 volvers;          /* ?? */
+  unsigned char *volname;      /* Volume Name */
+  int     flag_inservice;      /* Inservice flag (0 or not) */
+  int     flag_blessed;        /* Blessed to come online (0 or not) */
+  afs_uint32 voluniq;          /* Volume uniquifier */
+  int     voltype;             /* Volume type */
+  afs_uint32 parent_volid;     /* Parent volume ID */
+  afs_uint32 clone_volid;      /* Clone volume ID */
+  afs_uint32 maxquota;         /* Max quota */
+  afs_uint32 minquota;         /* Min quota (obsolete) */
+  afs_uint32 diskused;         /* Disk blocks used */
+  afs_uint32 nfiles;           /* Number of files in volume */
+  afs_uint32 account_no;       /* Account number (unused) */
+  afs_uint32 owner;            /* Volume owner */
+  afs_uint32 create_date;      /* Creation date of this copy */
+  afs_uint32 access_date;      /* Last access */
+  afs_uint32 update_date;      /* Last modification */
+  afs_uint32 expire_date;      /* Expiration (unused) */
+  afs_uint32 backup_date;      /* Last backup clone */
+  unsigned char *offline_msg;  /* Offline message */
+  unsigned char *motd_msg;     /* Volume MOTD */
+  afs_uint32 weekuse[7];       /* Weekuse data */
+  afs_uint32 dayuse;           /* # accesses in last day */
+  afs_uint32 dayuse_date;      /* Date for which dayuse is valid */
+} afs_vol_header;
+
+
+/** AFS vnode **/
+#define F_VNODE_TYPE          0x00000001
+#define F_VNODE_NLINKS        0x00000002
+#define F_VNODE_PARENT        0x00000004
+#define F_VNODE_DVERS         0x00000008
+#define F_VNODE_AUTHOR        0x00000010
+#define F_VNODE_OWNER         0x00000020
+#define F_VNODE_GROUP         0x00000040
+#define F_VNODE_MODE          0x00000080
+#define F_VNODE_CDATE         0x00000100
+#define F_VNODE_SDATE         0x00000200
+#define F_VNODE_ACL           0x00000400
+#define F_VNODE_SIZE          0x00000800 /* Set if size is present */
+#define F_VNODE_DATA          0x00001000 /* Set if size nonzero and data present */
+#define F_VNODE_PARTIAL       0x00002000 /* Partial vnode continuation (no header) */
+#define F_VNODE_LINK_TARGET   0x00004000 /* Symlink target present */
+typedef struct {
+  u_int64 offset;              /* Where in the input stream is it? */
+  afs_uint32 field_mask;       /* What fields are present? */
+  afs_uint32 vnode;            /* Vnode number */
+  afs_uint32 vuniq;            /* Uniquifier */
+  int     type;                /* Vnode type */
+  afs_uint16 nlinks;           /* Number of links (should be in 1 dir!) */
+  afs_uint32 parent;           /* Parent vnode */
+  afs_uint32 datavers;         /* Data version */
+  afs_uint32 author;           /* Last writer */
+  afs_uint32 owner;            /* Owner UID */
+  afs_uint32 group;            /* Owning group */
+  afs_uint16 mode;             /* UNIX mode bits */
+  afs_uint32 client_date;      /* Last modified date from client */
+  afs_uint32 server_date;      /* Last modified date on server */
+  afs_uint32 size;             /* Size of data */
+  u_int64 d_offset;            /* Where in the input stream is the data? */
+  char *link_target;           /* Target of symbolic link */
+  unsigned char acl[SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE];
+} afs_vnode;
+
+
+/** AFS directory entry **/
+typedef struct {
+  int  slot;                /* Directory slot # (info only) */
+  char *name;               /* Name of entry */
+  afs_uint32 vnode;            /* Vnode number */
+  afs_uint32 uniq;             /* Uniquifier */
+} afs_dir_entry;
+
+
+/** Tagged field definitions **/
+#define DKIND_NOOP      0x00  /* No data */
+#define DKIND_BYTE      0x10  /* 1 byte  - decimal */
+#define DKIND_HEX8      0x11  /* 1 byte  - hex */
+#define DKIND_CHAR      0x12  /* 1 byte  - character */
+#define DKIND_FLAG      0x13  /* 1 byte  - true/false */
+#define DKIND_INT16     0x20  /* 2 bytes - decimal */
+#define DKIND_HEX16     0x21  /* 2 bytes - hex */
+#define DKIND_OCT16     0x28  /* 2 bytes - octal */
+#define DKIND_INT32     0x30  /* 4 bytes - decimal */
+#define DKIND_HEX32     0x31  /* 4 bytes - hex */
+#define DKIND_TIME      0x32  /* 4 bytes - time */
+#define DKIND_OCT32     0x38  /* 4 bytes - octal */
+#define DKIND_STRING    0x40  /* ASCIIZ string */
+#define DKIND_SPECIAL   0x50  /* Custom parser */
+#define DKIND_MASK     (~0x0f)
+struct tag_parse_info {
+  void *err_refcon;
+  afs_uint32 (*cb_error)(afs_uint32, int, void *, char *, ...);
+  afs_uint32 flags;
+#define TPFLAG_SKIP   0x0001
+#define TPFLAG_RSKIP  0x0002
+  int shift_offset;
+  u_int64 shift_start;
+};
+struct tagged_field {
+  char tag;        /* Tag character */
+  int  kind;       /* Kind of object */
+  char *label;     /* Label to use (for debugging) */
+  tag_parser func; /* Parser function (for DKIND_SPECIAL) */
+  void *refptr;    /* Reference pointer (for parser's use) */
+  int  refarg;     /* Reference argument (for parser's use) */
+};
+
+
+/** Control structure for parsing volume dumps **/
+typedef struct {
+  /* Callback functions:
+   * Whenever a "complex" object is parsed, we call a callback function.
+   * The callback gets a pointer to the complex object, the file pointer
+   * for the dump we're parsing, and the value of refcon in this structure.
+   * Callbacks should return 0 if all is well, non-0 to abort the dump.
+   * By convention, positive numbers should be errno values, and negative
+   * numbers can be used for other things.  It is OK to _try_ to seek anywhere
+   * in the file.  Beware, though, that the input is not always seekable.
+   * Also, note that the structures passed to these callbacks are going to
+   * go away after the callback returns.  There is no way to prevent this;
+   * make a copy if you want one.
+   */
+  void *refcon;
+  afs_uint32 (*cb_bckhdr)(backup_system_header *, XFILE *, void *); /* Backup Header   */
+  afs_uint32 (*cb_dumphdr)(afs_dump_header *, XFILE *, void *);     /* Dump Header     */
+  afs_uint32 (*cb_volhdr)(afs_vol_header *, XFILE *, void *);       /* Volume Header   */
+  afs_uint32 (*cb_vnode_dir)(afs_vnode *, XFILE *, void *);         /* Directory Vnode */
+  afs_uint32 (*cb_vnode_file)(afs_vnode *, XFILE *, void *);        /* File Vnode      */
+  afs_uint32 (*cb_vnode_link)(afs_vnode *, XFILE *, void *);        /* Symlink Vnode   */
+  afs_uint32 (*cb_vnode_empty)(afs_vnode *, XFILE *, void *);       /* vnode+uniq only */
+  afs_uint32 (*cb_vnode_wierd)(afs_vnode *, XFILE *, void *);       /* Unknown type    */
+  afs_uint32 (*cb_file_data)(afs_vnode *, XFILE *, void *);         /* File Data       */
+  afs_uint32 (*cb_dir_data)(afs_vnode *, XFILE *, void *);          /* Directory Data  */
+  afs_uint32 (*cb_link_data)(afs_vnode *, XFILE *, void *);         /* Symlink Data    */
+
+  /* This function is called when there is an error in the dump. */
+  /* (cb_error)(errno, fatal, refcon, msg_fmt, msg_args...) */
+  void *err_refcon; /* If set, use instead of refcon for dir entries */
+  afs_uint32 (*cb_error)(afs_uint32, int, void *, char *, ...);
+
+  /* This function is called for each directory entry, if set */
+  afs_uint32 (*cb_dirent)(afs_vnode *, afs_dir_entry *, XFILE *, void *);
+
+  int flags;            /* Flags and options */
+#define DSFLAG_SEEK     0x0001  /* Input file is seekable */
+
+  int print_flags;      /* Flags to control what is printed */
+#define DSPRINT_BCKHDR  0x0001  /* Print backup system header */
+#define DSPRINT_DUMPHDR 0x0002  /* Print AFS dump header */
+#define DSPRINT_VOLHDR  0x0004  /* Print AFS volume header */
+#define DSPRINT_ITEM    0x0010  /* Print top-level tags */
+#define DSPRINT_VNODE   0x0020  /* Print vnode attributes */
+#define DSPRINT_ACL     0x0040  /* Print directory ACL's */
+#define DSPRINT_DIR     0x0080  /* Print directory contents */
+#define DSPRINT_DEBUG   0x0100  /* Print debugging info */
+#define DSPRINT_PATH    0x0200  /* Print vnode paths */
+
+  int repair_flags;     /* Flags to control what is repaired.
+                         * Most of these _require_ DSFLAG_SEEK */
+#define DSFIX_SKIP      0x0001  /* Try to skip null tags */
+#define DSFIX_RSKIP     0x0002  /* Seek back to fing skipped tags */
+#define DSFIX_VDSYNC    0x0004  /* Resync location after vnode data */
+#define DSFIX_VFSYNC    0x0008  /* Try to resync after bad vnode */
+
+  /** Things below this point for internal use only **/
+  afs_uint32 vol_uniquifier;
+} dump_parser;
+
+
+/** Hash table and control info for pathname manipulation **/
+typedef struct vhash_ent {
+  struct vhash_ent *next;    /* Pointer to next entry */
+  afs_uint32 vnode;             /* VNode number */
+  afs_uint32 parent;            /* Parent VNode number */
+  u_int64 v_offset;          /* Offset to start of vnode */
+  u_int64 d_offset;          /* Offset to data (0 if none) */
+  afs_uint32 d_size;            /* Size of data */
+} vhash_ent;
+typedef struct {
+  afs_uint32 n_vnodes;          /* Number of vnodes in volume */
+  afs_uint32 n_dirs;            /* Number of file vnodes */
+  afs_uint32 n_files;           /* Number of directory vnodes */
+  int hash_size;             /* Hash table size (bits) */
+  vhash_ent **hash_table;    /* Hash table */
+  dump_parser *p;            /* Dump parser to use */
+} path_hashinfo;
+
+
+/** Function prototypes **/
+/** Only the functions declared below are public interfaces **/
+/** Maybe someday, I'll write man pages for these **/
+
+/* primitive.c - I/O primitives */
+extern afs_uint32 ReadByte(XFILE *, unsigned char *);
+extern afs_uint32 ReadInt16(XFILE *, afs_uint16 *);
+extern afs_uint32 ReadInt32(XFILE *, afs_uint32 *);
+extern afs_uint32 ReadString(XFILE *, unsigned char **);
+extern afs_uint32 WriteByte(XFILE *, unsigned char);
+extern afs_uint32 WriteInt16(XFILE *, afs_uint16);
+extern afs_uint32 WriteInt32(XFILE *, afs_uint32);
+extern afs_uint32 WriteString(XFILE *, unsigned char *);
+extern afs_uint32 WriteTagByte(XFILE *, unsigned char, unsigned char);
+extern afs_uint32 WriteTagInt16(XFILE *, unsigned char, afs_uint16);
+extern afs_uint32 WriteTagInt32(XFILE *, unsigned char, afs_uint32);
+extern afs_uint32 WriteTagInt32Pair(XFILE *, unsigned char, afs_uint32, afs_uint32);
+extern afs_uint32 WriteTagString(XFILE *, unsigned char, unsigned char *);
+
+/* parsetag.c - Parse tagged data */
+extern afs_uint32 ParseTaggedData(XFILE *, tagged_field *, unsigned char *,
+                           tag_parse_info *, void *, void *);
+
+/* stagehdr.c - Parse and dump Stage dump headers */
+extern afs_uint32 ParseStageHdr(XFILE *, unsigned char *, backup_system_header *);
+extern afs_uint32 ParseStageV20Hdr(XFILE *, unsigned char *, backup_system_header *);
+extern afs_uint32 DumpStageV20Hdr(XFILE *, backup_system_header *);
+
+/* backuphdr.c - Parse and print backup system headers */
+extern void PrintBackupHdr(backup_system_header *);
+
+/* parsedump.c - Parse all or part of a volume dump */
+extern afs_uint32 ParseDumpFile(XFILE *, dump_parser *);
+extern afs_uint32 ParseDumpHeader(XFILE *, dump_parser *);
+extern afs_uint32 ParseVolumeHeader(XFILE *, dump_parser *);
+extern afs_uint32 ParseVNode(XFILE *, dump_parser *);
+
+
+/* directory.c - Directory parsing, lookup, and generation */
+extern afs_uint32 ParseDirectory(XFILE *, dump_parser *, afs_uint32, int);
+extern afs_uint32 DirectoryLookup(XFILE *, dump_parser *, afs_uint32,
+                           char **, afs_uint32 *, afs_uint32 *);
+extern afs_uint32 Dir_Init(dir_state **);
+extern afs_uint32 Dir_AddEntry(dir_state *, char *, afs_uint32, afs_uint32);
+extern afs_uint32 Dir_Finalize(dir_state *);
+extern afs_uint32 Dir_EmitData(dir_state *, XFILE *, int);
+extern afs_uint32 Dir_Free(dir_state *ds);
+
+
+/* dump.c - Dump parts of a volume dump */
+extern afs_uint32 DumpDumpHeader(XFILE *, afs_dump_header *);
+extern afs_uint32 DumpVolumeHeader(XFILE *, afs_vol_header *);
+extern afs_uint32 DumpVNode(XFILE *, afs_vnode *);
+extern afs_uint32 DumpVnodeData(XFILE *, char *, afs_uint32);
+extern afs_uint32 CopyVnodeData(XFILE *, XFILE *, afs_uint32);
+extern afs_uint32 DumpVNodeData(XFILE *OX, char *buf, afs_uint32 size);
+extern afs_uint32 DumpDumpEnd(XFILE *OX);
+
+/* pathname.c - Follow and construct pathnames */
+extern afs_uint32 Path_PreScan(XFILE *, path_hashinfo *, int);
+extern void Path_FreeHashTable(path_hashinfo *);
+extern afs_uint32 Path_Follow(XFILE *, path_hashinfo *, char *, vhash_ent *);
+extern afs_uint32 Path_Build(XFILE *, path_hashinfo *, afs_uint32, char **, int);
+
+#endif
diff --git a/src/tools/dumpscan_errs.et b/src/tools/dumpscan_errs.et
new file mode 100644 (file)
index 0000000..e15e4c1
--- /dev/null
@@ -0,0 +1,37 @@
+# COPYRIGHT NOTICE
+# Copyright (c) 1997 Carnegie Mellon University
+# All Rights Reserved.
+#
+# Permission to use, copy, modify and distribute this software and its
+# documentation is hereby granted, provided that both the copyright
+# notice and this permission notice appear in all copies of the
+# software, derivative works or modified versions, and any portions
+# thereof, and that both notices appear in supporting documentation.
+#
+# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+# CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+#
+# Carnegie Mellon requests users of this software to return to
+#
+#  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+#  School of Computer Science
+#  Carnegie Mellon University
+#  Pittsburgh PA 15213-3890
+#
+# any improvements or extensions that they make and grant Carnegie Mellon
+# the rights to redistribute these changes.
+
+# UB - Unified Backups
+# methods/afs/dumpscan/afsdump_errs.et - AFS dump scanner errors
+
+error_table AVds
+  ec DSERR_TAG,            "Unknown tag in AFS volume dump"
+  ec DSERR_MAGIC,          "Bad magic number in AFS volume dump"
+  ec DSERR_BOGUS,          "Bogus value in AFS volume dump"
+  ec DSERR_FMT,            "AFS volume dump format incorrect"
+  ec DSERR_KEEP,           "[AFS dumpscan internal: keep string]"
+  ec DSERR_PANIC,          "[AFS dumpscan internal: panic]"
+  ec DSERR_DONE,           "[AFS dumpscan internal: done]"
+  ec DSERR_MEM,            "[AFS dumpscan internal: out of memory]"
+end
diff --git a/src/tools/dumptool.c b/src/tools/dumptool.c
new file mode 100644 (file)
index 0000000..d514cde
--- /dev/null
@@ -0,0 +1,2622 @@
+/*
+ * $Id$
+ *
+ * dumptool - A tool to manage MR-AFS dump files
+ *
+ * The dump file format ought to be documented _somewhere_, and
+ * this seems like a good as a place as any ...
+ *
+ * A AFS dump file is marked off into a series of sections.  Each
+ * section marked by a dump tag.  A tag is a single byte who's value
+ * corresponds with the next section.  The sections are (in order):
+ *
+ * DUMPHEADER (tag 0x01)
+ * VOLUMEHEADER (tag 0x02)
+ * VNODE (tag 0x03)
+ * DUMPEND (tag 0x04)
+ *
+ * Descriptions of the sections follow.  Note that in all cases, data is
+ * stored in the dump in network byte order.
+ *
+ * DUMPHEADER:
+ *
+ * DUMPHEADER contains two parts: the DUMPMAGIC magic number (32 bits)
+ * and the dump header itself.
+ *
+ * The dump header itself consists of a series of tagged values,
+ * each tag marking out members of the DumpHeader structure.  The
+ * routine ReadDumpHeader explains the specifics of these tags.
+ *
+ * VOLUMEHEADER:
+ *
+ * VOLUMEHEADER is a series of tagged values corresponding to the elements
+ * of the VolumeDiskData structure.  See ReadVolumeHeader for more
+ * information
+ *
+ * VNODE:
+ *
+ * The VNODE section is all vnodes contained in the volume (each vnode
+ * itself is marked with the VNODE tag, so it's really a sequence of
+ * VNODE tags, unlike other sections).
+ *
+ * Each vnode consists of three parts: the vnode number (32 bits), the
+ * uniqifier (32 bits), and a tagged list of elements corresponding to
+ * the elements of the VnodeDiskData structure.  See ScanVnodes for
+ * more information.  Note that if file data is associated with a vnode,
+ * it will be contained here.
+ *
+ * DUMPEND:
+ *
+ * The DUMPEND section consists of one part: the DUMPENDMAGIC magic
+ * number (32 bits).
+ *
+ * Notes:
+ *
+ * The tagged elements are all ASCII letters, as opposed to the section
+ * headers (which are 0x01, 0x02, ...).  Thus, an easy way to tell when
+ * you've reached the end of an element sequence is to check to see if
+ * the next tag is a printable character (this code tests for < 20).
+ *
+ * "vos dump" dumps the large vnode index, then the small vnode index,
+ * so directories will appear first in the VNODE section.
+ */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <termios.h>
+#include <fnmatch.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <lock.h>
+#include <afs/afsint.h>
+#include <afs/nfs.h>
+#include <afs/acl.h>
+#if !defined(PRE_AFS_36) && !defined(RESIDENCY)
+#include <afs/ihandle.h>
+#endif /* !defined(PRE_AFS_36) && !defined(RESIDENCY) */
+#include <afs/vnode.h>
+#include <afs/volume.h>
+
+#ifdef AFS_LINUX24_ENV
+#define _LARGEFILE64_SOURCE 1
+#endif
+#ifdef RESIDENCY
+#include <afs/rsdefs.h>
+#include <afs/remioint.h>
+#endif /* RESIDENCY */
+
+#include <afs/dir.h>
+
+#ifndef HAVE_OFF64_T
+typedef off_t off64_t;
+#endif /* !HAVE_OFF64_T */
+#ifndef HAVE_FSEEKO64
+#define fseeko64 fseeko
+#endif /* HAVE_FSEEKO64 */
+#ifndef HAVE_FTELLO64
+#define ftello64 ftello
+#endif /* HAVE_FTELLO64 */
+
+/*
+ * Sigh.  Linux blows it again
+ */
+
+#ifdef linux
+#include <pty.h>
+#endif
+
+/*
+ * Stuff that is in private AFS header files, unfortunately
+ */
+
+#define DUMPVERSION    1
+#define DUMPENDMAGIC   0x3A214B6E
+#define DUMPBEGINMAGIC 0xB3A11322
+#define D_DUMPHEADER   1
+#define D_VOLUMEHEADER 2
+#define D_VNODE                3
+#define D_DUMPEND      4
+#define D_MAX          20
+
+#define MAXDUMPTIMES   50
+
+struct DumpHeader {
+    int32_t version;
+    VolumeId volumeId;
+    char volumeName[VNAMESIZE];
+    int nDumpTimes;            /* Number of pairs */
+    struct {
+       int32_t from, to;
+    } dumpTimes[MAXDUMPTIMES];
+};
+
+/*
+ * Our command-line arguments
+ */
+
+#ifdef RESIDENCY
+struct {
+    int Algorithm;             /* Conversion algorithm */
+    int Size;                  /* Directory hierarchy size */
+    int FSType;                        /* File system type */
+    int DeviceTag;             /* Device Tag */
+} rscmdlineinfo[RS_MAXRESIDENCIES];
+
+/*
+ * This stuff comes from ufsname.c (which itself takes it from
+ * ufs_interfaces.c)
+ */
+
+/* There is an assumption that all of the prefixes will have exactly one '/' */
+static char *Ufs_Prefixes[] = { "/ufs", "/slowufs", "/cdmf", "/sdmf" };
+
+#define MAX_ITERATIONS 10
+#define UFS_SUMMARYTREENAME "Summaries"
+#define UFS_STAGINGTREENAME "Staging"
+#define UFS_VOLUMEHEADERTREENAME "VolHeaders"
+#define UFS_VOLUMETREENAME "Volumes"
+#define UFS_ALGORITHMBASE 'A'
+#define UFS_MOUNTPOINTBASE 'a'
+#define UFS_ALGORITHMS 3
+#define UFS_LINK_MAX 64                /* Arbitrary. */
+#define HARD_LINKED_FILE -2
+#define TAGSTONAME(FileName, MountPoint, Sections, Level1, RWVolume, Vnode, Uniquifier, Algorithm) \
+{ \
+    if (Level1) \
+        sprintf(FileName,"%s/%lu/%lu/%c%lu.%lu.%lu.%lu.%lu", MountPoint, \
+                (Sections)[0], (Sections)[1], UFS_ALGORITHMBASE + Algorithm, \
+                (Sections)[2], (Sections)[3], RWVolume, Vnode, Uniquifier); \
+    else \
+        sprintf(FileName,"%s/%lu/%c%lu.%lu.%lu.%lu.%lu", MountPoint, \
+                (Sections)[0], UFS_ALGORITHMBASE + Algorithm, \
+                (Sections)[1], (Sections)[2], RWVolume, Vnode, Uniquifier); \
+}
+#define TAGSTOSTAGINGNAME(FileName, MountPoint, RWVolume, Vnode, Uniquifier) \
+    sprintf(FileName,"%s/%s/%lu.%lu.%lu", MountPoint, \
+           UFS_STAGINGTREENAME, RWVolume, Vnode, Uniquifier)
+#define TAGSTOVOLUMEHEADERNAME(FileName, MountPoint, FileTag1, FileTag2) \
+    sprintf(FileName,"%s/%s/%lu", MountPoint, UFS_VOLUMEHEADERTREENAME, \
+           FileTag1)
+#define TAGSTOVOLUMEINFONAME(FileName, MountPoint, FileTag1, FileTag2) \
+    sprintf(FileName,"%s/%s/%lu/%lu", MountPoint, \
+           UFS_VOLUMETREENAME, FileTag2, FileTag1)
+#define TAGSTOVOLUMENAME(FileName, MountPoint, FileTag1, FileTag2, RWVolume) \
+    sprintf(FileName,"%s/%s/%lu/%lu.%lu", MountPoint, \
+           UFS_VOLUMETREENAME, FileTag2, FileTag1, RWVolume)
+#define TAGSTOSUMMARYNAME(FileName, MountPoint, FileTag1, FileTag2, SummaryRequestor, Residency) \
+    sprintf(FileName,"%s/%s/%lu.%lu.%lu.%lu", MountPoint, \
+           UFS_SUMMARYTREENAME, FileTag1, FileTag2, SummaryRequestor, \
+           Residency)
+#define DEVICETAGNUMBERTOMOUNTPOINT(MountPoint, DeviceTagNumber, FSType) \
+    sprintf(MountPoint,"%s%c", Ufs_Prefixes[FSType], UFS_MOUNTPOINTBASE + \
+           DeviceTagNumber)
+#define MOUNTPOINTTODEVICETAGNUMBER(MountPoint) \
+    MountPoint[strlen(MountPoint) - 1] - UFS_MOUNTPOINTBASE
+#define DEVICETAGNUMBERTOVOLUMEHEADERTREE(TreeName, MountPoint) \
+    sprintf(TreeName,"%s/%s", MountPoint, UFS_VOLUMEHEADERTREENAME)
+#define UFS_RESIDENCIES_FILE "Residencies"
+
+/* We don't ever want to map to uid/gid -1.  fchown() takes that as a
+   don't change flag.  We know however that volume number range from
+   0x2000000 to 0x20FFFFFF (see VAllocateVolumeId() in vol/vutil.c)
+   so we will use that to insure that -1 never appears. */
+#define RWVolumeToUid(RWVolume) ((RWVolume >> 12) & 0xFFFF)
+#define RWVolumeToGid(RWVolume) ((RWVolume & 0xFFF) | \
+                                (((RWVolume >> 28) & 0xF) << 12))
+#define UidGidToRWVolume(Uid, Gid) ((Gid & 0xFFF) | ((Uid & 0xFFFF) << 12) | \
+                                   ((Gid & 0xF000) << 16))
+
+
+/* These routines generate a file name to correspond to the given tag
+   numbers. */
+
+/* The following entropy array contains the order of bits from highest entropy
+   to lowest in the numbers FileTag1 and FileTag2.  Bit numbers 32 and above
+   correspond to FileTag2.  This ordering was determined by examining all read-
+   write volumes in the psc.edu cell. */
+char UfsEntropy[1][64] = {
+    {1, 2, 3, 4, 33, 5, 6, 7, 44, 45, 46, 36, 8, 34, 42, 35,
+     9, 40, 38, 32, 43, 10, 39, 37, 11, 41, 12, 13, 14, 0,
+     15, 16, 61, 17, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
+     50, 49, 48, 47, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
+     21, 20, 19, 18, 62, 63},
+};
+
+uint32_t Directories[3][2] = { {256, 0}, {256, 16}, {256, 256}, };
+#endif /* RESIDENCY */
+
+static int verbose = 0;
+static int numNoDirData = 0;
+static int termsize = 0;
+int Testing = 0;
+#ifdef RESIDENCY
+extern resid ServerRequestorId;
+#endif /* RESIDENCY */
+
+/*
+ * We use this structure to hold vnode data in our hash table.
+ * It's indexed by vnode number.
+ */
+
+struct vnodeData {
+    struct VnodeDiskObject *vnode;     /* A pointer to the disk vnode */
+    int vnodeNumber;           /* The vnode number */
+    off64_t dumpdata;          /* File offset of dump data (if
+                                * available */
+    unsigned char *filedata;   /* A pointer to the actual file
+                                * data itself (if available) */
+    unsigned int datalength;   /* The length of the data */
+};
+
+/*
+ * This contains the current location when we're doing a scan of a
+ * directory.
+ */
+
+struct DirCursor {
+    int hashbucket;            /* Current hash bucket */
+    int entry;                 /* Entry within hash bucket */
+};
+
+/*
+ * Arrays to hold vnode data
+ */
+
+struct vnodeData **LargeVnodeIndex;
+struct vnodeData **SmallVnodeIndex;
+int numLargeVnodes = 0;
+int numSmallVnodes = 0;
+
+/*
+ * Crap for the libraries
+ */
+
+int ShutdownInProgress = 0;
+
+/*
+ * Our local function prototypes
+ */
+
+static int DirHash(char *string);
+static int ReadDumpHeader(FILE *, struct DumpHeader *);
+static int ReadVolumeHeader(FILE *, VolumeDiskData *);
+static int ScanVnodes(FILE *, VolumeDiskData *, int);
+static struct vnodeData *InsertVnode(unsigned int, struct VnodeDiskObject *);
+static struct vnodeData *GetVnode(unsigned int);
+static int CompareVnode(const void *, const void *);
+static void InteractiveRestore(FILE *, VolumeDiskData *);
+static void DirectoryList(int, char **, struct vnodeData *, VolumeDiskData *);
+static void DirListInternal(struct vnodeData *, char *[], int, int, int, int,
+                           int, int, VolumeDiskData *, char *);
+static int CompareDirEntry(const void *, const void *);
+static struct vnodeData *ChangeDirectory(int, char **, struct vnodeData *);
+static void CopyFile(int, char **, struct vnodeData *, FILE *);
+static void CopyVnode(int, char **, FILE *);
+static void DumpAllFiles(int, char **, struct vnodeData *, VolumeDiskData *);
+static struct vnodeData *FindFile(struct vnodeData *, char *);
+static void ResetDirCursor(struct DirCursor *, struct vnodeData *);
+static struct DirEntry *ReadNextDir(struct DirCursor *, struct vnodeData *);
+static void MakeArgv(char *, int *, char ***);
+static char *GetToken(char *, char **, char *, char *[]);
+static int ReadInt16(FILE *, uint16_t *);
+static int ReadInt32(FILE *, uint32_t *);
+static int ReadString(FILE *, char *, int);
+static int ReadByteString(FILE *, void *, int);
+
+#ifdef RESIDENCY
+static int DumpVnodeFile(FILE *, struct VnodeDiskObject *, VolumeDiskData *);
+static void DumpAllResidencies(FILE *, struct vnodeData *, VolumeDiskData *);
+#endif
+
+int
+main(int argc, char *argv[])
+{
+    int c, errflg = 0, force = 0, inode = 0;
+    unsigned int magic;
+    struct DumpHeader dheader;
+    VolumeDiskData vol;
+    off64_t offset;
+#ifdef RESIDENCY
+    int Res, Arg1, Arg2, Arg3, i;
+    int dumpvnodes = 0;
+#endif
+    char *p;
+    struct winsize win;
+    FILE *f;
+    int fd;
+    time_t tmv;
+
+#ifdef RESIDENCY
+    for (i = 0; i < RS_MAXRESIDENCIES; i++) {
+       rscmdlineinfo[i].Algorithm = -1;
+       rscmdlineinfo[i].Size = -1;
+       rscmdlineinfo[i].DeviceTag = -1;
+       rscmdlineinfo[i].FSType = -1;
+    }
+#endif /* RESIDENCY */
+
+    /*
+     * Sigh, this is dumb, but we need the terminal window size
+     * to do intelligent things with "ls" later on.
+     */
+
+    if (isatty(STDOUT_FILENO)) {
+       if ((p = getenv("COLUMNS")) != NULL)
+           termsize = atoi(p);
+       else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0
+                && win.ws_col > 0)
+           termsize = win.ws_col;
+    }
+
+    while ((c = getopt(argc, argv, "difr:t:v")) != EOF)
+       switch (c) {
+       case 't':
+#ifdef RESIDENCY
+           if (sscanf(optarg, "%d/%d", &Res, &Arg1) != 2) {
+               errflg++;
+               break;
+           }
+
+           if (1 << (ffs(Res) - 1) != Res) {
+               fprintf(stderr, "Invalid residency %d\n", Res);
+               errflg++;
+               break;
+           }
+
+           if (Arg1 < 0 || Arg1 > 26) {
+               fprintf(stderr, "Invalid device tag: %d\n", Arg1);
+               errflg++;
+               break;
+           }
+           rscmdlineinfo[ffs(Res) - 1].DeviceTag = Arg1;
+#else /* RESIDENCY */
+           fprintf(stderr, "-t not supported in non-MRAFS " "dumptool.\n");
+           errflg++;
+#endif /* RESIDENCY */
+           break;
+
+       case 'r':
+#ifdef RESIDENCY
+           if (sscanf(optarg, "%d/%d/%d/%d", &Res, &Arg1, &Arg2, &Arg3) != 4) {
+               errflg++;
+               break;
+           }
+
+           if (Arg1 < 0 || Arg1 > 3) {
+               fprintf(stderr, "Invalid fstype: %d\n", Arg1);
+               errflg++;
+               break;
+           }
+
+           if (Arg2 < 0 || Arg2 > 2) {
+               fprintf(stderr, "Invalid size: %d\n", Arg2);
+               errflg++;
+               break;
+           }
+
+           if (Arg3 <= 0 || Arg3 > UFS_ALGORITHMS) {
+               fprintf(stderr, "Invalid algorithm: %d\n", Arg3);
+               errflg++;
+               break;
+           }
+           rscmdlineinfo[ffs(Res) - 1].FSType = Arg1;
+           rscmdlineinfo[ffs(Res) - 1].Size = Arg2;
+           rscmdlineinfo[ffs(Res) - 1].Algorithm = Arg3;
+#else /* RESIDENCY */
+           fprintf(stderr, "-r not supported in non-MRAFS " "dumptool.\n");
+           errflg++;
+#endif /* RESIDENCY */
+           break;
+       case 'd':
+#ifdef RESIDENCY
+           dumpvnodes++;
+#else /* RESIDENCY */
+           fprintf(stderr, "-d not supported in non-MRAFS " "dumptool.\n");
+           errflg++;
+#endif /* RESIDENCY */
+           break;
+       case 'v':
+           verbose++;
+           break;
+       case 'f':
+           force++;
+           break;
+       case 'i':
+           inode++;
+           break;
+       case '?':
+       default:
+           errflg++;
+       }
+
+    if (errflg || optind == argc) {
+       fprintf(stderr, "Usage: %s\n\t[-v] [-f]\n\t"
+#ifdef RESIDENCY
+               "[-t Residency/Tag]\n\t"
+               "[-r Residency/Type/Size/Algorithm]\n\t"
+               "[-d] filename [file_in_dump [file in dump ...]]\n",
+#else /* RESIDENCY */
+               "filename\n",
+#endif /* RESIDENCY */
+               argv[0]);
+       exit(1);
+    }
+
+    /*
+     * Try opening the dump file
+     */
+
+#ifdef O_LARGEFILE
+    if ((fd = open(argv[optind], O_RDONLY | O_LARGEFILE)) < 0) {
+#else
+    if ((fd = open(argv[optind], O_RDONLY)) < 0) {
+#endif
+       fprintf(stderr, "open of dumpfile %s failed: %s\n", argv[optind],
+               strerror(errno));
+       exit(1);
+    }
+
+    if ((f = fdopen(fd, "rb")) == NULL) {
+        fprintf(stderr, "fdopen of dumpfile %s failed: %s\n", argv[optind],
+               strerror(errno));
+       exit(1);
+    }
+
+    if (ReadDumpHeader(f, &dheader)) {
+       fprintf(stderr, "Failed to read dump header!\n");
+       exit(1);
+    }
+
+    if (verbose)
+       printf("Dump is for volume %lu (%s)\n",
+              (unsigned long) dheader.volumeId, dheader.volumeName);
+
+    if (getc(f) != D_VOLUMEHEADER) {
+       fprintf(stderr, "Volume header is missing from dump, aborting\n");
+       exit(1);
+    }
+
+    if (ReadVolumeHeader(f, &vol)) {
+       fprintf(stderr, "Unable to read volume header\n");
+       exit(1);
+    }
+
+    if (verbose) {
+       printf("Volume information:\n");
+       printf("\tid = %lu\n", (unsigned long) vol.id);
+       printf("\tparent id = %lu\n", (unsigned long) vol.parentId);
+       printf("\tname = %s\n", vol.name);
+       printf("\tflags =");
+       if (vol.inUse)
+           printf(" inUse");
+       if (vol.inService)
+           printf(" inService");
+       if (vol.blessed)
+           printf(" blessed");
+       if (vol.needsSalvaged)
+           printf(" needsSalvaged");
+       printf("\n");
+       printf("\tuniquifier = %lu\n", (unsigned long) vol.uniquifier);
+       tmv = vol.creationDate;
+       printf("\tCreation date = %s", ctime(&tmv));
+       tmv = vol.accessDate;
+       printf("\tLast access date = %s", ctime(&tmv));
+       tmv = vol.updateDate;
+       printf("\tLast update date = %s", ctime(&tmv));
+       printf("\tVolume owner = %lu\n", (unsigned long) vol.owner);
+    }
+
+    if (verbose)
+       printf("Scanning vnodes (this may take a while)\n");
+
+    /*
+     * We need to do two vnode scans; one to get the number of
+     * vnodes, the other to actually build the index.
+     */
+
+    offset = ftello64(f);
+
+    if (ScanVnodes(f, &vol, 1)) {
+       fprintf(stderr, "First vnode scan failed, aborting\n");
+       exit(1);
+    }
+
+    fseeko64(f, offset, SEEK_SET);
+
+    if (ScanVnodes(f, &vol, 0)) {
+       fprintf(stderr, "Second vnode scan failed, aborting\n");
+       exit(1);
+    }
+
+    if (getc(f) != D_DUMPEND || ReadInt32(f, &magic) || magic != DUMPENDMAGIC) {
+       fprintf(stderr, "Couldn't find dump postamble, ");
+       if (!force) {
+           fprintf(stderr, "aborting (use -f to override)\n");
+           exit(1);
+       } else {
+           fprintf(stderr, "continuing anyway\n");
+           fprintf(stderr, "WARNING: Dump may not be complete!\n");
+       }
+    }
+
+    /*
+     * If we wanted to simply dump all vnodes, do it now
+     */
+
+#ifdef RESIDENCY
+    if (dumpvnodes) {
+       struct vnodeData *vdata;
+
+       for (i = 0; i < numLargeVnodes; i++) {
+
+           vdata = LargeVnodeIndex[i];
+
+           if (vdata->vnode->type == vFidLookup)
+               if (DumpVnodeFile(stdout, vdata->vnode, &vol)) {
+                   fprintf(stderr, "DumpVnodeFile failed, " "aborting\n");
+                   exit(1);
+               }
+       }
+
+       for (i = 0; i < numSmallVnodes; i++) {
+
+           vdata = SmallVnodeIndex[i];
+
+           if (vdata->vnode->type == vFidLookup)
+               if (DumpVnodeFile(stdout, vdata->vnode, &vol)) {
+                   fprintf(stderr, "DumpVnodeFile failed, " "aborting\n");
+                   exit(1);
+               }
+       }
+
+    } else
+#endif /* RESIDENCY */
+    if (inode) {
+       /*
+        * Dump out all filenames with their corresponding FID
+        */
+
+       struct vnodeData *rootvdata;
+
+       if ((rootvdata = GetVnode(1)) == NULL) {
+           fprintf(stderr,
+                   "Can't get vnode data for root " "vnode!  Aborting\n");
+           exit(1);
+       }
+
+       DirListInternal(rootvdata, NULL, 0, 0, 1, 0, 1, 0, &vol, "");
+
+    } else if (argc > optind + 1) {
+#ifdef RESIDENCY
+       /*
+        * Dump out residencies of files given on the command line.
+        */
+
+       struct vnodeData *vdata, *rootvdata;
+
+       if ((rootvdata = GetVnode(1)) == NULL) {
+           fprintf(stderr,
+                   "Can't get vnode data for root " "vnode!  Aborting\n");
+           exit(1);
+       }
+
+       for (i = optind + 1; i < argc; i++) {
+
+           if ((vdata = FindFile(rootvdata, argv[i])) == NULL) {
+               fprintf(stderr, "Skipping file %s\n", argv[i]);
+               continue;
+           }
+
+           if (verbose)
+               printf("Residency locations for %s:\n", argv[i]);
+
+           while (vdata->vnode->NextVnodeId != 0) {
+
+               vdata = GetVnode(vdata->vnode->NextVnodeId);
+
+               if (vdata == NULL) {
+                   fprintf(stderr,
+                           "We had a vnode chain " "pointer to a vnode that "
+                           "doesn't exist, aborting!\n");
+                   exit(1);
+               }
+               if (vdata->vnode->type == vFidLookup)
+                   DumpVnodeFile(stdout, vdata->vnode, &vol);
+           }
+       }
+#else /* RESIDENCY */
+       fprintf(stderr, "Extra arguments after dump filename: %s\n",
+               argv[optind]);
+       exit(1);
+#endif /* RESIDENCY */
+    } else {
+       /*
+        * Perform an interactive restore
+        */
+
+       InteractiveRestore(f, &vol);
+    }
+
+    exit(0);
+}
+
+/*
+ * Read the dump header, which is at the beginning of every dump
+ */
+
+static int
+ReadDumpHeader(FILE * f, struct DumpHeader *header)
+{
+    unsigned int magic;
+    int tag, i;
+
+    if (getc(f) != D_DUMPHEADER || ReadInt32(f, &magic)
+       || ReadInt32(f, (unsigned int *)
+                    &header->version) || magic != DUMPBEGINMAGIC) {
+       if (verbose)
+           fprintf(stderr, "Couldn't find dump magic numbers\n");
+       return -1;
+    }
+
+    header->volumeId = 0;
+    header->nDumpTimes = 0;
+
+    while ((tag = getc(f)) > D_MAX && tag != EOF) {
+       unsigned short length;
+       switch (tag) {
+       case 'v':
+           if (ReadInt32(f, &header->volumeId)) {
+               if (verbose)
+                   fprintf(stderr, "Failed to read " "volumeId\n");
+               return -1;
+           }
+           break;
+       case 'n':
+           if (ReadString(f, header->volumeName, sizeof(header->volumeName))) {
+               if (verbose)
+                   fprintf(stderr, "Failed to read " "volume name\n");
+               return -1;
+           }
+           break;
+       case 't':
+           if (ReadInt16(f, &length)) {
+               if (verbose)
+                   fprintf(stderr,
+                           "Failed to read " "dump time array length\n");
+               return -1;
+           }
+           header->nDumpTimes = (length >> 1);
+           for (i = 0; i < header->nDumpTimes; i++)
+               if (ReadInt32(f, (unsigned int *)
+                             &header->dumpTimes[i].from)
+                   || ReadInt32(f, (unsigned int *)
+                                &header->dumpTimes[i].to)) {
+                   if (verbose)
+                       fprintf(stderr, "Failed to " "read dump times\n");
+                   return -1;
+               }
+           break;
+       default:
+           if (verbose)
+               fprintf(stderr, "Unknown dump tag \"%c\"\n", tag);
+           return -1;
+       }
+    }
+
+    if (!header->volumeId || !header->nDumpTimes) {
+       if (verbose)
+           fprintf(stderr,
+                   "We didn't get a volume Id or " "dump times listing\n");
+       return 1;
+    }
+
+    ungetc(tag, f);
+    return 0;
+}
+
+/*
+ * Read the volume header; this is the information stored in VolumeDiskData.
+ *
+ * I'm not sure we need all of this, but read it in just in case.
+ */
+
+static int
+ReadVolumeHeader(FILE * f, VolumeDiskData * vol)
+{
+    int tag;
+    unsigned int trash;
+    memset((void *)vol, 0, sizeof(*vol));
+
+    while ((tag = getc(f)) > D_MAX && tag != EOF) {
+       switch (tag) {
+       case 'i':
+           if (ReadInt32(f, &vol->id))
+               return -1;
+           break;
+       case 'v':
+           if (ReadInt32(f, &trash))
+               return -1;
+           break;
+       case 'n':
+           if (ReadString(f, vol->name, sizeof(vol->name)))
+               return -1;
+           break;
+       case 's':
+           vol->inService = getc(f);
+           break;
+       case 'b':
+           vol->blessed = getc(f);
+           break;
+       case 'u':
+           if (ReadInt32(f, &vol->uniquifier))
+               return -1;
+           break;
+       case 't':
+           vol->type = getc(f);
+           break;
+       case 'p':
+           if (ReadInt32(f, &vol->parentId))
+               return -1;
+           break;
+       case 'c':
+           if (ReadInt32(f, &vol->cloneId))
+               return -1;
+           break;
+       case 'q':
+           if (ReadInt32(f, (uint32_t *) & vol->maxquota))
+               return -1;
+           break;
+       case 'm':
+           if (ReadInt32(f, (uint32_t *) & vol->minquota))
+               return -1;
+           break;
+       case 'd':
+           if (ReadInt32(f, (uint32_t *) & vol->diskused))
+               return -1;
+           break;
+       case 'f':
+           if (ReadInt32(f, (uint32_t *) & vol->filecount))
+               return -1;
+           break;
+       case 'a':
+           if (ReadInt32(f, &vol->accountNumber))
+               return -1;
+           break;
+       case 'o':
+           if (ReadInt32(f, &vol->owner))
+               return -1;
+           break;
+       case 'C':
+           if (ReadInt32(f, &vol->creationDate))
+               return -1;
+           break;
+       case 'A':
+           if (ReadInt32(f, &vol->accessDate))
+               return -1;
+           break;
+       case 'U':
+           if (ReadInt32(f, &vol->updateDate))
+               return -1;
+           break;
+       case 'E':
+           if (ReadInt32(f, &vol->expirationDate))
+               return -1;
+           break;
+       case 'B':
+           if (ReadInt32(f, &vol->backupDate))
+               return -1;
+           break;
+       case 'O':
+           if (ReadString
+               (f, vol->offlineMessage, sizeof(vol->offlineMessage)))
+               return -1;
+           break;
+       case 'M':
+           if (ReadString(f, (char *)vol->stat_reads, VMSGSIZE))
+               return -1;
+           break;
+       case 'W':{
+               unsigned short length;
+               int i;
+               unsigned int data;
+               if (ReadInt16(f, &length))
+                   return -1;
+               for (i = 0; i < length; i++) {
+                   if (ReadInt32(f, &data))
+                       return -1;
+                   if (i < sizeof(vol->weekUse) / sizeof(vol->weekUse[0]))
+                       vol->weekUse[i] = data;
+               }
+               break;
+           }
+       case 'D':
+           if (ReadInt32(f, &vol->dayUseDate))
+               return -1;
+           break;
+       case 'Z':
+           if (ReadInt32(f, (uint32_t *) & vol->dayUse))
+               return -1;
+           break;
+#ifdef RESIDENCY
+       case 'R':{
+               unsigned short length;
+               int i;
+               unsigned int data;
+
+               if (ReadInt16(f, &length))
+                   return -1;
+               for (i = 0; i < length; i++) {
+                   if (ReadInt32(f, &data))
+                       return -1;
+                   if (i <
+                       sizeof(vol->DesiredInfo.DesiredResidencyWords) /
+                       sizeof(vol->DesiredInfo.DesiredResidencyWords[0]))
+                       vol->DesiredInfo.DesiredResidencyWords[i] = data;
+               }
+               break;
+           }
+       case 'S':{
+               unsigned short length;
+               int i;
+               unsigned int data;
+
+               if (ReadInt16(f, &length))
+                   return -1;
+               for (i = 0; i < length; i++) {
+                   if (ReadInt32(f, &data))
+                       return -1;
+                   if (i <
+                       sizeof(vol->UnDesiredInfo.UnDesiredResidencyWords) /
+                       sizeof(vol->UnDesiredInfo.UnDesiredResidencyWords[0]))
+                       vol->UnDesiredInfo.UnDesiredResidencyWords[i] = data;
+               }
+               break;
+           }
+#endif
+       default:
+           if (verbose)
+               fprintf(stderr, "Unknown dump tag \"%c\"\n", tag);
+           return -1;
+       }
+    }
+
+    ungetc(tag, f);
+    return 0;
+}
+
+/*
+ * Scan all our vnode entries, and build indexing information.
+ */
+
+static int
+ScanVnodes(FILE * f, VolumeDiskData * vol, int sizescan)
+{
+    int vnodeNumber;
+    int tag;
+    int numFileVnodes = 0;
+    int numDirVnodes = 0;
+    unsigned char buf[SIZEOF_LARGEDISKVNODE];
+    struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
+    off64_t offset, oldoffset;
+    struct vnodeData *vdata;
+    unsigned int length;
+
+    tag = getc(f);
+
+    while (tag == D_VNODE) {
+
+       offset = 0;
+       length = 0;
+       vnode->type = -1;
+       vnode->length = -1;
+
+       if (ReadInt32(f, (uint32_t *) & vnodeNumber)) {
+           fprintf(stderr, "failed int32 for 'vnodenum'\n");
+           return -1;
+       }
+
+       if (ReadInt32(f, &vnode->uniquifier)) {
+           fprintf(stderr, "failed int32 for 'uniquifier'\n");
+           return -1;
+       }
+
+       if (verbose > 1 && !sizescan)
+           printf("Got vnode %d\n", vnodeNumber);
+
+       while ((tag = getc(f)) > D_MAX && tag != EOF)
+           switch (tag) {
+           case 't':
+               vnode->type = (VnodeType) getc(f);
+               break;
+           case 'l':
+               {
+                   unsigned short tmp;
+                   if (ReadInt16(f, &tmp)) {
+                       fprintf(stderr, "failed int16 for 'l'\n");
+                       return -1;
+                   }
+                   vnode->linkCount = tmp;
+               }
+               break;
+           case 'v':
+               if (ReadInt32(f, &vnode->dataVersion)) {
+                   fprintf(stderr, "failed int32 for 'v'\n");
+                   return -1;
+               }
+               break;
+           case 'm':
+               if (ReadInt32(f, (uint32_t *) & vnode->unixModifyTime)) {
+                   fprintf(stderr, "failed int32 for 'm'\n");
+                   return -1;
+               }
+               break;
+           case 's':
+               if (ReadInt32(f, (uint32_t *) & vnode->serverModifyTime)) {
+                   fprintf(stderr, "failed int32 for 's'\n");
+                   return -1;
+               }
+               break;
+           case 'a':
+               if (ReadInt32(f, &vnode->author)) {
+                   fprintf(stderr, "failed int32 for 'a'\n");
+                   return -1;
+               }
+               break;
+           case 'o':
+               if (ReadInt32(f, &vnode->owner)) {
+                   fprintf(stderr, "failed int32 for 'o'\n");
+                   return -1;
+               }
+               break;
+           case 'g':
+               if (ReadInt32(f, (uint32_t *) & vnode->group)) {
+                   fprintf(stderr, "failed int32 for 'g'\n");
+                   return -1;
+               }
+               break;
+           case 'b':{
+                   unsigned short modeBits;
+                   if (ReadInt16(f, &modeBits))
+                       return -1;
+                   vnode->modeBits = modeBits;
+                   break;
+               }
+           case 'p':
+               if (ReadInt32(f, &vnode->parent)) {
+                   fprintf(stderr, "failed int32 for 'p'\n");
+                   return -1;
+               }
+               break;
+#ifdef RESIDENCY
+           case 'N':
+               if (ReadInt32(f, &vnode->NextVnodeId)) {
+                   fprintf(stderr, "failed int32 for 'N'\n");
+                   return -1;
+               }
+               break;
+           case 'R':
+               if (ReadInt32(f, &VLkp_Residencies(vnode))) {
+                   fprintf(stderr, "failed int32 for 'R'\n");
+                   return -1;
+               }
+               break;
+#endif
+           case 'S':
+               if (ReadInt32(f, &vnode->length)) {
+                   fprintf(stderr, "failed int32 for 'S'\n");
+                   return -1;
+               }
+               break;
+           case 'F':
+               if (ReadInt32(f, (uint32_t *) & vnode->vn_ino_lo))
+                   return -1;
+               break;
+           case 'A':
+               if (ReadByteString
+                   (f, (void *)VVnodeDiskACL(vnode), VAclDiskSize(vnode))) {
+                   fprintf(stderr, "failed readbystring for 'A'\n");
+                   return -1;
+               }
+#if 0
+               acl_NtohACL(VVnodeDiskACL(vnode));
+#endif
+               break;
+#ifdef RESIDENCY
+           case 'h':
+               if (ReadInt32(f, &vnode->length_hi)) {
+                   fprintf(stderr, "failed int32 for 'h'\n");
+                   return -1;
+               }
+#endif
+           case 'f':
+               if (verbose > 1 && !sizescan)
+                   printf("We have file data!\n");
+               if (ReadInt32(f, &length)) {
+                   fprintf(stderr, "failed int32 for 'f'\n");
+                   return -1;
+               }
+               vnode->length = length;
+               offset = ftello64(f);
+               fseeko64(f, length, SEEK_CUR);
+               break;
+           default:
+               if (verbose)
+                   fprintf(stderr, "Unknown dump tag \"%c\"\n", tag);
+               return -1;
+           }
+
+       /*
+        * If we're doing an incremental restore, then vnodes
+        * will be listed in the dump, but won't contain any
+        * vnode information at all (I don't know why they're
+        * included _at all_).  If we get one of these vnodes, then
+        * just skip it (because we can't do anything with it.
+        */
+
+       if (vnode->type == -1)
+           continue;
+
+#ifdef RESIDENCY
+       if (verbose > 1 && vnode->type == vFidLookup && !sizescan) {
+           printf
+               ("This is an auxiliary vnode (lookup) for vnode %d, residency %d\n",
+                VLkp_ParentVnodeId(vnode), VLkp_Residencies(vnode));
+           if (DumpVnodeFile(stdout, vnode, vol))
+               return -1;
+       }
+
+       if (verbose > 1 && vnode->type == vAccessHistory && !sizescan)
+           printf("This is an auxiliary vnode (history) for vnode %d\n",
+                  VLkp_ParentVnodeId(vnode));
+#endif
+
+       if (vnode->type == vDirectory)
+           numDirVnodes++;
+       else
+           numFileVnodes++;
+
+       /*
+        * We know now all we would ever know about the vnode;
+        * insert it into our hash table (but only if we're not
+        * doing a vnode scan).
+        */
+
+       if (!sizescan) {
+
+           vdata = InsertVnode(vnodeNumber, vnode);
+
+           if (vdata == NULL) {
+               if (verbose)
+                   fprintf(stderr,
+                           "Failed to insert " "vnode into hash table");
+               return -1;
+           }
+
+           vdata->dumpdata = offset;
+           vdata->datalength = length;
+
+           /*
+            * Save directory data, since we'll need it later.
+            */
+
+           if (vnode->type == vDirectory && length) {
+
+               vdata->filedata = malloc(length);
+
+               if (!vdata->filedata) {
+                   if (verbose)
+                       fprintf(stderr,
+                               "Unable to " "allocate space for "
+                               "file data (%d)\n", length);
+                   return -1;
+               }
+
+               oldoffset = ftello64(f);
+               fseeko64(f, offset, SEEK_SET);
+
+               if (fread(vdata->filedata, length, 1, f) != 1) {
+                   if (verbose)
+                       fprintf(stderr, "Unable to " "read in file data!\n");
+                   return -1;
+               }
+
+               fseeko64(f, oldoffset, SEEK_SET);
+           } else if (vnode->type == vDirectory)
+               /*
+                * Warn the user we may not have all directory
+                * vnodes
+                */
+               numNoDirData++;
+       }
+    }
+
+    ungetc(tag, f);
+
+    if (!sizescan) {
+
+       numLargeVnodes = numDirVnodes;
+       numSmallVnodes = numFileVnodes;
+
+    } else {
+       LargeVnodeIndex = (struct vnodeData **)
+           malloc(numDirVnodes * sizeof(struct vnodeData));
+       SmallVnodeIndex = (struct vnodeData **)
+           malloc(numFileVnodes * sizeof(struct vnodeData));
+
+       if (LargeVnodeIndex == NULL || SmallVnodeIndex == NULL) {
+           if (verbose)
+               fprintf(stderr,
+                       "Unable to allocate space " "for vnode tables\n");
+           return -1;
+       }
+    }
+
+    if (verbose)
+       fprintf(stderr, "%s vnode scan completed\n",
+               sizescan ? "Primary" : "Secondary");
+
+    return 0;
+}
+
+/*
+ * Perform an interactive restore
+ *
+ * Parsing the directory information is a pain, but other than that
+ * we just use the other tools we already have in here.
+ */
+#define CMDBUFSIZE     (AFSPATHMAX * 2)
+static void
+InteractiveRestore(FILE * f, VolumeDiskData * vol)
+{
+    struct vnodeData *vdatacwd;        /* Vnode data for our current dir */
+    char cmdbuf[CMDBUFSIZE];
+    int argc;
+    char **argv;
+
+    /*
+     * Let's see if we can at least get the data for our root directory.
+     * If we can't, there's no way we can do an interactive restore.
+     */
+
+    if ((vdatacwd = GetVnode(1)) == NULL) {
+       fprintf(stderr, "No entry for our root vnode!  Aborting\n");
+       return;
+    }
+
+    if (!vdatacwd->filedata) {
+       fprintf(stderr,
+               "There is no directory data for the root "
+               "vnode (1.1).  An interactive\nrestore is not "
+               "possible.\n");
+       return;
+    }
+
+    /*
+     * If you're doing a selective dump correctly, then you should get all
+     * directory vnode data.  But just in case you didn't, let the user
+     * know there may be a problem.
+     */
+
+    if (numNoDirData)
+       fprintf(stderr,
+               "WARNING: %d directory vnodes had no file "
+               "data.  An interactive restore\nmay not be possible\n",
+               numNoDirData);
+
+    printf("> ");
+    while (fgets(cmdbuf, CMDBUFSIZE, stdin)) {
+
+       cmdbuf[strlen(cmdbuf) - 1] = '\0';
+
+       if (strlen(cmdbuf) == 0) {
+           printf("> ");
+           continue;
+       }
+
+       MakeArgv(cmdbuf, &argc, &argv);
+
+       if (strcmp(argv[0], "ls") == 0) {
+           DirectoryList(argc, argv, vdatacwd, vol);
+       } else if (strcmp(argv[0], "cd") == 0) {
+           struct vnodeData *newvdata;
+
+           newvdata = ChangeDirectory(argc, argv, vdatacwd);
+
+           if (newvdata)
+               vdatacwd = newvdata;
+       } else if (strcmp(argv[0], "file") == 0) {
+           DumpAllFiles(argc, argv, vdatacwd, vol);
+       } else if (strcmp(argv[0], "cp") == 0) {
+           CopyFile(argc, argv, vdatacwd, f);
+       } else if (strcmp(argv[0], "vcp") == 0) {
+           CopyVnode(argc, argv, f);
+       } else if (strcmp(argv[0], "quit") == 0
+                  || strcmp(argv[0], "exit") == 0)
+           break;
+       else if (strcmp(argv[0], "?") == 0 || strcmp(argv[0], "help") == 0) {
+           printf("Valid commands are:\n");
+           printf("\tls\t\tList current directory\n");
+           printf("\tcd\t\tChange current directory\n");
+           printf("\tcp\t\tCopy file from dump\n");
+           printf("\tvcp\t\tCopy file from dump (via vnode)\n");
+#ifdef RESIDENCY
+           printf("\tfile\t\tList residency filenames\n");
+#endif /* RESIDENCY */
+           printf("\tquit | exit\tExit program\n");
+           printf("\thelp | ?\tBrief help\n");
+       } else
+           fprintf(stderr,
+                   "Unknown command, \"%s\", enter "
+                   "\"help\" for a list of commands.\n", argv[0]);
+
+       printf("> ");
+    }
+
+    return;
+}
+
+/*
+ * Do a listing of all files in a directory.  Sigh, I wish this wasn't
+ * so complicated.
+ *
+ * With the reorganizing, this is just a front-end to DirListInternal()
+ */
+
+static void
+DirectoryList(int argc, char **argv, struct vnodeData *vdata,
+             VolumeDiskData * vol)
+{
+    int errflg = 0, lflag = 0, iflag = 0, Fflag = 0, sflag = 0, Rflag = 0;
+    int c;
+
+    optind = 1;
+
+    while ((c = getopt(argc, argv, "liFRs")) != EOF)
+       switch (c) {
+       case 'l':
+           lflag++;
+           break;
+       case 'i':
+           iflag++;
+           break;
+       case 'F':
+           Fflag++;
+           break;
+       case 'R':
+           Rflag++;
+       case 's':
+           sflag++;
+           break;
+       case '?':
+       default:
+           errflg++;
+       }
+
+    if (errflg) {
+       fprintf(stderr, "Usage: %s [-liFs] filename [filename ...]\n",
+               argv[0]);
+       return;
+    }
+
+    DirListInternal(vdata, &(argv[optind]), argc - optind, lflag, iflag,
+                   Fflag, Rflag, 1, vol, NULL);
+
+    return;
+}
+
+/*
+ * Function that does the REAL work in terms of directory listing
+ */
+
+static void
+DirListInternal(struct vnodeData *vdata, char *pathnames[], int numpathnames,
+               int lflag, int iflag, int Fflag, int Rflag, int verbose,
+               VolumeDiskData * vol, char *path)
+{
+    struct DirEntry *ep, **eplist = NULL, **eprecurse = NULL;
+    struct DirCursor cursor;
+    struct vnodeData *lvdata;
+
+    int i, j, numentries = 0, longestname = 0, numcols, col, numrows;
+    int numrecurse = 0;
+
+    if (!vdata->filedata) {
+       fprintf(stderr, "There is no vnode data for this " "directory!\n");
+       return;
+    }
+
+    ResetDirCursor(&cursor, vdata);
+
+    /*
+     * Scan through the whole directory
+     */
+
+    while ((ep = ReadNextDir(&cursor, vdata)) != NULL) {
+
+       /*
+        * If we didn't get any filenames on the command line,
+        * get them all.
+        */
+
+       if (numpathnames == 0) {
+           eplist =
+               realloc(eplist, sizeof(struct DirEntry *) * ++numentries);
+           eplist[numentries - 1] = ep;
+           if (strlen(ep->name) > longestname)
+               longestname = strlen(ep->name);
+           if (Rflag)
+               if ((lvdata = GetVnode(ntohl(ep->fid.vnode)))
+                   && lvdata->vnode->type == vDirectory
+                   && !(strcmp(ep->name, ".") == 0
+                        || strcmp(ep->name, "..") == 0)) {
+                   eprecurse =
+                       realloc(eprecurse,
+                               sizeof(struct DirEntry *) * ++numrecurse);
+                   eprecurse[numrecurse - 1] = ep;
+               }
+
+       } else {
+           /*
+            * Do glob matching via fnmatch()
+            */
+
+           for (i = 0; i < numpathnames; i++)
+               if (fnmatch(pathnames[i], ep->name, FNM_PATHNAME) == 0) {
+                   eplist =
+                       realloc(eplist,
+                               sizeof(struct DirEntry *) * ++numentries);
+                   eplist[numentries - 1] = ep;
+                   if (strlen(ep->name) > longestname)
+                       longestname = strlen(ep->name);
+                   if (Rflag)
+                       if ((lvdata = GetVnode(ntohl(ep->fid.vnode)))
+                           && lvdata->vnode->type == vDirectory
+                           && !(strcmp(ep->name, ".") == 0
+                                || strcmp(ep->name, "..") == 0)) {
+                           eprecurse =
+                               realloc(eprecurse,
+                                       sizeof(struct DirEntry *) *
+                                       ++numrecurse);
+                           eprecurse[numrecurse - 1] = ep;
+                       }
+                   break;
+               }
+       }
+    }
+
+    qsort((void *)eplist, numentries, sizeof(struct DirEntry *),
+         CompareDirEntry);
+
+    if (Rflag && eprecurse)
+       qsort((void *)eprecurse, numrecurse, sizeof(struct DirEntry *),
+             CompareDirEntry);
+    /*
+     * We don't have to do column printing if we have the -l or the -i
+     * options.  Sigh, column printing is WAY TOO FUCKING COMPLICATED!
+     */
+
+    if (!lflag && !iflag) {
+       char c;
+
+       if (Fflag)
+           longestname++;
+
+       longestname++;
+
+       numcols = termsize / longestname ? termsize / longestname : 1;
+       numrows = numentries / numcols + (numentries % numcols ? 1 : 0);
+
+       for (i = 0; i < numrows; i++) {
+           col = 0;
+           while (col < numcols && (i + col * numrows) < numentries) {
+               ep = eplist[i + col++ * numrows];
+               if (Fflag) {
+                   if (!(lvdata = GetVnode(ntohl(ep->fid.vnode))))
+                       c = ' ';
+                   else if (lvdata->vnode->type == vDirectory)
+                       c = '/';
+                   else if (lvdata->vnode->type == vSymlink)
+                       c = '@';
+                   else if ((lvdata->vnode->modeBits & 0111) != 0)
+                       c = '*';
+                   else
+                       c = ' ';
+                   printf("%s%-*c", ep->name, (int)(longestname -
+                                                    strlen(ep->name)), c);
+               } else
+                   printf("%-*s", longestname, ep->name);
+           }
+
+           printf("\n");
+       }
+    } else if (iflag)
+       for (i = 0; i < numentries; i++)
+           if (!(lvdata = GetVnode(ntohl(eplist[i]->fid.vnode))))
+               printf("%d.0.0\t%s\n",
+                      vol->parentId ? vol->parentId : vol->id,
+                      eplist[i]->name);
+           else if (path)
+               printf("%d.%d.%d\t%s/%s\n", vol->id,
+                      ntohl(eplist[i]->fid.vnode),
+                      ntohl(eplist[i]->fid.vunique), path, eplist[i]->name);
+           else
+               printf("%d.%d.%d\t%s\n", vol->id, ntohl(eplist[i]->fid.vnode),
+                      ntohl(eplist[i]->fid.vunique), eplist[i]->name);
+    else if (lflag) {
+       for (i = 0; i < numentries; i++)
+           if (!(lvdata = GetVnode(ntohl(eplist[i]->fid.vnode))))
+               printf("----------   0 0        " "0                 0 %s\n",
+                      eplist[i]->name);
+           else {
+               switch (lvdata->vnode->type) {
+               case vDirectory:
+                   printf("d");
+                   break;
+               case vSymlink:
+                   printf("l");
+                   break;
+               default:
+                   printf("-");
+               }
+
+               for (j = 8; j >= 0; j--) {
+                   if (lvdata->vnode->modeBits & (1 << j))
+                       switch (j % 3) {
+                       case 2:
+                           printf("r");
+                           break;
+                       case 1:
+                           printf("w");
+                           break;
+                       case 0:
+                           printf("x");
+                   } else
+                       printf("-");
+               }
+
+               printf(" %-3d %-8d %-8d %10d %s\n", lvdata->vnode->linkCount,
+                      lvdata->vnode->owner, lvdata->vnode->group,
+                      lvdata->vnode->length, eplist[i]->name);
+           }
+    }
+
+    free(eplist);
+
+    if (Rflag && eprecurse) {
+       char *lpath;
+       lpath = NULL;
+       for (i = 0; i < numrecurse; i++) {
+           if (verbose)
+               printf("\n%s:\n", eprecurse[i]->name);
+           if (path) {
+               lpath = malloc(strlen(path) + strlen(eprecurse[i]->name) + 2);
+               if (lpath)
+                   sprintf(lpath, "%s/%s", path, eprecurse[i]->name);
+           }
+           DirListInternal(GetVnode(ntohl(eprecurse[i]->fid.vnode)), NULL, 0,
+                           lflag, iflag, Fflag, Rflag, verbose, vol, lpath);
+           if (lpath) {
+               free(lpath);
+               lpath = NULL;
+           }
+       }
+    }
+
+    if (eprecurse)
+       free(eprecurse);
+
+    return;
+}
+
+
+/*
+ * Directory name comparison function, used by qsort
+ */
+
+static int
+CompareDirEntry(const void *e1, const void *e2)
+{
+    struct DirEntry **ep1 = (struct DirEntry **)e1;
+    struct DirEntry **ep2 = (struct DirEntry **)e2;
+
+    return strcmp((*ep1)->name, (*ep2)->name);
+}
+
+/*
+ * Change a directory.  Return a pointer to our new vdata structure for
+ * this directory.
+ */
+
+static struct vnodeData *
+ChangeDirectory(int argc, char **argv, struct vnodeData *vdatacwd)
+{
+    struct vnodeData *newvdatacwd;
+
+    if (argc != 2) {
+       fprintf(stderr, "Usage: %s directory\n", argv[0]);
+       return NULL;
+    }
+
+    if ((newvdatacwd = FindFile(vdatacwd, argv[1])) == NULL)
+       return NULL;
+
+    if (newvdatacwd->vnode->type != vDirectory) {
+       fprintf(stderr, "%s: Not a directory\n", argv[1]);
+       return NULL;
+    }
+
+    if (newvdatacwd->filedata == NULL) {
+       fprintf(stderr, "%s: No directory data found.\n", argv[1]);
+       return NULL;
+    }
+
+    return newvdatacwd;
+}
+
+/*
+ * Copy a file from out of the dump file
+ */
+
+#define COPYBUFSIZE 8192
+
+static void
+CopyFile(int argc, char **argv, struct vnodeData *vdatacwd, FILE * f)
+{
+    struct vnodeData *vdata;
+    FILE *out;
+    off64_t cur = 0;
+    int bytes, ret;
+    char buffer[COPYBUFSIZE];
+
+    if (argc != 3) {
+       fprintf(stderr, "Usage: %s dumpfile destfile\n", argv[0]);
+       return;
+    }
+
+    if ((vdata = FindFile(vdatacwd, argv[1])) == NULL)
+       return;
+
+    if (vdata->dumpdata == 0) {
+       fprintf(stderr, "File %s has no data in dump file\n", argv[1]);
+       return;
+    }
+
+    if ((out = fopen(argv[2], "wb")) == NULL) {
+       fprintf(stderr, "Open of %s failed: %s\n", argv[2], strerror(errno));
+       return;
+    }
+
+    if (fseeko64(f, vdata->dumpdata, SEEK_SET)) {
+       fprintf(stderr, "Seek failed: %s\n", strerror(errno));
+       fclose(out);
+       return;
+    }
+
+    while (cur < vdata->datalength) {
+
+       bytes =
+           cur + COPYBUFSIZE <
+           vdata->datalength ? COPYBUFSIZE : vdata->datalength - cur;
+
+       ret = fread(buffer, sizeof(char), bytes, f);
+       if (ret != bytes) {
+           if (ret != 0)
+               fprintf(stderr, "Short read (expected %d, " "got %d)\n",
+                       bytes, ret);
+           else
+               fprintf(stderr, "Error during read: %s\n", strerror(errno));
+           fclose(out);
+           return;
+       }
+
+       ret = fwrite(buffer, sizeof(char), bytes, out);
+       if (ret != bytes) {
+           if (ret != 0)
+               fprintf(stderr, "Short write (expected %d, " "got %d)\n",
+                       bytes, ret);
+           else
+               fprintf(stderr, "Error during write: %s\n", strerror(errno));
+           fclose(out);
+           return;
+       }
+
+       cur += bytes;
+    }
+
+    fclose(out);
+}
+
+/*
+ * Copy a file from out of the dump file, by using the vnode
+ */
+
+static void
+CopyVnode(int argc, char *argv[], FILE * f)
+{
+    struct vnodeData *vdata;
+    FILE *out;
+    off64_t cur = 0;
+    int bytes, ret;
+    char buffer[COPYBUFSIZE];
+    unsigned int vnode, uniquifier = 0;
+
+    if (argc != 3) {
+       fprintf(stderr, "Usage: %s vnode[.uniqifier] destfile\n", argv[0]);
+       return;
+    }
+
+    ret = sscanf(argv[1], "%d.%d", &vnode, &uniquifier);
+
+    if (ret < 1) {
+       fprintf(stderr, "Invalid file identifier: %s\n", argv[1]);
+       return;
+    }
+
+    if (!(vdata = GetVnode(vnode))) {
+       fprintf(stderr, "Vnode %d not in dump file\n", vnode);
+       return;
+    }
+
+    if (ret == 2 && vdata->vnode->uniquifier != uniquifier) {
+       fprintf(stderr,
+               "Specified uniquifier %d did not match "
+               "uniquifier %d found in dump file!\n", uniquifier,
+               vdata->vnode->uniquifier);
+       return;
+    }
+
+    if (vdata->dumpdata == 0) {
+       fprintf(stderr, "File %s has no data in dump file\n", argv[1]);
+       return;
+    }
+
+    if ((out = fopen(argv[2], "wb")) == NULL) {
+       fprintf(stderr, "Open of %s failed: %s\n", argv[2], strerror(errno));
+       return;
+    }
+
+    if (fseeko64(f, vdata->dumpdata, SEEK_SET)) {
+       fprintf(stderr, "Seek failed: %s\n", strerror(errno));
+       fclose(out);
+       return;
+    }
+
+    while (cur < vdata->datalength) {
+
+       bytes =
+           cur + COPYBUFSIZE <
+           vdata->datalength ? COPYBUFSIZE : vdata->datalength - cur;
+
+       ret = fread(buffer, sizeof(char), bytes, f);
+       if (ret != bytes) {
+           if (ret != 0)
+               fprintf(stderr, "Short read (expected %d, " "got %d)\n",
+                       bytes, ret);
+           else
+               fprintf(stderr, "Error during read: %s\n", strerror(errno));
+           fclose(out);
+           return;
+       }
+
+       ret = fwrite(buffer, sizeof(char), bytes, out);
+       if (ret != bytes) {
+           if (ret != 0)
+               fprintf(stderr, "Short write (expected %d, " "got %d)\n",
+                       bytes, ret);
+           else
+               fprintf(stderr, "Error during write: %s\n", strerror(errno));
+           fclose(out);
+           return;
+       }
+
+       cur += bytes;
+    }
+
+    fclose(out);
+}
+
+/*
+ * Dump all residency filenames associated with a file, or all files
+ * within a directory.
+ */
+
+static void
+DumpAllFiles(int argc, char **argv, struct vnodeData *vdatacwd,
+            VolumeDiskData * vol)
+{
+#ifdef RESIDENCY
+    struct vnodeData *vdata, *nvdata;
+    struct DirCursor cursor;
+    struct DirEntry *ep;
+    FILE *f = stdout;
+    int c, i;
+    int dflag = 0, fflag = 0, errflg = 0;
+
+    optind = 1;
+
+    while ((c = getopt(argc, argv, "df:")) != EOF)
+       switch (c) {
+       case 'd':
+           dflag++;
+           break;
+       case 'f':
+           if ((f = fopen(optarg, "a")) == NULL) {
+               fprintf(stderr, "Cannot open \"%s\": %s\n", optarg,
+                       strerror(errno));
+               return;
+           }
+           fflag++;
+           break;
+       case 'h':
+       case '?':
+       default:
+           errflg++;
+       }
+
+    if (errflg || argc == optind) {
+       fprintf(stderr, "Usage: %s [-d] [-f filename] file " "[file ...]\n",
+               argv[0]);
+       if (fflag)
+           fclose(f);
+       return;
+    }
+
+    for (i = optind; i < argc; i++) {
+
+       if ((vdata = FindFile(vdatacwd, argv[i])) == NULL)
+           continue;
+
+       if (vdata->vnode->type == vDirectory && !dflag) {
+
+           ResetDirCursor(&cursor, vdata);
+
+           while ((ep = ReadNextDir(&cursor, vdata)) != NULL) {
+
+               if (!(nvdata = GetVnode(ntohl(ep->fid.vnode)))) {
+                   fprintf(stderr,
+                           "Cannot find vnode " "entry for %s (%d)\n",
+                           ep->name, ntohl(ep->fid.vnode));
+                   continue;
+               }
+
+
+               if (!fflag) {
+                   printf("Residency locations for %s:\n", ep->name);
+
+                   if (nvdata->dumpdata)
+                       printf("Local disk (in dump " "file)\n");
+               }
+
+               DumpAllResidencies(f, nvdata, vol);
+
+           }
+
+       } else {
+           if (!fflag) {
+               printf("Residency locations for %s:\n", argv[i]);
+
+               if (vdata->dumpdata)
+                   printf("Local disk (in dump file)\n");
+           }
+
+           DumpAllResidencies(f, vdata, vol);
+       }
+    }
+
+    if (fflag)
+       fclose(f);
+#else /* RESIDENCY */
+    fprintf(stderr,
+           "The \"file\" command is not available in the non-"
+           "MRAFS version of dumptool.\n");
+#endif /* RESIDENCY */
+    return;
+}
+
+/*
+ * Take a vnode, traverse the vnode chain, and dump out all files on
+ * all residencies corresponding to that parent vnode.
+ */
+
+#ifdef RESIDENCY
+static void
+DumpAllResidencies(FILE * f, struct vnodeData *vdata,
+                  struct VolumeDiskData *vol)
+{
+    unsigned int nextVnodeNum;
+
+    while (nextVnodeNum = vdata->vnode->NextVnodeId) {
+       if ((vdata = GetVnode(nextVnodeNum)) == NULL) {
+           fprintf(stderr,
+                   "We had a pointer to %lu in it's "
+                   "vnode chain, but there\nisn't a record of "
+                   "it!  The dump might be corrupt.\n", nextVnodeNum);
+           return;
+       }
+
+       if (vdata->vnode->type == vFidLookup)
+           DumpVnodeFile(f, vdata->vnode, vol);
+    }
+
+    return;
+}
+#endif
+
+
+/*
+ * Given a directory vnode and a filename, return the vnode corresponding
+ * to the file in that directory.
+ *
+ * We now handle pathnames with directories in them.
+ */
+
+static struct vnodeData *
+FindFile(struct vnodeData *vdatacwd, char *filename)
+{
+    struct DirHeader *dhp;
+    struct DirEntry *ep;
+    int i, num;
+    struct vnodeData *vdata;
+    char *c, newstr[MAXPATHLEN];
+
+    if (!vdatacwd->filedata) {
+       fprintf(stderr, "There is no vnode data for this " "directory!\n");
+       return NULL;
+    }
+
+    /*
+     * If we have a "/" in here, look up the vnode data for the
+     * directory (everything before the "/") and use that as our
+     * current directory.  We automagically handle multiple directories
+     * by using FindFile recursively.
+     */
+
+    if ((c = strrchr(filename, '/')) != NULL) {
+
+       strncpy(newstr, filename, c - filename);
+       newstr[c - filename] = '\0';
+
+       if ((vdatacwd = FindFile(vdatacwd, newstr)) == NULL)
+           return NULL;
+
+       if (vdatacwd->vnode->type != vDirectory) {
+           fprintf(stderr, "%s: Not a directory\n", newstr);
+           return NULL;
+       }
+
+       filename = c + 1;
+    }
+
+    dhp = (struct DirHeader *)vdatacwd->filedata;
+
+    i = DirHash(filename);
+
+    num = ntohs(dhp->hashTable[i]);
+
+    while (num) {
+       ep = (struct DirEntry *)(vdatacwd->filedata + (num * 32));
+       if (strcmp(ep->name, filename) == 0)
+           break;
+       num = ntohs(ep->next);
+    }
+
+    if (!num) {
+       fprintf(stderr, "%s: No such file or directory\n", filename);
+       return NULL;
+    }
+
+    if ((vdata = GetVnode(ntohl(ep->fid.vnode))) == NULL) {
+       fprintf(stderr, "%s: No vnode information for %u found\n", filename,
+               ntohl(ep->fid.vnode));
+       return NULL;
+    }
+
+    return vdata;
+}
+
+/*
+ * Reset a structure containing the current directory scan location
+ */
+
+static void
+ResetDirCursor(struct DirCursor *cursor, struct vnodeData *vdata)
+{
+    struct DirHeader *dhp;
+
+    cursor->hashbucket = 0;
+
+    dhp = (struct DirHeader *)vdata->filedata;
+
+    cursor->entry = ntohs(dhp->hashTable[0]);
+}
+
+/*
+ * Given a cursor and a directory entry, return the next entry in the
+ * directory.
+ */
+
+static struct DirEntry *
+ReadNextDir(struct DirCursor *cursor, struct vnodeData *vdata)
+{
+    struct DirHeader *dhp;
+    struct DirEntry *ep;
+
+    dhp = (struct DirHeader *)vdata->filedata;
+
+    if (cursor->entry) {
+       ep = (struct DirEntry *)(vdata->filedata + (cursor->entry * 32));
+       cursor->entry = ntohs(ep->next);
+       return ep;
+    } else {
+       while (++(cursor->hashbucket) < NHASHENT) {
+           cursor->entry = ntohs(dhp->hashTable[cursor->hashbucket]);
+           if (cursor->entry) {
+               ep = (struct DirEntry *)(vdata->filedata +
+                                        (cursor->entry * 32));
+               cursor->entry = ntohs(ep->next);
+               return ep;
+           }
+       }
+    }
+
+    return NULL;
+}
+
+/*
+ * Given a string, split it up into components a la Unix argc/argv.
+ *
+ * This code is most stolen from ftp.
+ */
+
+static void
+MakeArgv(char *string, int *argc, char ***argv)
+{
+    static char *largv[64];
+    char **la = largv;
+    char *s = string;
+    static char argbuf[CMDBUFSIZE];
+    char *ap = argbuf;
+
+    *argc = 0;
+    *argv = largv;
+
+    while ((*la++ = GetToken(s, &s, ap, &ap)) != NULL)
+       (*argc)++;
+}
+
+/*
+ * Return a pointer to the next token, and update the current string
+ * position.
+ */
+
+static char *
+GetToken(char *string, char **nexttoken, char argbuf[], char *nextargbuf[])
+{
+    char *sp = string;
+    char *ap = argbuf;
+    int got_one = 0;
+
+  S0:
+    switch (*sp) {
+
+    case '\0':
+       goto OUTTOKEN;
+
+    case ' ':
+    case '\t':
+       sp++;
+       goto S0;
+
+    default:
+       goto S1;
+    }
+
+  S1:
+    switch (*sp) {
+
+    case ' ':
+    case '\t':
+    case '\0':
+       goto OUTTOKEN;          /* End of our token */
+
+    case '\\':
+       sp++;
+       goto S2;                /* Get next character */
+
+    case '"':
+       sp++;
+       goto S3;                /* Get quoted string */
+
+    default:
+       *ap++ = *sp++;          /* Add a character to our token */
+       got_one = 1;
+       goto S1;
+    }
+
+  S2:
+    switch (*sp) {
+
+    case '\0':
+       goto OUTTOKEN;
+
+    default:
+       *ap++ = *sp++;
+       got_one = 1;
+       goto S1;
+    }
+
+  S3:
+    switch (*sp) {
+
+    case '\0':
+       goto OUTTOKEN;
+
+    case '"':
+       sp++;
+       goto S1;
+
+    default:
+       *ap++ = *sp++;
+       got_one = 1;
+       goto S3;
+    }
+
+  OUTTOKEN:
+    if (got_one)
+       *ap++ = '\0';
+    *nextargbuf = ap;          /* Update storage pointer */
+    *nexttoken = sp;           /* Update token pointer */
+
+    return got_one ? argbuf : NULL;
+}
+
+/*
+ * Insert vnodes into our hash table.
+ */
+
+static struct vnodeData *
+InsertVnode(unsigned int vnodeNumber, struct VnodeDiskObject *vnode)
+{
+    struct VnodeDiskObject *nvnode;
+    struct vnodeData *vdata;
+    static int curSmallVnodeIndex = 0;
+    static int curLargeVnodeIndex = 0;
+    struct vnodeData ***vnodeIndex;
+    int *curIndex;
+
+    nvnode = (struct VnodeDiskObject *)malloc(sizeof(struct VnodeDiskObject));
+
+    if (!nvnode) {
+       if (verbose)
+           fprintf(stderr, "Unable to allocate space for vnode\n");
+       return NULL;
+    }
+
+    memcpy((void *)nvnode, (void *)vnode, sizeof(struct VnodeDiskObject));
+
+    if (vnodeNumber & 1) {
+       vnodeIndex = &LargeVnodeIndex;
+       curIndex = &curLargeVnodeIndex;
+    } else {
+       vnodeIndex = &SmallVnodeIndex;
+       curIndex = &curSmallVnodeIndex;
+    }
+
+    vdata = (struct vnodeData *)malloc(sizeof(struct vnodeData));
+
+    vdata->vnode = nvnode;
+    vdata->vnodeNumber = vnodeNumber;
+    vdata->dumpdata = 0;
+    vdata->filedata = 0;
+    vdata->datalength = 0;
+
+    (*vnodeIndex)[(*curIndex)++] = vdata;
+
+    return vdata;
+}
+
+/*
+ * Routine to retrieve a vnode from the hash table.
+ */
+
+static struct vnodeData *
+GetVnode(unsigned int vnodeNumber)
+{
+    struct vnodeData vnode, *vnodep, **tmp;
+
+    vnode.vnodeNumber = vnodeNumber;
+    vnodep = &vnode;
+
+    tmp = (struct vnodeData **)
+       bsearch((void *)&vnodep,
+               vnodeNumber & 1 ? LargeVnodeIndex : SmallVnodeIndex,
+               vnodeNumber & 1 ? numLargeVnodes : numSmallVnodes,
+               sizeof(struct vnodeData *), CompareVnode);
+
+    return tmp ? *tmp : NULL;
+}
+
+/*
+ * Our comparator function for bsearch
+ */
+
+static int
+CompareVnode(const void *node1, const void *node2)
+{
+    struct vnodeData **vnode1 = (struct vnodeData **)node1;
+    struct vnodeData **vnode2 = (struct vnodeData **)node2;
+
+    if ((*vnode1)->vnodeNumber == (*vnode2)->vnodeNumber)
+       return 0;
+    else if ((*vnode1)->vnodeNumber > (*vnode2)->vnodeNumber)
+       return 1;
+    else
+       return -1;
+}
+
+#ifdef RESIDENCY
+/*
+ * Dump out the filename corresponding to a particular vnode.
+ *
+ * This routine has the following dependancies:
+ *
+ * - Only will work on UFS filesystems at this point
+ * - Has to talk to the rsserver.
+ * - Can only determine UFS algorithm type when run on the same machine
+ *   as the residency (unless you manually specify algorithm information)
+ */
+
+static int
+DumpVnodeFile(FILE * f, struct VnodeDiskObject *vnode, VolumeDiskData * vol)
+{
+    static int rscache = 0;
+    static rsaccessinfoList rsnlist = { 0, 0 };
+    char MountPoint[MAXPATHLEN + 1];
+    char FileName[MAXPATHLEN + 1];
+    unsigned int Size, Level[4];
+    unsigned int DeviceTag, Algorithm;
+    FileSystems *FSInfo;
+    int i, found, FSType, rsindex;
+
+    /*
+     * Maybe we found out something about this residency via the
+     * command-line; check that first.
+     */
+
+    rsindex = ffs(VLkp_Residencies(vnode)) - 1;
+
+    /*
+     * We need to get information from the rsserver (so we can
+     * find out the device tag for a given residency).  If we
+     * haven't cached that, talk to the rsserver to get it.
+     * If we have info about this already, then don't talk to
+     * the rsserver (this lets us still do disaster recovery if
+     * MR-AFS is completely hosed).
+     */
+
+    if (!rscache && rscmdlineinfo[rsindex].DeviceTag == -1) {
+       int code;
+
+       code = ServerInitResidencyConnection();
+
+       if (code) {
+           fprintf(stderr,
+                   "ServerInitResidencyConnection failed " "with code %d\n",
+                   code);
+           return -1;
+       }
+
+       code = rs_GetResidencySummary(ServerRequestorId, &rsnlist);
+
+       if (code) {
+           fprintf(stderr, "rs_GetResidencySummary failed " "with code %d\n",
+                   code);
+           return -1;
+       }
+
+       rscache = 1;
+    }
+
+    /*
+     * For a given residency (as specified in the vnode),
+     * find out it's device tag number, either via the rsserver
+     * or via the command line.
+     */
+
+    if (rscmdlineinfo[rsindex].DeviceTag != -1) {
+       DeviceTag = rscmdlineinfo[rsindex].DeviceTag;
+       found = 1;
+    } else
+       for (i = 0, found = 0; (i < rsnlist.rsaccessinfoList_len) && (!found);
+            i++) {
+           if (rsnlist.rsaccessinfoList_val[i].id.residency ==
+               VLkp_Residencies(vnode)) {
+               found = 1;
+               DeviceTag = rsnlist.rsaccessinfoList_val[i].devicetagnumber;
+               break;
+           }
+       }
+
+    if (!found) {
+       if (verbose)
+           fprintf(stderr,
+                   "Unable to find residency %d in "
+                   "rsserver database, aborting\n", VLkp_Residencies(vnode));
+       return -1;
+    }
+
+    /*
+     * Okay, now we've got the DeviceTag ... which we can use to
+     * lookup the on-disk configuration information (which we
+     * assume is locally stored).  We also need the DeviceTag to
+     * print out which partition we're using (but that comes later).
+     *
+     * We lookup the on-disk configuration information by calling
+     * Ufs_GetFSInfo() to get the configuration information on the
+     * filesystems specified by the given DeviceTag.
+     *
+     * Before we call Ufs_GetFSInfo, check the command-line cache;
+     * if we got something via the command-line, don't go to disk.
+     */
+
+    if (rscmdlineinfo[rsindex].FSType == -1
+       && Ufs_GetFSInfo(&FSInfo, DeviceTag)) {
+       if (verbose)
+           fprintf(stderr,
+                   "Ufs_GetFSInfo failed for DeviceTag "
+                   "%d, Residency %d\n", DeviceTag, VLkp_Residencies(vnode));
+       return -1;
+    }
+
+    /*
+     * The FSInfo structure has the last two things we need: the
+     * FSType (ufs, slowufs, etc etc), and the usage algorithm (which
+     * ends up being how many directories are being used on the
+     * residency filesystem).
+     *
+     * With these last two parameters, use routines stolen from
+     * ufsname to generate the filename.
+     *
+     * (Actually, I lied - we also need the "Size" parameter, which
+     * we can also get from FSInfo);
+     */
+
+    if (rscmdlineinfo[rsindex].FSType != -1) {
+       FSType = rscmdlineinfo[rsindex].FSType;
+       Algorithm = rscmdlineinfo[rsindex].Algorithm;
+       Size = rscmdlineinfo[rsindex].Size;
+    } else {
+       FSType = FSInfo->FileSystems_u.UfsInterface.FSType;
+       Algorithm = FSInfo->FileSystems_u.UfsInterface.Algorithm;
+       if (FSInfo->FileSystems_u.UfsInterface.Directories[1] == 0)
+           Size = 0;
+       else if (FSInfo->FileSystems_u.UfsInterface.Directories[1] == 16)
+           Size = 1;
+       else if (FSInfo->FileSystems_u.UfsInterface.Directories[1] == 256)
+           Size = 2;
+       else {
+           if (verbose)
+               fprintf(stderr, "Unknown directory size %d, " "aborting\n",
+                       FSInfo->FileSystems_u.UfsInterface.Directories[1]);
+           return -1;
+       }
+    }
+
+    /*
+     * First, generate our mount point from the DeviceTag and
+     * FSType.
+     */
+
+    DEVICETAGNUMBERTOMOUNTPOINT(MountPoint, DeviceTag, FSType);
+
+    /*
+     * Then, generate the "level" (directory bitmasks) from the
+     * file tags, size, and algorithm
+     */
+
+    UfsTagsToLevel(VLkp_FileTag1(vnode), VLkp_FileTag2(vnode), Algorithm,
+                  Size, Level, VLkp_ParentVnodeId(vnode),
+                  VLkp_ParentUniquifierId(vnode));
+
+    /*
+     * Finally, take the above information and generate the
+     * corresponding filename (this macro ends up being a
+     * sprintf() call)
+     */
+
+    TAGSTONAME(FileName, MountPoint, Level, Directories[Size][1],
+              vol->parentId, VLkp_ParentVnodeId(vnode),
+              VLkp_ParentUniquifierId(vnode), Algorithm);
+
+    fprintf(f, "%s\n", FileName);
+
+    return 0;
+}
+#endif
+
+/*
+ * Read a 16 bit integer in network order
+ */
+
+static int
+ReadInt16(FILE * f, unsigned short *s)
+{
+    unsigned short in;
+
+    if (fread((void *)&in, sizeof(in), 1, f) != 1) {
+       if (verbose)
+           fprintf(stderr, "ReadInt16 failed!\n");
+       return -1;
+    }
+
+    *s = ntohs(in);
+
+    return 0;
+}
+
+
+/*
+ * Read a 32 bit integer in network order
+ */
+
+static int
+ReadInt32(FILE * f, unsigned int *i)
+{
+    unsigned int in;
+
+    if (fread((void *)&in, sizeof(in), 1, f) != 1) {
+       if (verbose)
+           fprintf(stderr, "ReadInt32 failed!\n");
+       return -1;
+    }
+
+    *i = ntohl((unsigned long)in);
+
+    return 0;
+}
+
+/*
+ * Read a string from a dump file
+ */
+
+static int
+ReadString(FILE * f, char *string, int maxlen)
+{
+    int c;
+
+    while (maxlen--) {
+       if ((*string++ = getc(f)) == 0)
+           break;
+    }
+
+    /*
+     * I'm not sure what the _hell_ this is supposed to do ...
+     * but it was in the original dump code
+     */
+
+    if (string[-1]) {
+       while ((c = getc(f)) && c != EOF);
+       string[-1] = 0;
+    }
+
+    return 0;
+}
+
+static int
+ReadByteString(FILE * f, void *s, int size)
+{
+    unsigned char *c = (unsigned char *)s;
+
+    while (size--)
+       *c++ = getc(f);
+
+    return 0;
+}
+
+/*
+ * The directory hashing algorithm used by AFS
+ */
+
+static int
+DirHash(char *string)
+{
+    /* Hash a string to a number between 0 and NHASHENT. */
+    unsigned char tc;
+    int hval;
+    int tval;
+    hval = 0;
+    while ((tc = (*string++)) != '\0') {
+       hval *= 173;
+       hval += tc;
+    }
+    tval = hval & (NHASHENT - 1);
+#ifdef AFS_CRAY_ENV            /* actually, any > 32 bit environment */
+    if (tval == 0)
+       return tval;
+    else if (hval & 0x80000000)
+       tval = NHASHENT - tval;
+#else /* AFS_CRAY_ENV */
+    if (tval == 0)
+       return tval;
+    else if (hval < 0)
+       tval = NHASHENT - tval;
+#endif /* AFS_CRAY_ENV */
+    return tval;
+}
+
+#ifdef RESIDENCY
+/*
+ * Sigh, we need this for the AFS libraries
+ */
+
+int
+LogErrors(int level, char *a, char *b, char *c, char *d, char *e, char *f,
+         char *g, char *h, char *i, char *j, char *k)
+{
+    if (level <= 0) {
+       fprintf(stderr, a, b, c, d, e, f, g, h, i, j, k);
+    }
+    return 0;
+}
+
+/*
+ * These are routines taken from AFS libraries and programs.  Most of
+ * them are from ufsname.c, but a few are from the dir library (the dir
+ * library has a bunch of hidden dependancies, so it's not suitable to
+ * include it outright).
+ */
+
+UfsEntropiesToTags(HighEntropy, LowEntropy, Algorithm, FileTag1, FileTag2)
+     uint32_t HighEntropy;
+     uint32_t LowEntropy;
+     uint32_t Algorithm;
+     uint32_t *FileTag1;
+     uint32_t *FileTag2;
+{
+    int i;
+
+    if ((Algorithm > UFS_ALGORITHMS) || (Algorithm <= 0))
+       return -1;
+    *FileTag1 = 0;
+    *FileTag2 = 0;
+    for (i = 0; i < 32; ++i) {
+       if (UfsEntropy[Algorithm - 1][i] < 32)
+           *FileTag1 |=
+               ((HighEntropy & (1 << i)) ==
+                0) ? 0 : 1 << UfsEntropy[Algorithm - 1][i];
+       else
+           *FileTag2 |=
+               ((HighEntropy & (1 << i)) ==
+                0) ? 0 : 1 << (UfsEntropy[Algorithm - 1][i] - 32);
+    }
+    for (i = 32; i < 64; ++i) {
+       if (UfsEntropy[Algorithm - 1][i] < 32)
+           *FileTag1 |=
+               ((LowEntropy & (1 << (i - 32))) ==
+                0) ? 0 : 1 << UfsEntropy[Algorithm - 1][i];
+       else
+           *FileTag2 |=
+               ((LowEntropy & (1 << (i - 32))) ==
+                0) ? 0 : 1 << (UfsEntropy[Algorithm - 1][i] - 32);
+    }
+    return 0;
+}
+
+uint32_t
+UfsTagsToHighEntropy(FileTag1, FileTag2, Algorithm)
+     uint32_t FileTag1;
+     uint32_t FileTag2;
+     uint32_t Algorithm;
+{
+    int i;
+    uint32_t Value;
+
+    Value = 0;
+    for (i = 0; i < 32; ++i) {
+       if (UfsEntropy[Algorithm - 1][i] < 32)
+           Value |= ((FileTag1 & (1 << UfsEntropy[Algorithm - 1][i]))
+                     == 0) ? 0 : 1 << i;
+       else
+           Value |=
+               ((FileTag2 & (1 << (UfsEntropy[Algorithm - 1][i] - 32))) ==
+                0) ? 0 : 1 << i;
+    }
+    return Value;
+}
+
+uint32_t
+UfsTagsToLowEntropy(FileTag1, FileTag2, Algorithm)
+     uint32_t FileTag1;
+     uint32_t FileTag2;
+     uint32_t Algorithm;
+{
+    int i;
+    uint32_t Value;
+
+    Value = 0;
+    for (i = 32; i < 64; ++i) {
+       if (UfsEntropy[Algorithm - 1][i] < 32)
+           Value |= ((FileTag1 & (1 << UfsEntropy[Algorithm - 1][i]))
+                     == 0) ? 0 : 1 << (i - 32);
+       else
+           Value |=
+               ((FileTag2 & (1 << (UfsEntropy[Algorithm - 1][i] - 32))) ==
+                0) ? 0 : 1 << (i - 32);
+    }
+    return Value;
+}
+
+UfsTagsToLevel(FileTag1, FileTag2, Algorithm, Size, Sections, vnode,
+              Uniquifier)
+     uint32_t FileTag1;
+     uint32_t FileTag2;
+     uint32_t Algorithm;
+     uint32_t Size;
+     uint32_t Sections[4];
+     uint32_t vnode;
+     uint32_t Uniquifier;
+{
+    uint32_t HighEntropy;
+    uint32_t LowEntropy;
+
+    switch (Algorithm) {
+    case 1:
+       LowEntropy = UfsTagsToLowEntropy(FileTag1, FileTag2, Algorithm);
+       HighEntropy = UfsTagsToHighEntropy(FileTag1, FileTag2, Algorithm);
+       Sections[0] = HighEntropy % Directories[Size][0];
+       HighEntropy /= Directories[Size][0];
+       if (Directories[Size][1]) {
+           Sections[1] = HighEntropy % Directories[Size][1];
+           HighEntropy /= Directories[Size][1];
+           Sections[2] = HighEntropy;
+           Sections[3] = LowEntropy;
+       } else {
+           Sections[1] = HighEntropy;
+           Sections[2] = LowEntropy;
+       }
+       break;
+    case 2:
+       Sections[0] = FileTag1 & 0xff;
+       if (Directories[Size][1]) {
+           Sections[1] = Uniquifier & 0xff;
+           if (Directories[Size][1] == 16)
+               Sections[1] &= 0xf;
+           Sections[2] = FileTag1;
+           Sections[3] = FileTag2;
+       } else {
+           Sections[1] = FileTag1;
+           Sections[2] = FileTag2;
+       }
+       break;
+    case 3:
+       Sections[0] = FileTag1 & 0xff;
+       if (Directories[Size][1]) {
+           Sections[1] = (vnode >> 1) & 0xff;
+           if (Directories[Size][1] == 16)
+               Sections[1] &= 0xf;
+           Sections[2] = FileTag1;
+           Sections[3] = FileTag2;
+       } else {
+           Sections[1] = FileTag1;
+           Sections[2] = FileTag2;
+       }
+       break;
+    default:
+       fprintf(stderr, "UfsTagsToLevel: bad algorithm %lu!\n", Algorithm);
+       return -1;
+    }
+    return 0;
+}
+
+#include <afs/afscbdummies.h>
+#endif /* RESIDENCY */
diff --git a/src/tools/int64.c b/src/tools/int64.c
new file mode 100644 (file)
index 0000000..de3396b
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* int64.c - Support for 64-bit integers */
+
+#include <stdio.h>
+#include <string.h>
+#include "intNN.h"
+
+char *
+hexify_int64(u_int64 * X, char *buf)
+{
+    static char mybuf[17];
+
+#ifdef NATIVE_INT64
+    char c, *p;
+    u_int64 x = *X;
+
+    if (!buf)
+       buf = mybuf;
+    p = buf + 16;
+    *p-- = 0;
+    while (x && p >= buf) {
+       c = x & 0xf;
+       c += ((c < 10) ? '0' : 'a' - 10);
+       *p-- = c;
+       x >>= 4;
+    }
+    while (p >= buf)
+       *p-- = '0';
+
+#else
+    if (!buf)
+       buf = mybuf;
+    sprintf(buf, "%08lx%08lx", (unsigned long)X->hi, (unsigned long)X->lo);
+#endif
+
+    return buf;
+}
+
+
+#ifdef NATIVE_INT64
+char *
+decimate_int64(u_int64 * X, char *buf)
+{
+    static char mybuf[21];
+    char *p;
+    u_int64 x = *X;
+
+    if (!buf)
+       buf = mybuf;
+    p = buf + 21;
+    *--p = 0;
+    while (x && p > buf) {
+       *--p = ((x % 10) + '0');
+       x /= 10;
+    }
+    if (!*p)
+       *--p = '0';
+    return p;
+}
+
+#else
+static char bitvals[64][21] = {
+/*                1 */ "00000000000000000001",
+/*                2 */ "00000000000000000002",
+/*                4 */ "00000000000000000004",
+/*                8 */ "00000000000000000008",
+/*               10 */ "00000000000000000016",
+/*               20 */ "00000000000000000032",
+/*               40 */ "00000000000000000064",
+/*               80 */ "00000000000000000128",
+/*              100 */ "00000000000000000256",
+/*              200 */ "00000000000000000512",
+/*              400 */ "00000000000000001024",
+/*              800 */ "00000000000000002048",
+/*             1000 */ "00000000000000004096",
+/*             2000 */ "00000000000000008192",
+/*             4000 */ "00000000000000016384",
+/*             8000 */ "00000000000000032768",
+/*            10000 */ "00000000000000065536",
+/*            20000 */ "00000000000000131072",
+/*            40000 */ "00000000000000262144",
+/*            80000 */ "00000000000000524288",
+/*           100000 */ "00000000000001048576",
+/*           200000 */ "00000000000002097152",
+/*           400000 */ "00000000000004194304",
+/*           800000 */ "00000000000008388608",
+/*          1000000 */ "00000000000016777216",
+/*          2000000 */ "00000000000033554432",
+/*          4000000 */ "00000000000067108864",
+/*          8000000 */ "00000000000134217728",
+/*         10000000 */ "00000000000268435456",
+/*         20000000 */ "00000000000536870912",
+/*         40000000 */ "00000000001073741824",
+/*         80000000 */ "00000000002147483648",
+/*        100000000 */ "00000000004294967296",
+/*        200000000 */ "00000000008589934592",
+/*        400000000 */ "00000000017179869184",
+/*        800000000 */ "00000000034359738368",
+/*       1000000000 */ "00000000068719476736",
+/*       2000000000 */ "00000000137438953472",
+/*       4000000000 */ "00000000274877906944",
+/*       8000000000 */ "00000000549755813888",
+/*      10000000000 */ "00000001099511627776",
+/*      20000000000 */ "00000002199023255552",
+/*      40000000000 */ "00000004398046511104",
+/*      80000000000 */ "00000008796093022208",
+/*     100000000000 */ "00000017592186044416",
+/*     200000000000 */ "00000035184372088832",
+/*     400000000000 */ "00000070368744177664",
+/*     800000000000 */ "00000140737488355328",
+/*    1000000000000 */ "00000281474976710656",
+/*    2000000000000 */ "00000562949953421312",
+/*    4000000000000 */ "00001125899906842624",
+/*    8000000000000 */ "00002251799813685248",
+/*   10000000000000 */ "00004503599627370496",
+/*   20000000000000 */ "00009007199254740992",
+/*   40000000000000 */ "00018014398509481984",
+/*   80000000000000 */ "00036028797018963968",
+/*  100000000000000 */ "00072057594037927936",
+/*  200000000000000 */ "00144115188075855872",
+/*  400000000000000 */ "00288230376151711744",
+/*  800000000000000 */ "00576460752303423488",
+/* 1000000000000000 */ "01152921504606846976",
+/* 2000000000000000 */ "02305843009213693952",
+/* 4000000000000000 */ "04611686018427387904",
+/* 8000000000000000 */ "09223372036854775808"
+};
+
+
+static void
+prep_table(void)
+{
+    int bit, digit;
+
+    if (bitvals[0][0] < '0')
+       return;
+    for (bit = 0; bit < 64; bit++)
+       for (digit = 0; digit < 20; digit++)
+           bitvals[bit][digit] -= '0';
+}
+
+
+static void
+add_bit(int bit, char *answer)
+{
+    int digit;
+
+    for (digit = 19; digit >= 0; digit--) {
+       answer[digit] += bitvals[bit][digit];
+       if (!digit)
+           break;
+       while (answer[digit] > 9) {
+           answer[digit] -= 10;
+           answer[digit - 1]++;
+       }
+    }
+}
+
+
+static void
+decimate(unsigned long hi, unsigned long lo, char *answer)
+{
+    unsigned long mask;
+    int bit, digit;
+
+    memset(answer, 0, 21);
+    for (bit = 0, mask = 1; bit < 32; bit++, mask <<= 1)
+       if (lo & mask)
+           add_bit(bit, answer);
+    for (bit = 0, mask = 1; bit < 32; bit++, mask <<= 1)
+       if (hi & mask)
+           add_bit(bit + 32, answer);
+
+    for (digit = 0; digit < 20; digit++)
+       answer[digit] += '0';
+}
+
+char *
+decimate_int64(u_int64 * X, char *buf)
+{
+    static char mybuf[21];
+    char *p;
+
+    prep_table();
+    if (!buf)
+       buf = mybuf;
+    decimate(X->hi, X->lo, buf);
+    for (p = buf; *p == '0'; p++);
+    return (*p) ? p : p - 1;
+}
+
+#endif /* NATIVE_INT64 */
+
+
+void
+shift_int64(u_int64 * X, int bits)
+{
+#ifdef NATIVE_INT64
+    if (bits < 0)
+       *X >>= (-bits);
+    else
+       *X <<= bits;
+#else
+    if (bits < 0) {
+       bits = -bits;
+       if (bits >= 32) {
+           X->lo = ((X->hi & 0xffffffffL) >> (bits - 32));
+           X->hi = 0;
+       } else {
+           X->lo = ((X->lo & 0xffffffffL) >> bits)
+               | ((X->hi & ((1 << (32 - bits)) - 1)) << (32 - bits));
+           X->hi = ((X->hi & 0xffffffffL) >> bits);
+       }
+    } else {
+       if (bits >= 32) {
+           X->hi = ((X->lo & 0xffffffffL) << (bits - 32));
+           X->lo = 0;
+       } else {
+           X->hi = ((X->hi & 0xffffffffL) << bits)
+               | ((X->lo & (((1 << bits) - 1) << (32 - bits))) >>
+                  (32 - bits));
+           X->lo = ((X->lo & 0xffffffffL) << bits);
+       }
+    }
+#endif
+}
+
+
+#ifdef TEST_INT64
+
+/** the rest of this is for testing the int64 suite **/
+
+#ifdef NATIVE_INT64
+
+#define xize(x) #x
+#define stringize(x) xize(x)
+#define INT64_NAME stringize(unsigned NATIVE_INT64)
+
+
+#endif /* NATIVE_INT64 */
+
+
+void
+verify_int64_size()
+{
+#ifdef NATIVE_INT64
+    signed char testchar = -1;
+    unsigned int testint = (unsigned char)testchar;
+
+    printf("We think '%s' is a native 64-bit type\n", INT64_NAME);
+
+    if (testint != 0xff) {
+       printf("testint = 0x%x; should be 0xff\n", testint);
+       fprintf(stderr, "Hmm...  char's are not 8 bits.  That sucks!\n");
+       exit(-1);
+    }
+    printf("Looks like a char is 8 bits...\n");
+
+    if (sizeof(unsigned NATIVE_INT64) != 8) {
+       printf("sizeof(%s) = %d; should be 8\n", INT64_NAME,
+              sizeof(unsigned NATIVE_INT64));
+       fprintf(stderr, "Hey!  You said a %s was 64-bits wide!\n",
+               INT64_NAME);
+       exit(-1);
+    }
+    printf("Yippee!  We have a native 64-bit type (%s)\n\n", INT64_NAME);
+
+#else /* !NATIVE_INT64 */
+
+    printf("Using fake 64-bit integers...\n\n");
+#endif /* NATIVE_INT64 */
+}
+
+
+void
+test_int64_constructs(void)
+{
+    u_int64 x, y;
+    afs_uint32 hi, lo;
+    int failures = 0, pass;
+    char buf[17];
+
+    printf("Constructor/accessor tests:\n");
+    printf("Setting x := %s\n", INT64_TEST_STR);
+    mk64(x, INT64_TEST_HI, INT64_TEST_LO);
+
+#ifdef NATIVE_INT64
+    pass = (x == INT64_TEST_CONST);
+    hexify_int64(&x, buf);
+    printf("NATIVE mk64: x       = 0x%16s                %s\n", buf,
+          pass ? "PASSED" : "FAILED");
+    if (!pass)
+       failures++;
+#else
+    pass = (x.hi == INT64_TEST_HI && x.lo == INT64_TEST_LO);
+    printf("FAKE mk64:   x.hi    = 0x%08lx  x.lo    = 0x%08lx  %s\n", x.hi,
+          x.lo, pass ? "PASSED" : "FAILED");
+    if (!pass)
+       failures++;
+#endif
+
+    pass = (hi64(x) == INT64_TEST_HI && lo64(x) == INT64_TEST_LO);
+    printf("hi64/lo64:   hi64(x) = 0x%08lx  lo64(x) = 0x%08lx  %s\n", hi64(x),
+          lo64(x), pass ? "PASSED" : "FAILED");
+    if (!pass)
+       failures++;
+
+    ex64(x, hi, lo);
+    pass = (hi == INT64_TEST_HI && lo == INT64_TEST_LO);
+    printf("ex64:        hi      = 0x%08lx  lo      = 0x%08lx  %s\n", hi, lo,
+          pass ? "PASSED" : "FAILED");
+    if (!pass)
+       failures++;
+
+    cp64(y, x);
+    pass = (hi64(y) == INT64_TEST_HI && lo64(y) == INT64_TEST_LO);
+    printf("cp64:        hi64(y) = 0x%08lx  lo64(y) = 0x%08lx  %s\n", hi64(y),
+          lo64(y), pass ? "PASSED" : "FAILED");
+    if (!pass)
+       failures++;
+
+    if (failures)
+       printf("%d/4 tests FAILED\n\n", failures);
+    else
+       printf("All 4 tests PASSED\n\n");
+}
+
+
+void
+test_int64_compares()
+{
+#define NCOMPARE 9
+    u_int64 control, test[NCOMPARE];
+    char cbuf[17], tbuf[17];
+    int i, r, result[NCOMPARE];
+    int pass, failures, FAILURES = 0;
+
+    printf("Comparison tests:\n");
+
+    mk64(control, 0x12345678, 0xabcdabcd);
+    mk64(test[0], 0x12340000, 0xabcd0000);
+    result[0] = +1;
+    mk64(test[1], 0x12340000, 0xabcdabcd);
+    result[1] = +1;
+    mk64(test[2], 0x12340000, 0xabcdffff);
+    result[2] = +1;
+    mk64(test[3], 0x12345678, 0xabcd0000);
+    result[3] = +1;
+    mk64(test[4], 0x12345678, 0xabcdabcd);
+    result[4] = 0;
+    mk64(test[5], 0x12345678, 0xabcdffff);
+    result[5] = -1;
+    mk64(test[6], 0x1234ffff, 0xabcd0000);
+    result[6] = -1;
+    mk64(test[7], 0x1234ffff, 0xabcdabcd);
+    result[7] = -1;
+    mk64(test[8], 0x1234ffff, 0xabcdffff);
+    result[8] = -1;
+
+    for (i = 0; i < NCOMPARE; i++) {
+       failures = 0;
+       hexify_int64(&control, cbuf);
+       hexify_int64(&test[i], tbuf);
+
+       r = eq64(control, test[i]);
+       pass = (r == (result[i] == 0));
+       if (!pass)
+           failures++;
+       printf("0x%s == 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
+
+       r = ne64(control, test[i]);
+       pass = (r == (result[i] != 0));
+       if (!pass)
+           failures++;
+       printf("0x%s != 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
+
+       r = lt64(control, test[i]);
+       pass = (r == (result[i] < 0));
+       if (!pass)
+           failures++;
+       printf("0x%s <  0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
+
+       r = le64(control, test[i]);
+       pass = (r == (result[i] <= 0));
+       if (!pass)
+           failures++;
+       printf("0x%s <= 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
+
+       r = gt64(control, test[i]);
+       pass = (r == (result[i] > 0));
+       if (!pass)
+           failures++;
+       printf("0x%s >  0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
+
+       r = ge64(control, test[i]);
+       pass = (r == (result[i] >= 0));
+       if (!pass)
+           failures++;
+       printf("0x%s >= 0x%s %s\n", cbuf, tbuf, pass ? "PASSED" : "FAILED");
+
+       r = zero64(test[i]);
+       pass = !r;
+       if (!pass)
+           failures++;
+       printf("0x%s is nonzero            %s\n", tbuf,
+              pass ? "PASSED" : "FAILED");
+
+       if (failures)
+           printf("%d/7 tests on this pair FAILED\n\n", failures);
+       else
+           printf("All 7 tests on this pair PASSED\n\n");
+    }
+
+    mk64(control, 0, 0);
+    pass = zero64(control);
+    if (!pass)
+       FAILURES++;
+    printf("0x0000000000000000 is zero               %s\n",
+          pass ? "PASSED" : "FAILED");
+
+    if (FAILURES)
+       printf("%d/%d comparison tests FAILED\n\n", FAILURES,
+              7 * NCOMPARE + 1);
+    else
+       printf("All %d comparison tests PASSED\n\n", 7 * NCOMPARE + 1);
+}
+
+
+void
+test_int64_arith()
+{
+    printf("No arithmetic tests yet!!!\n");
+}
+
+
+void
+main()
+{
+    verify_int64_size();
+    test_int64_constructs();
+    test_int64_compares();
+    test_int64_arith();
+    exit(0);
+}
+#endif
diff --git a/src/tools/intNN.h b/src/tools/intNN.h
new file mode 100644 (file)
index 0000000..bc56bfe
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _INTNN_H_
+#define _INTNN_H_
+
+/* intNN.h - Sized integer types */
+#include <afs/stds.h>
+#if 0
+typedef short afs_int16;
+typedef unsigned short afs_uint16;
+
+typedef long afs_int32;
+typedef unsigned long afs_uint32;
+#endif
+
+
+/* Support for 64-bit integers.
+ * Presently, only unsigned 64-bit numbers are supported.
+ */
+#define INT64_TEST_STR "0x12345678fedcba98"
+#define INT64_TEST_HI  0x12345678
+#define INT64_TEST_LO  0xfedcba98
+
+
+#ifdef NATIVE_INT64
+typedef unsigned NATIVE_INT64 u_int64;
+
+/* construct/extract/assign */
+#define mk64(X,H,L) ((X) = ( ((u_int64)(H) << 32) \
+                           | ((u_int64)(L) & 0xffffffff)))
+#define hi64(Y)     ((afs_uint32)(((Y) >> 32) & 0xffffffff))
+#define lo64(Y)     ((afs_uint32)((Y) & 0xffffffff))
+#define ex64(Y,H,L) ((H) = hi64(Y), (L) = lo64(Y))
+#define cp64(X,Y)   ((X) = (Y))
+#define get64(X)    (X)
+#define set64(X,V)  ((X) = (V))
+
+/* Comparison */
+#define eq64(X,Y)   ((X) == (Y))
+#define ne64(X,Y)   ((X) != (Y))
+#define lt64(X,Y)   ((X) <  (Y))
+#define le64(X,Y)   ((X) <= (Y))
+#define gt64(X,Y)   ((X) >  (Y))
+#define ge64(X,Y)   ((X) >= (Y))
+#define zero64(X)   (!(X))
+
+/* Arithmetic */
+#define add64_32(X,A,B) ((X) = (A) + (u_int64)(B))
+#define add64_64(X,A,B) ((X) = (A) + (B))
+#define sub64_32(X,A,B) ((X) = (A) - (u_int64)(B))
+#define sub64_64(X,A,B) ((X) = (A) - (B))
+
+/* Byte-order */
+#ifdef WORDS_BIGENDIAN
+#define hton64(X,Y) cp64(X,Y)
+#define ntoh64(X,Y) cp64(X,Y)
+#else
+#define hton64(X,Y) mk64(X,htonl(lo64(Y)),htonl(hi64(Y)))
+#define ntoh64(X,Y) mk64(X,ntohl(lo64(Y)),ntohl(hi64(Y)))
+#endif
+
+#else /* !NATIVE_INT64 */
+/** We have to provide our own 64-bit integers **/
+typedef struct {
+    afs_uint32 hi, lo;
+} u_int64;
+
+/* construct/extract/assign */
+#define mk64(X,H,L) ((X).hi = (H), (X).lo = (L))
+#define ex64(Y,H,L) ((H) = (Y).hi, (L) = (Y).lo)
+#define hi64(Y)     ((Y).hi)
+#define lo64(Y)     ((Y).lo)
+#define cp64(X,Y)   ((X).hi = (Y).hi, (X).lo = (Y).lo)
+#define get64(X)    ((X).lo)
+#define set64(X,V)  ((X).hi = 0, (X).lo = (V))
+
+/* Comparison */
+#define eq64(A,B) ((A).hi == (B).hi && (A).lo == (B).lo)
+#define ne64(A,B) ((A).hi != (B).hi || (A).lo != (B).lo)
+#define lt64(A,B) ((A).hi <  (B).hi || ((A).hi == (B).hi && (A).lo <  (B).lo))
+#define le64(A,B) ((A).hi <  (B).hi || ((A).hi == (B).hi && (A).lo <= (B).lo))
+#define gt64(A,B) ((A).hi >  (B).hi || ((A).hi == (B).hi && (A).lo >  (B).lo))
+#define ge64(A,B) ((A).hi >  (B).hi || ((A).hi == (B).hi && (A).lo >= (B).lo))
+#define zero64(X) ((X).hi == 0 && (X).lo == 0)
+
+/* Arithmetic */
+#define add64_32(X,A,B) (                                              \
+  (X).lo = (A).lo + (B),                                               \
+  (X).hi = (A).hi +                                                    \
+   (((((A).lo & 0x80000000) ^  ((B) & 0x80000000)) && !((X).lo & 0x80000000)) \
+  || (((A).lo & 0x80000000) && ((B) & 0x80000000)))                     \
+  )
+#define add64_64(X,A,B) (add64_32(X,A,(B).lo), (X).hi += (B).hi)
+
+#define sub64_32(X,A,B) ((X).lo = (A).lo - (B), \
+                         (X).hi = (A).hi - ((A).lo < (B)))
+#define sub64_64(X,A,B) (sub64_32(X,A,(B).lo), (X).hi -= (B).hi)
+
+/* Byte-order */
+#define hton64(X,Y) mk64(X,htonl(hi64(Y)),htonl(lo64(Y)))
+#define ntoh64(X,Y) mk64(X,ntohl(hi64(Y)),ntohl(lo64(Y)))
+
+#endif /* NATIVE_INT64 */
+
+
+/* The following are too complex to be macros: */
+
+/* char *hexify_int64(u_int64 a, char *buf)
+ * Produces an ASCII representation of a in hexadecimal, and returns
+ * a pointer to the resulting string.  If buf is non-NULL, it is taken
+ * to be a pointer to the buffer to be used, which must be at least 17
+ * bytes long.  This function is thread-safe iff buf is provided.
+ */
+extern char *hexify_int64(u_int64 *, char *);
+
+/* char *decimate_int64(u_int64 a, char *buf)
+ * Produces an ASCII representation of a in decimal, and returns
+ * a pointer to the resulting string.  If buf is non-NULL, it is taken
+ * to be a pointer to the buffer to be used, which must be at least 21
+ * bytes long.  This function is thread-safe iff buf is provided.
+ */
+extern char *decimate_int64(u_int64 *, char *);
+
+/* void shift_int64(u_int64 a, int bits)
+ * Shifts the 64-bit integer in a by the specified number of bits.
+ * If bits is positive, the shift is to the left; if negative, the
+ * shift is to the right.
+ */
+extern void shift_int64(u_int64 *, int);
+
+#endif /* _INTNN_H_ */
diff --git a/src/tools/internal.h b/src/tools/internal.h
new file mode 100644 (file)
index 0000000..276767a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* internal.h - Routines for internal use only */
+
+#include "xfiles.h"
+#include "dumpscan.h"
+
+
+/* parsevol.c - Routines to parse volume headers */
+extern afs_uint32 parse_volhdr(XFILE *, unsigned char *, tagged_field *,
+                              afs_uint32, tag_parse_info *, void *, void *);
+
+/* parsevnode.c - Routines to parse vnodes and their fields */
+extern afs_uint32 parse_vnode(XFILE *, unsigned char *, tagged_field *,
+                             afs_uint32, tag_parse_info *, void *, void *);
+
+/* directory.c - Routines for parsing AFS directories */
+extern afs_uint32 parse_directory(XFILE *, dump_parser *, afs_vnode *,
+                                 afs_uint32, int);
+
+/* backuphdr.c - Generic support for backup system headers */
+extern afs_uint32 try_backuphdr(XFILE * X, unsigned char *tag,
+                               tagged_field * field, afs_uint32 value,
+                               tag_parse_info * pi, void *g_refcon,
+                               void *l_refcon);
+
+/* util.c - Random utilities */
+extern afs_uint32 handle_return(int, XFILE *, unsigned char, dump_parser *);
+extern void prep_pi(dump_parser *, tag_parse_info *);
+extern afs_uint32 match_next_vnode(XFILE *, dump_parser *, u_int64 *,
+                                  afs_uint32);
diff --git a/src/tools/parsedump.c b/src/tools/parsedump.c
new file mode 100644 (file)
index 0000000..bbb48e8
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* parsedump.c - Parse a volume dump file */
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "dumpfmt.h"
+#include "internal.h"
+#include "stagehdr.h"
+
+static afs_uint32 parse_dumphdr(XFILE *, unsigned char *, tagged_field *,
+                               afs_uint32, tag_parse_info *, void *, void *);
+static afs_uint32 parse_dumpend(XFILE *, unsigned char *, tagged_field *,
+                               afs_uint32, tag_parse_info *, void *, void *);
+static afs_uint32 store_dumphdr(XFILE *, unsigned char *, tagged_field *,
+                               afs_uint32, tag_parse_info *, void *, void *);
+static afs_uint32 parse_dumptimes(XFILE *, unsigned char *, tagged_field *,
+                                 afs_uint32, tag_parse_info *, void *,
+                                 void *);
+
+/** Field list for top-level objects **/
+static tagged_field top_fields[] = {
+    {TAG_DUMPHEADER, DKIND_SPECIAL, "* DUMP HEADER", parse_dumphdr, 0, 0},
+    {TAG_VOLHEADER, DKIND_SPECIAL, "* VOLUME HEADER", parse_volhdr, 0, 0},
+    {TAG_VNODE, DKIND_SPECIAL, "* VNODE ", parse_vnode, 0, 0},
+    {TAG_DUMPEND, DKIND_INT32, "* DUMP END", parse_dumpend, 0, 0},
+    {STAGE_VERSMIN, DKIND_SPECIAL, "* STAGE HEADER", try_backuphdr, 0, 0},
+    {0, 0, 0, 0, 0, 0}
+};
+
+
+/** Field list for dump headers **/
+static tagged_field dumphdr_fields[] = {
+    {DHTAG_VOLNAME, DKIND_STRING, " Volume name:  ", store_dumphdr, 0, 0},
+    {DHTAG_VOLID, DKIND_INT32, " Volume ID:    ", store_dumphdr, 0, 0},
+    {DHTAG_DUMPTIMES, DKIND_SPECIAL, " Dump Range:   ", parse_dumptimes, 0,
+     0},
+    {0, 0, 0, 0, 0, 0}
+};
+
+
+/* Parse a dump header, including its tagged attributes, and call the
+ * dump-header callback, if one is defined.
+ */
+static afs_uint32
+parse_dumphdr(XFILE * X, unsigned char *tag, tagged_field * field,
+             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+             void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_dump_header hdr;
+    u_int64 where;
+    afs_uint32 r;
+
+    memset(&hdr, 0, sizeof(hdr));
+    if ((r = xftell(X, &where)))
+       return r;
+    sub64_32(hdr.offset, where, 1);
+
+    if ((r = ReadInt32(X, &hdr.magic)))
+       return r;
+    if ((r = ReadInt32(X, &hdr.version)))
+       return r;
+
+    if (hdr.magic != DUMPBEGINMAGIC) {
+       if (p->cb_error)
+           (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
+                          "Invalid magic number (0x%08x) in dump header",
+                          hdr.magic);
+       return DSERR_MAGIC;
+    }
+    if (hdr.version != DUMPVERSION) {
+       if (p->cb_error)
+           (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
+                          "Unknown dump format version (%d) in dump header",
+                          hdr.version);
+       return DSERR_MAGIC;
+    }
+
+    if (p->print_flags & DSPRINT_DUMPHDR)
+       printf("%s [%s = 0x%s]\n", field->label,
+              decimate_int64(&hdr.offset, 0), hexify_int64(&hdr.offset, 0));
+    if (p->print_flags & DSPRINT_DUMPHDR) {
+       printf(" Magic number: 0x%08x\n", hdr.magic);
+       printf(" Version:      %d\n", hdr.version);
+    }
+    r = ParseTaggedData(X, dumphdr_fields, tag, pi, g_refcon, (void *)&hdr);
+
+    if (!r && p->cb_dumphdr) {
+       r = xftell(X, &where);
+       if (!r)
+           r = (p->cb_dumphdr) (&hdr, X, p->refcon);
+       if (p->flags & DSFLAG_SEEK) {
+           if (!r)
+               r = xfseek(X, &where);
+           else
+               xfseek(X, &where);
+       }
+    }
+    if (hdr.field_mask & F_DUMPHDR_VOLNAME)
+       free(hdr.volname);
+    return r;
+}
+
+
+/* Store tagged attributes into a dump header */
+static afs_uint32
+store_dumphdr(XFILE * X, unsigned char *tag, tagged_field * field,
+             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+             void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_dump_header *hdr = (afs_dump_header *) l_refcon;
+
+    switch (field->tag) {
+    case DHTAG_VOLID:
+       hdr->field_mask |= F_DUMPHDR_VOLID;
+       hdr->volid = value;
+       if (p->print_flags & DSPRINT_DUMPHDR)
+           printf("%s%d\n", field->label, hdr->volid);
+       return 0;
+
+    case DHTAG_VOLNAME:
+       if (tag && tag[0]) {
+           hdr->field_mask |= F_DUMPHDR_VOLNAME;
+           hdr->volname = tag;
+           if (p->print_flags & DSPRINT_DUMPHDR)
+               printf("%s%s\n", field->label, hdr->volname);
+           return DSERR_KEEP;
+       } else
+           return 0;
+
+    default:
+       if (p->print_flags & DSPRINT_DUMPHDR)
+           printf("%s<<< UNKNOWN FIELD >>>\n", field->label);
+       return 0;
+    }
+}
+
+
+/* Parse and store the dump time range from a dump header */
+static afs_uint32
+parse_dumptimes(XFILE * X, unsigned char *tag, tagged_field * field,
+               afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+               void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_dump_header *hdr = (afs_dump_header *) l_refcon;
+    afs_uint16 count;
+    afs_uint32 r;
+
+    if ((r = ReadInt16(X, &count)))
+       return r;
+    if (count != 2) {
+       if (p->cb_error)
+           (p->cb_error) (DSERR_FMT, 1, p->err_refcon,
+                          "Incorrect array count (%d) in dump times", count);
+       return DSERR_FMT;
+    }
+    if ((r = ReadInt32(X, &hdr->from_date)))
+       return r;
+    if ((r = ReadInt32(X, &hdr->to_date)))
+       return r;
+    hdr->field_mask |= (F_DUMPHDR_FROM | F_DUMPHDR_TO);
+    if (p->print_flags & DSPRINT_DUMPHDR)
+       printf("%s%d => %d\n", field->label, hdr->from_date, hdr->to_date);
+
+    return ReadByte(X, tag);
+}
+
+
+/* Parse a dump_end record */
+static afs_uint32
+parse_dumpend(XFILE * X, unsigned char *tag, tagged_field * field,
+             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+             void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+
+    if (value != DUMPENDMAGIC) {
+       if (p->cb_error)
+           (p->cb_error) (DSERR_MAGIC, 1, p->err_refcon,
+                          "Invalid magic number (0x%08x) in dump trailer",
+                          value);
+       return DSERR_MAGIC;
+    }
+    if (p->print_flags & (DSPRINT_DUMPHDR | DSPRINT_ITEM))
+       printf("%s\n", field->label);
+    return DSERR_DONE;
+}
+
+
+
+afs_uint32
+ParseDumpFile(XFILE * X, dump_parser * p)
+{
+    tag_parse_info pi;
+    unsigned char tag;
+    afs_uint32 r;
+
+    prep_pi(p, &pi);
+    r = ParseTaggedData(X, top_fields, &tag, &pi, (void *)p, 0);
+    return handle_return(r, X, tag, p);
+}
+
+
+afs_uint32
+ParseDumpHeader(XFILE * X, dump_parser * p)
+{
+    tag_parse_info pi;
+    unsigned char tag;
+    afs_uint32 r;
+
+    prep_pi(p, &pi);
+    if ((r = ReadByte(X, &tag)))
+       return handle_return(r, X, tag, p);
+    if (tag != TAG_DUMPHEADER)
+       return handle_return(0, X, tag, p);
+    r = parse_dumphdr(X, &tag, &top_fields[0], 0, &pi, (void *)p, 0);
+    if (!r && tag >= 1 && tag <= 4)
+       r = DSERR_DONE;
+    return handle_return(r, X, tag, p);
+}
+
+
+afs_uint32
+ParseVolumeHeader(XFILE * X, dump_parser * p)
+{
+    tag_parse_info pi;
+    unsigned char tag;
+    afs_uint32 r;
+
+    prep_pi(p, &pi);
+    if ((r = ReadByte(X, &tag)))
+       return handle_return(r, X, tag, p);
+    if (tag != TAG_VOLHEADER)
+       return handle_return(0, X, tag, p);
+    r = parse_volhdr(X, &tag, &top_fields[1], 0, &pi, (void *)p, 0);
+    if (!r && tag >= 1 && tag <= 4)
+       r = DSERR_DONE;
+    return handle_return(r, X, tag, p);
+}
+
+
+afs_uint32
+ParseVNode(XFILE * X, dump_parser * p)
+{
+    tag_parse_info pi;
+    unsigned char tag;
+    afs_uint32 r;
+
+    prep_pi(p, &pi);
+    if ((r = ReadByte(X, &tag)))
+       return handle_return(r, X, tag, p);
+    if (tag != TAG_VNODE)
+       return handle_return(0, X, tag, p);
+    r = parse_vnode(X, &tag, &top_fields[2], 0, &pi, (void *)p, 0);
+    if (!r && tag >= 1 && tag <= 4)
+       r = DSERR_DONE;
+    return handle_return(r, X, tag, p);
+}
diff --git a/src/tools/parsetag.c b/src/tools/parsetag.c
new file mode 100644 (file)
index 0000000..67e8a2c
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* parsetag.c - Parse a tagged data stream */
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+
+/* If a parser function is defined, it will be called after the data value
+ * (if any) is read.  The parser is called as follows:
+ *
+ *   parser(input_file, &tag, &field_rec, value, g_refcon, l_refcon);
+ *
+ * - input_file is the FILE * for the input stream
+ * - field_rec is a pointer to the field record for the field just read
+ * - g_refcon and l_refcon are as passed in to ParseTaggedData
+ * - For integer types, value is the integer value
+ * - For DKIND_STRING, tag is a pointer to the string just read
+ * - For DKIND_SPEACH, tag is a pointer to the place to put the next tag.
+ *
+ * If the field type is DKIND_SPECIAL, the parser is expected to read its
+ * own data from the input stream, and return when ParseTaggedData is supposed
+ * to take over, with the next tag to process in *tag.  At no other time
+ * should the parser read, write, or reposition the input stream.
+ *
+ * The parser routine should return 0 on success, non-0 on failure.  If the
+ * data type is DKIND_STRING, the parser may return DSERR_KEEP to indicate
+ * that the memory allocated for the value should not be freed.
+ */
+
+/* Parse a file containing tagged data and attributes **/
+afs_uint32
+ParseTaggedData(XFILE * X, tagged_field * fields, unsigned char *tag,
+               tag_parse_info * pi, void *g_refcon, void *l_refcon)
+{
+    int i = -1;
+    afs_uint32 r, val;
+    afs_uint16 val16;
+    unsigned char val8;
+    unsigned char *strval;
+
+    for (;;) {
+       if (i < 0 || (fields[i].kind & DKIND_MASK) != DKIND_SPECIAL) {
+           /* Need to read in a tag */
+           if ((r = ReadByte(X, tag)))
+               return r;
+       }
+
+       /* Simple error recovery - if we encounter a 0, it can never be
+        * a valid tag.  If TPFLAG_SKIP is set, we can skip over any
+        * such null bytes, and process whatever tag we find beyond.
+        * In addition, if TPFLAG_RSKIP is set, then the next time
+        * we encounter a 0, try skipping backwards.  That seems to
+        * work much of the time.
+        */
+       if (!*tag && pi->shift_offset && (pi->flags & TPFLAG_RSKIP)) {
+           u_int64 where, tmp64a, tmp64b;
+           char buf1[21], buf2[21], buf3[21];
+           char *p1, *p2, *p3;
+
+           if ((r = xftell(X, &tmp64a)))
+               return r;
+           sub64_32(where, tmp64a, pi->shift_offset + 1);
+           if ((r = xfseek(X, &where)))
+               return r;
+           if (pi->cb_error) {
+               (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
+                               "Inserted %d bytes before offset %d",
+                               pi->shift_offset, decimate_int64(&where, 0));
+               add64_32(tmp64a, pi->shift_start, pi->shift_offset);
+               p1 = decimate_int64(&tmp64a, buf1);
+               sub64_64(tmp64b, where, tmp64a);
+               p2 = decimate_int64(&tmp64b, buf2);
+               p3 = decimate_int64(&pi->shift_start, buf3);
+               (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
+                               ">>> SHIFT start=%s length=%s target=%s", p1,
+                               p2, p3);
+           }
+           pi->shift_offset = 0;
+           if ((r = ReadByte(X, tag)))
+               return r;
+       }
+       if (!*tag && (pi->flags & TPFLAG_SKIP)) {
+           int count = 0;
+           u_int64 where, tmp64a;
+
+           if ((r = xftell(X, &where)))
+               return r;
+
+           while (!*tag) {
+               if ((r = ReadByte(X, tag)))
+                   return r;
+               count++;
+           }
+           pi->shift_offset += count;
+           cp64(pi->shift_start, where);
+           if (pi->cb_error) {
+               sub64_32(tmp64a, where, 1);
+               (pi->cb_error) (DSERR_FMT, 0, pi->err_refcon,
+                               "Skipped %d bytes at offset %s", count,
+                               decimate_int64(&tmp64a, 0));
+           }
+       }
+
+       for (i = 0; fields[i].tag && fields[i].tag != *tag; i++);
+       if (!fields[i].tag)
+           return 0;
+
+       switch (fields[i].kind & DKIND_MASK) {
+       case DKIND_NOOP:
+           if (fields[i].func) {
+               r = (fields[i].func) (X, 0, fields + i, 0, pi, g_refcon,
+                                     l_refcon);
+               if (r)
+                   return r;
+           }
+           break;
+
+       case DKIND_BYTE:
+           if ((r = ReadByte(X, &val8)))
+               return r;
+           if (fields[i].func) {
+               r = (fields[i].func) (X, 0, fields + i, val8, pi, g_refcon,
+                                     l_refcon);
+               if (r)
+                   return r;
+           }
+           break;
+
+       case DKIND_INT16:
+           if ((r = ReadInt16(X, &val16)))
+               return r;
+           if (fields[i].func) {
+               r = (fields[i].func) (X, 0, fields + i, val16, pi, g_refcon,
+                                     l_refcon);
+               if (r)
+                   return r;
+           }
+           break;
+
+       case DKIND_INT32:
+           if ((r = ReadInt32(X, &val)))
+               return r;
+           if (fields[i].func) {
+               r = (fields[i].func) (X, 0, fields + i, val, pi, g_refcon,
+                                     l_refcon);
+               if (r)
+                   return r;
+           }
+           break;
+
+       case DKIND_STRING:
+           if ((r = ReadString(X, &strval)))
+               return r;
+           if (fields[i].func) {
+               r = (fields[i].func) (X, strval, fields + i, 0, pi, g_refcon,
+                                     l_refcon);
+               if (r != DSERR_KEEP)
+                   free(strval);
+               if (r && r != DSERR_KEEP)
+                   return r;
+           } else
+               free(strval);
+           break;
+
+       case DKIND_SPECIAL:
+           if (fields[i].func) {
+               r = (fields[i].func) (X, tag, fields + i, 0, pi, g_refcon,
+                                     l_refcon);
+               if (r)
+                   return r;
+           } else
+               i = -1;
+       }
+    }
+}
diff --git a/src/tools/parsevnode.c b/src/tools/parsevnode.c
new file mode 100644 (file)
index 0000000..8f09fd1
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* parsevnode.c - Parse a VNode */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "dumpfmt.h"
+#include "internal.h"
+
+#include <afs/acl.h>
+#include <afs/prs_fs.h>
+
+static afs_uint32 LastGoodVNode = 0;
+static afs_uint32 store_vnode(XFILE *, unsigned char *, tagged_field *,
+                             afs_uint32, tag_parse_info *, void *, void *);
+static afs_uint32 parse_acl(XFILE *, unsigned char *, tagged_field *,
+                           afs_uint32, tag_parse_info *, void *, void *);
+static afs_uint32 parse_vdata(XFILE *, unsigned char *, tagged_field *,
+                             afs_uint32, tag_parse_info *, void *, void *);
+
+/** Field list for vnodes **/
+static tagged_field vnode_fields[] = {
+    {VTAG_TYPE, DKIND_BYTE, " VNode type:   ", store_vnode, 0, 0},
+    {VTAG_NLINKS, DKIND_INT16, " Link count:   ", store_vnode, 0, 0},
+    {VTAG_DVERS, DKIND_INT32, " Version:      ", store_vnode, 0, 0},
+    {VTAG_CLIENT_DATE, DKIND_TIME, " Server Date:  ", store_vnode, 0, 0},
+    {VTAG_AUTHOR, DKIND_INT32, " Author:       ", store_vnode, 0, 0},
+    {VTAG_OWNER, DKIND_INT32, " Owner:        ", store_vnode, 0, 0},
+    {VTAG_GROUP, DKIND_INT32, " Group:        ", store_vnode, 0, 0},
+    {VTAG_MODE, DKIND_INT16, " UNIX mode:    ", store_vnode, 0, 0},
+    {VTAG_PARENT, DKIND_INT32, " Parent:       ", store_vnode, 0, 0},
+    {VTAG_SERVER_DATE, DKIND_TIME, " Client Date:  ", store_vnode, 0, 0},
+    {VTAG_ACL, DKIND_SPECIAL, " xxxxxxxx ACL: ", parse_acl, 0, 0},
+    {VTAG_DATA, DKIND_SPECIAL, " Contents:     ", parse_vdata, 0, 0},
+    {0, 0, 0, 0, 0, 0}
+};
+
+
+static afs_uint32
+resync_vnode(XFILE * X, dump_parser * p, afs_vnode * v, int start, int limit)
+{
+    u_int64 where, expected_where;
+    afs_uint32 r;
+    int i;
+
+    if ((r = xftell(X, &expected_where)))
+       return r;
+    cp64(where, expected_where);
+
+    r = match_next_vnode(X, p, &where, v->vnode);
+    if (r && r != DSERR_FMT)
+       return r;
+    if (r)
+       for (i = -start; i < limit; i++) {
+           add64_32(where, expected_where, i);
+           r = match_next_vnode(X, p, &where, v->vnode);
+           if (!r)
+               break;
+           if (r != DSERR_FMT)
+               return r;
+       }
+    if (r) {
+       if (p->cb_error)
+           (p->cb_error) (r, 1, p->err_refcon,
+                          "Unable to resync after vnode %d [%s = 0x%s]",
+                          v->vnode, decimate_int64(&expected_where, 0),
+                          hexify_int64(&expected_where, 0));
+       return r;
+    }
+    if (ne64(where, expected_where) && p->cb_error) {
+       (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
+                      "Vnode after %d not in expected location", v->vnode);
+       (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
+                      "Expected location: %s = 0x%s",
+                      decimate_int64(&expected_where, 0),
+                      hexify_int64(&expected_where, 0));
+       (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
+                      "Actual location: %s = 0x%s", decimate_int64(&where,
+                                                                   0),
+                      hexify_int64(&where, 0));
+    }
+    return xfseek(X, &where);
+}
+
+
+/* Parse a VNode, including any tagged attributes and data, and call the
+ * appropriate callback, if one is defined.
+ */
+afs_uint32
+parse_vnode(XFILE * X, unsigned char *tag, tagged_field * field,
+           afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+           void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_uint32(*cb) (afs_vnode *, XFILE *, void *);
+    u_int64 where, offset2k;
+    afs_vnode v;
+    afs_uint32 r;
+
+
+    if ((r = xftell(X, &where)))
+       return r;
+    memset(&v, 0, sizeof(v));
+    sub64_32(v.offset, where, 1);
+    if ((r = ReadInt32(X, &v.vnode)))
+       return r;
+    if ((r = ReadInt32(X, &v.vuniq)))
+       return r;
+
+    mk64(offset2k, 0, 2048);
+    if (!LastGoodVNode
+       || ((p->flags & DSFLAG_SEEK) && v.vnode == 1
+           && lt64(v.offset, offset2k)))
+       LastGoodVNode = -1;
+
+    if (p->print_flags & DSPRINT_ITEM) {
+       printf("%s %d/%d [%s = 0x%s]\n", field->label, v.vnode, v.vuniq,
+              decimate_int64(&where, 0), hexify_int64(&where, 0));
+    }
+
+    r = ParseTaggedData(X, vnode_fields, tag, pi, g_refcon, (void *)&v);
+
+    /* Try to resync, if requested */
+    if (!r && (p->repair_flags & DSFIX_VFSYNC)) {
+       afs_uint32 drop;
+       u_int64 xwhere;
+
+       if ((r = xftell(X, &where)))
+           return r;
+       sub64_32(xwhere, where, 1);
+
+       /* Are we at the start of a valid vnode (or dump end)? */
+       r = match_next_vnode(X, p, &xwhere, v.vnode);
+       if (r && r != DSERR_FMT)
+           return r;
+       if (r) {                /* Nope. */
+           /* Was _this_ a valid vnode?  If so, we can keep it and search for
+            * the next one.  Otherwise, we throw it out, and start the search
+            * at the starting point of this vnode.
+            */
+           drop = r = match_next_vnode(X, p, &v.offset, LastGoodVNode);
+           if (r && r != DSERR_FMT)
+               return r;
+           if (!r) {
+               add64_32(where, v.offset, 1);
+               if ((r = xfseek(X, &v.offset)))
+                   return r;
+           } else {
+               if ((r = xfseek(X, &xwhere)))
+                   return r;
+           }
+           if ((r = resync_vnode(X, p, &v, 0, 1024)))
+               return r;
+           if ((r = ReadByte(X, tag)))
+               return r;
+           if (drop) {
+               if (p->cb_error)
+                   (p->cb_error) (DSERR_FMT, 0, p->err_refcon,
+                                  "Dropping vnode %d", v.vnode);
+               return 0;
+           }
+       } else {
+           if ((r = xfseek(X, &where)))
+               return r;
+       }
+    }
+    LastGoodVNode = v.vnode;
+
+    if (!r) {
+       if (v.field_mask & F_VNODE_TYPE)
+           switch (v.type) {
+           case vFile:
+               cb = p->cb_vnode_file;
+               break;
+           case vDirectory:
+               cb = p->cb_vnode_dir;
+               break;
+           case vSymlink:
+               cb = p->cb_vnode_link;
+               break;
+           default:
+               cb = p->cb_vnode_wierd;
+               break;
+       } else
+           cb = p->cb_vnode_empty;
+       if (cb) {
+           u_int64 where;
+
+           if ((r = xftell(X, &where)))
+               return r;
+           r = (cb) (&v, X, p->refcon);
+           if (p->flags & DSFLAG_SEEK) {
+               if (!r)
+                   r = xfseek(X, &where);
+               else
+                   xfseek(X, &where);
+           }
+       }
+    }
+    return r;
+}
+
+
+/* Store data in a vnode */
+static afs_uint32
+store_vnode(XFILE * X, unsigned char *tag, tagged_field * field,
+           afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+           void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_vnode *v = (afs_vnode *) l_refcon;
+    time_t when;
+    afs_uint32 r = 0;
+
+    switch (field->tag) {
+    case VTAG_TYPE:
+       v->field_mask |= F_VNODE_TYPE;
+       v->type = value;
+       if (p->print_flags & DSPRINT_VNODE) {
+           switch (value) {
+           case vFile:
+               printf("%sFile (%d)\n", field->label, value);
+               break;
+           case vDirectory:
+               printf("%sDirectory (%d)\n", field->label, value);
+               break;
+           case vSymlink:
+               printf("%sSymbolic Link (%d)\n", field->label, value);
+               break;
+           default:
+               printf("%s??? (%d)\n", field->label, value);
+           }
+           return r;
+       }
+       break;
+
+    case VTAG_NLINKS:
+       v->field_mask |= F_VNODE_NLINKS;
+       v->nlinks = value;
+       break;
+
+    case VTAG_DVERS:
+       v->field_mask |= F_VNODE_DVERS;
+       v->datavers = value;
+       break;
+
+    case VTAG_CLIENT_DATE:
+       v->field_mask |= F_VNODE_CDATE;
+       v->client_date = value;
+       break;
+
+    case VTAG_SERVER_DATE:
+       v->field_mask |= F_VNODE_SDATE;
+       v->server_date = value;
+       break;
+
+    case VTAG_AUTHOR:
+       v->field_mask |= F_VNODE_AUTHOR;
+       v->author = value;
+       break;
+
+    case VTAG_OWNER:
+       v->field_mask |= F_VNODE_OWNER;
+       v->owner = value;
+       break;
+
+    case VTAG_GROUP:
+       v->field_mask |= F_VNODE_GROUP;
+       v->group = value;
+       break;
+
+    case VTAG_MODE:
+       v->field_mask |= F_VNODE_MODE;
+       v->mode = value;
+       break;
+
+    case VTAG_PARENT:
+       v->field_mask |= F_VNODE_PARENT;
+       v->parent = value;
+       break;
+    }
+
+    if (p->print_flags & DSPRINT_VNODE)
+       switch (field->kind) {
+       case DKIND_BYTE:
+       case DKIND_INT16:
+       case DKIND_INT32:
+           printf("%s%d\n", field->label, value);
+           break;
+       case DKIND_HEX8:
+           printf("%s0x%02x\n", field->label, value);
+           break;
+       case DKIND_HEX16:
+           printf("%s0x%04x\n", field->label, value);
+           break;
+       case DKIND_HEX32:
+           printf("%s0x%08x\n", field->label, value);
+           break;
+       case DKIND_CHAR:
+           printf("%s%c\n", field->label, value);
+           break;
+       case DKIND_STRING:
+           printf("%s%s\n", field->label, tag);
+           break;
+       case DKIND_FLAG:
+           printf("%s%s\n", field->label, value ? "true" : "false");
+           break;
+       case DKIND_TIME:
+           when = value;
+           printf("%s%s", field->label, ctime(&when));
+           break;
+       }
+    return r;
+}
+
+
+static char *
+rights2str(afs_uint32 rights)
+{
+    static char str[16];
+    char *p = str;
+
+    if (rights & PRSFS_READ)
+       *p++ = 'r';
+    if (rights & PRSFS_LOOKUP)
+       *p++ = 'l';
+    if (rights & PRSFS_INSERT)
+       *p++ = 'i';
+    if (rights & PRSFS_DELETE)
+       *p++ = 'd';
+    if (rights & PRSFS_WRITE)
+       *p++ = 'w';
+    if (rights & PRSFS_LOCK)
+       *p++ = 'k';
+    if (rights & PRSFS_ADMINISTER)
+       *p++ = 'a';
+    if (rights & PRSFS_USR0)
+       *p++ = 'A';
+    if (rights & PRSFS_USR1)
+       *p++ = 'B';
+    if (rights & PRSFS_USR2)
+       *p++ = 'C';
+    if (rights & PRSFS_USR3)
+       *p++ = 'D';
+    if (rights & PRSFS_USR4)
+       *p++ = 'E';
+    if (rights & PRSFS_USR5)
+       *p++ = 'F';
+    if (rights & PRSFS_USR6)
+       *p++ = 'G';
+    if (rights & PRSFS_USR7)
+       *p++ = 'H';
+
+    *p = 0;
+    if (!str[0])
+       strcpy(str, "none");
+    return str;
+}
+
+
+/* Parse and store the ACL data from a directory vnode */
+static afs_uint32
+parse_acl(XFILE * X, unsigned char *tag, tagged_field * field,
+         afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+         void *l_refcon)
+{
+    struct acl_accessList *acl;
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_vnode *v = (afs_vnode *) l_refcon;
+    afs_uint32 r, i, n;
+
+    if ((r = xfread(X, v->acl, SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE)))
+       return r;
+
+    v->field_mask |= F_VNODE_ACL;
+    if (p->print_flags & DSPRINT_ACL) {
+       acl = (struct acl_accessList *)(v->acl);
+       n = ntohl(acl->positive);
+       if (n) {
+           printf(" Positive ACL: %d entries\n", n);
+           for (i = 0; i < n; i++)
+               printf("              %9d  %s\n", ntohl(acl->entries[i].id),
+                      rights2str(ntohl(acl->entries[i].rights)));
+       }
+       n = ntohl(acl->negative);
+       if (n) {
+           printf(" Negative ACL: %d entries\n", n);
+           for (i = ntohl(acl->positive); i < ntohl(acl->total); i++)
+               printf("              %9d  %s\n", ntohl(acl->entries[i].id),
+                      rights2str(ntohl(acl->entries[i].rights)));
+       }
+    }
+    return ReadByte(X, tag);
+}
+
+
+/* Parse or skip over the vnode data */
+static afs_uint32
+parse_vdata(XFILE * X, unsigned char *tag, tagged_field * field,
+           afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+           void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_vnode *v = (afs_vnode *) l_refcon;
+    static char *symlink_buf = 0;
+    static int symlink_size = 0;
+    afs_uint32 r;
+
+    if ((r = ReadInt32(X, &v->size)))
+       return r;
+    v->field_mask |= F_VNODE_SIZE;
+
+    if (v->size) {
+       v->field_mask |= F_VNODE_DATA;
+       if ((r = xftell(X, &v->d_offset)))
+           return r;
+       if (p->print_flags & DSPRINT_VNODE)
+           printf("%s%d (0x%08x) bytes at %s (0x%s)\n", field->label,
+                  v->size, v->size, decimate_int64(&v->d_offset, 0),
+                  hexify_int64(&v->d_offset, 0));
+
+       switch (v->type) {
+       case vSymlink:
+           if (v->size > symlink_size) {
+               if (symlink_buf)
+                   symlink_buf = (char *)realloc(symlink_buf, v->size + 1);
+               else
+                   symlink_buf = (char *)malloc(v->size + 1);
+               symlink_size = symlink_buf ? v->size : 0;
+           }
+           if (symlink_buf) {
+               if ((r = xfread(X, symlink_buf, v->size)))
+                   return r;
+               symlink_buf[v->size] = 0;
+               if (p->print_flags & DSPRINT_VNODE)
+                   printf(" Target:       %s\n", symlink_buf);
+           } else {
+               /* Call the callback here, because it's non-fatal */
+               if (p->cb_error)
+                   (p->cb_error) (ENOMEM, 0, p->err_refcon,
+                                  "Out of memory reading symlink");
+               if ((r = xfskip(X, v->size)))
+                   return r;
+           }
+           break;
+
+       case vDirectory:
+           if (p->cb_dirent || (p->print_flags & DSPRINT_DIR)) {
+               if ((r = parse_directory(X, p, v, v->size, 0)))
+                   return r;
+               break;
+           }
+
+       default:
+           if ((r = xfskip(X, v->size)))
+               return r;
+       }
+    } else if (p->print_flags & DSPRINT_VNODE) {
+       printf("%sEmpty\n", field->label);
+    }
+    if (p->repair_flags & DSFIX_VDSYNC) {
+       r = resync_vnode(X, p, v, 10, 15);
+       if (r)
+           return r;
+    }
+    return ReadByte(X, tag);
+}
diff --git a/src/tools/parsevol.c b/src/tools/parsevol.c
new file mode 100644 (file)
index 0000000..9b95368
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* parsevol.c - Parse a volume header */
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "dumpfmt.h"
+
+static afs_uint32 store_volhdr(XFILE *, unsigned char *, tagged_field *,
+                              afs_uint32, tag_parse_info *, void *, void *);
+static afs_uint32 parse_weekuse(XFILE *, unsigned char *, tagged_field *,
+                               afs_uint32, tag_parse_info *, void *, void *);
+
+/** Field list for volume headers **/
+static tagged_field volhdr_fields[] = {
+    {VHTAG_VOLID, DKIND_INT32, " Volume ID:   ", store_volhdr, 0, 0},
+    {VHTAG_VERS, DKIND_INT32, " Version:     ", store_volhdr, 0, 0},
+    {VHTAG_VOLNAME, DKIND_STRING, " Volume name: ", store_volhdr, 0, 0},
+    {VHTAG_INSERV, DKIND_FLAG, " In service?  ", store_volhdr, 0, 0},
+    {VHTAG_BLESSED, DKIND_FLAG, " Blessed?     ", store_volhdr, 0, 0},
+    {VHTAG_VUNIQ, DKIND_INT32, " Uniquifier:  ", store_volhdr, 0, 0},
+    {VHTAG_TYPE, DKIND_BYTE, " Type:        ", store_volhdr, 0, 0},
+    {VHTAG_PARENT, DKIND_INT32, " Parent ID:   ", store_volhdr, 0, 0},
+    {VHTAG_CLONE, DKIND_INT32, " Clone ID:    ", store_volhdr, 0, 0},
+    {VHTAG_MAXQUOTA, DKIND_INT32, " Max quota:   ", store_volhdr, 0, 0},
+    {VHTAG_MINQUOTA, DKIND_INT32, " Min quota:   ", store_volhdr, 0, 0},
+    {VHTAG_DISKUSED, DKIND_INT32, " Disk used:   ", store_volhdr, 0, 0},
+    {VHTAG_FILECNT, DKIND_INT32, " File count:  ", store_volhdr, 0, 0},
+    {VHTAG_ACCOUNT, DKIND_INT32, " Account:     ", store_volhdr, 0, 0},
+    {VHTAG_OWNER, DKIND_INT32, " Owner:       ", store_volhdr, 0, 0},
+    {VHTAG_CREAT, DKIND_TIME, " Created:     ", store_volhdr, 0, 0},
+    {VHTAG_ACCESS, DKIND_TIME, " Accessed:    ", store_volhdr, 0, 0},
+    {VHTAG_UPDATE, DKIND_TIME, " Updated:     ", store_volhdr, 0, 0},
+    {VHTAG_EXPIRE, DKIND_TIME, " Expires:     ", store_volhdr, 0, 0},
+    {VHTAG_BACKUP, DKIND_TIME, " Backed up:   ", store_volhdr, 0, 0},
+    {VHTAG_OFFLINE, DKIND_STRING, " Offine Msg:  ", store_volhdr, 0, 0},
+    {VHTAG_MOTD, DKIND_STRING, " MOTD:        ", store_volhdr, 0, 0},
+    {VHTAG_WEEKUSE, DKIND_SPECIAL, " Weekuse:     ", parse_weekuse, 0, 0},
+    {VHTAG_DUDATE, DKIND_TIME, " Dayuse Date: ", store_volhdr, 0, 0},
+    {VHTAG_DAYUSE, DKIND_INT32, " Daily usage: ", store_volhdr, 0, 0},
+    {0, 0, 0, 0, 0, 0}
+};
+
+
+/* Parse a volume header, including any tagged attributes, and call the
+ * volume-header callback, if one is defined.
+ */
+afs_uint32
+parse_volhdr(XFILE * X, unsigned char *tag, tagged_field * field,
+            afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+            void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_vol_header hdr;
+    u_int64 where;
+    afs_uint32 r;
+
+    memset(&hdr, 0, sizeof(hdr));
+    if ((r = xftell(X, &where)))
+       return r;
+    sub64_32(hdr.offset, where, 1);
+    if (p->print_flags & DSPRINT_VOLHDR)
+       printf("%s [%s = 0x%s]\n", field->label,
+              decimate_int64(&hdr.offset, 0), hexify_int64(&hdr.offset, 0));
+
+    r = ParseTaggedData(X, volhdr_fields, tag, pi, g_refcon, (void *)&hdr);
+
+    if (!r && p->cb_volhdr) {
+      if ((r = xftell(X, &where)))
+           return r;
+       r = (p->cb_volhdr) (&hdr, X, p->refcon);
+       if (p->flags & DSFLAG_SEEK) {
+           if (!r)
+               r = xfseek(X, &where);
+           else
+               xfseek(X, &where);
+       }
+    }
+    if (hdr.field_mask & F_VOLHDR_VOLUNIQ)
+       p->vol_uniquifier = hdr.voluniq;
+    if (hdr.field_mask & F_VOLHDR_VOLNAME)
+       free(hdr.volname);
+    if (hdr.field_mask & F_VOLHDR_OFFLINE_MSG)
+       free(hdr.offline_msg);
+    if (hdr.field_mask & F_VOLHDR_MOTD)
+       free(hdr.motd_msg);
+    return r;
+}
+
+
+/* Store data in a volume header */
+static afs_uint32
+store_volhdr(XFILE * X, unsigned char *tag, tagged_field * field,
+            afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+            void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_vol_header *hdr = (afs_vol_header *) l_refcon;
+    time_t when;
+    afs_uint32 r = 0;
+
+    switch (field->tag) {
+    case VHTAG_VOLID:
+       hdr->field_mask |= F_VOLHDR_VOLID;
+       hdr->volid = value;
+       break;
+
+    case VHTAG_VERS:
+       hdr->field_mask |= F_VOLHDR_VOLVERS;
+       hdr->volvers = value;
+       break;
+
+    case VHTAG_VOLNAME:
+       if (tag && tag[0]) {
+           hdr->field_mask |= F_VOLHDR_VOLNAME;
+           hdr->volname = tag;
+           r = DSERR_KEEP;
+       }
+       break;
+
+    case VHTAG_INSERV:
+       hdr->field_mask |= F_VOLHDR_INSERV;
+       hdr->flag_inservice = value;
+       break;
+
+    case VHTAG_BLESSED:
+       hdr->field_mask |= F_VOLHDR_BLESSED;
+       hdr->flag_blessed = value;
+       break;
+
+    case VHTAG_VUNIQ:
+       hdr->field_mask |= F_VOLHDR_VOLUNIQ;
+       hdr->voluniq = value;
+       break;
+
+    case VHTAG_TYPE:
+       hdr->field_mask |= F_VOLHDR_VOLTYPE;
+       hdr->voltype = value;
+       break;
+
+    case VHTAG_PARENT:
+       hdr->field_mask |= F_VOLHDR_PARENT;
+       hdr->parent_volid = value;
+       break;
+
+    case VHTAG_CLONE:
+       hdr->field_mask |= F_VOLHDR_CLONE;
+       hdr->clone_volid = value;
+       break;
+
+    case VHTAG_MAXQUOTA:
+       hdr->field_mask |= F_VOLHDR_MAXQ;
+       hdr->maxquota = value;
+       break;
+
+    case VHTAG_MINQUOTA:
+       hdr->field_mask |= F_VOLHDR_MINQ;
+       hdr->minquota = value;
+       break;
+
+    case VHTAG_DISKUSED:
+       hdr->field_mask |= F_VOLHDR_DISKUSED;
+       hdr->diskused = value;
+       break;
+
+    case VHTAG_FILECNT:
+       hdr->field_mask |= F_VOLHDR_NFILES;
+       hdr->nfiles = value;
+       break;
+
+    case VHTAG_ACCOUNT:
+       hdr->field_mask |= F_VOLHDR_ACCOUNT;
+       hdr->account_no = value;
+       break;
+
+    case VHTAG_OWNER:
+       hdr->field_mask |= F_VOLHDR_OWNER;
+       hdr->owner = value;
+       break;
+
+    case VHTAG_CREAT:
+       hdr->field_mask |= F_VOLHDR_CREATE_DATE;
+       hdr->create_date = value;
+       break;
+
+    case VHTAG_ACCESS:
+       hdr->field_mask |= F_VOLHDR_ACCESS_DATE;
+       hdr->access_date = value;
+       break;
+
+    case VHTAG_UPDATE:
+       hdr->field_mask |= F_VOLHDR_UPDATE_DATE;
+       hdr->update_date = value;
+       break;
+
+    case VHTAG_EXPIRE:
+       hdr->field_mask |= F_VOLHDR_EXPIRE_DATE;
+       hdr->expire_date = value;
+       break;
+
+    case VHTAG_BACKUP:
+       hdr->field_mask |= F_VOLHDR_BACKUP_DATE;
+       hdr->backup_date = value;
+       break;
+
+    case VHTAG_OFFLINE:
+       if (tag && tag[0]) {
+           hdr->field_mask |= F_VOLHDR_OFFLINE_MSG;
+           hdr->offline_msg = tag;
+           r = DSERR_KEEP;
+       }
+       break;
+
+    case VHTAG_MOTD:
+       if (tag && tag[0]) {
+           hdr->field_mask |= F_VOLHDR_MOTD;
+           hdr->motd_msg = tag;
+           r = DSERR_KEEP;
+       }
+       break;
+
+    case VHTAG_DUDATE:
+       hdr->field_mask |= F_VOLHDR_DAYUSE_DATE;
+       hdr->dayuse_date = value;
+       break;
+
+    case VHTAG_DAYUSE:
+       hdr->field_mask |= F_VOLHDR_DAYUSE;
+       hdr->dayuse = value;
+       break;
+    }
+
+    if (p->print_flags & DSPRINT_VOLHDR)
+       switch (field->kind) {
+       case DKIND_BYTE:
+       case DKIND_INT16:
+       case DKIND_INT32:
+           printf("%s%d\n", field->label, value);
+           break;
+       case DKIND_HEX8:
+           printf("%s0x%02x\n", field->label, value);
+           break;
+       case DKIND_HEX16:
+           printf("%s0x%04x\n", field->label, value);
+           break;
+       case DKIND_HEX32:
+           printf("%s0x%08x\n", field->label, value);
+           break;
+       case DKIND_CHAR:
+           printf("%s%c\n", field->label, value);
+           break;
+       case DKIND_STRING:
+           printf("%s%s\n", field->label, tag);
+           break;
+       case DKIND_FLAG:
+           printf("%s%s\n", field->label, value ? "true" : "false");
+           break;
+       case DKIND_TIME:
+           when = value;
+           printf("%s%s", field->label, ctime(&when));
+           break;
+       }
+    return r;
+}
+
+
+/* Parse and store the week use data from a volume header */
+static afs_uint32
+parse_weekuse(XFILE * X, unsigned char *tag, tagged_field * field,
+             afs_uint32 value, tag_parse_info * pi, void *g_refcon,
+             void *l_refcon)
+{
+    dump_parser *p = (dump_parser *) g_refcon;
+    afs_vol_header *hdr = (afs_vol_header *) l_refcon;
+    afs_uint16 count;
+    afs_uint32 r;
+    unsigned int i;
+
+    if ((r = ReadInt16(X, &count)))
+       return r;
+    if (count != 7) {
+       if (p->cb_error)
+           (p->cb_error) (DSERR_FMT, 1, p->err_refcon,
+                          "Incorrect array count (%d) in weekuse data",
+                          count);
+       return DSERR_FMT;
+    }
+    for (i = 0; i < count; i++)
+       if ((r = ReadInt32(X, hdr->weekuse + i)))
+           return r;
+    hdr->field_mask |= F_VOLHDR_WEEKUSE;
+    if (p->print_flags & DSPRINT_VOLHDR) {
+       printf("%s%10d %10d %10d %10d\n", field->label, hdr->weekuse[0],
+              hdr->weekuse[1], hdr->weekuse[2], hdr->weekuse[3]);
+       printf("%s%10d %10d %10d\n", field->label, hdr->weekuse[4],
+              hdr->weekuse[5], hdr->weekuse[6]);
+    }
+    return ReadByte(X, tag);
+}
diff --git a/src/tools/pathname.c b/src/tools/pathname.c
new file mode 100644 (file)
index 0000000..0057df8
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* pathname.c - Pathname lookup and traversal */
+
+#include <errno.h>
+#include <string.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+
+/* Hash function for a vnode */
+#define BUCKET_SIZE 32
+#define vnode_hash(phi,vnode) ((vnode) & ((1 << (phi)->hash_size) - 1))
+
+
+static vhash_ent *
+get_vhash_ent(path_hashinfo * phi, afs_uint32 vnode, int make)
+{
+    int key = vnode_hash(phi, vnode);
+    vhash_ent *vhe;
+
+    for (vhe = phi->hash_table[key]; vhe && vhe->vnode != vnode;
+        vhe = vhe->next);
+    if (make && !vhe) {
+       vhe = (vhash_ent *) malloc(sizeof(vhash_ent));
+       if (vhe) {
+           memset(vhe, 0, sizeof(vhash_ent));
+           vhe->vnode = vnode;
+           vhe->next = phi->hash_table[key];
+           phi->hash_table[key] = vhe;
+       }
+    }
+    return vhe;
+}
+
+
+static afs_uint32
+volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
+{
+    path_hashinfo *phi = (path_hashinfo *) refcon;
+    int nfiles, hsize;
+
+    if (hdr->field_mask & F_VOLHDR_NFILES) {
+       nfiles = phi->n_vnodes = hdr->nfiles;
+       for (phi->hash_size = 1; nfiles > BUCKET_SIZE;
+            phi->hash_size++, nfiles >>= 1);
+       hsize = (1 << phi->hash_size);
+       phi->hash_table = (vhash_ent **) malloc(hsize * sizeof(vhash_ent *));
+       if (!phi->hash_table)
+           return ENOMEM;
+       memset(phi->hash_table, 0, hsize * sizeof(vhash_ent *));
+       return 0;
+    } else {
+       if (phi->p->cb_error)
+           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                               "File count missing from volume header");
+       return DSERR_FMT;
+    }
+}
+
+
+static afs_uint32
+vnode_keep(afs_vnode * v, XFILE * X, void *refcon)
+{
+    path_hashinfo *phi = (path_hashinfo *) refcon;
+    vhash_ent *vhe;
+
+    if (!phi->hash_table) {
+       if (phi->p->cb_error)
+           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->refcon,
+                               "No volume header in dump???");
+       return DSERR_FMT;
+    }
+    vhe = get_vhash_ent(phi, v->vnode, 1);
+    if (!vhe)
+       return ENOMEM;
+    cp64(vhe->v_offset, v->offset);
+    if (v->field_mask & F_VNODE_PARENT)
+       vhe->parent = v->parent;
+    if (v->field_mask & F_VNODE_DATA) {
+       cp64(vhe->d_offset, v->d_offset);
+       vhe->d_size = v->size;
+    }
+    if ((v->field_mask & F_VNODE_TYPE) && v->type == vDirectory)
+       phi->n_dirs++;
+    else
+       phi->n_files++;
+    return 0;
+}
+
+
+static afs_uint32
+vnode_stop(afs_vnode * v, XFILE * X, void *refcon)
+{
+    path_hashinfo *phi = (path_hashinfo *) refcon;
+    int r;
+
+    /* If the file is seekable, try to position so we can pick up later... */
+    if (phi->p->flags & DSFLAG_SEEK)
+      if ((r = xfseek(X, &v->offset)))
+           return r;
+    return DSERR_DONE;
+}
+
+
+static afs_uint32
+dirent_cb(afs_vnode * v, afs_dir_entry * de, XFILE * X, void *refcon)
+{
+    path_hashinfo *phi = (path_hashinfo *) refcon;
+    vhash_ent *vhe;
+
+    if (!phi->hash_table) {
+       if (phi->p->cb_error)
+           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->refcon,
+                               "No volume header in dump???");
+       return DSERR_FMT;
+    }
+    if (!strcmp(de->name, ".") || !strcmp(de->name, ".."))
+       return 0;
+    vhe = get_vhash_ent(phi, de->vnode, 1);
+    if (!vhe)
+       return ENOMEM;
+    vhe->parent = v->vnode;
+    return 0;
+}
+
+
+/* Prescan the vnodes in a dump file, collecting information that will
+ * be useful in generating and following pathnames.
+ */
+afs_uint32
+Path_PreScan(XFILE * X, path_hashinfo * phi, int full)
+{
+    dump_parser my_p, *p = phi->p;
+
+    memset(phi, 0, sizeof(path_hashinfo));
+    phi->p = p;
+    memset(&my_p, 0, sizeof(my_p));
+    my_p.refcon = (void *)phi;
+    my_p.cb_volhdr = volhdr_cb;
+    my_p.cb_vnode_dir = vnode_keep;
+    if (full) {
+       my_p.cb_vnode_file = vnode_keep;
+       my_p.cb_vnode_link = vnode_keep;
+       my_p.cb_vnode_empty = vnode_keep;
+       my_p.cb_vnode_wierd = vnode_keep;
+    } else {
+       my_p.cb_vnode_file = vnode_stop;
+       my_p.cb_vnode_link = vnode_stop;
+       my_p.cb_vnode_empty = vnode_stop;
+       my_p.cb_vnode_wierd = vnode_stop;
+    }
+    my_p.err_refcon = p->err_refcon;
+    my_p.cb_error = p->cb_error;
+    my_p.cb_dirent = dirent_cb;
+    my_p.flags = p->flags;
+    my_p.print_flags = p->print_flags;
+    my_p.repair_flags = p->repair_flags;
+
+    return ParseDumpFile(X, &my_p);
+}
+
+
+/* Free the hash table in a path_hashinfo */
+void
+Path_FreeHashTable(path_hashinfo * phi)
+{
+    int i, size;
+    vhash_ent *vhe, *next_vhe;
+
+    if (phi->hash_table) {
+       size = (1 << phi->hash_size);
+       for (i = 0; i < size; i++)
+           for (vhe = phi->hash_table[i]; vhe; vhe = next_vhe) {
+               next_vhe = vhe->next;
+               free(vhe);
+           }
+       free(phi->hash_table);
+    }
+}
+
+
+/* Follow a pathname to the vnode it represents */
+afs_uint32
+Path_Follow(XFILE * X, path_hashinfo * phi, char *path, vhash_ent * his_vhe)
+{
+    vhash_ent *vhe;
+    char *name;
+    afs_uint32 r, vnum = 1;
+
+    if (*path == '/')
+       path++;
+    name = strtok(path, "/");
+
+    for (name = strtok(path, "/"); name; name = strtok(0, "/")) {
+       if (!(vnum & 1)) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (ENOTDIR, 1, phi->p->err_refcon,
+                                   "Not a directory vnode");
+           return ENOTDIR;
+       }
+       vhe = get_vhash_ent(phi, vnum, 0);
+       if (!vhe) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                                   "Vnode %d not found in hash table", vnum);
+           return DSERR_FMT;
+       }
+       if (zero64(vhe->d_offset)) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                                   "Directory vnode %d is incomplete", vnum);
+           return DSERR_FMT;
+       }
+       if ((r = xfseek(X, &vhe->d_offset))) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (r, 1, phi->p->err_refcon,
+                                   "Unable to seek to directory %d", vnum);
+           return r;
+       }
+       vnum = 0;
+       r = DirectoryLookup(X, phi->p, vhe->d_size, &name, &vnum, 0);
+       if (r)
+           return r;
+       if (!vnum) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (ENOENT, 1, phi->p->err_refcon,
+                                   "No such vnode");
+           return ENOENT;
+       }
+    }
+    vhe = get_vhash_ent(phi, vnum, 0);
+    if (!vhe) {
+       if (phi->p->cb_error)
+           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                               "Vnode %d not found in hash table", vnum);
+       return DSERR_FMT;
+    }
+    if (his_vhe)
+       *his_vhe = *vhe;
+    return 0;
+}
+
+
+afs_uint32
+Path_Build(XFILE * X, path_hashinfo * phi, afs_uint32 vnode, char **his_path,
+          int fast)
+{
+    vhash_ent *vhe;
+    char *name, *path = 0, fastbuf[12];
+    char *x, *y;
+    afs_uint32 parent, r;
+    int nl, pl = 0;
+
+    if (vnode == 1) {
+       *his_path = (char *)malloc(2);
+       if (!his_path) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
+                                   "No memory for pathname of vnode 1");
+           return ENOMEM;
+       }
+       strcpy(*his_path, "/");
+       return 0;
+    }
+
+    *his_path = 0;
+    vhe = get_vhash_ent(phi, vnode, 0);
+    if (!vhe) {
+       if (phi->p->cb_error)
+           (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                               "Vnode %d not found in hash table", vnode);
+       return DSERR_FMT;
+    }
+    while (vnode != 1) {
+       /* Find the parent */
+       if (!vhe->parent) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                                   "Vnode %d has no parent?", vnode);
+           if (path)
+               free(path);
+           return DSERR_FMT;
+       }
+       parent = vhe->parent;
+       vhe = get_vhash_ent(phi, parent, 0);
+       if (phi->p->print_flags & DSPRINT_DEBUG)
+           fprintf(stderr, "Searching for vnode %d in parent %d\n", vnode,
+                   parent);
+       if (!vhe) {
+           if (phi->p->cb_error)
+               (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                                   "Vnode %d not found in hash table",
+                                   parent);
+           if (path)
+               free(path);
+           return DSERR_FMT;
+       }
+
+       if (fast) {
+           /* Make up a path component from the vnode number */
+           sprintf(fastbuf, "%d", vnode);
+           name = fastbuf;
+       } else {
+           /* Do a reverse-lookup in the parent directory */
+           if (zero64(vhe->d_offset)) {
+               if (phi->p->cb_error)
+                   (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                                       "Directory vnode %d is incomplete",
+                                       parent);
+               if (path)
+                   free(path);
+               return DSERR_FMT;
+           }
+           if ((r = xfseek(X, &vhe->d_offset))) {
+               if (phi->p->cb_error)
+                   (phi->p->cb_error) (errno, 1, phi->p->err_refcon,
+                                       "Unable to seek to directory %d",
+                                       parent);
+               if (path)
+                   free(path);
+               return r;
+           }
+
+           name = 0;
+           r = DirectoryLookup(X, phi->p, vhe->d_size, &name, &vnode, 0);
+           if (r)
+               return r;
+           if (!name) {
+               if (phi->p->cb_error)
+                   (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
+                                       "No entry for vnode %d in directory %d",
+                                       vnode, parent);
+               if (path)
+                   free(path);
+               return ENOENT;
+           }
+       }
+
+       nl = strlen(name);
+       if (path) {
+           path = (char *)realloc(path, nl + pl + 2);
+           if (!path) {
+               if (phi->p->cb_error)
+                   (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
+                                       "No memory for pathname of vnode 1");
+               return ENOMEM;
+           }
+           x = path + pl;
+           y = x + nl + 1;
+           while (x >= path)
+               *y-- = *x--;
+           path[0] = '/';
+           for (x = name, y = path + 1; *x;)
+               *y++ = *x++;
+           pl += nl + 1;
+       } else {
+           path = (char *)malloc(nl + 2);
+           if (!path) {
+               if (phi->p->cb_error)
+                   (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
+                                       "No memory for pathname of vnode 1");
+               return ENOMEM;
+           }
+           path[0] = '/';
+           strcpy(path + 1, name);
+           pl = nl + 1;
+       }
+       if (!fast)
+           free(name);
+       vnode = parent;
+    }
+    *his_path = path;
+    return 0;
+}
diff --git a/src/tools/primitive.c b/src/tools/primitive.c
new file mode 100644 (file)
index 0000000..80e5dbd
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* primitive.c - Routines for reading and writing low-level things */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dumpscan.h"
+
+#define BUFSIZE 256
+
+
+afs_uint32
+ReadByte(XFILE * X, unsigned char *val)
+{
+    return xfread(X, val, 1);
+}
+
+afs_uint32
+ReadInt16(XFILE * X, afs_uint16 * val)
+{
+    afs_uint32 r;
+
+    if ((r = xfread(X, val, 2)))
+       return r;
+    *val = ntohs(*val);
+    return 0;
+}
+
+afs_uint32
+ReadInt32(XFILE * X, afs_uint32 * val)
+{
+    afs_uint32 r;
+
+    if ((r = xfread(X, val, 4)))
+       return r;
+    *val = ntohl(*val);
+    return 0;
+}
+
+/* Read in a NUL-terminated string.  This method is kind of messy, but
+ * has the advantage that it reads the data stream only once, doesn't
+ * read anything extra, and never has to seek on the data stream.
+ */
+afs_uint32
+ReadString(XFILE * X, unsigned char **val)
+{
+    static unsigned char buf[BUFSIZE];
+    unsigned char *result = 0;
+    afs_uint32 r;
+    int i, l = 0;
+
+    *val = 0;
+    for (;;) {
+       for (i = 0; i < BUFSIZE; i++) {
+           r = ReadByte(X, buf + i);
+           if (r) {
+               if (result)
+                   free(result);
+               return r;
+           }
+           if (!buf[i])
+               break;
+       }
+       /* iff we found a null, i < BUFSIZE and buf[i] holds the NUL */
+       if (result)
+           result = (unsigned char *)realloc(result, l + i + 1);
+       else
+           result = (unsigned char *)malloc(i + 1);
+       if (!result)
+           return ENOMEM;
+       memcpy(result + l, buf, i);
+       result[l + i] = 0;
+       l += i;
+       if (i < BUFSIZE)
+           break;
+    }
+    *val = result;
+    return 0;
+}
+
+
+afs_uint32
+WriteByte(XFILE * X, unsigned char val)
+{
+    return xfwrite(X, &val, 1);
+}
+
+afs_uint32
+WriteInt16(XFILE * X, afs_uint16 val)
+{
+    val = htons(val);
+    return xfwrite(X, &val, 2);
+}
+
+afs_uint32
+WriteInt32(XFILE * X, afs_uint32 val)
+{
+    val = htonl(val);
+    return xfwrite(X, &val, 4);
+}
+
+afs_uint32
+WriteString(XFILE * X, unsigned char *str)
+{
+    int len = strlen((char *)str) + 1;
+    return xfwrite(X, str, len);
+}
+
+afs_uint32
+WriteTagByte(XFILE * X, unsigned char tag, unsigned char val)
+{
+    char buffer[2];
+    buffer[0] = tag;
+    buffer[1] = val;
+    return xfwrite(X, buffer, 2);
+}
+
+afs_uint32
+WriteTagInt16(XFILE * X, unsigned char tag, afs_uint16 val)
+{
+    char buffer[3];
+    buffer[0] = tag;
+    buffer[1] = (val & 0xff00) >> 8;
+    buffer[2] = val & 0xff;
+    return xfwrite(X, buffer, 3);
+}
+
+afs_uint32
+WriteTagInt32(XFILE * X, unsigned char tag, afs_uint32 val)
+{
+    char buffer[5];
+    buffer[0] = tag;
+    buffer[1] = (val & 0xff000000) >> 24;
+    buffer[2] = (val & 0xff0000) >> 16;
+    buffer[3] = (val & 0xff00) >> 8;
+    buffer[4] = val & 0xff;
+    return xfwrite(X, buffer, 5);
+}
+
+afs_uint32
+WriteTagInt32Pair(XFILE * X, unsigned char tag, afs_uint32 val1,
+                 afs_uint32 val2)
+{
+    char buffer[9];
+    buffer[0] = tag;
+    buffer[1] = (val1 & 0xff000000) >> 24;
+    buffer[2] = (val1 & 0xff0000) >> 16;
+    buffer[3] = (val1 & 0xff00) >> 8;
+    buffer[4] = val1 & 0xff;
+    buffer[5] = (val2 & 0xff000000) >> 24;
+    buffer[6] = (val2 & 0xff0000) >> 16;
+    buffer[7] = (val2 & 0xff00) >> 8;
+    buffer[8] = val2 & 0xff;
+    return xfwrite(X, buffer, 9);
+}
diff --git a/src/tools/repair.c b/src/tools/repair.c
new file mode 100644 (file)
index 0000000..e4d80d5
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* repair.c - Routines to generate a repaired dump */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "dumpfmt.h"
+
+#include <afs/acl.h>
+#include <afs/dir.h>
+#include <afs/prs_fs.h>
+
+XFILE repair_output;
+int repair_verbose;
+#define RV repair_verbose
+
+extern afs_uint32 CopyVNodeData(XFILE * OX, XFILE * X, afs_uint32 size);
+extern afs_uint32 DumpVNodeData(XFILE * OX, char *buf, afs_uint32 size);
+
+/* Try to dump a dump header.  Generate missing fields, if neccessary */
+afs_uint32
+repair_dumphdr_cb(afs_dump_header * hdr, XFILE * X, void *refcon)
+{
+    afs_uint32 field_mask = hdr->field_mask;
+    char volname[22];
+
+    if (!(field_mask & F_DUMPHDR_VOLID)) {
+       if (RV)
+           fprintf(stderr, ">>> DUMP HEADER missing volume ID\n");
+       return DSERR_FMT;
+    }
+    if (!(field_mask & F_DUMPHDR_VOLNAME)) {
+       if (RV) {
+           fprintf(stderr, ">>> DUMP HEADER missing volume name\n");
+           fprintf(stderr, ">>> Will use RESTORED.%d\n", hdr->volid);
+       }
+       sprintf(volname, "RESTORED.%d", hdr->volid);
+       hdr->volname = (unsigned char *)malloc(strlen(volname) + 1);
+       if (!hdr->volname)
+           return ENOMEM;
+       strcpy((char *)hdr->volname, volname);
+       hdr->field_mask |= F_DUMPHDR_VOLNAME;
+    }
+    if (!(field_mask & F_DUMPHDR_FROM)) {
+       if (RV)
+           fprintf(stderr, ">>> DUMP HEADER missing from time (using 0)\n");
+       hdr->from_date = 0;
+       hdr->field_mask |= F_DUMPHDR_FROM;
+    }
+    if (!(field_mask & F_DUMPHDR_TO)) {
+       hdr->to_date = time(0);
+       if (RV)
+           fprintf(stderr, ">>> DUMP HEADER missing from time (using %d)\n",
+                   hdr->to_date);
+       hdr->field_mask |= F_DUMPHDR_TO;
+    }
+
+    return DumpDumpHeader(&repair_output, hdr);
+}
+
+
+/* Try to dump a volume header.  Generate missing fields, if necessary */
+afs_uint32
+repair_volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
+{
+    afs_uint32 field_mask = hdr->field_mask;
+    char volname[22];
+
+    if (!(field_mask & F_VOLHDR_VOLID)) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing volume ID\n");
+       return DSERR_FMT;
+    }
+    if (!(field_mask & F_VOLHDR_VOLVERS)) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing version (using 1)\n");
+       hdr->volvers = 1;
+       hdr->field_mask |= F_VOLHDR_VOLVERS;
+    } else if (hdr->volvers != 1) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER bogus version %d (using 1)\n",
+                   hdr->volvers);
+       hdr->volvers = 1;
+    }
+    if (!(field_mask & F_VOLHDR_VOLNAME)) {
+       if (RV) {
+           fprintf(stderr, ">>> VOL HEADER missing volume name\n");
+           fprintf(stderr, ">>> Will use RESTORED.%d\n", hdr->volid);
+       }
+       sprintf(volname, "RESTORED.%d", hdr->volid);
+       hdr->volname = (unsigned char *)malloc(strlen(volname) + 1);
+       if (!hdr->volname)
+           return ENOMEM;
+       strcpy((char *)hdr->volname, volname);
+       hdr->field_mask |= F_VOLHDR_VOLNAME;
+    }
+    if (!(field_mask & F_VOLHDR_INSERV)) {
+       if (RV)
+           fprintf(stderr,
+                   ">>> VOL HEADER missing in-service flag (using 1)\n");
+       hdr->flag_inservice = 1;
+       hdr->field_mask |= F_VOLHDR_INSERV;
+    }
+    if (!(field_mask & F_VOLHDR_BLESSED)) {
+       if (RV)
+           fprintf(stderr,
+                   ">>> VOL HEADER missing blessed flag (using 1)\n");
+       hdr->flag_blessed = 1;
+       hdr->field_mask |= F_VOLHDR_BLESSED;
+    }
+    if (!(field_mask & F_VOLHDR_VOLUNIQ)) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing uniquifier (using 1)\n");
+       hdr->voluniq = 1;
+       hdr->field_mask |= F_VOLHDR_VOLUNIQ;
+    }
+    if (!(field_mask & F_VOLHDR_VOLTYPE)) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing type (using 0: RW)\n");
+       hdr->voltype = 0;
+       hdr->field_mask |= F_VOLHDR_VOLTYPE;
+    } else if (hdr->voltype < 0 || hdr->voltype > 2) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER bogus type %d (using 0: RW)\n",
+                   hdr->voltype);
+       hdr->voltype = 0;
+    }
+    if (!(field_mask & F_VOLHDR_PARENT)) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER parent (using %d)\n", hdr->volid);
+       hdr->parent_volid = hdr->volid;
+       hdr->field_mask |= F_VOLHDR_PARENT;
+    }
+    if (!(field_mask & F_VOLHDR_MAXQ)) {
+       if (field_mask & F_VOLHDR_DISKUSED)
+           hdr->maxquota = hdr->diskused;
+       else
+           hdr->maxquota = 1;
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing max quota (using %d)\n",
+                   hdr->maxquota);
+       hdr->field_mask |= F_VOLHDR_MAXQ;
+    }
+    if (!(field_mask & F_VOLHDR_DISKUSED)) {
+       if (RV)
+           fprintf(stderr,
+                   ">>> VOL HEADER missing disk used (using 2048)\n");
+       hdr->diskused = 2048;
+       hdr->field_mask |= F_VOLHDR_DISKUSED;
+    }
+    if (!(field_mask & F_VOLHDR_NFILES)) {
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing file count (using 1)\n");
+       hdr->nfiles = 1;
+       hdr->field_mask |= F_VOLHDR_NFILES;
+    }
+    if (!(field_mask & F_VOLHDR_CREATE_DATE)) {
+       hdr->create_date = 0;
+       if ((field_mask & F_VOLHDR_ACCESS_DATE)
+           && (!hdr->create_date || hdr->access_date < hdr->create_date))
+           hdr->create_date = hdr->access_date;
+       if ((field_mask & F_VOLHDR_UPDATE_DATE)
+           && (!hdr->create_date || hdr->update_date < hdr->create_date))
+           hdr->create_date = hdr->update_date;
+       if ((field_mask & F_VOLHDR_BACKUP_DATE)
+           && (!hdr->create_date || hdr->backup_date < hdr->create_date))
+           hdr->create_date = hdr->backup_date;
+
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing create date (using %d)\n",
+                   hdr->create_date);
+       hdr->field_mask |= F_VOLHDR_CREATE_DATE;
+    }
+    if (!(field_mask & F_VOLHDR_ACCESS_DATE)) {
+       hdr->access_date = 0;
+       if ((field_mask & F_VOLHDR_CREATE_DATE)
+           && (!hdr->access_date || hdr->create_date > hdr->access_date))
+           hdr->access_date = hdr->create_date;
+       if ((field_mask & F_VOLHDR_UPDATE_DATE)
+           && (!hdr->access_date || hdr->update_date > hdr->access_date))
+           hdr->access_date = hdr->update_date;
+       if ((field_mask & F_VOLHDR_BACKUP_DATE)
+           && (!hdr->access_date || hdr->backup_date > hdr->access_date))
+           hdr->access_date = hdr->backup_date;
+
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing access date (using %d)\n",
+                   hdr->access_date);
+       hdr->field_mask |= F_VOLHDR_ACCESS_DATE;
+    }
+    if (!(field_mask & F_VOLHDR_UPDATE_DATE)) {
+       hdr->update_date = 0;
+       if ((field_mask & F_VOLHDR_CREATE_DATE)
+           && (!hdr->update_date || hdr->create_date > hdr->update_date))
+           hdr->update_date = hdr->create_date;
+       if ((field_mask & F_VOLHDR_ACCESS_DATE) && !hdr->update_date)
+           hdr->update_date = hdr->access_date;
+       if ((field_mask & F_VOLHDR_BACKUP_DATE) && !hdr->update_date)
+           hdr->update_date = hdr->backup_date;
+
+       if (RV)
+           fprintf(stderr, ">>> VOL HEADER missing update date (using %d)\n",
+                   hdr->update_date);
+       hdr->field_mask |= F_VOLHDR_UPDATE_DATE;
+    }
+
+    return DumpVolumeHeader(&repair_output, hdr);
+}
+
+
+/* Try to dump a vnode.  Generate missing fields, if necessary */
+afs_uint32
+repair_vnode_cb(afs_vnode * v, XFILE * X, void *refcon)
+{
+    afs_uint32 r, field_mask = v->field_mask;
+
+    if ((v->vnode & 1) && !field_mask) {
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d is directory but has no fields?\n", v->vnode);
+       v->type = vDirectory;
+       v->field_mask |= F_VNODE_TYPE;
+       field_mask = F_VNODE_TYPE;      /* Messy! */
+    }
+    if (field_mask && !(field_mask & F_VNODE_TYPE)) {
+       v->type = (v->vnode & 1) ? vDirectory : vFile;
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing type (using %d)\n",
+                   v->vnode, v->type);
+       v->field_mask |= F_VNODE_TYPE;
+    }
+    if (field_mask && !(field_mask & F_VNODE_NLINKS)) {
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing link count (using 1)\n",
+                   v->vnode);
+       v->nlinks = 1;
+       v->field_mask |= F_VNODE_NLINKS;
+    }
+    if (field_mask && !(field_mask & F_VNODE_PARENT)) {
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing parent (using 1)\n",
+                   v->vnode);
+       v->parent = 1;
+       v->field_mask |= F_VNODE_PARENT;
+    }
+    if (field_mask && !(field_mask & F_VNODE_DVERS)) {
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing data version (using 1)\n",
+                   v->vnode);
+       v->datavers = 1;
+       v->field_mask |= F_VNODE_DVERS;
+    }
+    if (field_mask && !(field_mask & F_VNODE_AUTHOR)) {
+       if (field_mask & F_VNODE_OWNER)
+           v->author = v->owner;
+       else
+           v->author = 0;
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing author (using %d)\n",
+                   v->vnode, v->author);
+       v->field_mask |= F_VNODE_AUTHOR;
+    }
+    if (field_mask && !(field_mask & F_VNODE_OWNER)) {
+       if (field_mask & F_VNODE_AUTHOR)
+           v->owner = v->author;
+       else
+           v->owner = 0;
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing owner (using %d)\n",
+                   v->vnode, v->owner);
+       v->field_mask |= F_VNODE_OWNER;
+    }
+    if (field_mask && !(field_mask & F_VNODE_MODE)) {
+       v->mode = (v->vnode & 1) ? 0755 : 0644;
+       if (RV)
+           fprintf(stderr, ">>> VNODE missing mode (using %d)\n", v->mode);
+       v->field_mask |= F_VNODE_MODE;
+    }
+    if (field_mask && !(field_mask & F_VNODE_CDATE)) {
+       if (field_mask & F_VNODE_SDATE)
+           v->client_date = v->server_date;
+       else
+           v->client_date = 0;
+
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing client date (using %d)\n",
+                   v->vnode, v->client_date);
+       v->field_mask |= F_VNODE_CDATE;
+    }
+    if (field_mask && !(field_mask & F_VNODE_SDATE)) {
+       if (field_mask & F_VNODE_CDATE)
+           v->server_date = v->client_date;
+       else
+           v->server_date = 0;
+
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d missing server date (using %d)\n",
+                   v->vnode, v->server_date);
+       v->field_mask |= F_VNODE_SDATE;
+    }
+    if (field_mask && !(field_mask & F_VNODE_SIZE)) {
+       if (RV)
+           fprintf(stderr, ">>> VNODE %d has no data size (using 0)\n", v->vnode);
+       v->size = 0;
+       v->field_mask |= F_VNODE_SIZE;
+    }
+    if ((field_mask & F_VNODE_DATA) && !v->size) {
+       if (RV)
+           fprintf(stderr,
+                   ">>> VNODE %d has data, but size == 0 (ignoring)\n",
+                   v->vnode);
+       v->field_mask &= ~F_VNODE_DATA;
+    }
+    if (field_mask && v->type == vDirectory && !(field_mask & F_VNODE_ACL)) {
+       struct acl_accessList *acl = (struct acl_accessList *)v->acl;
+       if (RV) {
+           fprintf(stderr, ">>> VNODE %d is directory but has no ACL\n", v->vnode);
+           fprintf(stderr, ">>> Will generate default ACL\n");
+       }
+       memset(v->acl, 0, SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE);
+       acl->size = htonl(SIZEOF_LARGEDISKVNODE - SIZEOF_SMALLDISKVNODE);
+       acl->version = htonl(ACL_ACLVERSION);
+       acl->total = htonl(v->owner ? 0 : 1);
+       acl->positive = acl->total;
+       acl->negative = 0;
+       if (v->owner) {
+           acl->entries[0].id = htonl(v->owner);
+           acl->entries[0].rights =
+               htonl((PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP
+                      | PRSFS_DELETE | PRSFS_LOCK | PRSFS_ADMINISTER));
+       }
+       v->field_mask |= F_VNODE_ACL;
+    }
+
+    r = DumpVNode(&repair_output, v);
+    if (r)
+       return r;
+
+    if (v->size) {
+       if ((r = xfseek(X, &v->d_offset)))
+           return r;
+       r = CopyVNodeData(&repair_output, X, v->size);
+    } else if (v->type == vDirectory) {
+       afs_dir_page page;
+       struct DirHeader *dhp = (struct DirHeader *)&page;
+       int i;
+
+       if (RV) {
+           fprintf(stderr,
+                   ">>> VNODE %d is directory but has no contents\n", v->vnode);
+           fprintf(stderr, ">>> Will generate deafult directory entries\n");
+       }
+       memset(&page, 0, sizeof(page));
+
+       /* Page and Directory Headers */
+       page.header.tag = htons(1234);
+       page.header.freecount = (EPP - DHE - 3);
+       page.header.freebitmap[0] = 0xff;
+       page.header.freebitmap[1] = 0x7f;
+       dhp->alloMap[0] = EPP - DHE - 3;
+       for (i = 1; i < MAXPAGES; i++)
+           dhp->alloMap[i] = EPP;
+
+       /* Entry for . */
+       page.entry[DHE + 1].flag = FFIRST;
+       page.entry[DHE + 1].length = 1;
+       page.entry[DHE + 1].vnode = v->vnode;
+       page.entry[DHE + 1].vunique = v->vuniq;
+       strcpy(page.entry[DHE + 1].name, ".");
+       dhp->hashTable[0x2e] = DHE + 1;
+
+       /* Entry for .. */
+       page.entry[DHE + 2].flag = FFIRST;
+       page.entry[DHE + 2].length = 1;
+       page.entry[DHE + 2].vnode = v->parent;
+       page.entry[DHE + 2].vunique = 1;        /* Can't have everything! */
+       strcpy(page.entry[DHE + 2].name, "..");
+       dhp->hashTable[0x44] = DHE + 2;
+
+       r = DumpVNodeData(&repair_output, (char *)&page, 2048);
+    } else if (field_mask) {
+       /* We wrote out attributes, so we should also write the 0-length data */
+       r = DumpVNodeData(&repair_output, "", 0);
+    }
+
+    return r;
+}
diff --git a/src/tools/stagehdr.c b/src/tools/stagehdr.c
new file mode 100644 (file)
index 0000000..ecdd2c2
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* stagehdr.c - Parse and dump stage backup headers */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "xf_errs.h"
+#include "stagehdr.h"
+
+static afs_uint32
+hdr_checksum(char *buf, int size)
+{
+    afs_uint32 sum = 0, n = size / sizeof(afs_uint32), *words =
+       (afs_uint32 *) buf;
+
+    while (--n)
+       sum += ntohl(*words++);
+    return sum;
+}
+
+
+/* Parse a stage backup header.
+ * If tag is non-NULL, *tag should contain the first byte (already read),
+ * and will be filled in with the first byte after the header, if one exists.
+ * On success, returns 0 and leaves us positioned after the header
+ * On failure, returns an error and position is undefined
+ * Iff there is no header, returns DSERR_MAGIC and leaves us
+ * positioned where we started.
+ */
+afs_uint32
+ParseStageHdr(XFILE * X, unsigned char *tag, backup_system_header * hdr)
+{
+    char buf[STAGE_HDRLEN];
+    struct stage_header *bckhdr = (struct stage_header *)buf;
+    u_int64 where;
+    afs_int32 r;
+
+    if ((r = xftell(X, &where)))
+       return r;
+    if (hdr)
+       memset(hdr, 0, sizeof(*hdr));
+    if (tag) {
+       if (*tag != STAGE_VERSMIN)
+           return DSERR_MAGIC;
+       buf[0] = *tag;
+       r = xfread(X, buf + 1, STAGE_HDRLEN - 1);
+    } else {
+       r = xfread(X, buf, STAGE_HDRLEN);
+    }
+
+    if (r == ERROR_XFILE_EOF) {
+       r = xfseek(X, &where);
+       return r ? r : DSERR_MAGIC;
+    } else if (r)
+       return r;
+
+    if (bckhdr->c_vers < STAGE_VERSMIN
+       || ntohl(bckhdr->c_magic) != STAGE_MAGIC
+       || hdr_checksum(buf, STAGE_HDRLEN) != STAGE_CHECKSUM) {
+       r = xfseek(X, &where);
+       return r ? r : DSERR_MAGIC;
+    }
+
+    if (hdr) {
+       hdr->version = bckhdr->c_vers;
+       hdr->from_date = ntohl(bckhdr->c_fdate);
+       hdr->to_date = ntohl(bckhdr->c_tdate);
+       hdr->dump_date = ntohl(bckhdr->c_time);
+       hdr->filenum = ntohl(bckhdr->c_filenum);
+       hdr->volid = ntohl(bckhdr->c_id);
+#ifdef NATIVE_INT64
+       hdr->dumplen = ntohl(bckhdr->c_length);
+#else
+        hdr->dumplen.hi = 0;
+        hdr->dumplen.lo = ntohl(bckhdr->c_length);
+#endif
+       hdr->level = ntohl(bckhdr->c_level);
+       hdr->magic = ntohl(bckhdr->c_magic);
+       hdr->cksum = ntohl(bckhdr->c_checksum);
+       hdr->flags = ntohl(bckhdr->c_flags);
+       hdr->server = malloc(strlen(bckhdr->c_host) + 1);
+       hdr->part = malloc(strlen(bckhdr->c_disk) + 1);
+       hdr->volname = malloc(strlen(bckhdr->c_name) + 1);
+
+       if (!hdr->server || !hdr->part || !hdr->volname) {
+           if (hdr->server)
+               free(hdr->server);
+           if (hdr->part)
+               free(hdr->part);
+           if (hdr->volname)
+               free(hdr->volname);
+           return ENOMEM;
+       }
+       strcpy((char *)hdr->server, bckhdr->c_host);
+       strcpy((char *)hdr->part, bckhdr->c_disk);
+       strcpy((char *)hdr->volname, bckhdr->c_name);
+    }
+
+    if (tag)
+       return ReadByte(X, tag);
+    else
+       return 0;
+}
+
+
+/* Dump a stage backup header */
+afs_uint32
+DumpStageHdr(XFILE * OX, backup_system_header * hdr)
+{
+    char buf[STAGE_HDRLEN];
+    struct stage_header *bckhdr = (struct stage_header *)buf;
+    afs_uint32 checksum;
+    afs_uint32 r;
+
+    memset(buf, 0, STAGE_HDRLEN);
+    bckhdr->c_vers = hdr->version;
+    bckhdr->c_fdate = htonl(hdr->from_date);
+    bckhdr->c_tdate = htonl(hdr->to_date);
+    bckhdr->c_filenum = htonl(hdr->filenum);
+    bckhdr->c_time = htonl(hdr->dump_date);
+    bckhdr->c_id = htonl(hdr->volid);
+#ifdef NATIVE_INT64
+    bckhdr->c_length = htonl((afs_uint32) hdr->dumplen);
+#else
+    bckhdr->c_length = htonl(hdr->dumplen.lo);
+#endif
+    bckhdr->c_level = htonl(hdr->level);
+    bckhdr->c_magic = htonl(STAGE_MAGIC);
+    bckhdr->c_flags = htonl(hdr->flags);
+
+    strcpy(bckhdr->c_host, (char *)hdr->server);
+    strcpy(bckhdr->c_disk, (char *)hdr->part);
+    strcpy(bckhdr->c_name, (char *)hdr->volname);
+
+    /* Now, compute the checksum */
+    checksum = hdr_checksum(buf, STAGE_HDRLEN);
+    bckhdr->c_checksum = htonl(STAGE_CHECKSUM - checksum);
+
+    if ((r = xfwrite(OX, buf, STAGE_HDRLEN)))
+       return r;
+    return 0;
+}
diff --git a/src/tools/stagehdr.h b/src/tools/stagehdr.h
new file mode 100644 (file)
index 0000000..b8e4ef3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* stagehdr.h - (old) Stage backup header format */
+
+#ifndef _STAGEHDR_H_
+#define _STAGEHDR_H_
+
+#include "intNN.h"
+
+/* Stage-related constants */
+#define STAGE_MAGIC    0x00adf8bc      /* magic number for stage header */
+#define STAGE_CHECKSUM 84446   /* checksum (same as 4.2bsd dump) */
+#define STAGE_VERSMIN  20      /* minimum version */
+#define STAGE_NAMLEN   64      /* length of host/part/vol names */
+#define STAGE_HDRLEN   1024    /* size of the header */
+
+struct stage_header {
+    unsigned char c_vers;      /* header version (starts at 20) */
+    unsigned char c_notused[3];
+    afs_uint32 c_fdate;                /* dump "from" date */
+    afs_uint32 c_tdate;                /* dump "to" date */
+    afs_uint32 c_filenum;      /* tape file number */
+    afs_uint32 c_time;         /* time dump was done */
+    char c_host[STAGE_NAMLEN]; /* hostname volume came from */
+    char c_disk[STAGE_NAMLEN]; /* partition volume came from */
+    char c_name[STAGE_NAMLEN]; /* volume name */
+    afs_uint32 c_id;           /* volume ID */
+    afs_uint32 c_length;       /* length of the dump */
+    afs_uint32 c_level;                /* dump level */
+    afs_uint32 c_magic;                /* magic number */
+    afs_uint32 c_checksum;     /* checksum of backup header */
+    afs_uint32 c_flags;                /* feature flags */
+};
+
+#endif /* _STAGEHDR_H_ */
diff --git a/src/tools/util.c b/src/tools/util.c
new file mode 100644 (file)
index 0000000..badf07e
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* util.c - Useful utilities */
+
+#include <errno.h>
+
+#include "xf_errs.h"
+#include "dumpscan.h"
+#include "dumpscan_errs.h"
+#include "dumpfmt.h"
+
+
+/* Take care of errno, ERROR_XFILE_EOF, and ENOMEM return codes.
+ * Call whatever callbacks are necessary, and return the code to
+ * actually use.  If you don't want '0' to result in a DSERR_TAG,
+ * then you must translate it to DSERR_DONE before calling this.
+ */
+/*** THIS FUNCTION INTENDED FOR INTERNAL USE ONLY ***/
+int
+handle_return(int r, XFILE * X, unsigned char tag, dump_parser * p)
+{
+    u_int64 where, xwhere;
+
+    switch (r) {
+    case 0:
+       if (p->cb_error) {
+           xftell(X, &where);
+           sub64_32(xwhere, where, 1);
+           (p->cb_error) (DSERR_TAG, 1, p->err_refcon,
+                          (tag > 0x20 && tag < 0x7f)
+                          ? "Unexpected tag '%c' at %s = 0x%s" :
+                          "Unexpected tag 0x%02x at %s = 0x%s", tag,
+                          decimate_int64(&xwhere, 0), hexify_int64(&xwhere,
+                                                                   0));
+       }
+       return DSERR_TAG;
+
+    case ERROR_XFILE_EOF:
+       if (p->cb_error) {
+           xftell(X, &where);
+           (p->cb_error) (ERROR_XFILE_EOF, 1, p->err_refcon,
+                          "Unexpected EOF at %s = 0x%s",
+                          decimate_int64(&where, 0), hexify_int64(&where,
+                                                                  0));
+       }
+       return ERROR_XFILE_EOF;
+
+    case ENOMEM:
+       if (p->cb_error) {
+           xftell(X, &where);
+           (p->cb_error) (ENOMEM, 1, p->err_refcon,
+                          "Out of memory at %s = 0x%s",
+                          decimate_int64(&where, 0), hexify_int64(&where,
+                                                                  0));
+       }
+       return ENOMEM;
+
+    case DSERR_DONE:
+       return 0;
+
+    default:
+       /* For other negative valuees, the callback was already done */
+       if (r > 0 && p->cb_error)
+           (p->cb_error) (r, 1, p->err_refcon,
+                          "System error %d reading dump file", r);
+       return r;
+    }
+}
+
+
+/* Prepare a tag_parse_info for use by the dump parser. */
+/* ** THIS FUNCTION INTENDED FOR INTERNAL USE ONLY ** */
+void
+prep_pi(dump_parser * p, tag_parse_info * pi)
+{
+    memset(pi, 0, sizeof(tag_parse_info));
+    pi->err_refcon = p->err_refcon;
+    pi->cb_error = p->cb_error;
+
+    if (p->repair_flags & DSFIX_SKIP)
+       pi->flags |= TPFLAG_SKIP;
+    if ((p->flags & DSFLAG_SEEK) && (p->repair_flags & DSFIX_RSKIP))
+       pi->flags |= TPFLAG_RSKIP;
+}
+
+
+/* Does the designated location match a vnode?
+ * Returns 0 if yes, DSERR_FMT if no, something else on error
+ */
+/*** THIS FUNCTION INTENDED FOR INTERNAL USE ONLY ***/
+int
+match_next_vnode(XFILE * X, dump_parser * p, u_int64 * where,
+                afs_uint32 vnode)
+{
+    afs_uint32 r, x, y, z;
+    unsigned char tag;
+
+    if ((r = xfseek(X, where)))
+       return r;
+    if ((r = ReadByte(X, &tag)))
+       return r;
+    switch (tag) {
+    case 3:                    /* A vnode? */
+       if ((r = ReadInt32(X, &x)))
+           return r;
+       if ((r = ReadInt32(X, &y)))
+           return r;
+       if ((r = ReadByte(X, &tag)))
+         return r;
+       if (!((vnode & 1) && !(x & 1) && x < vnode)
+           && !((vnode & 1) == (x & 1) && x > vnode))
+           return DSERR_FMT;
+       if (x > vnode && x - vnode > 10000)
+           return DSERR_FMT;
+       if (y < 0 || y > p->vol_uniquifier)
+           return DSERR_FMT;
+
+       /* Now, what follows the vnode/uniquifier? */
+       switch (tag) {
+       case 3:         /* Another vnode? - Only if this is a non-directory */
+           if (x & 1)
+               return DSERR_FMT;
+           if ((r = ReadInt32(X, &z)))
+               return r;
+           if (!((x & 1) && !(z & 1) && z < x)
+               && !((x & 1) == (z & 1) && z > x))
+               return DSERR_FMT;
+           return 0;
+
+       case 4:         /* Dump end - Only if this is a non-directory */
+           if (x & 1)
+               return DSERR_FMT;
+           if ((r = ReadInt32(X, &z)))
+               return r;
+           if (z != DUMPENDMAGIC)
+               return DSERR_FMT;
+           return 0;
+
+       case 't':               /* Vnode type byte */
+           if ((r = ReadByte(X, &tag)))
+               return r;
+           if ((tag == vFile || tag == vSymlink) && !(x & 1))
+               return 0;
+           if (tag == vDirectory && (x & 1))
+               return 0;
+           return DSERR_FMT;
+
+       default:
+           return DSERR_FMT;
+       }
+
+    case 4:                    /* A dump end? */
+       if ((r = ReadInt32(X, &x)))
+           return r;
+       if (x != DUMPENDMAGIC)
+           return DSERR_FMT;
+       return 0;
+
+    default:
+       return DSERR_FMT;
+    }
+}
diff --git a/src/tools/xf_errs.et b/src/tools/xf_errs.et
new file mode 100644 (file)
index 0000000..76c71d7
--- /dev/null
@@ -0,0 +1,37 @@
+# CMUCS AFStools
+# dumpscan - routines for scanning and manipulating AFS volume dumps
+#
+# Copyright (c) 1998 Carnegie Mellon University
+# All Rights Reserved.
+#
+# Permission to use, copy, modify and distribute this software and its
+# documentation is hereby granted, provided that both the copyright
+# notice and this permission notice appear in all copies of the
+# software, derivative works or modified versions, and any portions
+# thereof, and that both notices appear in supporting documentation.
+#
+# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+# CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+#
+# Carnegie Mellon requests users of this software to return to
+#
+#  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+#  School of Computer Science
+#  Carnegie Mellon University
+#  Pittsburgh PA 15213-3890
+#
+# any improvements or extensions that they make and grant Carnegie Mellon
+# the rights to redistribute these changes.
+
+# xf_errs.et - Error table for xfiles
+
+error_table xFil
+  ec ERROR_XFILE_EOF,            "EOF while reading XFILE"
+  ec ERROR_XFILE_WRONLY,         "XFILE may not be opened write-only"
+  ec ERROR_XFILE_RDONLY,         "XFILE is read-only"
+  ec ERROR_XFILE_NOSEEK,         "XFILE is not seekable"
+  ec ERROR_XFILE_ISPASS,         "XFILE passthru already set"
+  ec ERROR_XFILE_NOPASS,         "XFILE passthru not set"
+  ec ERROR_XFILE_TYPE,           "unknown XFILE type"
+end
diff --git a/src/tools/xf_files.c b/src/tools/xf_files.c
new file mode 100644 (file)
index 0000000..719d3a2
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* xf_files.c - XFILE routines for accessing UNIX files */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "xfiles.h"
+#include "xf_errs.h"
+
+#define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
+
+
+/* do_read for stdio xfiles */
+static afs_uint32
+xf_FILE_do_read(XFILE * X, void *buf, afs_uint32 count)
+{
+    FILE *F = X->refcon;
+
+    /* XXX: handle short and interrupted reads */
+    if (fread(buf, count, 1, F) != 1)
+       return ferror(F) ? errno : ERROR_XFILE_EOF;
+    return 0;
+}
+
+
+/* do_write for stdio xfiles */
+static afs_uint32
+xf_FILE_do_write(XFILE * X, void *buf, afs_uint32 count)
+{
+    FILE *F = X->refcon;
+
+    /* XXX: handle interrupted writes */
+    if (fwrite(buf, count, 1, F) != 1)
+       return errno;
+    return 0;
+}
+
+
+/* do_tell for stdio xfiles */
+static afs_uint32
+xf_FILE_do_tell(XFILE * X, u_int64 * offset)
+{
+    FILE *F = X->refcon;
+    off_t where;
+
+    where = ftell(F);
+    if (where == -1)
+       return errno;
+    set64(*offset, where);
+    return 0;
+}
+
+
+/* do_seek for stdio xfiles */
+static afs_uint32
+xf_FILE_do_seek(XFILE * X, u_int64 * offset)
+{
+    FILE *F = X->refcon;
+    off_t where = get64(*offset);
+
+    if (fseek(F, where, SEEK_SET) == -1)
+       return errno;
+    return 0;
+}
+
+
+/* do_skip for stdio xfiles */
+static afs_uint32
+xf_FILE_do_skip(XFILE * X, afs_uint32 count)
+{
+    FILE *F = X->refcon;
+
+    if (fseek(F, count, SEEK_CUR) == -1)
+       return errno;
+    return 0;
+}
+
+
+/* do_close for stdio xfiles */
+static afs_uint32
+xf_FILE_do_close(XFILE * X)
+{
+    FILE *F = X->refcon;
+
+    X->refcon = 0;
+    if (fclose(F))
+       return errno;
+    return 0;
+}
+
+
+/* Prepare a stdio XFILE */
+static void
+prepare(XFILE * X, FILE * F, int xflag)
+{
+    struct stat st;
+
+    memset(X, 0, sizeof(*X));
+    X->do_read = xf_FILE_do_read;
+    X->do_write = xf_FILE_do_write;
+    X->do_tell = xf_FILE_do_tell;
+    X->do_close = xf_FILE_do_close;
+    X->refcon = F;
+    if (xflag == O_RDWR)
+       X->is_writable = 1;
+
+    if (!fstat(fileno(F), &st)
+       && ((st.st_mode & S_IFMT) == S_IFREG
+           || (st.st_mode & S_IFMT) == S_IFBLK)) {
+       X->is_seekable = 1;
+       X->do_seek = xf_FILE_do_seek;
+       X->do_skip = xf_FILE_do_skip;
+    }
+}
+
+
+/* Open an XFILE by path */
+afs_uint32
+xfopen_path(XFILE * X, int flag, char *path, int mode)
+{
+    FILE *F = 0;
+    int fd = -1, xflag;
+    afs_uint32 code;
+
+    xflag = flag & O_MODE_MASK;
+    if (xflag == O_WRONLY)
+       return ERROR_XFILE_WRONLY;
+
+    if ((fd = open(path, flag, mode)) < 0)
+       return errno;
+    if (!(F = fdopen(fd, (xflag == O_RDONLY) ? "r" : "r+"))) {
+       code = errno;
+       close(fd);
+       return code;
+    }
+
+    prepare(X, F, xflag);
+    return 0;
+}
+
+
+/* Open an XFILE by FILE * */
+afs_uint32
+xfopen_FILE(XFILE * X, int flag, FILE * F)
+{
+    flag &= O_MODE_MASK;
+    if (flag == O_WRONLY)
+       return ERROR_XFILE_WRONLY;
+    prepare(X, F, flag);
+    return 0;
+}
+
+
+/* Open an XFILE by file descriptor */
+afs_uint32
+xfopen_fd(XFILE * X, int flag, int fd)
+{
+    FILE *F;
+
+    flag &= O_MODE_MASK;
+    if (flag == O_WRONLY)
+       return ERROR_XFILE_WRONLY;
+    if (!(F = fdopen(fd, (flag == O_RDONLY) ? "r" : "r+")))
+       return errno;
+    prepare(X, F, flag);
+    return 0;
+}
+
+
+/* open-by-name support for filenames */
+afs_uint32
+xfon_path(XFILE * X, int flag, char *name)
+{
+    return xfopen_path(X, flag, name, 0644);
+}
+
+
+/* open-by-name support for file descriptors */
+afs_uint32
+xfon_fd(XFILE * X, int flag, char *name)
+{
+    int fd = atoi(name);
+    return xfopen_fd(X, flag, fd);
+}
+
+
+/* open-by-name support for standard I/O */
+afs_uint32
+xfon_stdio(XFILE * X, int flag)
+{
+    flag &= O_MODE_MASK;
+    if (flag == O_WRONLY)
+       flag = O_RDWR;
+    return xfopen_FILE(X, flag, (flag == O_RDONLY) ? stdin : stdout);
+}
diff --git a/src/tools/xf_printf.c b/src/tools/xf_printf.c
new file mode 100644 (file)
index 0000000..6c5c9aa
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xfiles.h"
+#include "xf_errs.h"
+
+#define SPBUFLEN 40
+static char spbuf[SPBUFLEN + 1] = "";
+
+
+#define MAXPREC 100
+
+/* Generate an ASCII representation of an integer <val>, as follows:
+ * <base> indicates the base to be used (2-36)
+ * <uc> is nonzero if letter digits should be uppercase
+ * <prec> is the minimum number of digits
+ * The resulting number is stored in <buf>, which must be long enough
+ * to receive it.  The minimum length is <prec> or ceil(log{base}(val)),
+ * whichever is larger, plus room for a trailing NUL.
+ */
+static void
+mkint(char *buf, unsigned long val, int base, int uc, int prec)
+{
+    int len = 0, dig, i;
+
+    while (val) {
+       dig = val % base;
+       val = (val - dig) / base;
+       if (dig < 10)
+           dig = dig + '0';
+       else if (uc)
+           dig = dig + 'A' - 10;
+       else
+           dig = dig + 'a' - 10;
+       buf[len++] = dig;
+    }
+    while (len < prec)
+       buf[len++] = '0';
+    for (i = 0; i < (len + 1) / 2; i++) {
+       dig = buf[i];
+       buf[i] = buf[len - i - 1];
+       buf[len - i - 1] = dig;
+    }
+    buf[len] = 0;
+}
+
+
+/* Write spaces faster than one at a time */
+static afs_uint32
+wsp(XFILE * X, int count)
+{
+    char *x;
+    afs_uint32 err;
+    int i;
+
+    if (!spbuf[0]) {
+       for (x = spbuf, i = SPBUFLEN; i; x++, i--)
+           *x = ' ';
+    }
+
+    while (count > SPBUFLEN) {
+       err = xfwrite(X, spbuf, SPBUFLEN);
+       if (err)
+           return err;
+       count -= SPBUFLEN;
+    }
+    if (count > 0)
+       return xfwrite(X, spbuf, count);
+    return 0;
+}
+
+
+/* This function is a mostly-complete implementation of snprintf,
+ * with the following features:
+ *
+ *   - Actually obeys the length limit, which (unfortunately) many
+ *     implementations of snprintf do not.
+ *
+ *   - Supports all the standard format specifiers for integers
+ *     (d, i, o, u, x, X), floating-point values (f, e, E, g, G),
+ *     and strings and characters (c, s, %), plus a few unusual
+ *     but useful ones described below.
+ *
+ *   - Supports all the standard flags (-, 0, +, space, #).  These
+ *     flags are ignored if used when they are not appropriate.
+ *
+ *   - Supports the standard size modifiers for short (h), long (h),
+ *     and double (L) arguments.  These modifiers are ignored if used
+ *     when they are not appropriate.
+ *
+ *   - Supports minimum field width and precision, where appropriate,
+ *     including the use of '*' to specify a value given as an argument
+ *     instead of in the format string.  There is a maximum precision
+ *     of 100 digits.
+ *
+ *   - At present, the 'p' specifier for printing pointers is not
+ *     implemented, because it is inherently non-portable and thus
+ *     can be implemented correctly only by the compiler's run-time
+ *     library.
+ *
+ *   - Floating-point specifier (%e, %f, %g) are implemented by
+ *     calling the standard sprintf, and thus may be unsafe.
+ *
+ *   - The '%...$' notation is used primarily when the format string
+ *     is specified by the user, who knows but cannot change the order
+ *     of the arguments.  Such usage is inherently dangerous and
+ *     insecure; thus, it is not supported.
+ *
+ * The custom format specifier '%I' is supported.  This specifier
+ * takes as its argument an unsigned long integer containing an
+ * IPv4 address in network byte order.  The address is rendered
+ * either as a hostname or as a dotted quad, as follows:
+ *
+ *   - If precision is nonzero or unspecified, a hostname lookup
+ *     is attempted; if it is successful, the hostname is printed.
+ *     If the hostname lookup fails, the address is printed in
+ *     dotted-quad notation.
+ *
+ *   - If precision is explicitly specified as 0, then the hostname
+ *     lookup is skipped, and dotted-quad notation is always used.
+ *
+ *   - If a hostname is to be printed:
+ *     + The precision controls the maximum number of characters
+ *       printed, as with %s.
+ *     + If the '#' flag is specified, any letters in the hostname
+ *       will be forced to lower case before printing.
+ *     + If the '+' flag is specified, any letters in the hostname
+ *       will be forced to upper case before printing.  If both
+ *       '#' and '+' are given, the '+' flag will be ignored.
+ *     + The '0' and ' ' flags have no effect.
+ *
+ *   - If a dotted quad is to be printed:
+ *     + The precision has no effect; dotted quads are always
+ *       7 to 12 characters in length, depending on the value
+ *       to be printed and the format flags used.
+ *     + If the '0' flag is given, each field (byte) of the address
+ *       will be padded with '0' on the left to three digits.
+ *     + If the ' ' flag is given, each field (byte) of the address
+ *       will be padded with spaces on the left to three digits.  If
+ *       both '0' and ' ' are given, the ' ' flag will be ignored.
+ *     + The '#' and '+' flags have no effect.
+ */
+
+afs_uint32
+vxfprintf(XFILE * X, char *fmt, va_list ap)
+{
+    unsigned int width, precision, haveprec, len;
+    int ljust, plsign, spsign, altform, zfill;
+    int hflag, lflag, count, *countp, j;
+    char *x, *y, *lit = 0, xbuf[MAXPREC + 21], fbuf[20];
+    struct hostent *he;
+    struct in_addr ia;
+    unsigned long UVAL;
+    long SVAL, *lcountp;
+    double FVAL;
+    short *hcountp;
+    afs_uint32 err;
+
+    count = 0;
+    while (*fmt) {
+       if (*fmt != '%') {
+           if (!lit)
+               lit = fmt;
+           fmt++;
+           count++;
+           continue;
+       }
+       if (lit) {
+           if ((err = xfwrite(X, lit, fmt - lit)))
+               return err;
+           lit = 0;
+       }
+
+    /** Found a format specifier **/
+       ljust = plsign = spsign = altform = zfill = 0;
+       width = precision = haveprec = 0;
+       hflag = lflag = 0;
+       fmt++;
+
+       /* parse format flags */
+       while (*fmt) {
+           switch (*fmt) {
+           case '-':
+               ljust = 1;
+               fmt++;
+               continue;       /* left justify */
+           case '+':
+               plsign = 1;
+               fmt++;
+               continue;       /* use + or - */
+           case ' ':
+               spsign = 1;
+               fmt++;
+               continue;       /* use space or - */
+           case '#':
+               altform = 1;
+               fmt++;
+               continue;       /* alternate form */
+           case '0':
+               zfill = 1;
+               fmt++;
+               continue;       /* pad with 0 */
+           default:
+               break;
+           }
+           break;
+       }
+
+       /* parse minimum width */
+       if (*fmt == '*') {
+           width = va_arg(ap, int);
+           fmt++;
+       } else
+           while (isdigit(*fmt)) {
+               width = (width * 10) + (*fmt - '0');
+               fmt++;
+           }
+
+       /* parse precision */
+       if (*fmt == '.') {
+           fmt++;
+           haveprec = 1;
+           if (*fmt == '*') {
+               precision = va_arg(ap, int);
+               fmt++;
+           } else
+               while (isdigit(*fmt)) {
+                   precision = (precision * 10) + (*fmt - '0');
+                   fmt++;
+               }
+       }
+
+       /* parse size flags */
+       while (*fmt) {
+           switch (*fmt) {
+           case 'h':
+               hflag = 1;
+               fmt++;
+               continue;       /* short argument */
+           case 'l':
+               lflag = 1;
+               fmt++;
+               continue;       /* long argument */
+           default:
+               break;
+           }
+           break;
+       }
+
+       /* parse format specifier */
+       if (!*fmt)
+           break;
+       switch (*fmt++) {
+       case 'e':
+       case 'E':
+       case 'f':
+       case 'g':
+       case 'G':
+           FVAL = va_arg(ap, double);
+           sprintf(fbuf, "%%%s%s.*L%c", plsign ? "+" : (spsign ? " " : ""),
+                   altform ? "#" : "", fmt[-1]);
+           if (!haveprec)
+               precision = 6;
+           if (precision > MAXPREC)
+               precision = MAXPREC;
+           sprintf(xbuf, fbuf, precision, FVAL);
+           x = xbuf;
+           len = strlen(x);
+           break;
+
+       case 'i':
+       case 'd':               /* signed decimal integer */
+           if (lflag)
+               SVAL = va_arg(ap, long);
+           else if (hflag)
+               SVAL = va_arg(ap, int);
+           else
+               SVAL = va_arg(ap, int);
+           UVAL = (SVAL < 0) ? -SVAL : SVAL;
+
+           if (SVAL < 0)
+               xbuf[0] = '-';
+           else if (plsign)
+               xbuf[0] = '+';
+           else if (spsign)
+               xbuf[0] = ' ';
+           else
+               xbuf[0] = 0;
+
+           if (!haveprec) {
+               if (zfill && !ljust)
+                   precision = width - !!xbuf[0];
+               else
+                   precision = 1;
+               if (precision < 1 + !!xbuf[0])
+                   precision = 1 + !!xbuf[0];
+           }
+           if (precision > MAXPREC)
+               precision = MAXPREC;
+
+           mkint(xbuf + 1, UVAL, 10, 0, precision);
+           x = xbuf + !xbuf[0];
+           len = strlen(x);
+           break;
+
+
+       case 'o':               /* unsigned octal integer */
+           if (lflag)
+               UVAL = va_arg(ap, unsigned long);
+           else if (hflag)
+               UVAL = va_arg(ap, unsigned int);
+           else
+               UVAL = va_arg(ap, unsigned int);
+
+           xbuf[0] = '0';
+
+           if (!haveprec) {
+               if (zfill && !ljust)
+                   precision = width;
+               else
+                   precision = 1;
+           }
+           if (precision > MAXPREC)
+               precision = MAXPREC;
+
+           mkint(xbuf + 1, UVAL, 8, 0, precision);
+           x = xbuf + (xbuf[1] == '0' || !altform);
+           len = strlen(x);
+           break;
+
+       case 'u':               /* unsigned decimal integer */
+           if (lflag)
+               UVAL = va_arg(ap, unsigned long);
+           else if (hflag)
+               UVAL = va_arg(ap, unsigned int);
+           else
+               UVAL = va_arg(ap, unsigned int);
+
+           if (!haveprec) {
+               if (zfill && !ljust)
+                   precision = width;
+               else
+                   precision = 1;
+           }
+           if (precision > MAXPREC)
+               precision = MAXPREC;
+
+           mkint(xbuf, UVAL, 10, 0, precision);
+           x = xbuf;
+           len = strlen(x);
+           break;
+
+       case 'x':
+       case 'X':               /* unsigned hexadecimal integer */
+           if (lflag)
+               UVAL = va_arg(ap, unsigned long);
+           else if (hflag)
+               UVAL = va_arg(ap, unsigned int);
+           else
+               UVAL = va_arg(ap, unsigned int);
+
+           xbuf[0] = '0';
+           xbuf[1] = 'x';
+
+           if (!haveprec) {
+               if (zfill && !ljust)
+                   precision = width;
+               else
+                   precision = 1;
+           }
+           if (precision > MAXPREC)
+               precision = MAXPREC;
+
+           mkint(xbuf + 2, UVAL, 16, 0, precision);
+           x = xbuf + ((altform && UVAL) ? 0 : 2);
+           len = strlen(x);
+           break;
+
+       case '%':               /* literal % */
+           xbuf[0] = '%';
+           xbuf[1] = 0;
+           x = xbuf;
+           len = 1;
+           break;
+
+       case 'c':               /* character */
+           xbuf[0] = va_arg(ap, int);
+           xbuf[1] = 0;
+           x = xbuf;
+           len = 1;
+           break;
+
+       case 's':               /* string */
+           x = va_arg(ap, char *);
+           if (!x)
+               x = "<null>";
+           len = strlen(x);
+           if (haveprec && precision < len)
+               len = precision;
+           break;
+
+       case 'I':               /* IP address:
+                                * value is provided as a network-order unsigned long integer
+                                * precision specifies max hostname length, as for %s
+                                * if precision is explicitly 0, no hostname lookup is done
+                                * if 0fill specified, IPaddr fields are 0-filled to 3 digits
+                                * if spsign specified, IPaddr fields are space-filled to 3 digits
+                                */
+           UVAL = va_arg(ap, unsigned long);
+           ia.s_addr = UVAL;
+           /* XXX: add support for an application-provided function
+            * for doing hostname lookups.  We don't do it automatically
+            * because on some platforms that would prevent us from
+            * being fully statically linked.
+            */
+           if (haveprec && !precision)
+               he = 0;
+           else
+               he = gethostbyaddr((char *)&ia, 4, AF_INET);
+           if (he) {
+               x = he->h_name;
+               len = strlen(x);
+               if (haveprec && precision < len)
+                   len = precision;
+               if (altform)
+                   for (y = x; *y; y++)
+                       if (isupper(*y))
+                           *y = tolower(*y);
+                       else if (plsign)
+                           for (y = x; *y; y++)
+                               if (islower(*y))
+                                   *y = toupper(*y);
+           } else {
+               UVAL = ntohl(UVAL);
+               if (zfill)
+                   x = "%03u.%03u.%03u.%03u";
+               else if (spsign)
+                   x = "%3u.%3u.%3u.%3u";
+               else
+                   x = "%u.%u.%u.%u";
+               sprintf(xbuf, x, (UVAL & 0xff000000) >> 24,
+                       (UVAL & 0x00ff0000) >> 16, (UVAL & 0x0000ff00) >> 8,
+                       (UVAL & 0x000000ff));
+               x = xbuf;
+               len = strlen(xbuf);
+           }
+           break;
+
+       case 'n':               /* report count so far */
+           if (lflag) {
+               lcountp = va_arg(ap, long *);
+               *lcountp = count;
+           } else if (hflag) {
+               hcountp = va_arg(ap, short *);
+               *hcountp = count;
+           } else {
+               countp = va_arg(ap, int *);
+               *countp = count;
+           }
+           continue;
+
+       default:                /* unknown specifier */
+           continue;
+       }
+
+       /* render the results */
+       if (!width)
+           width = len;
+       j = width - len;
+       if (j > 0)
+           count += j;
+       count += len;
+
+       if (!ljust && (err = wsp(X, j)))
+           return err;
+       if ((err = xfwrite(X, x, len)))
+           return err;
+       if (ljust && (err = wsp(X, j)))
+           return err;
+    }
+    if (lit && (err = xfwrite(X, lit, fmt - lit)))
+       return err;
+    return 0;
+}
+
+
+afs_uint32
+xfprintf(XFILE * X, char *fmt, ...)
+{
+    va_list ap;
+    afs_uint32 err;
+
+    va_start(ap, fmt);
+    err = vxfprintf(X, fmt, ap);
+    va_end(ap);
+    return err;
+}
diff --git a/src/tools/xf_profile.c b/src/tools/xf_profile.c
new file mode 100644 (file)
index 0000000..f043849
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* xf_profile.c - XFILE routines for read/write profiling */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "xfiles.h"
+#include "xf_errs.h"
+
+#define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
+
+typedef struct {
+    XFILE content;
+    XFILE profile;
+} PFILE;
+
+
+/* do_read for profiled xfiles */
+static afs_uint32
+xf_PROFILE_do_read(XFILE * X, void *buf, afs_uint32 count)
+{
+    PFILE *PF = X->refcon;
+    afs_uint32 err;
+
+    err = xfread(&PF->content, buf, count);
+    xfprintf(&PF->profile, "R %ld =%ld\n", (long)count, (long)err);
+    return err;
+}
+
+
+/* do_write for profiled xfiles */
+static afs_uint32
+xf_PROFILE_do_write(XFILE * X, void *buf, afs_uint32 count)
+{
+    PFILE *PF = X->refcon;
+    afs_uint32 err;
+
+    err = xfwrite(&PF->content, buf, count);
+    xfprintf(&PF->profile, "W %ld =%ld\n", (long)count, (long)err);
+    return err;
+}
+
+
+/* do_tell for profiled xfiles */
+static afs_uint32
+xf_PROFILE_do_tell(XFILE * X, u_int64 * offset)
+{
+    PFILE *PF = X->refcon;
+    afs_uint32 err;
+
+    err = xftell(&PF->content, offset);
+    if (err)
+       xfprintf(&PF->profile, "TELL ERR =%ld\n", (long)err);
+    else
+       xfprintf(&PF->profile, "TELL %s =0\n", hexify_int64(offset, 0));
+    return err;
+}
+
+
+/* do_seek for profiled xfiles */
+static afs_uint32
+xf_PROFILE_do_seek(XFILE * X, u_int64 * offset)
+{
+    PFILE *PF = X->refcon;
+    afs_uint32 err;
+
+    err = xfseek(&PF->content, offset);
+    xfprintf(&PF->profile, "SEEK %s =%ld\n", hexify_int64(offset, 0),
+            (long)err);
+    return err;
+}
+
+
+/* do_skip for profiled xfiles */
+static afs_uint32
+xf_PROFILE_do_skip(XFILE * X, afs_uint32 count)
+{
+    PFILE *PF = X->refcon;
+    afs_uint32 err;
+
+    err = xfskip(&PF->content, count);
+    xfprintf(&PF->profile, "SKIP %ld =%ld\n", (long)count, (long)err);
+    return err;
+}
+
+
+/* do_close for profiled xfiles */
+static afs_uint32
+xf_PROFILE_do_close(XFILE * X)
+{
+    PFILE *PF = X->refcon;
+    afs_uint32 err, err2;
+
+    err = xfclose(&PF->content);
+    err2 = xfclose(&PF->profile);
+    free(PF);
+    return err ? err : err2;
+}
+
+
+/* Open a profiled XFILE */
+afs_uint32
+xfopen_profile(XFILE * X, int flag, char *xname, char *profile)
+{
+    PFILE *PF;
+    afs_uint32 err;
+
+    PF = malloc(sizeof(*PF));
+    if (!PF)
+       return ENOMEM;
+    memset(PF, 0, sizeof(*PF));
+
+    err = xfopen(&PF->profile, O_RDWR | O_CREAT | O_TRUNC, profile);
+    if (err) {
+       free(PF);
+       return err;
+    }
+
+    err = xfopen(&PF->content, flag, xname);
+    if (err) {
+       xfclose(&PF->profile);
+       free(PF);
+       return err;
+    }
+
+    memset(X, 0, sizeof(*X));
+    X->refcon = PF;
+    X->do_read = xf_PROFILE_do_read;
+    X->do_write = xf_PROFILE_do_write;
+    X->do_tell = xf_PROFILE_do_tell;
+    X->do_close = xf_PROFILE_do_close;
+    X->is_writable = PF->content.is_writable;
+    if (PF->content.is_seekable) {
+       X->is_seekable = 1;
+       X->do_seek = xf_PROFILE_do_seek;
+       X->do_skip = xf_PROFILE_do_skip;
+    }
+    xfprintf(&PF->profile, "OPEN %s\n", xname);
+    return 0;
+}
+
+
+afs_uint32
+xfon_profile(XFILE * X, int flag, char *name)
+{
+    char *x, *profile, *xname;
+    afs_uint32 err;
+
+    if (!(name = strdup(name)))
+       return ENOMEM;
+
+    profile = "-";
+    xname = name;
+    for (x = name; *x; x++) {
+       if (x[0] == ':' && x[1] == ':') {
+           *x = 0;
+           profile = name;
+           xname = x + 2;
+           break;
+       }
+    }
+    if (!*name)
+       profile = "-";
+    err = xfopen_profile(X, flag, xname, profile);
+    free(name);
+    return err;
+}
diff --git a/src/tools/xf_rxcall.c b/src/tools/xf_rxcall.c
new file mode 100644 (file)
index 0000000..e74eef4
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* xf_rxcall.c - XFILE routines for Rx bulk data transfers */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <netdb.h>
+
+#include "xfiles.h"
+#include "xf_errs.h"
+
+#include <rx/xdr.h>
+#include <rx/rx.h>
+#include <rx/rx_null.h>
+#include <rx/rxkad.h>
+#include <afs/auth.h>
+#include <afs/cellconfig.h>
+#include <afs/vlserver.h>
+#include <afs/volser.h>
+#include <afs/volint.h>
+
+#ifndef AFSCONF_CLIENTNAME
+#include <afs/dirpath.h>
+#define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
+#endif
+
+#define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
+
+struct rxinfo {
+    struct rx_connection *conn;        /* connection */
+    struct rx_call *call;      /* call */
+    afs_int32 tid;             /* volser transaction ID */
+    afs_uint32 code;           /* result code */
+};
+
+static afs_uint32
+xf_rxcall_do_read(XFILE * X, void *buf, afs_uint32 count)
+{
+    struct rxinfo *i = X->refcon;
+    afs_uint32 xcount;
+
+    xcount = rx_Read(i->call, buf, count);
+    if (xcount == count)
+       return 0;
+    i->code = rx_EndCall(i->call, 0);
+    i->call = 0;
+    return i->code ? i->code : ERROR_XFILE_RDONLY;
+}
+
+
+static afs_uint32
+xf_rxcall_do_write(XFILE * X, void *buf, afs_uint32 count)
+{
+    struct rxinfo *i = X->refcon;
+    afs_uint32 xcount;
+
+    xcount = rx_Write(i->call, buf, count);
+    if (xcount == count)
+       return 0;
+    i->code = rx_EndCall(i->call, 0);
+    i->call = 0;
+    return i->code;
+}
+
+
+static afs_uint32
+xf_rxcall_do_close(XFILE * X)
+{
+    struct rxinfo *i = X->refcon;
+    afs_uint32 code;
+
+    if (i->call) {
+       code = rx_EndCall(i->call, i->code);
+       i->call = 0;
+    } else {
+       code = i->code;
+    }
+    free(i);
+    return code;
+}
+
+
+static afs_uint32
+xf_voldump_do_close(XFILE * X)
+{
+    struct rxinfo *i = X->refcon;
+    struct rx_connection *conn = i->conn;
+    afs_int32 code, rcode, xcode;
+    afs_int32 tid = i->tid;
+
+    code = xf_rxcall_do_close(X);
+    xcode = AFSVolEndTrans(conn, tid, &rcode);
+    if (!code)
+       code = xcode ? xcode : rcode;
+    return code;
+}
+
+
+afs_uint32
+xfopen_rxcall(XFILE * X, int flag, struct rx_call * call)
+{
+    struct rxinfo *i;
+
+    flag &= O_MODE_MASK;
+    if (flag == O_WRONLY)
+       return ERROR_XFILE_WRONLY;
+    memset(X, 0, sizeof(*X));
+    if (!(i = (struct rxinfo *)malloc(sizeof(struct rxinfo))))
+       return ENOMEM;
+    i->call = call;
+    i->code = 0;
+    X->do_read = xf_rxcall_do_read;
+    X->do_write = xf_rxcall_do_write;
+    X->do_close = xf_rxcall_do_close;
+    X->is_writable = (flag == O_RDWR);
+    X->refcon = i;
+    return 0;
+}
+
+
+afs_uint32
+xfopen_voldump(XFILE * X, struct rx_connection * conn, afs_int32 part,
+              afs_int32 volid, afs_int32 date)
+{
+    struct rx_call *call;
+    struct rxinfo *i;
+    afs_int32 code, rcode;
+    afs_int32 tid;
+
+    if ((code = AFSVolTransCreate(conn, volid, part, ITBusy, &tid)))
+       return code;
+    call = rx_NewCall(conn);
+    if ((code = StartAFSVolDump(call, tid, date))
+       || (code = xfopen_rxcall(X, O_RDONLY, call))) {
+       rx_EndCall(call, 0);
+       AFSVolEndTrans(conn, tid, &rcode);
+       return code;
+    }
+
+    i = X->refcon;
+    i->conn = conn;
+    i->tid = tid;
+    X->do_close = xf_voldump_do_close;
+    return 0;
+}
+
+
+afs_uint32
+xfon_voldump(XFILE * X, int flag, char *name)
+{
+    struct hostent *he;
+    struct rx_securityClass *class;
+    struct rx_connection *conn;
+    struct ktc_principal sname;
+    struct ktc_token token;
+    struct afsconf_dir *confdir;
+    afs_uint32 code, server_addr = 0;
+    afs_int32 volid, date, partid = 0;
+    int isnum, index;
+    char *x, *y;
+
+    /* Parse out the optional date and server location */
+    if ((code = rx_Init(0)))
+       return code;
+    if (!(name = strdup(name)))
+       return ENOMEM;
+    if ((x = strrchr(name, ','))) {
+       *x++ = 0;
+       date = atoi(x);
+    } else {
+       date = 0;
+    }
+    if ((x = strrchr(name, '@'))) {
+       int a, b, c, d;
+
+       *x++ = 0;
+       if (!(y = strchr(x, '/'))) {
+           free(name);
+           return VL_BADPARTITION;
+       }
+       *y++ = 0;
+       if (sscanf(x, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 && a >= 0
+           && a <= 255 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0
+           && d <= 255) {
+           server_addr = (a << 24) | (b << 16) | (c << 8) | d;
+           server_addr = htonl(server_addr);
+       } else {
+           he = gethostbyname(x);
+           if (!he) {
+               free(name);
+               return VL_BADSERVER;
+           }
+           memcpy(&server_addr, he->h_addr, sizeof(server_addr));
+       }
+       partid = volutil_GetPartitionID(y);
+       if (partid < 0) {
+           free(name);
+           return VL_BADPARTITION;
+       }
+    }
+
+    /* Get tokens and set up a security object */
+    confdir = afsconf_Open(AFSCONF_CLIENTNAME);
+    if (!confdir) {
+       free(name);
+       return AFSCONF_NODB;
+    }
+    if ((code = afsconf_GetLocalCell(confdir, sname.cell, MAXKTCNAMELEN))) {
+       free(name);
+       return code;
+    }
+    afsconf_Close(confdir);
+    strcpy(sname.name, "afs");
+    sname.instance[0] = 0;
+    code = ktc_GetToken(&sname, &token, sizeof(token), 0);
+    if (code) {
+       class = rxnull_NewClientSecurityObject();
+       index = 0;
+    } else {
+       class =
+           rxkad_NewClientSecurityObject(rxkad_clear, &token.sessionKey,
+                                         token.kvno, token.ticketLen,
+                                         token.ticket);
+       index = 2;
+    }
+
+    /* Figure out the volume ID, looking it up in the VLDB if neccessary.
+     * Also look up the server and partition, if they were not specified.
+     */
+    for (isnum = 1, y = name; *y; y++)
+       if (*y < '0' || *y > '9')
+           isnum = 0;
+    if (isnum) {
+       volid = atoi(name);
+       if (!x) {
+           fprintf(stderr, "XXX: need to lookup volume by ID!\n");
+           exit(-1);
+       }
+    } else {
+       fprintf(stderr, "XXX: need to lookup volume by name!\n");
+       exit(-1);
+    }
+    free(name);
+
+    /* Establish a connection and start the call */
+    conn =
+       rx_NewConnection(server_addr, htons(AFSCONF_VOLUMEPORT),
+                        VOLSERVICE_ID, class, index);
+    return xfopen_voldump(X, conn, partid, volid, date);
+}
diff --git a/src/tools/xfiles.c b/src/tools/xfiles.c
new file mode 100644 (file)
index 0000000..08898fb
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* xfiles.c - General support routines for xfiles */
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "xfiles.h"
+#include "xf_errs.h"
+
+#define SKIP_SIZE 65536
+
+extern afs_uint32 xfon_path(XFILE *, int, char *);
+extern afs_uint32 xfon_fd(XFILE *, int, char *);
+extern afs_uint32 xfon_voldump(XFILE *, int, char *);
+extern afs_uint32 xfon_profile(XFILE *, int, char *);
+extern afs_uint32 xfon_stdio(XFILE *, int);
+
+struct xftype {
+    struct xftype *next;
+    char *name;
+      afs_uint32(*do_on) (XFILE *, int, char *);
+};
+
+
+static struct xftype *xftypes = 0;
+static int did_register_defaults = 0;
+
+
+afs_uint32
+xfread(XFILE * X, void *buf, afs_uint32 count)
+{
+    afs_uint32 code;
+    u_int64 tmp64;
+
+    code = (X->do_read) (X, buf, count);
+    if (code)
+       return code;
+
+    add64_32(tmp64, X->filepos, count);
+    cp64(X->filepos, tmp64);
+    if (X->passthru)
+       return xfwrite(X->passthru, buf, count);
+    return 0;
+}
+
+
+afs_uint32
+xfwrite(XFILE * X, void *buf, afs_uint32 count)
+{
+    afs_uint32 code;
+    u_int64 tmp64;
+
+    if (!X->is_writable)
+       return ERROR_XFILE_RDONLY;
+    code = (X->do_write) (X, buf, count);
+    if (code)
+       return code;
+
+    add64_32(tmp64, X->filepos, count);
+    cp64(X->filepos, tmp64);
+    return 0;
+}
+
+
+afs_uint32
+xftell(XFILE * X, u_int64 * offset)
+{
+    if (X->do_tell)
+       return (X->do_tell) (X, offset);
+    cp64(*offset, X->filepos);
+    return 0;
+}
+
+
+afs_uint32
+xfseek(XFILE * X, u_int64 * offset)
+{
+    afs_uint32 code;
+
+    if (!X->do_seek)
+       return ERROR_XFILE_NOSEEK;
+    code = (X->do_seek) (X, offset);
+    if (code)
+       return code;
+    cp64(X->filepos, *offset);
+    return 0;
+}
+
+
+afs_uint32
+xfskip(XFILE * X, afs_uint32 count)
+{
+    afs_uint32 code;
+    u_int64 tmp64;
+
+    /* Use the skip method, if there is one */
+    if (X->do_skip && !X->passthru) {
+       code = (X->do_skip) (X, count);
+       if (code)
+           return code;
+       add64_32(tmp64, X->filepos, count);
+       cp64(X->filepos, tmp64);
+       return 0;
+    }
+
+    /* Simulate using absolute seek, if available */
+    if (X->do_seek && !X->passthru) {
+       if ((code = xftell(X, &tmp64)))
+           return code;
+       add64_32(X->filepos, tmp64, count);
+       cp64(tmp64, X->filepos);
+       return xfseek(X, &tmp64);
+    }
+
+    /* Do it the hard/slow way - read all the data to be skipped.
+     * This is done if no other method is available, or if we are
+     * supposed to be copying all the data to another XFILE
+     */
+    {
+       char buf[SKIP_SIZE];
+       afs_uint32 n;
+
+       while (count) {
+           n = (count > SKIP_SIZE) ? SKIP_SIZE : count;
+           if ((code = xfread(X, buf, n)))
+               return code;
+           count -= n;
+       }
+       return 0;
+    }
+}
+
+
+afs_uint32
+xfpass(XFILE * X, XFILE * Y)
+{
+    if (X->passthru)
+       return ERROR_XFILE_ISPASS;
+    if (!Y->is_writable)
+       return ERROR_XFILE_RDONLY;
+    X->passthru = Y;
+    return 0;
+}
+
+
+afs_uint32
+xfunpass(XFILE * X)
+{
+    if (!X->passthru)
+       return ERROR_XFILE_NOPASS;
+    X->passthru = 0;
+    return 0;
+}
+
+
+afs_uint32
+xfclose(XFILE * X)
+{
+    int code = 0;
+
+    if (X->do_close)
+       code = (X->do_close) (X);
+    memset(X, 0, sizeof(*X));
+    return 0;
+}
+
+
+afs_uint32
+xfregister(char *name, afs_uint32(*do_on) (XFILE *, int, char *))
+{
+    struct xftype *x;
+
+    if (!(x = (struct xftype *)malloc(sizeof(struct xftype))))
+       return ENOMEM;
+    memset(x, 0, sizeof(*x));
+    x->next = xftypes;
+    x->name = name;
+    x->do_on = do_on;
+    xftypes = x;
+    return 0;
+}
+
+
+static void
+register_default_types(void)
+{
+    xfregister("FILE", xfon_path);
+    xfregister("FD", xfon_fd);
+    xfregister("AFSDUMP", xfon_voldump);
+    xfregister("PROFILE", xfon_profile);
+    did_register_defaults = 1;
+}
+
+
+afs_uint32
+xfopen(XFILE * X, int flag, char *name)
+{
+    struct xftype *x;
+    char *type, *sep;
+
+    if (!did_register_defaults)
+       register_default_types();
+    if (!strcmp(name, "-"))
+       return xfon_stdio(X, flag);
+
+    for (type = name; *name && *name != ':'; name++);
+    if (*name) {
+       sep = name;
+       *name++ = 0;
+    } else {
+       sep = 0;
+       name = type;
+       type = "FILE";
+    }
+
+    for (x = xftypes; x; x = x->next)
+       if (!strcmp(type, x->name))
+           break;
+    if (sep)
+       *sep = ':';
+    if (x)
+       return (x->do_on) (X, flag, name);
+    return ERROR_XFILE_TYPE;
+}
diff --git a/src/tools/xfiles.h b/src/tools/xfiles.h
new file mode 100644 (file)
index 0000000..83d3b7e
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * CMUCS AFStools
+ * dumpscan - routines for scanning and manipulating AFS volume dumps
+ *
+ * Copyright (c) 1998 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/* xfiles.h - Type, constant, and function declarations for
+ * extensible file-like things */
+
+#ifndef _XFILES_H_
+#define _XFILES_H_
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "intNN.h"
+
+struct rx_call;
+struct rx_connection;
+
+/* The XFILE structure */
+typedef struct XFILE XFILE;
+struct XFILE {
+    afs_uint32(*do_read) (XFILE *, void *, afs_uint32);        /* read data */
+    afs_uint32(*do_write) (XFILE *, void *, afs_uint32);       /* write data */
+    afs_uint32(*do_tell) (XFILE *, u_int64 *); /* find position */
+    afs_uint32(*do_seek) (XFILE *, u_int64 *); /* set position */
+    afs_uint32(*do_skip) (XFILE *, afs_uint32);        /* skip forward */
+    afs_uint32(*do_close) (XFILE *);   /* close */
+    u_int64 filepos;           /* position (counted) */
+    int is_seekable;           /* 1 if seek works */
+    int is_writable;           /* 1 if write works */
+    XFILE *passthru;           /* XFILE to pass thru to */
+    void *refcon;              /* type-specific data */
+};
+
+
+/* Functions for opening XFILEs.  For these, the first two arguments are
+ * always a pointer to an XFILE to fill in, and the mode in which to
+ * open the file.  O_RDONLY and O_RDWR are permitted; O_WRONLY is not.
+ * Other open modes may or may not be used, depending on the object type.
+ * Remaining arguments are a function of the object type
+ */
+extern afs_uint32 xfopen(XFILE *, int, char *);        /* open by TYPE:name */
+extern afs_uint32 xfopen_path(XFILE *, int, char *, int);      /* open by path   */
+extern afs_uint32 xfopen_FILE(XFILE *, int, FILE *);   /* open by FILE * */
+extern afs_uint32 xfopen_fd(XFILE *, int, int);        /* open by fd     */
+extern afs_uint32 xfopen_rxcall(XFILE *, int, struct rx_call *);
+extern afs_uint32 xfopen_voldump(XFILE *, struct rx_connection *, afs_int32,
+                                afs_int32, afs_int32);
+extern afs_uint32 xfopen_profile(XFILE *, int, char *, char *);
+
+extern afs_uint32 xfregister(char *, afs_uint32(*)(XFILE *, int, char *));
+
+/* Standard operations on XFILEs */
+extern afs_uint32 xfread(XFILE *, void *, afs_uint32); /* read data */
+extern afs_uint32 xfwrite(XFILE *, void *, afs_uint32);        /* write data */
+extern afs_uint32 xfprintf(XFILE *, char *, ...);      /* formatted */
+extern afs_uint32 vxfprintf(XFILE *, char *, va_list); /* formatted VA */
+extern afs_uint32 xftell(XFILE *, u_int64 *);  /* get position */
+extern afs_uint32 xfseek(XFILE *, u_int64 *);  /* set position */
+extern afs_uint32 xfskip(XFILE *, afs_uint32); /* skip forward */
+extern afs_uint32 xfpass(XFILE *, XFILE *);    /* set passthru */
+extern afs_uint32 xfunpass(XFILE *);   /* unset passthru */
+extern afs_uint32 xfclose(XFILE *);    /* close */
+
+#endif /* _XFILES_H_ */