merge ntops and namei
authorDerrick Brashear <shadow@dementia.org>
Thu, 28 Oct 2010 05:03:49 +0000 (01:03 -0400)
committerDerrick Brashear <shadow@dementia.org>
Fri, 5 Nov 2010 19:27:14 +0000 (12:27 -0700)
instead of having 2 implementations of nearly the same thing,
merge what we can. this can get closer, probably, but this is
a start.

Change-Id: I8446649e37ab0856e6e40933a44a35edbc708638
Reviewed-on: http://gerrit.openafs.org/3180
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

12 files changed:
src/viced/afsfileprocs.c
src/vol/NTMakefile
src/vol/ihandle.c
src/vol/ihandle.h
src/vol/namei_ops.c
src/vol/namei_ops.h
src/vol/ntops.c
src/vol/ntops.h
src/vol/nuke.c
src/vol/vol-info.c
src/vol/vol-salvage.c
src/vol/vutil.c

index c960b66..74fef85 100644 (file)
@@ -7184,11 +7184,7 @@ GetLinkCountAndSize(Volume * vp, FdHandle_t * fdP, int *lc,
     lhp = IH_OPEN(V_linkHandle(vp));
     if (!lhp)
        return EIO;
-#ifdef AFS_NT40_ENV
-    *lc = nt_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
-#else
-    *lc = namei_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
-#endif
+    *lc = namei_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0, 0, 1);
     FDH_CLOSE(lhp);
     if (*lc < 0)
        return -1;
index d149662..e4682bf 100644 (file)
@@ -20,6 +20,7 @@ INCFILES =\
        $(INCFILEDIR)\afs\fssync.h \
        $(INCFILEDIR)\afs\ihandle.h \
        $(INCFILEDIR)\afs\nfs.h \
+       $(INCFILEDIR)\afs\namei_ops.h \
        $(INCFILEDIR)\afs\ntops.h \
        $(INCFILEDIR)\afs\partition.h \
        $(INCFILEDIR)\afs\viceinode.h \
@@ -46,6 +47,7 @@ LIBOBJS =\
        $(OUT)\fssync-client.obj \
        $(OUT)\fssync-server.obj \
        $(OUT)\daemon_com.obj \
+       $(OUT)\namei_ops.obj \
        $(OUT)\ntops.obj \
        $(OUT)\nuke.obj \
        $(OUT)\partition.obj \
@@ -62,6 +64,7 @@ MT_LIBOBJS =\
        $(OUT)\fssync-client_mt.obj \
        $(OUT)\fssync-server_mt.obj \
        $(OUT)\daemon_com_mt.obj \
+       $(OUT)\namei_ops.obj \
        $(OUT)\ntops.obj \
        $(OUT)\nuke_mt.obj \
        $(OUT)\partition_mt.obj \
@@ -114,6 +117,7 @@ DAFS_LIBOBJS =\
        $(OUT)\fssync-client_dafs.obj \
        $(OUT)\fssync-server_dafs.obj \
        $(OUT)\daemon_com_dafs.obj \
+       $(OUT)\namei_ops.obj \
        $(OUT)\ntops.obj \
        $(OUT)\nuke_dafs.obj \
        $(OUT)\partition_dafs.obj \
index 821330b..2985bff 100644 (file)
@@ -1034,17 +1034,21 @@ ih_icreate(IHandle_t * ih, int dev, char *part, Inode nI, int p1, int p2,
 }
 #endif /* AFS_NAMEI_ENV */
 
-
-#ifndef AFS_NT40_ENV
 afs_sfsize_t
-ih_size(int fd)
+ih_size(FD_t fd)
 {
+#ifdef AFS_NT40_ENV
+    LARGE_INTEGER size;
+    if (!GetFileSizeEx(fd, &size))
+       return -1;
+    return size.QuadPart;
+#else
     struct afs_stat status;
     if (afs_fstat(fd, &status) < 0)
        return -1;
     return status.st_size;
-}
 #endif
+}
 
 #ifndef HAVE_PIO
 ssize_t
index c36acd7..70c3f50 100644 (file)
@@ -55,6 +55,8 @@
  * FDH_REALLYCLOSE - Close a file descriptor, do not return to the cache
  * FDH_SYNC - Unconditionally sync an open file.
  * FDH_TRUNC - Truncate a file
+ * FDH_LOCKFILE - Lock a whole file
+ * FDH_UNLOCKFILE - Unlock a whole file
  *
  * status information:
  * FDH_SIZE - returns the size of the file.
@@ -147,10 +149,11 @@ struct IHandle_s;
  */
 #ifdef AFS_NT40_ENV
 typedef HANDLE FD_t;
+#define INVALID_FD INVALID_HANDLE_VALUE
 #else
 typedef int FD_t;
-#endif
 #define INVALID_FD ((FD_t)-1)
+#endif
 
 /* file descriptor handle */
 typedef struct FdHandle_s {
@@ -279,9 +282,9 @@ typedef struct IHashBucket_s {
 #ifdef AFS_NAMEI_ENV
 #ifdef AFS_NT40_ENV
 #include "ntops.h"
-#else
-#include "namei_ops.h"
 #endif
+#include "namei_ops.h"
+
 extern void ih_clear(IHandle_t * h);
 extern Inode ih_create(IHandle_t * h, int dev, char *part, Inode nI, int p1,
                       int p2, int p3, int p4);
@@ -374,14 +377,27 @@ extern ssize_t ih_pwrite(int fd, const void * buf, size_t count, afs_foff_t offs
 #define OS_PREAD(FD, B, S, O) ih_pread(FD, B, S, O)
 #define OS_PWRITE(FD, B, S, O) ih_pwrite(FD, B, S, O)
 #endif /* !HAVE_PIO */
+#ifdef AFS_NT40_ENV
+#define OS_LOCKFILE(FD, O) LockFile(FD, (O & 0xFFFFFFFF), (O >> 32), 2, 0)
+#define OS_UNLOCKFILE(FD, O) UnlockFile(FD, (O & 0xFFFFFFFF), (O >> 32), 2, 0)
+#define OS_ERROR(X) nterr_nt2unix(GetLastError(), X)
+#define OS_UNLINK(X) nt_unlink(X)
+#define OS_DIRSEP "\\"
+#define OS_DIRSEPC '\\'
+#else
+#define OS_LOCKFILE(FD, O) flock(FD, LOCK_EX)
+#define OS_UNLOCKFILE(FD, O) flock(FD, LOCK_UN)
+#define OS_ERROR(X) X
+#define OS_UNLINK(X) unlink(X)
+#define OS_DIRSEP "/"
+#define OS_DIRSEPC '/'
+#endif
+
+
 
 #ifdef AFS_NAMEI_ENV
 
 #ifdef AFS_NT40_ENV
-#define IH_CREATE(H, D, P, N, P1, P2, P3, P4) \
-       nt_icreate(H, P, P1, P2, P3, P4)
-
-#define OS_IOPEN(H) nt_iopen(H)
 #define OS_OPEN(F, M, P) nt_open(F, M, P)
 #define OS_CLOSE(FD) nt_close(FD)
 
@@ -391,12 +407,6 @@ extern ssize_t ih_pwrite(int fd, const void * buf, size_t count, afs_foff_t offs
 
 #define OS_SYNC(FD) nt_fsync(FD)
 #define OS_TRUNC(FD, L) nt_ftruncate(FD, L)
-#define OS_SIZE(FD) nt_size(FD)
-
-#define IH_INC(H, I, P) nt_inc(H, I, P)
-#define IH_DEC(H, I, P) nt_dec(H, I, P)
-#define IH_IREAD(H, O, B, S) nt_iread(H, O, B, S)
-#define IH_IWRITE(H, O, B, S) nt_iwrite(H, O, B, S)
 
 #else /* AFS_NT40_ENV */
 
@@ -423,18 +433,15 @@ extern afs_sfsize_t IH_IREAD(IHandle_t * H, afs_foff_t O, void *B,
 extern afs_sfsize_t IH_IWRITE(IHandle_t * H, afs_foff_t O, void *B,
                              afs_fsize_t S);
 #ifdef O_LARGEFILE
-extern off64_t OS_SEEK(int FD, off64_t O, int F);
-extern int OS_TRUNC(int FD, off64_t L);
-#else /* !O_LARGEFILE */
-extern off_t OS_SEEK(int FD, off_t O, int F);
-extern int OS_TRUNC(int FD, off_t L);
-#endif /* !O_LARGEFILE */
-#endif /*S_SPLINT_S */
+#define OFFT off64_t
+#else
+#define OFFT off_t
+#endif
 
-#define IH_CREATE(H, D, P, N, P1, P2, P3, P4) \
-       namei_icreate(H, P, P1, P2, P3, P4)
+extern OFFT OS_SEEK(int FD, OFFT O, int F);
+extern int OS_TRUNC(int FD, OFFT L);
+#endif /*S_SPLINT_S */
 
-#define OS_IOPEN(H) namei_iopen(H)
 #ifdef O_LARGEFILE
 #define OS_OPEN(F, M, P) open64(F, M, P)
 #else /* !O_LARGEFILE */
@@ -446,25 +453,24 @@ extern int OS_TRUNC(int FD, off_t L);
 #define OS_WRITE(FD, B, S) write(FD, B, S)
 #ifdef O_LARGEFILE
 #define OS_SEEK(FD, O, F) lseek64(FD, (off64_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
 #else /* !O_LARGEFILE */
 #define OS_SEEK(FD, O, F) lseek(FD, (off_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
 #endif /* !O_LARGEFILE */
 
 #define OS_SYNC(FD) fsync(FD)
-#ifdef O_LARGEFILE
-#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
-#else /* !O_LARGEFILE */
-#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
-#endif /* !O_LARGEFILE */
-#define OS_SIZE(FD) ih_size(FD)
-extern afs_sfsize_t ih_size(int fd);
 
+/*@=fcnmacros =macrofcndecl@*/
+#endif /* AFS_NT40_ENV */
 #define IH_INC(H, I, P) namei_inc(H, I, P)
 #define IH_DEC(H, I, P) namei_dec(H, I, P)
 #define IH_IREAD(H, O, B, S) namei_iread(H, O, B, S)
 #define IH_IWRITE(H, O, B, S) namei_iwrite(H, O, B, S)
-/*@=fcnmacros =macrofcndecl@*/
-#endif /* AFS_NT40_ENV */
+#define IH_CREATE(H, D, P, N, P1, P2, P3, P4) \
+       namei_icreate(H, P, P1, P2, P3, P4)
+#define OS_IOPEN(H) namei_iopen(H)
+
 
 #else /* AFS_NAMEI_ENV */
 extern Inode ih_icreate(IHandle_t * ih, int dev, char *part, Inode nI, int p1,
@@ -487,18 +493,13 @@ extern Inode ih_icreate(IHandle_t * ih, int dev, char *part, Inode nI, int p1,
 
 #ifdef O_LARGEFILE
 #define OS_SEEK(FD, O, F) lseek64(FD, (off64_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
 #else /* !O_LARGEFILE */
 #define OS_SEEK(FD, O, F) lseek(FD, (off_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
 #endif /* !O_LARGEFILE */
 
 #define OS_SYNC(FD) fsync(FD)
-#ifdef O_LARGEFILE
-#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
-#else /* !O_LARGEFILE */
-#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
-#endif /* !O_LARGEFILE */
-#define OS_SIZE(FD) ih_size(FD)
-extern afs_sfsize_t ih_size(int fd);
 
 #ifdef AFS_LINUX22_ENV
 #define IH_INC(H, I, P) -1
@@ -516,6 +517,8 @@ extern afs_sfsize_t ih_size(int fd);
 
 
 #endif /* AFS_NAMEI_ENV */
+#define OS_SIZE(FD) ih_size(FD)
+extern afs_sfsize_t ih_size(FD_t);
 
 #ifndef AFS_NT40_ENV
 #define FDH_READV(H, I, N) readv((H)->fd_fd, I, N)
@@ -536,5 +539,7 @@ extern afs_sfsize_t ih_size(int fd);
 #define FDH_SYNC(H) ((H->fd_ih!=NULL) ? ( H->fd_ih->ih_synced = 1) - 1 : 1)
 #define FDH_TRUNC(H, L) OS_TRUNC((H)->fd_fd, L)
 #define FDH_SIZE(H) OS_SIZE((H)->fd_fd)
+#define FDH_LOCKFILE(H, O) OS_LOCKFILE((H)->fd_fd, O)
+#define FDH_UNLOCKFILE(H, O) OS_UNLOCKFILE((H)->fd_fd, O)
 
 #endif /* _IHANDLE_H_ */
index 7262037..9d5eda6 100644 (file)
 #ifdef AFS_NAMEI_ENV
 #include <stdio.h>
 #include <stdlib.h>
+#ifndef AFS_NT40_ENV
 #include <unistd.h>
+#else
+#define DELETE_ZLC
+#include <io.h>
+#include <windows.h>
+#include <winnt.h>
+#include <winbase.h>
+#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/stat.h>
+#ifdef AFS_NT40_ENV
+#include <direct.h>
+#else
+#include <sys/file.h>
+#include <sys/param.h>
+#endif
 #include <dirent.h>
 #include <afs/afs_assert.h>
 #include <string.h>
-#include <sys/file.h>
-#include <sys/param.h>
 #include <lock.h>
-#if defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
-#include <unistd.h>
-#endif
 #include <afs/afsutil.h>
 #include <lwp.h>
 #include "nfs.h"
@@ -43,6 +52,9 @@
 #include "volume_inline.h"
 #include "common.h"
 #include <afs/errors.h>
+#ifdef AFS_NT40_ENV
+#include <afs/errmap_nt.h>
+#endif
 
 /*@+fcnmacros +macrofcndecl@*/
 #ifdef O_LARGEFILE
 #endif /*S_SPLINT_S */
 #define afs_stat               stat64
 #define afs_fstat              fstat64
+#ifdef AFS_NT40_ENV
+#define afs_open                nt_open
+#else
 #define afs_open               open64
+#endif
 #define afs_fopen              fopen64
 #else /* !O_LARGEFILE */
 #ifdef S_SPLINT_S
 #endif /*S_SPLINT_S */
 #define afs_stat               stat
 #define afs_fstat              fstat
+#ifdef AFS_NT40_ENV
+#define afs_open                nt_open
+#else
 #define afs_open               open
+#endif
 #define afs_fopen              fopen
 #endif /* !O_LARGEFILE */
 /*@=fcnmacros =macrofcndecl@*/
@@ -76,7 +96,7 @@
 #include <vol/vol-salvage.h>
 #endif
 
-#ifndef HAVE_FLOCK
+#if !defined(HAVE_FLOCK) && !defined(AFS_NT40_ENV)
 #include <fcntl.h>
 
 /*
@@ -136,6 +156,20 @@ namei_iwrite(IHandle_t * h, afs_foff_t offset, char *buf, afs_fsize_t size)
 
 
 
+#ifdef AFS_NT40_ENV
+/* Inode number format:
+ * low 32 bits - if a regular file or directory, the vnode. Else the type.
+ * 32-36 - unquifier tag and index into counts array for this vnode. Only
+ *         two of the available bits are currently used. The rest are
+ *         present in case we ever increase the number of types of volumes
+ *         in the volume group.
+ * bit 37 : 1  == special, 0 == regular
+ */
+#define NAMEI_VNODEMASK    0x00ffffffff
+#define NAMEI_TAGSHIFT     32
+#define NAMEI_INODESPECIAL 0x2000000000
+#define NAMEI_SPECDIR "R"
+#else
 /* Inode number format:
  * low 26 bits - vnode number - all 1's if volume special file.
  * next 3 bits - tag
@@ -143,20 +177,20 @@ namei_iwrite(IHandle_t * h, afs_foff_t offset, char *buf, afs_fsize_t size)
  * high 32 bits - uniquifier (regular) or type if spare
  */
 #define NAMEI_VNODEMASK    0x003ffffff
-#define NAMEI_TAGMASK      0x7
 #define NAMEI_TAGSHIFT     26
 #define NAMEI_UNIQMASK     0xffffffff
 #define NAMEI_UNIQSHIFT    32
 #define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
-#define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
-
 /* dir1 is the high 8 bits of the 26 bit vnode */
 #define VNO_DIR1(vno) ((vno >> 14) & 0xff)
 /* dir2 is the next 9 bits */
 #define VNO_DIR2(vno) ((vno >> 9) & 0x1ff)
 /* "name" is the low 9 bits of the vnode, the 3 bit tag and the uniq */
-
 #define NAMEI_SPECDIR "special"
+#endif
+#define NAMEI_TAGMASK      0x7
+#define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
+
 #define NAMEI_SPECDIRLEN (sizeof(NAMEI_SPECDIR)-1)
 
 #define NAMEI_MAXVOLS 5                /* Maximum supported number of volumes per volume
@@ -173,8 +207,6 @@ typedef struct {
     int ogm_mode;
 } namei_ogm_t;
 
-static int namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite);
-
 static int GetFreeTag(IHandle_t * ih, int vno);
 
 /* namei_HandleToInodeDir
@@ -183,6 +215,17 @@ static int GetFreeTag(IHandle_t * ih, int vno);
  * Format: /<vicepx>/INODEDIR
  *
  */
+#ifdef AFS_NT40_ENV
+static void
+namei_HandleToInodeDir(namei_t * name, IHandle_t * ih)
+{
+    memset(name, '\0', sizeof(*name));
+    nt_DevToDrive(name->n_drive, ih->ih_dev);
+    strlcpy(name->n_path, name->n_drive, sizeof(name->n_path));
+}
+
+#else
+/* Format: /<vicepx>/INODEDIR */
 #define PNAME_BLEN 64
 static void
 namei_HandleToInodeDir(namei_t * name, IHandle_t * ih)
@@ -206,14 +249,36 @@ namei_HandleToInodeDir(namei_t * name, IHandle_t * ih)
     strlcpy(name->n_base + offset, INODEDIR, sizeof(name->n_base) - offset);
     strlcpy(name->n_path, name->n_base, sizeof(name->n_path));
 }
+#endif
 
 #define addtoname(N, C)                                 \
 do {                                                    \
-    strlcat((N)->n_path, "/", sizeof((N)->n_path));     \
+    strlcat((N)->n_path, OS_DIRSEP, sizeof((N)->n_path));     \
     strlcat((N)->n_path, (C), sizeof((N)->n_path));     \
 } while(0)
 
 
+#ifdef AFS_NT40_ENV
+static void
+namei_HandleToVolDir(namei_t * name, IHandle_t * ih)
+{
+    /* X:\Vol_XXXXXXX.data */
+    b32_string_t str1;
+    char *namep;
+
+    namei_HandleToInodeDir(name, ih);
+    addtoname(name, name->n_drive);
+    namep = name->n_voldir;
+    (void)memcpy(namep, "\\Vol_", 5);
+    namep += 5;
+    (void)strcpy(namep, int_to_base32(str1, ih->ih_vid));
+    namep += strlen(namep);
+    memcpy(namep, ".data", 5);
+    namep += 5;
+    *namep = '\0';
+    addtoname(name, name->n_voldir);
+}
+#else
 static void
 namei_HandleToVolDir(namei_t * name, IHandle_t * ih)
 {
@@ -227,17 +292,52 @@ namei_HandleToVolDir(namei_t * name, IHandle_t * ih)
     strlcpy(name->n_voldir2, tmp, sizeof(name->n_voldir2));
     addtoname(name, name->n_voldir2);
 }
+#endif
 
 /* namei_HandleToName
  *
  * Constructs a file name for the fully qualified handle.
- * Note that special files end up in /vicepX/InodeDir/Vxx/V*.data/special
  */
+#ifdef AFS_NT40_ENV
+/* Note that special files end up in X:\Vol_XXXXXXX.data\R */
 void
 namei_HandleToName(namei_t * name, IHandle_t * ih)
 {
-    lb64_string_t str;
     int vno = (int)(ih->ih_ino & NAMEI_VNODEMASK);
+    int tag = (int)((ih->ih_ino >> NAMEI_TAGSHIFT) & NAMEI_TAGMASK);
+    b32_string_t str1;
+    char *namep;
+    namei_HandleToVolDir(name, ih);
+
+    if (vno == NAMEI_VNODESPECIAL) {
+       name->n_dir[0] = 'R';
+    } else {
+       if (vno & 0x1)
+            name->n_dir[0] = 'Q';
+        else
+            name->n_dir[0] = ((vno & 0x1f) >> 1) + 'A';
+
+    }
+    name->n_dir[1] = '\0';
+    addtoname(name, name->n_dir);
+    /* X:\Vol_XXXXXXX.data\X\V_XXXXXXX.XXX */
+    namep = name->n_inode;
+    (void)memcpy(namep, "\\V_", 3);
+    namep += 3;
+    (void)strcpy(namep, int_to_base32(str1, vno));
+    namep += strlen(namep);
+    *(namep++) = '.';
+    (void)strcpy(namep, int_to_base32(str1, tag));
+    namep += strlen(namep);
+    addtoname(name, name->n_inode);
+}
+#else
+/* Note that special files end up in /vicepX/InodeDir/Vxx/V*.data/special */
+void
+namei_HandleToName(namei_t * name, IHandle_t * ih)
+{
+    int vno = (int)(ih->ih_ino & NAMEI_VNODEMASK);
+    lb64_string_t str;
 
     namei_HandleToVolDir(name, ih);
 
@@ -257,7 +357,9 @@ namei_HandleToName(namei_t * name, IHandle_t * ih)
     strlcpy(name->n_inode, str, sizeof(name->n_inode));
     addtoname(name, name->n_inode);
 }
+#endif
 
+#ifndef AFS_NT40_ENV
 /* The following is a warning to tell sys-admins to not muck about in this
  * name space.
  */
@@ -284,8 +386,43 @@ namei_ViceREADME(char *partition)
     }
     return (errno);
 }
+#endif
 
+/* namei_CreateDataDirectories
+ *
+ * If creating the file failed because of ENOENT or ENOTDIR, try
+ * creating all the directories first.
+ */
+#ifdef AFS_NT40_ENV
+static int
+namei_CreateDataDirectories(namei_t * name, int *created)
+{
+    char tmp[256];
+    char *s;
+    int i;
+
+    *created = 0;
+    afs_snprintf(tmp, 256, "%s\\%s", name->n_drive, name->n_voldir);
 
+    if (mkdir(tmp) < 0) {
+        if (errno != EEXIST)
+            return -1;
+    } else
+        *created = 1;
+
+    s = tmp;
+    s += strlen(tmp);
+
+    *s++ = '\\';
+    *(s + 1) = '\0';
+    for (i = 'A'; i <= 'R'; i++) {
+        *s = (char)i;
+        if (mkdir(tmp) < 0 && errno != EEXIST)
+            return -1;
+    }
+    return 0;
+}
+#else
 #define create_dir() \
 do { \
     if (mkdir(tmp, 0700)<0) { \
@@ -302,11 +439,6 @@ do { \
         strcat(tmp, "/"); strcat(tmp, A); create_dir();  \
 } while(0)
 
-/* namei_CreateDataDirectories
- *
- * If creating the file failed because of ENOENT or ENOTDIR, try
- * creating all the directories first.
- */
 static int
 namei_CreateDataDirectories(namei_t * name, int *created)
 {
@@ -325,7 +457,9 @@ namei_CreateDataDirectories(namei_t * name, int *created)
     }
     return 0;
 }
+#endif
 
+#ifndef AFS_NT40_ENV
 /* delTree(): Deletes an entire tree of directories (no files)
  * Input:
  *   root : Full path to the subtree. Should be big enough for PATH_MAX
@@ -407,23 +541,62 @@ delTree(char *root, char *tree, int *errp)
     return 0;
 
 }
+#endif
 
 /* namei_RemoveDataDirectories
  * Return Values:
  * Returns 0 on success.
- * Returns -1 on error. Typically, callers ignore this error bcause we
+ * Returns -1 on error. Typically, callers ignore this error because we
  * can continue running if the removes fail. The salvage process will
- * finish tidying up for us. We only use the n_base and n_voldir1 entries
- * and only do rmdir's.
+ * finish tidying up for us.
  */
 
+#ifdef AFS_NT40_ENV
+static int
+namei_RemoveDataDirectories(namei_t * name)
+{
+    int code = 0;
+    char *path;
+    char tmp[256];
+    int i;
+
+    afs_snprintf(tmp, 256, "%s\\%s", name->n_drive, name->n_voldir);
+
+    path = tmp;
+    path += strlen(path);
+    *path++ = '\\';
+    *(path + 1) = '\0';
+    for (i = 'A'; i <= 'R'; i++) {
+        *path = (char)i;
+        if (rmdir(name->n_path) < 0 && errno != ENOENT)
+            code = -1;
+    }
+
+    if (!code) {
+       /* Delete the Vol_NNNNNN.data directory. */
+       path--;
+       *path = '\0';
+       if (rmdir(name->n_path) < 0 && errno != ENOENT) {
+           code = -1;
+       }
+    }
+    return code;
+}
+#else
+/*
+ * We only use the n_base and n_voldir1 entries
+ * and only do rmdir's.
+ */
 static int
 namei_RemoveDataDirectories(namei_t * name)
 {
-    char pbuf[MAXPATHLEN], *path = pbuf;
+    int code = 0;
+    char *path;
     int prefixlen = strlen(name->n_base), err = 0;
     int vollen = strlen(name->n_voldir1);
-    int code;
+    char pbuf[MAXPATHLEN];
+
+    path = pbuf;
 
     strlcpy(path, name->n_path, sizeof(pbuf));
 
@@ -439,9 +612,9 @@ namei_RemoveDataDirectories(namei_t * name)
      * some locking to make this safe (or only remove it for whole-partition
      * salvages), but by not deleting it we only leave behind a maximum of
      * 256 empty directories. So at least for now, don't bother. */
-
     return code;
 }
+#endif
 
 /* Create the file in the name space.
  *
@@ -474,21 +647,26 @@ namei_MakeSpecIno(int volid, int type)
 {
     Inode ino;
     ino = NAMEI_INODESPECIAL;
+#ifdef AFS_NT40_ENV
+    ino |= type;
+#else
     type &= NAMEI_TAGMASK;
     ino |= ((Inode) type) << NAMEI_TAGSHIFT;
     ino |= ((Inode) volid) << NAMEI_UNIQSHIFT;
+#endif
     return ino;
 }
 
-/* SetOGM - set owner group and mode bits from parm and tag
- *
+/* SetOGM - set owner group and mode bits from parm and tag */
+static int
+SetOGM(FD_t fd, int parm, int tag)
+{
+#ifndef AFS_NT40_ENV
+/*
  * owner - low 15 bits of parm.
  * group - next 15 bits of parm.
  * mode - 2 bits of parm, then lowest = 3 bits of tag.
  */
-static int
-SetOGM(int fd, int parm, int tag)
-{
     int owner, group, mode;
 
     owner = parm & 0x7fff;
@@ -500,11 +678,33 @@ SetOGM(int fd, int parm, int tag)
     mode |= tag & 0x7;
     if (fchmod(fd, mode) < 0)
        return -1;
-
+#endif
     return 0;
-
 }
 
+#ifdef AFS_NT40_ENV
+static int
+CheckOGM(namei_t *name, FdHandle_t *fdP, int p1)
+{
+    WIN32_FIND_DATA info;
+    HANDLE dirH;
+
+    dirH =
+       FindFirstFileEx(name->n_path, FindExInfoStandard, &info,
+                       FindExSearchNameMatch, NULL,
+                       FIND_FIRST_EX_CASE_SENSITIVE);
+
+    if (!dirH)
+       return -1;          /* Can't get info, leave alone */
+
+    FindClose(dirH);
+
+    if (info.ftCreationTime.dwHighDateTime != (unsigned int)p1)
+       return -1;
+
+    return 0;
+}
+#else
 /* GetOGM - get parm and tag from owner, group and mode bits. */
 static void
 GetOGMFromStat(struct afs_stat *status, int *parm, int *tag)
@@ -515,23 +715,156 @@ GetOGMFromStat(struct afs_stat *status, int *parm, int *tag)
 }
 
 static int
-GetOGM(int fd, int *parm, int *tag)
+CheckOGM(namei_t *name, FdHandle_t *fdP, int p1)
 {
     struct afs_stat status;
-    if (afs_fstat(fd, &status) < 0)
+    int parm, tag;
+    if (afs_fstat(fdP->fd_fd, &status) < 0)
+       return -1;
+
+    GetOGMFromStat(&status, &parm, &tag);
+    if (parm != p1)
        return -1;
 
-    GetOGMFromStat(&status, parm, tag);
     return 0;
 }
+#endif
 
 int big_vno = 0;               /* Just in case we ever do 64 bit vnodes. */
 
 /* Derive the name and create it O_EXCL. If that fails we have an error.
  * Get the tag from a free column in the link table.
  */
+#ifdef AFS_NT40_ENV
 Inode
-namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
+namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
+{
+    namei_t name;
+    FD_t fd = INVALID_FD;
+    int code = 0;
+    int created_dir = 0;
+    IHandle_t tmp;
+    FdHandle_t *fdP;
+    FdHandle_t tfd;
+    int tag, i;
+    FILETIME ftime;
+    char *p;
+    b32_string_t str1;
+
+    memset((void *)&tmp, 0, sizeof(IHandle_t));
+
+    tmp.ih_dev = nt_DriveToDev(part);
+    if (tmp.ih_dev == -1) {
+       errno = EINVAL;
+       return -1;
+    }
+
+    if (p2 == -1) {
+       /* Parameters for special file:
+        * p1 - volume id - goes into owner/group/mode
+        * p2 - vnode == -1
+        * p3 - type
+        * p4 - parent volume id
+        */
+        ftime.dwHighDateTime = p1;
+        ftime.dwLowDateTime = p2;
+       tag = p3;
+       tmp.ih_vid = p4;        /* Use parent volume id, where this file will be. */
+       tmp.ih_ino = namei_MakeSpecIno(p1, p3);
+    } else {
+       int vno = p2 & NAMEI_VNODEMASK;
+       /* Parameters for regular file:
+        * p1 - volume id
+        * p2 - vnode
+        * p3 - uniq
+        * p4 - dv
+        */
+
+       if (vno != p2) {
+           big_vno++;
+           errno = EINVAL;
+           return -1;
+       }
+
+       tmp.ih_vid = p1;
+       tmp.ih_ino = (Inode) p2;
+       ftime.dwHighDateTime = p3;
+        ftime.dwLowDateTime = p4;
+    }
+
+    namei_HandleToName(&name, &tmp);
+    p = strrchr((char *)&name.n_path, '.');
+    p++;
+    for (i = 0; i < NAMEI_MAXVOLS; i++) {
+        *p = *int_to_base32(str1, i);
+        fd = nt_open((char *)&name.n_path, O_CREAT | O_RDWR | O_TRUNC | O_EXCL, 0666);
+        if (fd != INVALID_FD)
+            break;
+        if (p2 == -1 && p3 == VI_LINKTABLE)
+            break;
+    }
+    if (fd == INVALID_FD) {
+        code = -1;
+        goto bad;
+    }
+    tmp.ih_ino &= ~((Inode) NAMEI_TAGMASK << NAMEI_TAGSHIFT);
+    tmp.ih_ino |= ((Inode) i << NAMEI_TAGSHIFT);
+
+    if (!code) {
+        if (!SetFileTime((HANDLE) fd, &ftime, NULL, NULL)) {
+           errno = OS_ERROR(EBADF);
+            code = -1;
+        }
+    }
+
+    if (!code) {
+        if (p2 != -1) {
+            if (fd == INVALID_FD) {
+                errno = ENOENT;
+                code = nt_unlink((char *)&name.n_path);
+                code = -1;
+                goto bad;
+            }
+            fdP = IH_OPEN(lh);
+            if (fdP == NULL) {
+                code = -1;
+                goto bad;
+            }
+            code = namei_SetLinkCount(fdP, tmp.ih_ino, 1, 0);
+            FDH_CLOSE(fdP);
+        } else if (p2 == -1 && p3 == VI_LINKTABLE) {
+            if (fd == INVALID_FD)
+                goto bad;
+            /* hack at tmp to setup for set link count call. */
+            tfd.fd_fd = fd;
+            code = namei_SetLinkCount(&tfd, (Inode) 0, 1, 0);
+        }
+    }
+
+bad:
+    if (fd != INVALID_FD)
+        nt_close(fd);
+
+    if (code || (fd == INVALID_FD)) {
+       if (p2 != -1) {
+            fdP = IH_OPEN(lh);
+            if (fdP) {
+                namei_SetLinkCount(fdP, tmp.ih_ino, 0, 0);
+                FDH_CLOSE(fdP);
+            }
+        }
+
+       if (created_dir) {
+           int save_errno = errno;
+           namei_RemoveDataDirectories(&name);
+           errno = save_errno;
+       }
+    }
+    return (code || (fd == INVALID_FD)) ? (Inode) - 1 : tmp.ih_ino;
+}
+#else
+Inode
+namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
 {
     namei_t name;
     int fd = -1;
@@ -543,10 +876,8 @@ namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
     int tag;
     int ogm_parm;
 
-
     memset((void *)&tmp, 0, sizeof(IHandle_t));
 
-
     tmp.ih_dev = volutil_GetPartitionID(part);
     if (tmp.ih_dev == -1) {
        errno = EINVAL;
@@ -561,8 +892,8 @@ namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
         * p4 - parent volume id
         */
        ogm_parm = p1;
-       tag = p3;
 
+       tag = p3;
        tmp.ih_vid = p4;        /* Use parent volume id, where this file will be. */
        tmp.ih_ino = namei_MakeSpecIno(p1, p3);
     } else {
@@ -584,9 +915,9 @@ namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
        if (tag < 0)
            goto bad;
 
-       /* name is <uniq(p3)><tag><vno(p2)> */
        tmp.ih_vid = p1;
        tmp.ih_ino = (Inode) p2;
+       /* name is <uniq(p3)><tag><vno(p2)> */
        tmp.ih_ino |= ((Inode) tag) << NAMEI_TAGSHIFT;
        tmp.ih_ino |= ((Inode) p3) << NAMEI_UNIQSHIFT;
 
@@ -637,18 +968,18 @@ namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
     }
     return (code || (fd < 0)) ? (Inode) - 1 : tmp.ih_ino;
 }
-
+#endif
 
 /* namei_iopen */
-int
+FD_t
 namei_iopen(IHandle_t * h)
 {
-    int fd;
+    FD_t fd;
     namei_t name;
 
     /* Convert handle to file name. */
     namei_HandleToName(&name, h);
-    fd = afs_open(name.n_path, O_RDWR, 0666);
+    fd = afs_open((char *)&name.n_path, O_RDWR, 0666);
     return fd;
 }
 
@@ -666,29 +997,30 @@ namei_dec(IHandle_t * ih, Inode ino, int p1)
 
     if ((ino & NAMEI_INODESPECIAL) == NAMEI_INODESPECIAL) {
        IHandle_t *tmp;
-       int inode_p1, tag;
        int type = (int)((ino >> NAMEI_TAGSHIFT) & NAMEI_TAGMASK);
 
        /* Verify this is the right file. */
        IH_INIT(tmp, ih->ih_dev, ih->ih_vid, ino);
 
+       namei_HandleToName(&name, tmp);
+
        fdP = IH_OPEN(tmp);
        if (fdP == NULL) {
            IH_RELEASE(tmp);
-           errno = EINVAL;
+           errno = OS_ERROR(ENOENT);
            return -1;
        }
 
-       if ((GetOGM(fdP->fd_fd, &inode_p1, &tag) < 0) || (inode_p1 != p1)) {
+       if (CheckOGM(&name, fdP, p1) < 0) {
            FDH_REALLYCLOSE(fdP);
            IH_RELEASE(tmp);
-           errno = EINVAL;
+           errno = OS_ERROR(EINVAL);
            return -1;
        }
 
        /* If it's the link table itself, decrement the link count. */
        if (type == VI_LINKTABLE) {
-           if ((count = namei_GetLinkCount(fdP, (Inode) 0, 1)) < 0) {
+         if ((count = namei_GetLinkCount(fdP, (Inode) 0, 1, 0, 1)) < 0) {
                FDH_REALLYCLOSE(fdP);
                IH_RELEASE(tmp);
                return -1;
@@ -709,8 +1041,7 @@ namei_dec(IHandle_t * ih, Inode ino, int p1)
            }
        }
 
-       namei_HandleToName(&name, tmp);
-       if ((code = unlink(name.n_path)) == 0) {
+       if ((code = OS_UNLINK(name.n_path)) == 0) {
            if (type == VI_LINKTABLE) {
                /* Try to remove directory. If it fails, that's ok.
                 * Salvage will clean up.
@@ -727,7 +1058,7 @@ namei_dec(IHandle_t * ih, Inode ino, int p1)
            return -1;
        }
 
-       if ((count = namei_GetLinkCount(fdP, ino, 1)) < 0) {
+       if ((count = namei_GetLinkCount(fdP, ino, 1, 0, 1)) < 0) {
            FDH_REALLYCLOSE(fdP);
            return -1;
        }
@@ -758,7 +1089,7 @@ namei_dec(IHandle_t * ih, Inode ino, int p1)
 
            namei_HandleToName(&name, th);
            IH_RELEASE(th);
-           code = unlink(name.n_path);
+           code = OS_UNLINK(name.n_path);
        }
        FDH_CLOSE(fdP);
     }
@@ -786,12 +1117,12 @@ namei_inc(IHandle_t * h, Inode ino, int p1)
        return -1;
     }
 
-    if ((count = namei_GetLinkCount(fdP, ino, 1)) < 0)
+    if ((count = namei_GetLinkCount(fdP, ino, 1, 0, 1)) < 0)
        code = -1;
     else {
        count++;
        if (count > 7) {
-           errno = EINVAL;
+           errno = OS_ERROR(EINVAL);
            code = -1;
            count = 7;
        }
@@ -806,6 +1137,7 @@ namei_inc(IHandle_t * h, Inode ino, int p1)
     return code;
 }
 
+#ifndef AFS_NT40_ENV
 int
 namei_replace_file_by_hardlink(IHandle_t *hLink, IHandle_t *hTarget)
 {
@@ -879,6 +1211,7 @@ namei_copy_on_write(IHandle_t *h)
     }
     return code;
 }
+#endif
 
 /************************************************************************
  * File Name Structure
@@ -907,6 +1240,41 @@ namei_copy_on_write(IHandle_t *h)
  * Organization" below for more information on the tag. The tag is
  * required in the name of the file to ensure a unique name.
  *
+ * ifdef AFS_NT40_ENV
+ * The data for each volume group is in a separate directory. The name of the
+ * volume is of the form: Vol_NNNNNN.data, where NNNNNN is a base 32
+ * representation of the RW volume ID (even where the RO is the only volume
+ * on the partition). Below that are separate subdirectories for the
+ * AFS directories and special files. There are also 16 directories for files,
+ * hashed on the low 5 bits (recall bit0 is always 0) of the vnode number.
+ * These directories are named:
+ * A - P - 16 file directories.
+ * Q ----- data directory
+ * R ----- special files directory
+ *
+ * The vnode is hashed into the directory using the low bits of the
+ * vnode number.
+ *
+ * The format of a file name for a regular file is:
+ * Y:\Vol_NNNNNN.data\X\V_IIIIII.J
+ * Y - partition encoded as drive letter, starting with D
+ * NNNNNN - base 32 encoded volume number of RW volume
+ * X - hash directory, as above
+ * IIIIII - base 32 encoded vnode number
+ * J - base 32 encoded tag
+ *
+ * uniq is stored in the dwHighDateTime creation time field
+ * dv is stored in the dwLowDateTime creation time field
+ *
+ * Special inodes are always in the R directory, as above, and are
+ * encoded:
+ * True child volid is stored in the dwHighDateTime creation time field
+ * vnode number is always -1 (Special)
+ * type is the IIIIII part of the filename
+ * uniq is the J part of the filename
+ * parent volume id is implied in the containing directory
+ *
+ * else
  * We can store data in the uid, gid and mode bits of the files, provided
  * the directories have root only access. This gives us 15 bits for each
  * of uid and gid (GNU chown considers 65535 to mean "don't change").
@@ -934,6 +1302,8 @@ namei_copy_on_write(IHandle_t *h)
  * as possible, leading to faster discards of incorrect matches in the
  * lookup code.
  *
+ * endif
+ *
  */
 
 
@@ -956,8 +1326,15 @@ namei_copy_on_write(IHandle_t *h)
  * different version of the file (or a different uniquifer) for the BU volume.
  * Then one column would be holding the link count of 2 for the RW and RO
  * and a different column would hold the link count of 1 for the BU volume.
+ * # ifdef AFS_NT40_ENV
+ * The column used is determined for NT by the uniquifier tag applied to
+ * generate a unique file name in the NTFS namespace. The file name is
+ * of the form "V_<vno>.<tag>" . And the <tag> is also the column number
+ * in the link table.
+ * # else
  * Note that we allow only 5 volumes per file, giving 15 bits used in the
  * short.
+ * # endif
  */
 #define LINKTABLE_WIDTH 2
 #define LINKTABLE_SHIFT 1      /* log 2 = 1 */
@@ -1009,8 +1386,8 @@ pthread_mutex_t _namei_glc_lock = PTHREAD_MUTEX_INITIALIZER;
  *
  * @internal
  */
-static int
-namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite)
+int
+namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite)
 {
     unsigned short row = 0;
     afs_foff_t offset;
@@ -1018,12 +1395,12 @@ namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrit
     int index;
 
     /* there's no linktable yet. the salvager will create one later */
-    if (h->fd_fd == -1 && fixup)
+    if (h->fd_fd == INVALID_FD && fixup)
        return 1;
     namei_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
 
     if (lockit) {
-       if (flock(h->fd_fd, LOCK_EX) < 0)
+       if (FDH_LOCKFILE(h, offset) != 0)
            return -1;
     }
 
@@ -1037,9 +1414,8 @@ namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrit
         * in order to make MT-safe, truncation (extension really)
         * must happen under a mutex
         */
-        struct stat st;
        NAMEI_GLC_LOCK;
-        if (fstat(h->fd_fd, &st) || st.st_size >= offset+sizeof(row)) {
+        if (FDH_SIZE(h) >= offset+sizeof(row)) {
            NAMEI_GLC_UNLOCK;
            goto bad_getLinkByte;
        }
@@ -1074,14 +1450,14 @@ namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrit
 
   bad_getLinkByte:
     if (lockit)
-       flock(h->fd_fd, LOCK_UN);
+       FDH_UNLOCKFILE(h, offset);
     return -1;
 }
 
 int
-namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit)
+namei_SetNonZLC(FdHandle_t * h, Inode ino)
 {
-    return namei_GetLinkCount2(h, ino, lockit, 0, 1);
+    return namei_GetLinkCount(h, ino, 0, 1, 0);
 }
 
 /* Return a free column index for this vnode. */
@@ -1101,7 +1477,7 @@ GetFreeTag(IHandle_t * ih, int vno)
        return -1;
 
     /* Only one manipulates at a time. */
-    if (flock(fdP->fd_fd, LOCK_EX) < 0) {
+    if (FDH_LOCKFILE(fdP, offset) != 0) {
        FDH_REALLYCLOSE(fdP);
        return -1;
     }
@@ -1133,12 +1509,12 @@ GetFreeTag(IHandle_t * ih, int vno)
        goto badGetFreeTag;
     }
     FDH_SYNC(fdP);
-    flock(fdP->fd_fd, LOCK_UN);
+    FDH_UNLOCKFILE(fdP, offset);
     FDH_REALLYCLOSE(fdP);
     return col;;
 
   badGetFreeTag:
-    flock(fdP->fd_fd, LOCK_UN);
+    FDH_UNLOCKFILE(fdP, offset);
     FDH_REALLYCLOSE(fdP);
     return -1;
 }
@@ -1155,13 +1531,13 @@ namei_SetLinkCount(FdHandle_t * fdP, Inode ino, int count, int locked)
     afs_foff_t offset;
     int index;
     unsigned short row;
-    int junk;
+    int bytesRead;
     ssize_t nBytes = -1;
 
     namei_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
 
     if (!locked) {
-       if (flock(fdP->fd_fd, LOCK_EX) < 0) {
+       if (FDH_LOCKFILE(fdP, offset) != 0) {
            return -1;
        }
     }
@@ -1169,19 +1545,19 @@ namei_SetLinkCount(FdHandle_t * fdP, Inode ino, int count, int locked)
     nBytes = FDH_PREAD(fdP, (char *)&row, sizeof(row), offset);
     if (nBytes != sizeof(row)) {
        if (nBytes != 0) {
-           errno = EBADF;
+           errno = OS_ERROR(EBADF);
            goto bad_SetLinkCount;
        }
        row = 0;
     }
 
-    junk = 7 << index;
+    bytesRead = 7 << index;
     count <<= index;
-    row &= (unsigned short)~junk;
+    row &= (unsigned short)~bytesRead;
     row |= (unsigned short)count;
 
     if (FDH_PWRITE(fdP, (char *)&row, sizeof(short), offset) != sizeof(short)) {
-       errno = EBADF;
+       errno = OS_ERROR(EBADF);
        goto bad_SetLinkCount;
     }
     FDH_SYNC(fdP);
@@ -1190,9 +1566,10 @@ namei_SetLinkCount(FdHandle_t * fdP, Inode ino, int count, int locked)
 
 
   bad_SetLinkCount:
-    flock(fdP->fd_fd, LOCK_UN);
+    FDH_UNLOCKFILE(fdP, offset);
 
-    return nBytes;
+    /* disallowed above 7, so... */
+    return (int)nBytes;
 }
 
 
@@ -1221,7 +1598,7 @@ static int namei_ListAFSSubDirs(IHandle_t * dirIH,
 static int
 WriteInodeInfo(FILE * fp, struct ViceInodeInfo *info, char *dir, char *name)
 {
-    int n;
+    size_t n;
     n = fwrite(info, sizeof(*info), 1, fp);
     return (n == 1) ? 0 : -2;
 }
@@ -1352,15 +1729,23 @@ namei_ListAFSFiles(char *dev,
     IHandle_t ih;
     namei_t name;
     int ninodes = 0;
-    DIR *dirp1, *dirp2;
-    struct dirent *dp1, *dp2;
+    DIR *dirp1;
+    struct dirent *dp1;
+#ifndef AFS_NT40_ENV
+    DIR *dirp2;
+    struct dirent *dp2;
     char path2[512];
+#endif
 #ifdef DELETE_ZLC
     static void FreeZLCList(void);
 #endif
 
     memset((void *)&ih, 0, sizeof(IHandle_t));
+#ifdef AFS_NT40_ENV
+    ih.ih_dev = nt_DriveToDev(dev);
+#else
     ih.ih_dev = volutil_GetPartitionID(dev);
+#endif
 
     if (singleVolumeNumber) {
        ih.ih_vid = singleVolumeNumber;
@@ -1378,6 +1763,14 @@ namei_ListAFSFiles(char *dev,
        if (!dirp1)
            return 0;
        while ((dp1 = readdir(dirp1))) {
+#ifdef AFS_NT40_ENV
+           /* Heirarchy is one level on Windows */
+           if (!DecodeVolumeName(dp1->d_name, &ih.ih_vid)) {
+               ninodes +=
+                   namei_ListAFSSubDirs(&ih, writeFun, fp, judgeFun,
+                                        0, rock);
+           }
+#else
            if (*dp1->d_name == '.')
                continue;
            afs_snprintf(path2, sizeof(path2), "%s/%s", name.n_path,
@@ -1395,6 +1788,7 @@ namei_ListAFSFiles(char *dev,
                }
                closedir(dirp2);
            }
+#endif
        }
        closedir(dirp1);
     }
@@ -1467,7 +1861,7 @@ _namei_examine_special(char * path1,
                           "%s/%s", path1, dname);
        linkHandle->fd_fd = afs_open(path2, Testing ? O_RDONLY : O_RDWR, 0666);
        info.linkCount =
-           namei_GetLinkCount2(linkHandle, (Inode) 0, 1, 1, Testing);
+           namei_GetLinkCount(linkHandle, (Inode) 0, 1, 1, Testing);
     }
 
     if (!judgeFun ||
@@ -1525,8 +1919,7 @@ _namei_examine_reg(char * path3,
     int ret = 0;
     struct ViceInodeInfo info;
 #ifdef DELETE_ZLC
-    int i; /* XXX this isn't set anywhere, nor was it set in
-           *     namei_ListAFSSubdirs.  wtf? */
+    int i; /* Windows-only (one level hash dir) */
 #endif
 
     if (DecodeInode(path3, dname, &info, myIH->ih_vid) < 0) {
@@ -1534,7 +1927,7 @@ _namei_examine_reg(char * path3,
     }
 
     info.linkCount =
-       namei_GetLinkCount2(linkHandle,
+       namei_GetLinkCount(linkHandle,
                            info.inodeNumber, 1, 1, Testing);
     if (info.linkCount == 0) {
 #ifdef DELETE_ZLC
@@ -1919,9 +2312,13 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
     int code = 0, ret = 0;
     IHandle_t myIH = *dirIH;
     namei_t name;
-    char path1[512], path2[512], path3[512];
+    char path1[512], path3[512];
     DIR *dirp1, *dirp2, *dirp3;
-    struct dirent *dp1, *dp2, *dp3;
+#ifndef AFS_NT40_ENV
+    struct dirent *dp2;
+    char path2[512];
+#endif
+    struct dirent *dp1, *dp3;
     FdHandle_t linkHandle;
     int ninodes = 0;
     struct listsubdirs_work_node work;
@@ -1943,10 +2340,10 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
     /* Do the directory containing the special files first to pick up link
      * counts.
      */
-    (void)strcat(path1, "/");
+    (void)strcat(path1, OS_DIRSEP);
     (void)strcat(path1, NAMEI_SPECDIR);
 
-    linkHandle.fd_fd = -1;
+    linkHandle.fd_fd = INVALID_FD;
 #ifdef AFS_SALSRV_ENV
     osi_Assert(pthread_once(&wq_once, _namei_wq_keycreate) == 0);
 
@@ -2026,11 +2423,14 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
     dirp1 = opendir(path1);
     if (dirp1) {
        while ((dp1 = readdir(dirp1))) {
+#ifndef AFS_NT40_ENV
            if (*dp1->d_name == '.')
                continue;
+#endif
            if (!strcmp(dp1->d_name, NAMEI_SPECDIR))
                continue;
 
+#ifndef AFS_NT40_ENV /* This level missing on Windows */
            /* Now we've got a next level subdir. */
            afs_snprintf(path2, sizeof(path2), "%s/%s", path1, dp1->d_name);
            dirp2 = opendir(path2);
@@ -2042,12 +2442,18 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
                    /* Now we've got to the actual data */
                    afs_snprintf(path3, sizeof(path3), "%s/%s", path2,
                                 dp2->d_name);
-
+#else
+                   /* Now we've got to the actual data */
+                   afs_snprintf(path3, sizeof(path3), "%s\\%s", path1,
+                                dp1->d_name);
+#endif
                    dirp3 = opendir(path3);
                    if (dirp3) {
                        while ((dp3 = readdir(dirp3))) {
+#ifndef AFS_NT40_ENV
                            if (*dp3->d_name == '.')
                                continue;
+#endif
 
 #ifdef AFS_SALSRV_ENV
                            if (error) {
@@ -2080,9 +2486,11 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
                        }
                        closedir(dirp3);
                    }
+#ifndef AFS_NT40_ENV /* This level missing on Windows */
                }
                closedir(dirp2);
            }
+#endif
        }
        closedir(dirp1);
     }
@@ -2112,8 +2520,8 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
     }
     _namei_listsubdirs_cleanup_results(&resultlist);
 #endif
-    if (linkHandle.fd_fd >= 0)
-       close(linkHandle.fd_fd);
+    if (linkHandle.fd_fd != INVALID_FD)
+       OS_CLOSE(linkHandle.fd_fd);
 
     if (!ret) {
        ret = ninodes;
@@ -2123,6 +2531,27 @@ namei_ListAFSSubDirs(IHandle_t * dirIH,
 
 /*@}*/
 
+#ifdef AFS_NT40_ENV
+static int
+DecodeVolumeName(char *name, unsigned int *vid)
+{
+    /* Name begins with "Vol_" and ends with .data.  See nt_HandleToVolDir() */
+    char stmp[32];
+    size_t len;
+
+    len = strlen(name);
+    if (len <= 9)
+        return -1;
+    if (strncmp(name, "Vol_", 4))
+        return -1;
+    if (strcmp(name + len - 5, ".data"))
+        return -1;
+    strcpy(stmp, name);
+    stmp[len - 5] = '\0';
+    *vid = base32_to_int(stmp + 4);
+    return 0;
+}
+#else
 static int
 DecodeVolumeName(char *name, unsigned int *vid)
 {
@@ -2131,13 +2560,91 @@ DecodeVolumeName(char *name, unsigned int *vid)
     *vid = (unsigned int)flipbase64_to_int64(name);
     return 0;
 }
+#endif
 
 
 /* DecodeInode
  *
  * Get the inode number from the name.
- * Get
+ *
  */
+#ifdef AFS_NT40_ENV
+static int
+DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
+           unsigned int volid)
+{
+    char fpath[512];
+    int tag, vno;
+    WIN32_FIND_DATA data;
+    HANDLE dirH;
+    char *s, *t;
+    char stmp[16];
+    FdHandle_t linkHandle;
+    char dirl;
+
+    afs_snprintf(fpath, sizeof(fpath), "%s\\%s", dpath, name);
+
+    dirH = FindFirstFileEx(fpath, FindExInfoStandard, &data,
+                          FindExSearchNameMatch, NULL,
+                          FIND_FIRST_EX_CASE_SENSITIVE);
+    if (dirH == INVALID_HANDLE_VALUE)
+       return -1;
+
+    (void)strcpy(stmp, name);
+    s = strrchr(stmp, '_');
+    if (!s)
+        return -1;
+    s++;
+    t = strrchr(s, '.');
+    if (!t)
+        return -1;
+
+    *t = '\0';
+    vno = base32_to_int(s);
+    tag = base32_to_int(t+1);
+    info->inodeNumber = (Inode) tag << NAMEI_TAGSHIFT;
+    info->inodeNumber |= (Inode) vno;
+    info->byteCount = data.nFileSizeLow;
+
+    dirl = dpath[strlen(dpath)-1];
+    if (dirl == 'R') { /* Special inode. */
+       info->inodeNumber |= NAMEI_INODESPECIAL;
+       info->u.param[0] = data.ftCreationTime.dwHighDateTime;
+       info->u.param[1] = data.ftCreationTime.dwLowDateTime;
+       info->u.param[2] = tag;
+       info->u.param[3] = volid;
+       if (tag != VI_LINKTABLE)
+           info->linkCount = 1;
+       else {
+           /* Open this handle */
+           char lpath[1024];
+           (void)sprintf(lpath, "%s\\%s", fpath, data.cFileName);
+           linkHandle.fd_fd = nt_open(lpath, O_RDONLY, 0666);
+           info->linkCount =
+               namei_GetLinkCount(&linkHandle, (Inode) 0, 0, 0, 0);
+       }
+    } else {
+       info->linkCount =
+           namei_GetLinkCount(&linkHandle, info->inodeNumber, 0, 0, 0);
+       if (info->linkCount == 0) {
+#ifdef DELETE_ZLC
+           Log("Found 0 link count file %s\\%s, deleting it.\n",
+               fpath, data.cFileName);
+           AddToZLCDeleteList(dirl, data.cFileName);
+#else
+           Log("Found 0 link count file %s\\%s.\n", path,
+               data.cFileName);
+#endif
+       } else {
+           info->u.param[2] = data.ftCreationTime.dwHighDateTime;
+           info->u.param[3] = data.ftCreationTime.dwLowDateTime;
+           info->u.param[1] = vno;
+           info->u.param[0] = volid;
+       }
+    }
+    return 0;
+}
+#else
 static int
 DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
            unsigned int volid)
@@ -2177,6 +2684,7 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
     }
     return 0;
 }
+#endif
 
 /*
  * Convert the VolumeInfo file from RO to RW
@@ -2185,12 +2693,12 @@ DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
 
 #ifdef FSSYNC_BUILD_CLIENT
 static afs_int32
-convertVolumeInfo(int fdr, int fdw, afs_uint32 vid)
+convertVolumeInfo(FD_t fdr, FD_t fdw, afs_uint32 vid)
 {
     struct VolumeDiskData vd;
     char *p;
 
-    if (read(fdr, &vd, sizeof(struct VolumeDiskData)) !=
+    if (OS_READ(fdr, (char *)&vd, sizeof(struct VolumeDiskData)) !=
        sizeof(struct VolumeDiskData)) {
        Log("1 convertVolumeInfo: read failed for %lu with code %d\n",
            afs_printable_uint32_lu(vid),
@@ -2209,7 +2717,7 @@ convertVolumeInfo(int fdr, int fdw, afs_uint32 vid)
     if (p && !strcmp(p, ".readonly")) {
        memset(p, 0, 9);
     }
-    if (write(fdw, &vd, sizeof(struct VolumeDiskData)) !=
+    if (OS_WRITE(fdw, (char *)&vd, sizeof(struct VolumeDiskData)) !=
        sizeof(struct VolumeDiskData)) {
        Log("1 convertVolumeInfo: write failed for %lu with code %d\n",
            afs_printable_uint32_lu(vid),
@@ -2256,7 +2764,7 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
     char smallSeen = 0;
     char largeSeen = 0;
     char linkSeen = 0;
-    int fd, fd2;
+    FD_t fd, fd2;
     char *p;
     DIR *dirp;
     Inode ino;
@@ -2300,7 +2808,7 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
 
     namei_HandleToName(&n, ih);
     strlcpy(dir_name, n.n_path, sizeof(dir_name));
-    p = strrchr(dir_name, '/');
+    p = strrchr(dir_name, OS_DIRSEPC);
     *p = 0;
     dirp = opendir(dir_name);
     if (!dirp) {
@@ -2311,9 +2819,10 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
 
     while ((dp = readdir(dirp))) {
        /* struct ViceInodeInfo info; */
-
+#ifndef AFS_NT40_ENV
        if (*dp->d_name == '.')
            continue;
+#endif
        if (DecodeInode(dir_name, dp->d_name, &info, ih->ih_vid) < 0) {
            Log("1 namei_ConvertROtoRWvolume: DecodeInode failed for %s/%s\n",
                dir_name, dp->d_name);
@@ -2374,7 +2883,8 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
     t_ih.ih_dev = ih->ih_dev;
     t_ih.ih_vid = ih->ih_vid;
 
-    (void)afs_snprintf(oldpath, sizeof oldpath, "%s/%s", dir_name, infoName);
+    (void)afs_snprintf(oldpath, sizeof oldpath, "%s" OS_DIRSEP "%s", dir_name,
+                      infoName);
     fd = afs_open(oldpath, O_RDWR, 0);
     if (fd < 0) {
        Log("1 namei_ConvertROtoRWvolume: could not open RO info file: %s\n",
@@ -2387,24 +2897,25 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
     fd2 = afs_open(n.n_path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0);
     if (fd2 < 0) {
        Log("1 namei_ConvertROtoRWvolume: could not create RW info file: %s\n", n.n_path);
-       close(fd);
+       OS_CLOSE(fd);
        code = -1;
        goto done;
     }
     code = convertVolumeInfo(fd, fd2, ih->ih_vid);
-    close(fd);
+    OS_CLOSE(fd);
     if (code) {
-       close(fd2);
-       unlink(n.n_path);
+       OS_CLOSE(fd2);
+       OS_UNLINK(n.n_path);
        code = -1;
        goto done;
     }
     SetOGM(fd2, ih->ih_vid, 1);
-    close(fd2);
+    OS_CLOSE(fd2);
 
     t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_SMALLINDEX);
     namei_HandleToName(&n, &t_ih);
-    (void)afs_snprintf(newpath, sizeof newpath, "%s/%s", dir_name, smallName);
+    (void)afs_snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
+                      smallName);
     fd = afs_open(newpath, O_RDWR, 0);
     if (fd < 0) {
        Log("1 namei_ConvertROtoRWvolume: could not open SmallIndex file: %s\n", newpath);
@@ -2412,13 +2923,18 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
        goto done;
     }
     SetOGM(fd, ih->ih_vid, 2);
-    close(fd);
+    OS_CLOSE(fd);
+#ifdef AFS_NT40_ENV
+    MoveFileEx(n.n_path, newpath, MOVEFILE_WRITE_THROUGH);
+#else
     link(newpath, n.n_path);
     unlink(newpath);
+#endif
 
     t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_LARGEINDEX);
     namei_HandleToName(&n, &t_ih);
-    (void)afs_snprintf(newpath, sizeof newpath, "%s/%s", dir_name, largeName);
+    (void)afs_snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
+                      largeName);
     fd = afs_open(newpath, O_RDWR, 0);
     if (fd < 0) {
        Log("1 namei_ConvertROtoRWvolume: could not open LargeIndex file: %s\n", newpath);
@@ -2426,11 +2942,15 @@ namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId)
        goto done;
     }
     SetOGM(fd, ih->ih_vid, 3);
-    close(fd);
+    OS_CLOSE(fd);
+#ifdef AFS_NT40_ENV
+    MoveFileEx(n.n_path, newpath, MOVEFILE_WRITE_THROUGH);
+#else
     link(newpath, n.n_path);
     unlink(newpath);
+#endif
 
-    unlink(oldpath);
+    OS_UNLINK(oldpath);
 
     h.id = h.parent;
     h.volumeInfo_hi = h.id;
@@ -2475,7 +2995,7 @@ PrintInode(char *s, Inode ino)
     if (!s)
        s = result;
 
-    (void)afs_snprintf(s, sizeof(afs_ino_str_t), "%llu", (afs_uintmax_t) ino);
+    (void)afs_snprintf(s, sizeof(afs_ino_str_t), "%" AFS_UINT64_FMT, (afs_uintmax_t) ino);
 
     return s;
 }
@@ -2517,7 +3037,11 @@ AddToZLCDeleteList(char dir, char *name)
        }
     }
 
-    (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%c\\%s", dir, name);
+    if (dir)
+       (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%c\\%s", dir, name);
+    else
+       (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%s", name);
+
     zlcCur->zlc_n++;
 }
 
@@ -2530,7 +3054,10 @@ DeleteZLCFiles(char *path)
 
     for (z = zlcAnchor; z; z = z->zlc_next) {
        for (i = 0; i < z->zlc_n; i++) {
-           (void)sprintf(fname, "%s\\%s", path, z->zlc_names[i]);
+           if (path)
+               (void)sprintf(fname, "%s\\%s", path, z->zlc_names[i]);
+           else
+               (void)sprintf(fname, "%s", z->zlc_names[i]);
            if (namei_unlink(fname) < 0) {
                Log("ZLC: Can't unlink %s, dos error = %d\n", fname,
                    GetLastError());
index 6705ebb..1d5d560 100644 (file)
 
 #ifdef AFS_NAMEI_ENV
 
-#ifdef notdef
-/* We don't include Unix afssyscalls.h, so: */
-#define VALID_INO(I) ((I != (__int64)-1) && (I != (__int64)0))
-
-/* minimum size of string to hand to PrintInode */
-#define AFS_INO_STR_LENGTH 32
-typedef char afs_ino_str_t[AFS_INO_STR_LENGTH];
-
-char *PrintInode(char *s, Inode ino);
-#endif
-
 /* Basic file operations */
 extern FILE *namei_fdopen(IHandle_t * h, char *fdperms);
 extern int namei_unlink(char *name);
 
 /* Inode operations */
 extern Inode namei_MakeSpecIno(int volid, int type);
-extern Inode namei_icreate(IHandle_t * h, char *p, int p1, int p2, int p3,
-                          int p4);
+extern Inode namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1,
+                          afs_uint32 p2, afs_uint32 p3, afs_uint32 p4);
 extern FD_t namei_iopen(IHandle_t * h);
 extern int namei_irelease(IHandle_t * h);
 afs_sfsize_t namei_iread(IHandle_t * h, afs_foff_t offset, char *buf,
@@ -41,7 +30,7 @@ afs_sfsize_t namei_iwrite(IHandle_t * h, afs_foff_t offset, char *buf,
                          afs_fsize_t size);
 extern int namei_dec(IHandle_t * h, Inode ino, int p1);
 extern int namei_inc(IHandle_t * h, Inode ino, int p1);
-extern int namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit);
+extern int namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite);
 extern int namei_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked);
 extern int namei_ViceREADME(char *partition);
 #include "nfs.h"
@@ -59,10 +48,22 @@ int ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
                   afs_uint32 singleVolumeNumber, int *forcep, int forceR,
                   char *wpath, void *rock);
 
-
 #define NAMEI_LCOMP_LEN 32
-#define NAMEI_SCOMP_LEN 12
 #define NAMEI_PATH_LEN 256
+
+#ifdef AFS_NT40_ENV
+#define NAMEI_DRIVE_LEN 3
+#define NAMEI_HASH_LEN 2
+#define NAMEI_COMP_LEN 18
+typedef struct {
+    char n_drive[NAMEI_DRIVE_LEN];
+    char n_voldir[NAMEI_COMP_LEN];
+    char n_dir[NAMEI_HASH_LEN];
+    char n_inode[NAMEI_COMP_LEN];
+    char n_path[NAMEI_PATH_LEN];
+} namei_t;
+#else
+#define NAMEI_SCOMP_LEN 12
 typedef struct {
     char n_base[NAMEI_LCOMP_LEN];
     char n_voldir1[NAMEI_SCOMP_LEN];
@@ -72,6 +73,7 @@ typedef struct {
     char n_inode[NAMEI_LCOMP_LEN];
     char n_path[NAMEI_PATH_LEN];
 } namei_t;
+#endif
 
 void namei_HandleToName(namei_t * name, IHandle_t * h);
 int namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId);
index 835bc51..5ee3f2f 100644 (file)
 
 #define BASEFILEATTRIBUTE FILE_ATTRIBUTE_NORMAL
 
-int Testing = 0;
-
-static void AddToZLCDeleteList(char dir, char *name);
-
 /* nt_unlink - unlink a case sensitive name.
  *
  * nt_unlink supports the nt_dec call.
@@ -224,37 +220,6 @@ nt_pread(FD_t fd, void * buf, size_t count, afs_foff_t offset)
 }
 
 int
-nt_iread(IHandle_t * h, int offset, char *buf, int size)
-{
-    int nBytes;
-    FdHandle_t *fdP;
-
-    fdP = IH_OPEN(h);
-    if (fdP == NULL)
-       return -1;
-
-    nBytes = FDH_PREAD(fdP, buf, size, offset);
-    FDH_CLOSE(fdP);
-    return nBytes;
-}
-
-int
-nt_iwrite(IHandle_t * h, int offset, char *buf, int size)
-{
-    int nBytes;
-    FdHandle_t *fdP;
-
-    fdP = IH_OPEN(h);
-    if (fdP == NULL)
-       return -1;
-
-    nBytes = FDH_PWRITE(fdP, buf, size, offset);
-    FDH_CLOSE(fdP);
-    return nBytes;
-}
-
-
-int
 nt_size(FD_t fd)
 {
     BY_HANDLE_FILE_INFORMATION finfo;
@@ -347,32 +312,6 @@ nt_seek(FD_t fd, int off, int where)
     return code;
 }
 
-
-/* Inode number format:
- * low 32 bits - if a regular file or directory, the vnode. Else the type.
- * 32-36 - unquifier tag and index into counts array for this vnode. Only
- *         two of the available bits are currently used. The rest are
- *         present in case we ever increase the number of types of volumes
- *         in the volume grou.
- * bit 37 : 1  == special, 0 == regular
- */
-#define NT_VNODEMASK    0x00ffffffff
-/* While the TAGMASK is 7, note that we are leaving 1 more bit available. */
-#define NT_TAGMASK      0x7
-#define NT_TAGSHIFT     32
-#define NT_INODESPECIAL 0x2000000000
-
-#define NT_MAXVOLS 5           /* Maximum supported number of volumes per volume
-                                * group, not counting temporary (move) volumes.
-                                * This is the number of separate files, all having
-                                * the same vnode number, which can occur in a volume
-                                * group at once.
-                                */
-
-
-int nt_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked);
-
-
 /* nt_DevToDrive
  * converts a device number (2-25) into a drive letter name.
  *
@@ -384,1017 +323,39 @@ int nt_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked);
  * Returns pointer to end of drive if successful, else NULL.
  *
  */
-char *
+void
 nt_DevToDrive(char *drive, int dev)
 {
     if (dev < 2 || dev > 25) {
        errno = EINVAL;
-       return NULL;            /* Invalid drive */
+       return;         /* Invalid drive */
     }
     drive[0] = (char)('A' + dev);
     drive[1] = ':';
     drive[2] = '\0';
 
-    return drive + 2;
-
-}
-
-/* Returns pointer to end of name if successful, else NULL. */
-char *
-nt_HandleToVolDir(char *name, IHandle_t * h)
-{
-    b32_string_t str1;
-
-    if (!(name = nt_DevToDrive(name, h->ih_dev)))
-       return NULL;
-
-    (void)memcpy(name, "\\Vol_", 5);
-    name += 5;
-    (void)strcpy(name, int_to_base32(str1, h->ih_vid));
-    name += strlen(name);
-    memcpy(name, ".data", 5);
-    name += 5;
-    *name = '\0';
-
-    return name;
-}
-
-/* nt_HandleToName
- *
- * Constructs a file name for the fully qualified handle.
- */
-int
-nt_HandleToName(char *name, IHandle_t * h)
-{
-    b32_string_t str1;
-    int tag = (int)((h->ih_ino >> NT_TAGSHIFT) & NT_TAGMASK);
-    int vno = (int)(h->ih_ino & NT_VNODEMASK);
-
-    if (!(name = nt_HandleToVolDir(name, h)))
-       return -1;
-
-    str1[0] = '\\';
-    if (h->ih_ino & NT_INODESPECIAL)
-       str1[1] = 'R';
-    else {
-       if (vno & 0x1)
-           str1[1] = 'Q';
-       else
-           str1[1] = ((vno & 0x1f) >> 1) + 'A';
-    }
-
-    memcpy(name, str1, 2);
-    name += 2;
-    (void)memcpy(name, "\\V_", 3);
-    name += 3;
-    (void)strcpy(name, int_to_base32(str1, vno));
-    name += strlen(name);
-    *(name++) = '.';
-    (void)strcpy(name, int_to_base32(str1, tag));
-    name += strlen(name);
-    *name = '\0';
-
-    return 0;
-}
-
-/* nt_CreateDataDirectories
- *
- * The data for each volume is in a separate directory. The name of the
- * volume is of the form: Vol_NNNNNN.data, where NNNNNN is a base 32
- * representation of the RW volume ID (even where the RO is the only volume
- * on the partition). Below that are separate subdirectories for the
- * AFS directories and special files. There are also 16 directories for files,
- * hashed on the low 5 bits (recall bit0 is always 0) of the vnode number.
- * These directories are named:
- * A - P - 16 file directories.
- * Q ----- data directory
- * R ----- special files directory
- */
-static int
-nt_CreateDataDirectories(IHandle_t * h, int *created)
-{
-    char name[128];
-    char *s;
-    int i;
-
-    if (!(s = nt_HandleToVolDir(name, h)))
-       return -1;
-
-    if (mkdir(name) < 0) {
-       if (errno != EEXIST)
-           return -1;
-    } else
-       *created = 1;
+    return;
 
-    *s++ = '\\';
-    *(s + 1) = '\0';
-    for (i = 'A'; i <= 'R'; i++) {
-       *s = (char)i;
-       if (mkdir(name) < 0 && errno != EEXIST)
-           return -1;
-    }
-    return 0;
 }
 
-/* nt_RemoveDataDirectories
+/* nt_DriveToDev
+ * converts a drive letter to a device number (2-25)
  *
- * Returns -1 on error. Typically, callers ignore this error bcause we
- * can continue running if the removes fail. The salvage process will
- * finish tidying up for us.
- */
-static int
-nt_RemoveDataDirectories(IHandle_t * h)
-{
-    char name[128];
-    char *s;
-    int i;
-
-    if (!(s = nt_HandleToVolDir(name, h)))
-       return -1;
-
-    *s++ = '\\';
-    *(s + 1) = '\0';
-    for (i = 'A'; i <= 'R'; i++) {
-       *s = (char)i;
-       if (rmdir(name) < 0 && errno != ENOENT)
-           return -1;
-    }
-
-    /* Delete the Vol_NNNNNN.data directory. */
-    s--;
-    *s = '\0';
-    if (rmdir(name) < 0 && errno != ENOENT) {
-       return -1;
-    }
-
-    return 0;
-}
-
-
-/* Create the file in the name space.
- *
- * Parameters stored as follows:
- * Regular files:
- * p1 - volid - implied in containing directory.
- * p2 - vnode - name is <vnode>.<tag> where tag is a file name unqiquifier.
- * p3 - uniq -- creation time - dwHighDateTime
- * p4 - dv ---- creation time - dwLowDateTime
- * Special files:
- * p1 - volid - creation time - dwHighDateTime
- * p2 - vnode - -1 means special, file goes in "S" subdirectory.
- * p3 - type -- name is <type>.<tag> where tag is a file name unqiquifier.
- * p4 - parid - parent volume id - implied in containing directory.
+ * Arguments:
+ * drive - assumes drive is a pointer to a string at least 3 bytes long.
  *
- * Return value is the inode number or (Inode)-1 if error.
- * We "know" there is only one link table, so return EEXIST if there already
- * is a link table. It's up to the calling code to test errno and increment
- * the link count.
- */
-
-/* nt_MakeSpecIno
+ * Return Value:
+ * dev   - drive number 2-25 if successful (A-C already in use), else -1
  *
- * This function is called by VCreateVolume to hide the implementation
- * details of the inode numbers.
- */
-Inode
-nt_MakeSpecIno(int type)
-{
-    return ((Inode) type | (Inode) NT_INODESPECIAL);
-}
-
-Inode
-nt_icreate(IHandle_t * h, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
-{
-    char filename[128];
-    b32_string_t str1;
-    char *p;
-    int i;
-    FD_t fd;
-    int created_dir = 0;
-    int code = 0;
-    FILETIME ftime;
-    IHandle_t tmp;
-    FdHandle_t *fdP;
-    FdHandle_t tfd;
-    int save_errno;
-
-    memset((void *)&tmp, 0, sizeof(IHandle_t));
-
-
-    tmp.ih_dev = tolower(*part) - 'a';
-
-    if (p2 == -1) {
-       tmp.ih_vid = p4;        /* Use parent volume id, where this file will be. */
-
-       if (nt_CreateDataDirectories(&tmp, &created_dir) < 0)
-           goto bad;
-
-       tmp.ih_ino = nt_MakeSpecIno(p3);
-       ftime.dwHighDateTime = p1;
-       ftime.dwLowDateTime = p2;
-    } else {
-       /* Regular file or directory.
-        * Encoding: p1 -> dir,  p2 -> name, p3,p4 -> Create time
-        */
-       tmp.ih_ino = (Inode) p2;
-       tmp.ih_vid = p1;
-
-       ftime.dwHighDateTime = p3;
-       ftime.dwLowDateTime = p4;
-    }
-
-    /* Now create file. */
-    if ((code = nt_HandleToName(filename, &tmp)) < 0)
-       goto bad;
-
-    p = filename + strlen(filename);
-    p--;
-    for (i = 0; i < NT_MAXVOLS; i++) {
-       *p = *int_to_base32(str1, i);
-       fd = nt_open(filename, O_CREAT | O_RDWR | O_TRUNC | O_EXCL, 0666);
-       if (fd != INVALID_FD)
-           break;
-       if (p2 == -1 && p3 == VI_LINKTABLE)
-           break;
-    }
-    if (fd == INVALID_FD) {
-       code = -1;
-       goto bad;
-    }
-
-    tmp.ih_ino &= ~((Inode) NT_TAGMASK << NT_TAGSHIFT);
-    tmp.ih_ino |= ((Inode) i << NT_TAGSHIFT);
-
-    if (!code) {
-       if (!SetFileTime((HANDLE) fd, &ftime, NULL, NULL)) {
-           errno = EBADF;
-           code = -1;
-       }
-    }
-
-    if (!code) {
-       if (p2 != -1) {
-           if (fd == INVALID_FD) {
-               errno = ENOENT;
-               code = nt_unlink(filename);
-               if (code == -1) {
-               }
-               code = -1;
-               goto bad;
-           }
-           fdP = IH_OPEN(h);
-           if (fdP == NULL) {
-               code = -1;
-               goto bad;
-           }
-           code = nt_SetLinkCount(fdP, tmp.ih_ino, 1, 0);
-           FDH_CLOSE(fdP);
-       } else if (p2 == -1 && p3 == VI_LINKTABLE) {
-           if (fd == INVALID_FD)
-               goto bad;
-           /* hack at tmp to setup for set link count call. */
-           tfd.fd_fd = fd;
-           code = nt_SetLinkCount(&tfd, (Inode) 0, 1, 0);
-       }
-    }
-
-  bad:
-    if (fd != INVALID_FD)
-       nt_close(fd);
-
-    if (code && created_dir) {
-       save_errno = errno;
-       nt_RemoveDataDirectories(&tmp);
-       errno = save_errno;
-    }
-    return code ? (Inode) - 1 : tmp.ih_ino;
-}
-
-
-FD_t
-nt_iopen(IHandle_t * h)
-{
-    FD_t fd;
-    char name[128];
-
-    /* Convert handle to file name. */
-    if (nt_HandleToName(name, h) < 0)
-       return INVALID_FD;
-
-    fd = nt_open(name, O_RDWR, 0666);
-    return fd;
-}
-
-/* Need to detect vol special file and just unlink. In those cases, the
- * handle passed in _is_ for the inode. We only check p1 for the special
- * files.
  */
 int
-nt_dec(IHandle_t * h, Inode ino, int p1)
+nt_DriveToDev(char *drive)
 {
-    int count = 0;
-    char name[128];
-    int code = 0;
-    FdHandle_t *fdP;
-
-    if (ino & NT_INODESPECIAL) {
-       IHandle_t *tmp;
-       int was_closed = 0;
-       WIN32_FIND_DATA info;
-       HANDLE dirH;
-
-       /* Verify this is the right file. */
-       IH_INIT(tmp, h->ih_dev, h->ih_vid, ino);
-
-       if (nt_HandleToName(name, tmp) < 0) {
-           IH_RELEASE(tmp);
-           errno = EINVAL;
-           return -1;
-       }
-
-       dirH =
-           FindFirstFileEx(name, FindExInfoStandard, &info,
-                           FindExSearchNameMatch, NULL,
-                           FIND_FIRST_EX_CASE_SENSITIVE);
-       if (!dirH) {
-           IH_RELEASE(tmp);
-           errno = ENOENT;
-           return -1;          /* Can't get info, leave alone */
-       }
+    int dev = -1;
 
-       FindClose(dirH);
-       if (info.ftCreationTime.dwHighDateTime != (unsigned int)p1) {
-           IH_RELEASE(tmp);
-           return -1;
-       }
-
-       /* If it's the link table itself, decrement the link count. */
-       if ((ino & NT_VNODEMASK) == VI_LINKTABLE) {
-           fdP = IH_OPEN(tmp);
-           if (fdP == NULL) {
-               IH_RELEASE(tmp);
-               return -1;
-           }
-
-           if ((count = nt_GetLinkCount(fdP, (Inode) 0, 1)) < 0) {
-               FDH_REALLYCLOSE(fdP);
-               IH_RELEASE(tmp);
-               return -1;
-           }
-
-           count--;
-           if (nt_SetLinkCount(fdP, (Inode) 0, count < 0 ? 0 : count, 1) < 0) {
-               FDH_REALLYCLOSE(fdP);
-               IH_RELEASE(tmp);
-               return -1;
-           }
-
-           FDH_REALLYCLOSE(fdP);
-           if (count > 0) {
-               IH_RELEASE(tmp);
-               return 0;
-           }
-       }
-
-       if ((code = nt_unlink(name)) == 0) {
-           if ((ino & NT_VNODEMASK) == VI_LINKTABLE) {
-               /* Try to remove directory. If it fails, that's ok.
-                * Salvage will clean up.
-                */
-               (void)nt_RemoveDataDirectories(tmp);
-           }
-       }
-
-       IH_RELEASE(tmp);
-    } else {
-       /* Get a file descriptor handle for this Inode */
-       fdP = IH_OPEN(h);
-       if (fdP == NULL) {
-           return -1;
-       }
-
-       if ((count = nt_GetLinkCount(fdP, ino, 1)) < 0) {
-           FDH_REALLYCLOSE(fdP);
-           return -1;
-       }
-
-       count--;
-       if (count >= 0) {
-           if (nt_SetLinkCount(fdP, ino, count, 1) < 0) {
-               FDH_REALLYCLOSE(fdP);
-               return -1;
-           }
-       }
-       if (count == 0) {
-           IHandle_t th = *h;
-           th.ih_ino = ino;
-           nt_HandleToName(name, &th);
-           code = nt_unlink(name);
-       }
-       FDH_CLOSE(fdP);
-    }
-
-    return code;
-}
-
-int
-nt_inc(IHandle_t * h, Inode ino, int p1)
-{
-    int count;
-    int code = 0;
-    FdHandle_t *fdP;
-
-    if (ino & NT_INODESPECIAL) {
-       if ((ino & NT_VNODEMASK) != VI_LINKTABLE)
-           return 0;
-       ino = (Inode) 0;
-    }
-
-    /* Get a file descriptor handle for this Inode */
-    fdP = IH_OPEN(h);
-    if (fdP == NULL) {
+    if (drive)
+       dev = toupper(*drive) - 'A';
+    if ((dev < 2) || (dev > 25))
        return -1;
-    }
-
-    if ((count = nt_GetLinkCount(fdP, ino, 1)) < 0)
-       code = -1;
-    else {
-       count++;
-       if (count > 7) {
-           errno = EINVAL;
-           code = -1;
-           count = 7;
-       }
-       if (nt_SetLinkCount(fdP, ino, count, 1) < 0)
-           code = -1;
-    }
-    if (code) {
-       FDH_REALLYCLOSE(fdP);
-    } else {
-       FDH_CLOSE(fdP);
-    }
-    return code;
 }
-
-
-
-/************************************************************************
- *  Link Table Organization
- ************************************************************************
- *
- * The link table volume special file is used to hold the link counts that
- * are held in the inodes in inode based AFS vice filesystems. Since NTFS
- * doesn't provide us that access, the link counts are being kept in a separate
- * volume special file. The file begins with the usual version stamp
- * information and is then followed by one row per vnode number. vnode 0
- * is used to hold the link count of the link table itself. That is because
- * the same link table is shared among all the volumes of the volume group
- * and is deleted only when the last volume of a volume group is deleted.
- *
- * Within each row, the columns are 3 bits wide. They can each hold a 0 based
- * link count from 0 through 7. Each colume represents a unique instance of
- * that vnode. Say we have a file shared between the RW and a RO and a
- * different version of the file (or a different uniquifer) for the BU volume.
- * Then one column would be holding the link count of 2 for the RW and RO
- * and a different column would hold the link count of 1 for the BU volume.
- * The column used is determined for NT by the uiquifier tag applied to
- * generate a unique file name in the NTFS namespace. The file name is
- * of the form "V_<vno>.<tag>" . And the <tag> is also the column number
- * in the link table.
- */
-#define LINKTABLE_WIDTH 2
-#define LINKTABLE_SHIFT 1      /* log 2 = 1 */
-
-static void
-nt_GetLCOffsetAndIndexFromIno(Inode ino, int *offset, int *index)
-{
-    int toff = (int)(ino & NT_VNODEMASK);
-    int tindex = (int)((ino >> NT_TAGSHIFT) & NT_TAGMASK);
-
-    *offset = (toff << LINKTABLE_SHIFT) + 8;   /* *2 + sizeof stamp */
-    *index = (tindex << 1) + tindex;
-}
-
-
-/* nt_GetLinkCount
- * If lockit is set, lock the file and leave it locked upon a successful
- * return.
- */
-static int
-nt_GetLinkCountInternal(FdHandle_t * h, Inode ino, int lockit, int fixup)
-{
-    unsigned short row = 0;
-    DWORD bytesRead, bytesWritten;
-    int offset, index;
-
-    /* there's no linktable yet. the salvager will create one later */
-    if (h->fd_fd == INVALID_HANDLE_VALUE && fixup)
-       return 1;
-
-    nt_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
-
-    if (lockit) {
-       if (!LockFile(h->fd_fd, offset, 0, 2, 0))
-           return -1;
-    }
-
-    if (!SetFilePointer(h->fd_fd, (LONG) offset, NULL, FILE_BEGIN))
-       goto bad_getLinkByte;
-
-    if (!ReadFile(h->fd_fd, (void *)&row, 2, &bytesRead, NULL))
-       goto bad_getLinkByte;
-
-    if (bytesRead == 0 && fixup) {
-       LARGE_INTEGER size;
-
-       if (!GetFileSizeEx(h->fd_fd, &size) || size.QuadPart >= offset+sizeof(row))
-           goto bad_getLinkByte;
-       FDH_TRUNC(h, offset+sizeof(row));
-       row = 1 << index;
-      rewrite:
-       WriteFile(h->fd_fd, (char *)&row, sizeof(row), &bytesWritten, NULL);
-    }
-
-    if (fixup && !((row >> index) & NT_TAGMASK)) {
-        row |= 1<<index;
-        goto rewrite;
-    }
-
-    return (int)((row >> index) & NT_TAGMASK);
-
-  bad_getLinkByte:
-    if (lockit)
-       UnlockFile(h->fd_fd, offset, 0, 2, 0);
-    return -1;
-}
-
-int
-nt_GetLinkCount(FdHandle_t * h, Inode ino, int lockit)
-{
-    return nt_GetLinkCountInternal(h, ino, lockit, 0);
-}
-
-void
-nt_SetNonZLC(FdHandle_t * h, Inode ino)
-{
-    (void)nt_GetLinkCountInternal(h, ino, 0, 1);
-}
-
-
-/* nt_SetLinkCount
- * If locked is set, assume file is locked. Otherwise, lock file before
- * proceeding to modify it.
- */
-int
-nt_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked)
-{
-    int offset, index;
-    unsigned short row;
-    DWORD bytesRead, bytesWritten;
-    int code = -1;
-
-    nt_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
-
-
-    if (!locked) {
-       if (!LockFile(h->fd_fd, offset, 0, 2, 0)) {
-           errno = nterr_nt2unix(GetLastError(), EBADF);
-           return -1;
-       }
-    }
-    if (!SetFilePointer(h->fd_fd, (LONG) offset, NULL, FILE_BEGIN)) {
-       errno = nterr_nt2unix(GetLastError(), EBADF);
-       goto bad_SetLinkCount;
-    }
-
-
-    if (!ReadFile(h->fd_fd, (void *)&row, 2, &bytesRead, NULL)) {
-       errno = nterr_nt2unix(GetLastError(), EBADF);
-       goto bad_SetLinkCount;
-    }
-    if (bytesRead == 0)
-       row = 0;
-
-    bytesRead = 7 << index;
-    count <<= index;
-    row &= (unsigned short)~bytesRead;
-    row |= (unsigned short)count;
-
-    if (!SetFilePointer(h->fd_fd, (LONG) offset, NULL, FILE_BEGIN)) {
-       errno = nterr_nt2unix(GetLastError(), EBADF);
-       goto bad_SetLinkCount;
-    }
-
-    if (!WriteFile(h->fd_fd, (void *)&row, 2, &bytesWritten, NULL)) {
-       errno = nterr_nt2unix(GetLastError(), EBADF);
-       goto bad_SetLinkCount;
-    }
-
-    code = 0;
-
-
-  bad_SetLinkCount:
-    UnlockFile(h->fd_fd, offset, 0, 2, 0);
-
-    return code;
-}
-
-
-/* ListViceInodes - write inode data to a results file. */
-static int DecodeInodeName(char *name, int *p1, int *p2);
-static int DecodeVolumeName(char *name, afs_uint32 *vid);
-static int nt_ListAFSSubDirs(IHandle_t * dirIH,
-                            int (*write_fun) (FILE *, struct ViceInodeInfo *,
-                                              char *, char *), FILE * fp,
-                            int (*judgeFun) (struct ViceInodeInfo *,
-                                             afs_uint32 vid, void *rock),
-                            afs_uint32 singleVolumeNumber, void *rock);
-
-
-/* WriteInodeInfo
- *
- * Write the inode data to the results file.
- *
- * Returns -2 on error, 0 on success.
- *
- * This is written as a callback simply so that other listing routines
- * can use the same inode reading code.
- */
-static int
-WriteInodeInfo(FILE * fp, struct ViceInodeInfo *info, char *dir, char *name)
-{
-    int n;
-    n = fwrite(info, sizeof(*info), 1, fp);
-    return (n == 1) ? 0 : -2;
-}
-
-
-/* ListViceInodes
- * Fill the results file with the requested inode information.
- *
- * Return values:
- *  0 - success
- * -1 - complete failure, salvage should terminate.
- * -2 - not enough space on partition, salvager has error message for this.
- *
- * This code optimizes single volume salvages by just looking at that one
- * volume's directory.
- *
- * If the inodeFile is NULL, then don't call the write routine.
- */
-int
-ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
-              int (*judgeInode) (struct ViceInodeInfo * info, afs_uint32 vid, void *rock),
-              afs_uint32 singleVolumeNumber, int *forcep, int forceR, char *wpath,
-              void *rock)
-{
-    int ninodes;
-    struct stat status;
-
-    ninodes =
-       nt_ListAFSFiles(wpath, WriteInodeInfo, inodeFile, judgeInode,
-                       singleVolumeNumber, rock);
-
-    if (!inodeFile)
-       return ninodes;
-
-    if (ninodes < 0) {
-       return ninodes;
-    }
-
-    if (fflush(inodeFile) == EOF) {
-       Log("Unable to successfully flush inode file for %s\n", mountedOn);
-       return -2;
-    }
-    if (fsync(fileno(inodeFile)) == -1) {
-       Log("Unable to successfully fsync inode file for %s\n", mountedOn);
-       return -2;
-    }
-
-    /*
-     * Paranoia:  check that the file is really the right size
-     */
-    if (fstat(fileno(inodeFile), &status) == -1) {
-       Log("Unable to successfully stat inode file for %s\n", mountedOn);
-       return -2;
-    }
-    if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
-       Log("Wrong size (%d instead of %d) in inode file for %s\n",
-           status.st_size, ninodes * sizeof(struct ViceInodeInfo),
-           mountedOn);
-       return -2;
-    }
-    return 0;
-}
-
-
-/* nt_ListAFSFiles
- *
- * Collect all the matching AFS files on the drive.
- * If singleVolumeNumber is non-zero, just return files for that volume.
- *
- * Returns <0 on error, else number of files found to match.
- */
-int
-nt_ListAFSFiles(char *dev,
-               int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
-                                char *), FILE * fp,
-               int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
-               afs_uint32 singleVolumeNumber, void *rock)
-{
-    IHandle_t h;
-    char name[MAX_PATH];
-    int ninodes = 0;
-    DIR *dirp;
-    struct dirent *dp;
-    static void FreeZLCList(void);
-
-    memset((void *)&h, 0, sizeof(IHandle_t));
-    h.ih_dev = toupper(*dev) - 'A';
-
-    if (singleVolumeNumber) {
-       h.ih_vid = singleVolumeNumber;
-       if (!nt_HandleToVolDir(name, &h))
-           return -1;
-       ninodes =
-           nt_ListAFSSubDirs(&h, writeFun, fp, judgeFun, singleVolumeNumber, rock);
-       if (ninodes < 0)
-           return ninodes;
-    } else {
-       /* Find all Vol_*.data directories and descend through them. */
-       if (!nt_DevToDrive(name, h.ih_dev))
-           return -1;
-       ninodes = 0;
-       dirp = opendir(name);
-       if (!dirp)
-           return -1;
-       while (dp = readdir(dirp)) {
-           if (!DecodeVolumeName(dp->d_name, &h.ih_vid)) {
-               ninodes += nt_ListAFSSubDirs(&h, writeFun, fp, judgeFun, 0, rock);
-           }
-       }
-    }
-    FreeZLCList();
-    return ninodes;
-}
-
-
-
-/* nt_ListAFSSubDirs
- *
- * List the S, F, and D subdirectories of this volume's directory.
- *
- * Return values:
- * < 0 - an error
- * > = 0 - number of AFS files found.
- */
-static int
-nt_ListAFSSubDirs(IHandle_t * dirIH,
-                 int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
-                                  char *), FILE * fp,
-                 int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
-                 afs_uint32 singleVolumeNumber, void *rock)
-{
-    int i;
-    IHandle_t myIH = *dirIH;
-    HANDLE dirH;
-    WIN32_FIND_DATA data;
-    char path[1024];
-    char basePath[1024];
-    char *s;
-    char findPath[1024];
-    struct ViceInodeInfo info;
-    int tag, vno;
-    FdHandle_t linkHandle;
-    int ninodes = 0;
-    static void DeleteZLCFiles(char *path);
-
-    s = nt_HandleToVolDir(path, &myIH);
-    strcpy(basePath, path);
-    if (!s)
-       return -1;
-    *s = '\\';
-    s++;
-    *(s + 1) = '\0';
-
-    /* Do the directory containing the special files first to pick up link
-     * counts.
-     */
-    for (i = 'R'; i >= 'A'; i--) {
-       *s = (char)i;
-       (void)strcpy(findPath, path);
-       (void)strcat(findPath, "\\*");
-       dirH =
-           FindFirstFileEx(findPath, FindExInfoStandard, &data,
-                           FindExSearchNameMatch, NULL,
-                           FIND_FIRST_EX_CASE_SENSITIVE);
-       if (dirH == INVALID_HANDLE_VALUE)
-           continue;
-       while (1) {
-           /* Store the vice info. */
-           memset((void *)&info, 0, sizeof(info));
-           if (*data.cFileName == '.')
-               goto next_file;
-           if (DecodeInodeName(data.cFileName, &vno, &tag) < 0) {
-               Log("Error parsing %s\\%s\n", path, data.cFileName);
-           } else {
-               info.inodeNumber = (Inode) tag << NT_TAGSHIFT;
-               info.inodeNumber |= (Inode) vno;
-               info.byteCount = data.nFileSizeLow;
-
-               if (i == 'R') { /* Special inode. */
-                   info.inodeNumber |= NT_INODESPECIAL;
-                   info.u.param[0] = data.ftCreationTime.dwHighDateTime;
-                   info.u.param[1] = data.ftCreationTime.dwLowDateTime;
-                   info.u.param[2] = vno;
-                   info.u.param[3] = dirIH->ih_vid;
-                   if (info.u.param[2] != VI_LINKTABLE) {
-                       info.linkCount = 1;
-                   } else {
-                       /* Open this handle */
-                       char lpath[1024];
-                       (void)sprintf(lpath, "%s\\%s", path, data.cFileName);
-                       linkHandle.fd_fd = nt_open(lpath, O_RDONLY, 0666);
-                       info.linkCount =
-                           nt_GetLinkCount(&linkHandle, (Inode) 0, 0);
-                   }
-               } else {        /* regular file. */
-                   info.linkCount =
-                       nt_GetLinkCount(&linkHandle, info.inodeNumber, 0);
-                   if (info.linkCount == 0) {
-#ifdef notdef
-                       Log("Found 0 link count file %s\\%s, deleting it.\n",
-                           path, data.cFileName);
-                       AddToZLCDeleteList((char)i, data.cFileName);
-#else
-                       Log("Found 0 link count file %s\\%s.\n", path,
-                           data.cFileName);
 #endif
-                       goto next_file;
-                   }
-                   info.u.param[0] = dirIH->ih_vid;
-                   info.u.param[1] = vno;
-                   info.u.param[2] = data.ftCreationTime.dwHighDateTime;
-                   info.u.param[3] = data.ftCreationTime.dwLowDateTime;
-               }
-               if (judgeFun && !(*judgeFun) (&info, singleVolumeNumber, rock))
-                   goto next_file;
-               if ((*writeFun) (fp, &info, path, data.cFileName) < 0) {
-                   nt_close(linkHandle.fd_fd);
-                   FindClose(dirH);
-                   return -1;
-               }
-               ninodes++;
-           }
-         next_file:
-           if (!FindNextFile(dirH, &data)) {
-               break;
-           }
-       }
-       FindClose(dirH);
-    }
-    nt_close(linkHandle.fd_fd);
-    DeleteZLCFiles(basePath);
-    if (!ninodes) {
-       /* Then why does this directory exist? Blow it away. */
-       nt_RemoveDataDirectories(dirIH);
-    }
-
-    return ninodes;
-}
-
-/* The name begins with "Vol_" and ends with .data.  See nt_HandleToVolDir() */
-static int
-DecodeVolumeName(char *name, afs_uint32 *vid)
-{
-    char stmp[32];
-    int len;
-
-    len = strlen(name);
-    if (len <= 9)
-       return -1;
-    if (strncmp(name, "Vol_", 4))
-       return -1;
-    if (strcmp(name + len - 5, ".data"))
-       return -1;
-    strcpy(stmp, name);
-    stmp[len - 5] = '\0';
-    *vid = base32_to_int(stmp + 4);
-    return 0;
-}
-
-/* Recall that the name beings with a "V_" */
-static int
-DecodeInodeName(char *name, int *p1, int *p2)
-{
-    char *s, *t;
-    char stmp[16];
-
-    (void)strcpy(stmp, name);
-    s = strrchr(stmp, '_');
-    if (!s)
-       return -1;
-    s++;
-    t = strrchr(s, '.');
-    if (!t)
-       return -1;
-
-    *t = '\0';
-    *p1 = base32_to_int(s);
-    *p2 = base32_to_int(t + 1);
-    return 0;
-}
-
-
-/* PrintInode
- *
- * returns a static string used to print either 32 or 64 bit inode numbers.
- */
-char *
-PrintInode(char *s, Inode ino)
-{
-    static afs_ino_str_t result;
-    if (!s)
-       s = result;
-
-    (void)sprintf((char *)s, "%I64u", ino);
-
-    return (char *)s;
-}
-
-
-/* Routines to facilitate removing zero link count files. */
-#define MAX_ZLC_NAMES 32
-#define MAX_ZLC_NAMELEN 16
-typedef struct zlcList_s {
-    struct zlcList_s *zlc_next;
-    int zlc_n;
-    char zlc_names[MAX_ZLC_NAMES][MAX_ZLC_NAMELEN];
-} zlcList_t;
-
-static zlcList_t *zlcAnchor = NULL;
-static zlcList_t *zlcCur = NULL;
-
-static void
-AddToZLCDeleteList(char dir, char *name)
-{
-    osi_Assert(strlen(name) <= MAX_ZLC_NAMELEN - 3);
-
-    if (!zlcCur || zlcCur->zlc_n >= MAX_ZLC_NAMES) {
-       if (zlcCur && zlcCur->zlc_next)
-           zlcCur = zlcCur->zlc_next;
-       else {
-           zlcList_t *tmp = (zlcList_t *) malloc(sizeof(zlcList_t));
-           if (!tmp)
-               return;
-           if (!zlcAnchor) {
-               zlcAnchor = tmp;
-           } else {
-               zlcCur->zlc_next = tmp;
-           }
-           zlcCur = tmp;
-           zlcCur->zlc_n = 0;
-           zlcCur->zlc_next = NULL;
-       }
-    }
-
-    (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%c\\%s", dir, name);
-    zlcCur->zlc_n++;
-}
-
-static void
-DeleteZLCFiles(char *path)
-{
-    zlcList_t *z;
-    int i;
-    char fname[1024];
-
-    for (z = zlcAnchor; z; z = z->zlc_next) {
-       for (i = 0; i < z->zlc_n; i++) {
-           (void)sprintf(fname, "%s\\%s", path, z->zlc_names[i]);
-           if (nt_unlink(fname) < 0) {
-               Log("ZLC: Can't unlink %s, dos error = %d\n", fname,
-                   GetLastError());
-           }
-       }
-       z->zlc_n = 0;           /* Can reuse space. */
-    }
-    zlcCur = zlcAnchor;
-}
-
-static void
-FreeZLCList(void)
-{
-    zlcList_t *tnext;
-    zlcList_t *i;
-
-    i = zlcAnchor;
-    while (i) {
-       tnext = i->zlc_next;
-       free(i);
-       i = tnext;
-    }
-    zlcCur = zlcAnchor = NULL;
-}
-
-#endif /* AFS_NT40_ENV */
index a01c4d9..784dbba 100644 (file)
 #ifndef _NTOPS_H_
 #define _NTOPS_H_
 
-
-/* We don't include Unix afssyscalls.h, so: */
+#ifdef AFS_NT40_ENV
+/* We don't include Unix afssyscalls.h on Windows, so: */
 #define VALID_INO(I) ((I != (__int64)-1) && (I != (__int64)0))
 
 /* minimum size of string to hand to PrintInode */
 #define AFS_INO_STR_LENGTH 32
 typedef char afs_ino_str_t[AFS_INO_STR_LENGTH];
 
-char *PrintInode(char *s, Inode ino);
+extern char *PrintInode(char *, Inode);
+#endif
 
 /* Basic file operations */
 extern FD_t nt_open(char *name, int flags, int mode);
@@ -37,31 +38,6 @@ extern int nt_seek(FD_t fd, int off, int where);
 extern FILE *nt_fdopen(IHandle_t * h, char *fdperms);
 extern int nt_unlink(char *name);
 
-/* Inode operations */
-extern Inode nt_MakeSpecIno(int type);
-extern Inode nt_icreate(IHandle_t * h, char *p, afs_uint32 p1, afs_uint32 p2,
-                        afs_uint32 p3, afs_uint32 p4);
-extern FD_t nt_iopen(IHandle_t * h);
-extern int nt_irelease(IHandle_t * h);
-int nt_iread(IHandle_t * h, int offset, char *buf, int size);
-int nt_iwrite(IHandle_t * h, int offset, char *buf, int size);
-extern int nt_dec(IHandle_t * h, Inode ino, int p1);
-extern int nt_inc(IHandle_t * h, Inode ino, int p1);
-extern int nt_GetLinkCount(FdHandle_t * h, Inode ino, int lockit);
-int nt_ListAFSFiles(char *dev,
-                   int (*write_fun) (FILE * fp, struct ViceInodeInfo *,
-                                     char *dir, char *file), FILE * fp,
-                   int (*judge_fun) (struct ViceInodeInfo *, afs_uint32 vid, void *rock),
-                   afs_uint32 singleVolumeNumber, void *rock);
-int ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
-                  int (*judgeInode) (struct ViceInodeInfo * info, afs_uint32 vid, void *rock),
-                  afs_uint32 singleVolumeNumber, int *forcep, int forceR,
-                  char *wpath, void *rock);
-
-
-int nt_HandleToName(char *name, IHandle_t * h);
-char *nt_HandleToVolDir(char *name, IHandle_t * h);
-
-extern int Testing;
-
+extern void nt_DevToDrive(char *drive, int dev);
+extern int nt_DriveToDev(char *drive);
 #endif /* _NTOPS_H_ */
index f1add7b..c5e5a89 100644 (file)
@@ -117,12 +117,9 @@ nuke(char *aname, afs_int32 avolid)
     char *lastDevComp;
     struct DiskPartition64 *dp;
 #ifdef AFS_NAMEI_ENV
-#ifdef AFS_NT40_ENV
-    char path[MAX_PATH];
-#else
     char *path;
+
     namei_t ufs_name;
-#endif
 #endif /* AFS_NAMEI_ENV */
 #ifndef AFS_NAMEI_ENV
     char devName[64];
@@ -186,15 +183,14 @@ nuke(char *aname, afs_int32 avolid)
 #ifdef AFS_NT40_ENV
                IH_INIT(fileH, (int)(*lastDevComp - 'A'), avolid,
                        ti->inode[i]);
-               nt_HandleToName(path, fileH);
 #else
                IH_INIT(fileH, (int)volutil_GetPartitionID(aname), avolid,
                        ti->inode[i]);
+#endif /* AFS_NT40_ENV */
                namei_HandleToName(&ufs_name, fileH);
                path = ufs_name.n_path;
-#endif /* AFS_NT40_ENV */
                IH_RELEASE(fileH);
-               if (unlink(path) < 0) {
+               if (OS_UNLINK(path) < 0) {
                    Log("Nuke: Failed to remove %s\n", path);
                }
 #else /* AFS_NAMEI_ENV */
index 31ce4df..0edc296 100644 (file)
@@ -872,11 +872,7 @@ PrintVnode(int offset, VnodeDiskObject * vnode, VnodeId vnodeNumber,
 {
 #if defined(AFS_NAMEI_ENV)
     IHandle_t *ihtmpp;
-#if !defined(AFS_NT40_ENV)
     namei_t filename;
-#else
-    char filename[MAX_PATH];
-#endif
 #endif
     afs_fsize_t fileLength;
 
@@ -899,12 +895,11 @@ PrintVnode(int offset, VnodeDiskObject * vnode, VnodeId vnodeNumber,
 #if defined(AFS_NAMEI_ENV)
     if (PrintFileNames) {
        IH_INIT(ihtmpp, V_device(vp), V_parentId(vp), ino);
-#if !defined(AFS_NT40_ENV)
        namei_HandleToName(&filename, ihtmpp);
+#if !defined(AFS_NT40_ENV)
        printf(" UFS-Filename: %s", filename.n_path);
 #else
-       nt_HandleToName(filename, ihtmpp);
-       printf(" NTFS-Filename: %s", filename);
+       printf(" NTFS-Filename: %s", filename.n_path);
 #endif
     }
 #endif
index 97f00e9..84efe4e 100644 (file)
@@ -1905,11 +1905,7 @@ DoSalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nV
                for (i = 0; i < nVols; i++) {
                        ip = allInodes + isp[i].index;
                         for (j = isp[i].nSpecialInodes; j < isp[i].nInodes; j++) {
-#ifdef AFS_NT40_ENV
-                                nt_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
-#else
                                 namei_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
-#endif
                    }
                }
            }
index fdd2b7a..1822103 100644 (file)
@@ -221,11 +221,7 @@ VCreateVolume_r(Error * ec, char *partname, VolId volumeId, VolId parentId)
                IHandle_t *lh;
                int code;
 
-#ifdef AFS_NT40_ENV
-               *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
-#else
                *(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
-#endif
                IH_INIT(lh, device, parentId, *(p->inode));
                fdP = IH_OPEN(lh);
                if (fdP == NULL) {