dread-do-validation-20041012
[openafs.git] / src / afs / VNOPS / afs_vnop_readdir.c
index 58bb488..d1d0330 100644 (file)
  */
 
 #include <afsconfig.h>
-#include "../afs/param.h"
+#include "afs/param.h"
 
-RCSID("$Header$");
+RCSID
+    ("$Header$");
 
-#include "../afs/sysincludes.h"        /* Standard vendor system headers */
-#include "../afs/afsincludes.h"        /* Afs-based standard headers */
-#include "../afs/afs_stats.h" /* statistics */
-#include "../afs/afs_cbqueue.h"
-#include "../afs/nfsclient.h"
-#include "../afs/afs_osidnlc.h"
+#include "afs/sysincludes.h"   /* Standard vendor system headers */
+#include "afsincludes.h"       /* Afs-based standard headers */
+#include "afs/afs_stats.h"     /* statistics */
+#include "afs/afs_cbqueue.h"
+#include "afs/nfsclient.h"
+#include "afs/afs_osidnlc.h"
 
 
+#if    defined(AFS_HPUX1122_ENV)
+#define DIRPAD 7
+#else
+#define DIRPAD 3
+#endif
 /**
  * A few definitions. This is until we have a proper header file
  * which ahs prototypes for all functions
  */
-    
-extern struct DirEntry * afs_dir_GetBlob();
+
+extern struct DirEntry *afs_dir_GetBlob();
 /*
  * AFS readdir vnodeop and bulk stat support.
  */
@@ -60,15 +66,8 @@ extern struct DirEntry * afs_dir_GetBlob();
     BlobScan is used by the Linux port in a separate file, so it should not
     become static.
 */
-#if defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV)
-int BlobScan(ino64_t *afile, afs_int32 ablob)
-#else
-#ifdef AFS_LINUX_64BIT_KERNEL
-int BlobScan(long *afile, afs_int32 ablob)
-#else
-int BlobScan(afs_int32 *afile, afs_int32 ablob)
-#endif
-#endif
+int
+BlobScan(struct fcache * afile, afs_int32 ablob)
 {
     register afs_int32 relativeBlob;
     afs_int32 pageBlob;
@@ -78,27 +77,31 @@ int BlobScan(afs_int32 *afile, afs_int32 ablob)
     AFS_STATCNT(BlobScan);
     /* advance ablob over free and header blobs */
     while (1) {
-       pageBlob = ablob & ~(EPP-1);    /* base blob in same page */
-       tpe = (struct PageHeader *) afs_dir_GetBlob(afile, pageBlob);
-       if (!tpe) return 0;                 /* we've past the end */
-       relativeBlob = ablob - pageBlob;    /* relative to page's first blob */
+       pageBlob = ablob & ~(EPP - 1);  /* base blob in same page */
+       tpe = (struct PageHeader *)afs_dir_GetBlob(afile, pageBlob);
+       if (!tpe)
+           return 0;           /* we've past the end */
+       relativeBlob = ablob - pageBlob;        /* relative to page's first blob */
        /* first watch for headers */
-       if (pageBlob == 0) {                /* first dir page has extra-big header */
+       if (pageBlob == 0) {    /* first dir page has extra-big header */
            /* first page */
-           if (relativeBlob < DHE+1) relativeBlob = DHE+1;
-       }
-       else {                              /* others have one header blob */
-           if (relativeBlob == 0) relativeBlob = 1;
+           if (relativeBlob < DHE + 1)
+               relativeBlob = DHE + 1;
+       } else {                /* others have one header blob */
+           if (relativeBlob == 0)
+               relativeBlob = 1;
        }
        /* make sure blob is allocated */
-       for(i = relativeBlob; i < EPP; i++) {
-           if (tpe->freebitmap[i>>3] & (1<<(i&7))) break;
+       for (i = relativeBlob; i < EPP; i++) {
+           if (tpe->freebitmap[i >> 3] & (1 << (i & 7)))
+               break;
        }
        /* now relativeBlob is the page-relative first allocated blob,
-        or EPP (if there are none in this page). */
-       DRelease(tpe, 0);
-       if (i != EPP) return i+pageBlob;
-       ablob = pageBlob + EPP; /* go around again */
+        * or EPP (if there are none in this page). */
+       DRelease((struct buffer *)tpe, 0);
+       if (i != EPP)
+           return i + pageBlob;
+       ablob = pageBlob + EPP; /* go around again */
     }
     /* never get here */
 }
@@ -117,18 +120,18 @@ int BlobScan(afs_int32 *afile, afs_int32 ablob)
 #if !defined(UKERNEL)
 #if defined(AFS_SGI_ENV)
 /* Long form for 64 bit apps and kernel requests. */
-struct min_dirent {     /* miniature dirent structure */
-                        /* If struct dirent changes, this must too */
-    ino_t       d_fileno; /* This is 32 bits for 3.5, 64 for 6.2+ */
-    off64_t     d_off;
-    u_short     d_reclen;
+struct min_dirent {            /* miniature dirent structure */
+    /* If struct dirent changes, this must too */
+    ino_t d_fileno;            /* This is 32 bits for 3.5, 64 for 6.2+ */
+    off64_t d_off;
+    u_short d_reclen;
 };
 /* Short form for 32 bit apps. */
-struct irix5_min_dirent {     /* miniature dirent structure */
-                        /* If struct dirent changes, this must too */
-    afs_uint32 d_fileno;
-    afs_int32  d_off;
-    u_short     d_reclen;
+struct irix5_min_dirent {      /* miniature dirent structure */
+    /* If struct dirent changes, this must too */
+    afs_uint32 d_fileno;
+    afs_int32 d_off;
+    u_short d_reclen;
 };
 #ifdef AFS_SGI62_ENV
 #define AFS_DIRENT32BASESIZE IRIX5_DIRENTBASESIZE
@@ -138,28 +141,28 @@ struct irix5_min_dirent {     /* miniature dirent structure */
 #define AFS_DIRENT64BASESIZE DIRENTBASESIZE
 #endif /* AFS_SGI62_ENV */
 #else
-struct min_direct {    /* miniature direct structure */
-                       /* If struct direct changes, this must too */
-#ifdef AFS_DARWIN_ENV
-    afs_uint32  d_fileno;
-    u_short     d_reclen;
-    u_char      d_type;
-    u_char      d_namlen;
-#else   
+struct min_direct {            /* miniature direct structure */
+    /* If struct direct changes, this must too */
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+    afs_uint32 d_fileno;
+    u_short d_reclen;
+    u_char d_type;
+    u_char d_namlen;
+#else
 #ifdef AFS_SUN5_ENV
-    afs_uint32 d_fileno;
-    afs_int32  d_off;
-    u_short    d_reclen;
+    afs_uint32 d_fileno;
+    afs_int32 d_off;
+    u_short d_reclen;
 #else
 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV)
-    afs_int32  d_off;
+    afs_int32 d_off;
 #endif
 #if     defined(AFS_HPUX100_ENV)
     unsigned long long d_off;
 #endif
-    afs_uint32 d_fileno;
-    u_short    d_reclen;
-    u_short    d_namlen;
+    afs_uint32 d_fileno;
+    u_short d_reclen;
+    u_short d_namlen;
 #endif
 #endif
 };
@@ -167,12 +170,12 @@ struct min_direct {       /* miniature direct structure */
 
 #if    defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
 struct minnfs_direct {
-    afs_int32  d_off;          /* XXX */
-    afs_uint32 d_fileno;
-    u_short    d_reclen;
-    u_short    d_namlen;
+    afs_int32 d_off;           /* XXX */
+    afs_uint32 d_fileno;
+    u_short d_reclen;
+    u_short d_namlen;
 };
-#define NDIRSIZ_LEN(len)   ((sizeof (struct dirent)+4 - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
+#define NDIRSIZ_LEN(len)   ((sizeof (struct dirent)+4 - (MAXNAMLEN+1)) + (((len)+1 + DIRPAD) &~ DIRPAD))
 #endif
 #endif /* !defined(UKERNEL) */
 
@@ -185,8 +188,8 @@ struct minnfs_direct {
  */
 
 #define        READDIR_STASH   AFSCBMAX
-struct AFSFid  afs_readdir_stash[READDIR_STASH];
-int    afs_rd_stash_i = 0;
+struct AFSFid afs_readdir_stash[READDIR_STASH];
+int afs_rd_stash_i = 0;
 
 /*
  *------------------------------------------------------------------------------
@@ -198,9 +201,10 @@ int        afs_rd_stash_i = 0;
  *
  *
 */
+
 #if    defined(AFS_HPUX100_ENV)
 #define DIRSIZ_LEN(len) \
-    ((sizeof (struct __dirent) - (_MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
+    ((sizeof (struct __dirent) - (_MAXNAMLEN+1)) + (((len)+1 + DIRPAD) &~ DIRPAD))
 #else
 #if    defined(AFS_SUN56_ENV)
 #define DIRSIZ_LEN(len) ((18 + (len) + 1 + 7) & ~7 )
@@ -224,7 +228,46 @@ int        afs_rd_stash_i = 0;
 #endif /* AFS_DIRENT */
 #endif /* AFS_SUN5_ENV */
 #endif /* AFS_SUN56_ENV */
-#endif /* AFS_HPUX100_ENV */
+#endif /* AFS_HPUX100_ENV */
+
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+int
+afs_readdir_type(avc, ade)
+     struct DirEntry *ade;
+     struct vcache *avc;
+{
+    struct VenusFid tfid;
+    struct vcache *tvc;
+    int vtype;
+    tfid.Cell = avc->fid.Cell;
+    tfid.Fid.Volume = avc->fid.Fid.Volume;
+    tfid.Fid.Vnode = ntohl(ade->fid.vnode);
+    tfid.Fid.Unique = ntohl(ade->fid.vunique);
+    if ((avc->states & CForeign) == 0 && (ntohl(ade->fid.vnode) & 1)) {
+       return DT_DIR;
+    } else if ((tvc = afs_FindVCache(&tfid, 0, 0))) {
+       if (tvc->mvstat) {
+           afs_PutVCache(tvc);
+           return DT_DIR;
+       } else if (((tvc->states) & (CStatd | CTruth))) {
+           /* CTruth will be set if the object has
+            *ever* been statd */
+           vtype = vType(tvc);
+           afs_PutVCache(tvc);
+           if (vtype == VDIR)
+               return DT_DIR;
+           else if (vtype == VREG)
+               return DT_REG;
+           /* Don't do this until we're sure it can't be a mtpt */
+           /* else if (vtype == VLNK)
+            * type=DT_LNK; */
+           /* what other types does AFS support? */
+       } else
+           afs_PutVCache(tvc);
+    }
+    return DT_UNKNOWN;
+}
+#endif
 
 #ifdef AFS_AIX41_ENV
 #define AFS_MOVE_LOCK()   AFS_GLOCK()
@@ -233,25 +276,26 @@ int       afs_rd_stash_i = 0;
 #define AFS_MOVE_LOCK()
 #define AFS_MOVE_UNLOCK()
 #endif
+char bufofzeros[64];           /* gotta fill with something */
 
-char bufofzeros[64];   /* gotta fill with something */
-afs_readdir_move (de, vc, auio, slen, rlen, off) 
-struct DirEntry *      de;
-struct vcache *                vc;
-struct uio *           auio;
-int                    slen;
+int
+afs_readdir_move(de, vc, auio, slen, rlen, off)
+     struct DirEntry *de;
+     struct vcache *vc;
+     struct uio *auio;
+     int slen;
 #ifdef AFS_SGI65_ENV
-ssize_t                        rlen;
+     ssize_t rlen;
 #else
-int                    rlen;
+     int rlen;
 #endif
-int                    off;
+     afs_size_t off;
 {
-    int        code = 0;
+    int code = 0;
 #if    defined(AFS_SUN56_ENV)
     struct dirent64 *direntp;
 #else
-#ifdef AFS_SUN5_ENV
+#if  defined(AFS_SUN5_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
     struct dirent *direntp;
 #endif
 #endif /* AFS_SUN56_ENV */
@@ -261,85 +305,100 @@ int                      off;
 
     AFS_STATCNT(afs_readdir_move);
 #ifdef AFS_SGI53_ENV
-{
-    afs_int32  use64BitDirent;
+    {
+       afs_int32 use64BitDirent;
 
 #ifdef AFS_SGI61_ENV
 #ifdef AFS_SGI62_ENV
-    use64BitDirent = ABI_IS(ABI_IRIX5_64,
-                           GETDENTS_ABI*OSI_GET_CURRENT_ABI(), auio));
+       use64BitDirent =
+           ABI_IS(ABI_IRIX5_64, GETDENTS_ABI(OSI_GET_CURRENT_ABI(), auio));
 #else
-    use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
-       (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32, u.u_procp->p_abi));
+       use64BitDirent =
+           (auio->uio_segflg !=
+            UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64 |
+                                                    ABI_IRIX5_N32,
+                                                    u.u_procp->p_abi));
 #endif
 #else /* AFS_SGI61_ENV */
-    use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
-       (ABI_IS(ABI_IRIX5_64, u.u_procp->p_abi));
+       use64BitDirent =
+           (auio->uio_segflg !=
+            UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64,
+                                                    u.u_procp->p_abi));
 #endif /* AFS_SGI61_ENV */
 
-    if (use64BitDirent) {
-       struct min_dirent sdirEntry;
-       sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
-       FIXUPSTUPIDINODE(sdirEntry.d_fileno);
-       sdirEntry.d_reclen = rlen;
-       sdirEntry.d_off = (off_t)off;
-       AFS_UIOMOVE(&sdirEntry, AFS_DIRENT64BASESIZE, UIO_READ, auio, code);
-       if (code == 0)
-           AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
-       if (code == 0)
-           AFS_UIOMOVE(bufofzeros,
-                       DIRENTSIZE(slen) - (AFS_DIRENT64BASESIZE + slen - 1),
-                       UIO_READ, auio, code);
-       if (DIRENTSIZE(slen) < rlen) {
-           while(DIRENTSIZE(slen) < rlen) {
-               int minLen = rlen - DIRENTSIZE(slen);
-               if (minLen > sizeof(bufofzeros)) minLen = sizeof(bufofzeros);
-               AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
-               rlen -= minLen;
+       if (use64BitDirent) {
+           struct min_dirent sdirEntry;
+           sdirEntry.d_fileno =
+               (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
+           FIXUPSTUPIDINODE(sdirEntry.d_fileno);
+           sdirEntry.d_reclen = rlen;
+           sdirEntry.d_off = (off_t) off;
+           AFS_UIOMOVE(&sdirEntry, AFS_DIRENT64BASESIZE, UIO_READ, auio,
+                       code);
+           if (code == 0)
+               AFS_UIOMOVE(de->name, slen - 1, UIO_READ, auio, code);
+           if (code == 0)
+               AFS_UIOMOVE(bufofzeros,
+                           DIRENTSIZE(slen) - (AFS_DIRENT64BASESIZE + slen -
+                                               1), UIO_READ, auio, code);
+           if (DIRENTSIZE(slen) < rlen) {
+               while (DIRENTSIZE(slen) < rlen) {
+                   int minLen = rlen - DIRENTSIZE(slen);
+                   if (minLen > sizeof(bufofzeros))
+                       minLen = sizeof(bufofzeros);
+                   AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
+                   rlen -= minLen;
+               }
            }
-       }
-    } else {
-       struct irix5_min_dirent sdirEntry;
-       sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
-       FIXUPSTUPIDINODE(sdirEntry.d_fileno);
-       sdirEntry.d_reclen = rlen;
-       sdirEntry.d_off = (afs_int32)off;
-       AFS_UIOMOVE(&sdirEntry, AFS_DIRENT32BASESIZE, UIO_READ, auio, code);
-       if (code == 0)
-           AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
-       if (code == 0)
-           AFS_UIOMOVE(bufofzeros,
-                       IRIX5_DIRENTSIZE(slen) -
-                       (AFS_DIRENT32BASESIZE + slen - 1),
-                          UIO_READ, auio, code);
-       if (IRIX5_DIRENTSIZE(slen) < rlen) {
-           while(IRIX5_DIRENTSIZE(slen) < rlen) {
-               int minLen = rlen - IRIX5_DIRENTSIZE(slen);
-               if (minLen > sizeof(bufofzeros)) minLen = sizeof(bufofzeros);
-               AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
-               rlen -= minLen;
+       } else {
+           struct irix5_min_dirent sdirEntry;
+           sdirEntry.d_fileno =
+               (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
+           FIXUPSTUPIDINODE(sdirEntry.d_fileno);
+           sdirEntry.d_reclen = rlen;
+           sdirEntry.d_off = (afs_int32) off;
+           AFS_UIOMOVE(&sdirEntry, AFS_DIRENT32BASESIZE, UIO_READ, auio,
+                       code);
+           if (code == 0)
+               AFS_UIOMOVE(de->name, slen - 1, UIO_READ, auio, code);
+           if (code == 0)
+               AFS_UIOMOVE(bufofzeros,
+                           IRIX5_DIRENTSIZE(slen) - (AFS_DIRENT32BASESIZE +
+                                                     slen - 1), UIO_READ,
+                           auio, code);
+           if (IRIX5_DIRENTSIZE(slen) < rlen) {
+               while (IRIX5_DIRENTSIZE(slen) < rlen) {
+                   int minLen = rlen - IRIX5_DIRENTSIZE(slen);
+                   if (minLen > sizeof(bufofzeros))
+                       minLen = sizeof(bufofzeros);
+                   AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
+                   rlen -= minLen;
+               }
            }
        }
     }
-}
 #else /* AFS_SGI53_ENV */
-#ifdef AFS_SUN5_ENV
+#if  defined(AFS_SUN5_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
 #if    defined(AFS_SUN56_ENV)
-    direntp = (struct dirent64 *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+    direntp = (struct dirent64 *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
 #else
-    direntp = (struct dirent *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+    direntp = (struct dirent *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
 #endif
-    direntp->d_ino =  (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
+    direntp->d_ino = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
     FIXUPSTUPIDINODE(direntp->d_ino);
+#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
+    direntp->d_offset = off;
+    direntp->d_namlen = slen;
+#else
     direntp->d_off = off;
+#endif
     direntp->d_reclen = rlen;
     strcpy(direntp->d_name, de->name);
-    AFS_UIOMOVE((caddr_t)direntp, rlen, UIO_READ, auio, code);
+    AFS_UIOMOVE((caddr_t) direntp, rlen, UIO_READ, auio, code);
     osi_FreeLargeSpace((char *)direntp);
 #else /* AFS_SUN5_ENV */
     /* Note the odd mechanism for building the inode number */
-    sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) +
-      ntohl(de->fid.vnode);
+    sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
     FIXUPSTUPIDINODE(sdirEntry.d_fileno);
     sdirEntry.d_reclen = rlen;
 #if !defined(AFS_SGI_ENV)
@@ -348,16 +407,18 @@ int                       off;
 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
     sdirEntry.d_off = off;
 #endif
-#if defined(AFS_DARWIN_ENV)
-    sdirEntry.d_type=DT_UNKNOWN;
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+    sdirEntry.d_type = afs_readdir_type(vc, de);
 #endif
 
 #if defined(AFS_SGI_ENV)
     AFS_UIOMOVE(&sdirEntry, DIRENTBASESIZE, UIO_READ, auio, code);
     if (code == 0)
-       AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
+       AFS_UIOMOVE(de->name, slen - 1, UIO_READ, auio, code);
     if (code == 0)
-        AFS_UIOMOVE(bufofzeros, DIRSIZ_LEN(slen) - (DIRENTBASESIZE + slen - 1), UIO_READ, auio, code);
+       AFS_UIOMOVE(bufofzeros,
+                   DIRSIZ_LEN(slen) - (DIRENTBASESIZE + slen - 1), UIO_READ,
+                   auio, code);
 #else /* AFS_SGI_ENV */
     AFS_MOVE_UNLOCK();
     AFS_UIOMOVE((char *)&sdirEntry, sizeof(sdirEntry), UIO_READ, auio, code);
@@ -367,30 +428,28 @@ int                       off;
     }
 
     /* pad out the remaining characters with zeros */
-    if (code == 0) { 
-       AFS_UIOMOVE(bufofzeros, ((slen + 4) & ~3) - slen, UIO_READ,
-                   auio, code);
+    if (code == 0) {
+       AFS_UIOMOVE(bufofzeros, ((slen + 1 + DIRPAD) & ~DIRPAD) - slen,
+                   UIO_READ, auio, code);
     }
     AFS_MOVE_LOCK();
 #endif /* AFS_SGI_ENV */
 
     /* pad out the difference between rlen and slen... */
-    if (DIRSIZ_LEN(slen) < rlen)
-       {
+    if (DIRSIZ_LEN(slen) < rlen) {
        AFS_MOVE_UNLOCK();
-       while(DIRSIZ_LEN(slen) < rlen)
-               {
-               int minLen = rlen - DIRSIZ_LEN(slen);
-               if (minLen > sizeof(bufofzeros))
-                       minLen = sizeof(bufofzeros);
-               AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
-               rlen -= minLen;
-               }
-       AFS_MOVE_LOCK();
+       while (DIRSIZ_LEN(slen) < rlen) {
+           int minLen = rlen - DIRSIZ_LEN(slen);
+           if (minLen > sizeof(bufofzeros))
+               minLen = sizeof(bufofzeros);
+           AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
+           rlen -= minLen;
        }
-#endif /* AFS_SUN5_ENV */
-#endif /* AFS_SGI53_ENV */
-    return(code);
+       AFS_MOVE_LOCK();
+    }
+#endif /* AFS_SUN5_ENV */
+#endif /* AFS_SGI53_ENV */
+    return (code);
 }
 
 
@@ -410,11 +469,11 @@ int                       off;
  * This routine encodes knowledge of Vice dirs.
  */
 
-void afs_bulkstat_send( avc, req )
-    struct vcache * avc;
-    struct vrequest * req;
+void
+afs_bulkstat_send(avc, req)
+     struct vcache *avc;
+     struct vrequest *req;
 {
-    XSTATS_DECLS
     afs_rd_stash_i = 0;
 }
 
@@ -423,88 +482,105 @@ void afs_bulkstat_send( avc, req )
  * It has to do with 'offset' (seek locations).
 */
 
-#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
+int
+#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 afs_readdir(OSI_VC_ARG(avc), auio, acred, eofp)
-    int *eofp;
+     int *eofp;
 #else
-#if defined(AFS_HPUX100_ENV) 
+#if defined(AFS_HPUX100_ENV)
 afs_readdir2(OSI_VC_ARG(avc), auio, acred)
 #else
 afs_readdir(OSI_VC_ARG(avc), auio, acred)
-#endif 
 #endif
-    OSI_VC_DECL(avc);
-    struct uio *auio;
-    struct AFS_UCRED *acred; {
+#endif
+     OSI_VC_DECL(avc);
+     struct uio *auio;
+     struct AFS_UCRED *acred;
+{
     struct vrequest treq;
     register struct dcache *tdc;
-    afs_int32 origOffset, len, dirsiz;
+    afs_size_t origOffset, tlen;
+    afs_int32 len;
     int code = 0;
     struct DirEntry *ode = 0, *nde = 0;
     int o_slen = 0, n_slen = 0;
     afs_uint32 us;
+    struct afs_fakestat_state fakestate;
 #if defined(AFS_SGI53_ENV)
-    afs_int32 use64BitDirent;
+    afs_int32 use64BitDirent, dirsiz;
 #endif /* defined(AFS_SGI53_ENV) */
-    OSI_VC_CONVERT(avc)
+    OSI_VC_CONVERT(avc);
 #ifdef AFS_HPUX_ENV
     /*
      * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
      * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
      * translator side XXX
      */
-    struct min_direct *sdirEntry = (struct min_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
+    struct min_direct *sdirEntry =
+       (struct min_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
     afs_int32 rlen;
 #endif
 
     /* opaque value is pointer into a vice dir; use bit map to decide
-       if the entries are in use.  Always assumed to be valid.  0 is
-       special, means start of a new dir.  Int32 inode, followed by
-       short reclen and short namelen.  Namelen does not include
-       the null byte.  Followed by null-terminated string.
-    */
+     * if the entries are in use.  Always assumed to be valid.  0 is
+     * special, means start of a new dir.  Int32 inode, followed by
+     * short reclen and short namelen.  Namelen does not include
+     * the null byte.  Followed by null-terminated string.
+     */
     AFS_STATCNT(afs_readdir);
 
 #if defined(AFS_SGI53_ENV)
 #ifdef AFS_SGI61_ENV
 #ifdef AFS_SGI62_ENV
-    use64BitDirent = ABI_IS(ABI_IRIX5_64,
-                           GETDENTS_ABI(OSI_GET_CURRENT_ABI(), auio));
+    use64BitDirent =
+       ABI_IS(ABI_IRIX5_64, GETDENTS_ABI(OSI_GET_CURRENT_ABI(), auio));
 #else
-    use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
-       (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32, u.u_procp->p_abi));
+    use64BitDirent =
+       (auio->uio_segflg !=
+        UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32,
+                                                u.u_procp->p_abi));
 #endif /* AFS_SGI62_ENV */
 #else /* AFS_SGI61_ENV */
-    use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
-       (ABI_IS(ABI_IRIX5_64, u.u_procp->p_abi));
+    use64BitDirent =
+       (auio->uio_segflg !=
+        UIO_USERSPACE) ? ABI_IRIX5_64 : (ABI_IS(ABI_IRIX5_64,
+                                                u.u_procp->p_abi));
 #endif /* AFS_SGI61_ENV */
 #endif /* defined(AFS_SGI53_ENV) */
 
-#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
+#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
     /* Not really used by the callee so we ignore it for now */
-    if (eofp) *eofp = 0;
+    if (eofp)
+       *eofp = 0;
 #endif
-    if ( AfsLargeFileUio(auio)                  /* file is large than 2 GB */
-        || AfsLargeFileSize(auio->uio_offset, auio->uio_resid) )
+    if (AfsLargeFileUio(auio)  /* file is large than 2 GB */
+       ||AfsLargeFileSize(auio->uio_offset, auio->uio_resid))
        return EFBIG;
 
-    if (code = afs_InitReq(&treq, acred)) {
+    if ((code = afs_InitReq(&treq, acred))) {
 #ifdef AFS_HPUX_ENV
        osi_FreeSmallSpace((char *)sdirEntry);
 #endif
        return code;
     }
     /* update the cache entry */
-tagain:
+    afs_InitFakeStat(&fakestate);
+    code = afs_EvalFakeStat(&avc, &fakestate, &treq);
+    if (code)
+       goto done;
+  tagain:
     code = afs_VerifyVCache(avc, &treq);
-    if (code) goto done;
+    if (code)
+       goto done;
     /* get a reference to the entire directory */
-    tdc = afs_GetDCache(avc, 0, &treq, &origOffset, &len, 1);
+    tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
+    len = tlen;
     if (!tdc) {
        code = ENOENT;
        goto done;
     }
     ObtainReadLock(&avc->lock);
+    ObtainReadLock(&tdc->lock);
 
     /*
      * Make sure that the data in the cache is current. There are two
@@ -513,76 +589,85 @@ tagain:
      * 2. The cache data is no longer valid
      */
     while ((avc->states & CStatd)
-          && (tdc->flags & DFFetching)
+          && (tdc->dflags & DFFetching)
           && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
-       tdc->flags |= DFWaiting;
+       afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
+                  __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
+                  ICL_TYPE_INT32, tdc->dflags);
+       ReleaseReadLock(&tdc->lock);
        ReleaseReadLock(&avc->lock);
        afs_osi_Sleep(&tdc->validPos);
        ObtainReadLock(&avc->lock);
+       ObtainReadLock(&tdc->lock);
     }
     if (!(avc->states & CStatd)
        || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
+       ReleaseReadLock(&tdc->lock);
        ReleaseReadLock(&avc->lock);
        afs_PutDCache(tdc);
        goto tagain;
     }
 
     /*
-     * iterator for the directory reads.  Takes the AFS DirEntry
-     * structure and slams them into UFS direct structures.
-     * uses afs_readdir_move to get the struct to the user space.
+     *  iterator for the directory reads.  Takes the AFS DirEntry
+     *  structure and slams them into UFS direct structures.
+     *  uses afs_readdir_move to get the struct to the user space.
      *
-     * The routine works by looking ahead one AFS directory entry.
-     * That's because the AFS entry we are currenly working with
-     * may not fit into the buffer the user has provided.  If it
-     * doesn't we have to change the size of the LAST AFS directory
-     * entry, so that it will FIT perfectly into the block the
-     * user has provided.
-     * 
-     * The 'forward looking' of the code makes it a bit tough to read.
-     * Remember we need to get an entry, see if it it fits, then
-     * set it up as the LAST entry, and find the next one.
+     *  The routine works by looking ahead one AFS directory entry.
+     *  That's because the AFS entry we are currenly working with
+     *  may not fit into the buffer the user has provided.  If it
+     *  doesn't we have to change the size of the LAST AFS directory
+     *  entry, so that it will FIT perfectly into the block the
+     *  user has provided.
+     *  
+     *  The 'forward looking' of the code makes it a bit tough to read.
+     *  Remember we need to get an entry, see if it it fits, then
+     *  set it up as the LAST entry, and find the next one.
      *
-     * Tough to take: We give out an EINVAL if we don't have enough
-     * space in the buffer, and at the same time, don't have an entry
-     * to put into the buffer. This CAN happen if the first AFS entry
-     * we get can't fit into the 512 character buffer provided.  Seems
-     * it ought not happen... 
+     *  Tough to take: We give out an EINVAL if we don't have enough
+     *  space in the buffer, and at the same time, don't have an entry
+     *  to put into the buffer. This CAN happen if the first AFS entry
+     *  we get can't fit into the 512 character buffer provided.  Seems
+     *  it ought not happen... 
      *
-     * Assumption: don't need to use anything but one dc entry:
-     * this means the directory ought not be greater than 64k.
+     *  Assumption: don't need to use anything but one dc entry:
+     *  this means the directory ought not be greater than 64k.
      */
     len = 0;
 #ifdef AFS_HPUX_ENV
     auio->uio_fpflags = 0;
 #endif
-    while (code==0) {
+    while (code == 0) {
        origOffset = auio->afsio_offset;
        /* scan for the next interesting entry scan for in-use blob otherwise up point at
         * this blob note that ode, if non-zero, also represents a held dir page */
-       if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)) )
-           || !(nde = (struct DirEntry *) afs_dir_GetBlob(&tdc->f.inode, us) ) ) {
+       if (!(us = BlobScan(&tdc->f, (origOffset >> 5)))
+           || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f, us))) {
            /* failed to setup nde, return what we've got, and release ode */
            if (len) {
                /* something to hand over. */
 #ifdef AFS_HPUX_ENV
-               sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
+               sdirEntry->d_fileno =
+                   (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
                FIXUPSTUPIDINODE(sdirEntry->d_fileno);
                sdirEntry->d_reclen = rlen = auio->afsio_resid;
                sdirEntry->d_namlen = o_slen;
 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
                sdirEntry->d_off = origOffset;
 #endif
-               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
+               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
+                           auio, code);
                if (code == 0)
                    AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
                /* pad out the remaining characters with zeros */
                if (code == 0) {
-                   AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
+                   AFS_UIOMOVE(bufofzeros,
+                               ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
+                               UIO_READ, auio, code);
                }
                /* pad out the difference between rlen and slen... */
                if (DIRSIZ_LEN(o_slen) < rlen) {
-                   while(DIRSIZ_LEN(o_slen) < rlen) {
+                   while (DIRSIZ_LEN(o_slen) < rlen) {
                        int minLen = rlen - DIRSIZ_LEN(o_slen);
                        if (minLen > sizeof(bufofzeros))
                            minLen = sizeof(bufofzeros);
@@ -593,7 +678,7 @@ tagain:
 #else
                code = afs_readdir_move(ode, avc, auio, o_slen,
 #if defined(AFS_SUN5_ENV)
-                                       len, origOffset);
+                                       len, origOffset);
 #else
                                        auio->afsio_resid, origOffset);
 #endif
@@ -604,10 +689,12 @@ tagain:
            } else {
                /* nothin to hand over */
            }
-#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
-       if (eofp) *eofp = 1;    /* Set it properly */
+#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+           if (eofp)
+               *eofp = 1;      /* Set it properly */
 #endif
-           if (ode) DRelease(ode, 0);
+           if (ode)
+               DRelease((struct buffer *)ode, 0);
            goto dirend;
        }
        /* by here nde is set */
@@ -619,33 +706,37 @@ tagain:
        n_slen = strlen(nde->name);
 #endif
 #ifdef AFS_SGI53_ENV
-        dirsiz = use64BitDirent ? DIRENTSIZE(n_slen) :
-           IRIX5_DIRENTSIZE(n_slen);
-       if (dirsiz >= (auio->afsio_resid-len)) {
+       dirsiz =
+           use64BitDirent ? DIRENTSIZE(n_slen) : IRIX5_DIRENTSIZE(n_slen);
+       if (dirsiz >= (auio->afsio_resid - len)) {
 #else
-       if (DIRSIZ_LEN(n_slen) >= (auio->afsio_resid-len)) {
+       if (DIRSIZ_LEN(n_slen) >= (auio->afsio_resid - len)) {
 #endif /* AFS_SGI53_ENV */
            /* No can do no more now; ya know... at this time */
-           DRelease (nde, 0); /* can't use this one. */
+           DRelease((struct buffer *)nde, 0);  /* can't use this one. */
            if (len) {
 #ifdef AFS_HPUX_ENV
-               sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
+               sdirEntry->d_fileno =
+                   (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
                FIXUPSTUPIDINODE(sdirEntry->d_fileno);
                sdirEntry->d_reclen = rlen = auio->afsio_resid;
                sdirEntry->d_namlen = o_slen;
 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
                sdirEntry->d_off = origOffset;
 #endif
-               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
+               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
+                           auio, code);
                if (code == 0)
                    AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
                /* pad out the remaining characters with zeros */
                if (code == 0) {
-                   AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
+                   AFS_UIOMOVE(bufofzeros,
+                               ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
+                               UIO_READ, auio, code);
                }
                /* pad out the difference between rlen and slen... */
                if (DIRSIZ_LEN(o_slen) < rlen) {
-                   while(DIRSIZ_LEN(o_slen) < rlen) {
+                   while (DIRSIZ_LEN(o_slen) < rlen) {
                        int minLen = rlen - DIRSIZ_LEN(o_slen);
                        if (minLen > sizeof(bufofzeros))
                            minLen = sizeof(bufofzeros);
@@ -654,21 +745,23 @@ tagain:
                    }
                }
 #else /* AFS_HPUX_ENV */
-               code = afs_readdir_move(ode, avc, auio, o_slen,
-                                       auio->afsio_resid, origOffset);
+               code =
+                   afs_readdir_move(ode, avc, auio, o_slen,
+                                    auio->afsio_resid, origOffset);
 #endif /* AFS_HPUX_ENV */
                /* this next line used to be AFSVFS40 or AIX 3.1, but is
                 * really generic */
                auio->afsio_offset = origOffset;
-               auio->afsio_resid = 0;  
-           } else { /* trouble, can't give anything to the user! */
+               auio->afsio_resid = 0;
+           } else {            /* trouble, can't give anything to the user! */
                /* even though he has given us a buffer, 
                 * even though we have something to give us,
                 * Looks like we lost something somewhere.
                 */
                code = EINVAL;
            }
-           if (ode) DRelease(ode, 0);
+           if (ode)
+               DRelease((struct buffer *)ode, 0);
            goto dirend;
        }
 
@@ -686,18 +779,19 @@ tagain:
 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
            sdirEntry->d_off = origOffset;
 #endif
-           AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
-                       auio, code);
+           AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
+                       code);
            if (code == 0)
                AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
            /* pad out the remaining characters with zeros */
            if (code == 0) {
-               AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen,
+               AFS_UIOMOVE(bufofzeros,
+                           ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
                            UIO_READ, auio, code);
            }
            /* pad out the difference between rlen and slen... */
            if (DIRSIZ_LEN(o_slen) < rlen) {
-               while(DIRSIZ_LEN(o_slen) < rlen) {
+               while (DIRSIZ_LEN(o_slen) < rlen) {
                    int minLen = rlen - DIRSIZ_LEN(o_slen);
                    if (minLen > sizeof(bufofzeros))
                        minLen = sizeof(bufofzeros);
@@ -706,29 +800,35 @@ tagain:
                }
            }
 #else /* AFS_HPUX_ENV */
-           code = afs_readdir_move (ode, avc, auio, o_slen, len, origOffset);
+           code = afs_readdir_move(ode, avc, auio, o_slen, len, origOffset);
 #endif /* AFS_HPUX_ENV */
        }
 #ifdef AFS_SGI53_ENV
-        len = use64BitDirent ? DIRENTSIZE(o_slen = n_slen) :
-           IRIX5_DIRENTSIZE(o_slen = n_slen);
+       len = use64BitDirent ? DIRENTSIZE(o_slen =
+                                         n_slen) : IRIX5_DIRENTSIZE(o_slen =
+                                                                    n_slen);
 #else
-       len = DIRSIZ_LEN( o_slen = n_slen );
+       len = DIRSIZ_LEN(o_slen = n_slen);
 #endif /* AFS_SGI53_ENV */
-       if (ode) DRelease(ode, 0);
+       if (ode)
+           DRelease((struct buffer *)ode, 0);
        ode = nde;
-       auio->afsio_offset = (afs_int32)((us + afs_dir_NameBlobs(nde->name)) << 5);
+       auio->afsio_offset =
+           (afs_int32) ((us + afs_dir_NameBlobs(nde->name)) << 5);
     }
-    if (ode) DRelease(ode, 0);
+    if (ode)
+       DRelease((struct buffer *)ode, 0);
 
-dirend:
+  dirend:
+    ReleaseReadLock(&tdc->lock);
     afs_PutDCache(tdc);
     ReleaseReadLock(&avc->lock);
 
-done:
+  done:
 #ifdef AFS_HPUX_ENV
     osi_FreeSmallSpace((char *)sdirEntry);
 #endif
+    afs_PutFakeStat(&fakestate);
     code = afs_CheckCode(code, &treq, 28);
     return code;
 }
@@ -736,16 +836,17 @@ done:
 #if    defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
 #ifdef AFS_OSF_ENV
 afs1_readdir(avc, auio, acred, eofp)
-    int *eofp;
+     int *eofp;
 #else
 afs1_readdir(avc, auio, acred)
 #endif
-    register struct vcache *avc;
-    struct uio *auio;
-    struct AFS_UCRED *acred; {
+     struct vcache *avc;
+     struct uio *auio;
+     struct AFS_UCRED *acred;
+{
     struct vrequest treq;
     register struct dcache *tdc;
-    afs_int32 origOffset, len;
+    afs_size_t origOffset, len;
     int code = 0;
     struct DirEntry *ode = 0, *nde = 0;
     int o_slen = 0, n_slen = 0;
@@ -756,13 +857,16 @@ afs1_readdir(avc, auio, acred)
      * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
      * translator side XXX
      */
-    struct minnfs_direct *sdirEntry = (struct minnfs_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
+    struct minnfs_direct *sdirEntry = (struct minnfs_direct *)
+       osi_AllocSmallSpace(sizeof(struct min_direct));
     afs_int32 rlen;
 #endif
+    struct afs_fakestat_state fakestate;
 
     AFS_STATCNT(afs_readdir);
 #if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
-    if (eofp) *eofp = 0;
+    if (eofp)
+       *eofp = 0;
 #endif
     if (code = afs_InitReq(&treq, acred)) {
 #ifdef AFS_HPUX_ENV
@@ -770,17 +874,28 @@ afs1_readdir(avc, auio, acred)
 #endif
        return code;
     }
+    afs_InitFakeStat(&fakestate);
+    code = afs_EvalFakeStat(&avc, &fakestate, &treq);
+    if (code) {
+#ifdef AFS_HPUX_ENV
+       osi_FreeSmallSpace((char *)sdirEntry);
+#endif
+       afs_PutFakeStat(&fakestate);
+       return code;
+    }
     /* update the cache entry */
-tagain:
+  tagain:
     code = afs_VerifyVCache(avc, &treq);
-    if (code) goto done;
+    if (code)
+       goto done;
     /* get a reference to the entire directory */
-    tdc = afs_GetDCache(avc, 0, &treq, &origOffset, &len, 1);
+    tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &len, 1);
     if (!tdc) {
        code = ENOENT;
        goto done;
     }
     ObtainReadLock(&avc->lock);
+    ObtainReadLock(&tdc->lock);
 
     /*
      * Make sure that the data in the cache is current. There are two
@@ -789,15 +904,20 @@ tagain:
      * 2. The cache data is no longer valid
      */
     while ((avc->states & CStatd)
-          && (tdc->flags & DFFetching)
+          && (tdc->dflags & DFFetching)
           && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
-       tdc->flags |= DFWaiting;
+       afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
+                  __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
+                  ICL_TYPE_INT32, tdc->dflags);
+       ReleaseReadLock(&tdc->lock);
        ReleaseReadLock(&avc->lock);
        afs_osi_Sleep(&tdc->validPos);
        ObtainReadLock(&avc->lock);
+       ObtainReadLock(&tdc->lock);
     }
     if (!(avc->states & CStatd)
        || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
+       ReleaseReadLock(&tdc->lock);
        ReleaseReadLock(&avc->lock);
        afs_PutDCache(tdc);
        goto tagain;
@@ -807,34 +927,38 @@ tagain:
 #ifdef AFS_HPUX_ENV
     auio->uio_fpflags = 0;
 #endif
-    while (code==0) {
+    while (code == 0) {
        origOffset = auio->afsio_offset;
 
        /* scan for the next interesting entry scan for in-use blob otherwise up point at
         * this blob note that ode, if non-zero, also represents a held dir page */
-       if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)) )
-           || !(nde = (struct DirEntry *) afs_dir_GetBlob(&tdc->f.inode, us) ) ) {
+       if (!(us = BlobScan(&tdc->f, (origOffset >> 5)))
+           || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f, us))) {
            /* failed to setup nde, return what we've got, and release ode */
            if (len) {
                /* something to hand over. */
 #if    defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
-               sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
+               sdirEntry->d_fileno =
+                   (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
                FIXUPSTUPIDINODE(sdirEntry->d_fileno);
                sdirEntry->d_reclen = rlen = auio->afsio_resid;
                sdirEntry->d_namlen = o_slen;
                sdirEntry->d_off = origOffset;
-               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
+               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
+                           auio, code);
                if (code == 0) {
                    AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
                }
                /* pad out the remaining characters with zeros */
                if (code == 0) {
-                   AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
+                   AFS_UIOMOVE(bufofzeros,
+                               ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
+                               UIO_READ, auio, code);
                }
                /* pad out the difference between rlen and slen... */
                if (NDIRSIZ_LEN(o_slen) < rlen) {
-                   while(NDIRSIZ_LEN(o_slen) < rlen) {
-                       int minLen = rlen - NDIRSIZ_LEN(o_slen);
+                   while (NDIRSIZ_LEN(o_slen) < rlen) {
+                       int minLen = rlen - NDIRSIZ_LEN(o_slen);
                        if (minLen > sizeof(bufofzeros))
                            minLen = sizeof(bufofzeros);
                        AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
@@ -842,17 +966,20 @@ tagain:
                    }
                }
 #else
-               code = afs_readdir_move(ode, avc, auio, o_slen,
-                                       auio->afsio_resid, origOffset);
+               code =
+                   afs_readdir_move(ode, avc, auio, o_slen,
+                                    auio->afsio_resid, origOffset);
 #endif /* AFS_HPUX_ENV */
-               auio->afsio_resid = 0;  
+               auio->afsio_resid = 0;
            } else {
                /* nothin to hand over */
            }
 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
-       if (eofp) *eofp = 1;
+           if (eofp)
+               *eofp = 1;
 #endif
-       if (ode) DRelease(ode, 0);
+           if (ode)
+               DRelease(ode, 0);
            goto dirend;
        }
        /* by here nde is set */
@@ -863,26 +990,30 @@ tagain:
 #else
        n_slen = strlen(nde->name);
 #endif
-       if (NDIRSIZ_LEN(n_slen) >= (auio->afsio_resid-len)) {
+       if (NDIRSIZ_LEN(n_slen) >= (auio->afsio_resid - len)) {
            /* No can do no more now; ya know... at this time */
-           DRelease (nde, 0); /* can't use this one. */
+           DRelease(nde, 0);   /* can't use this one. */
            if (len) {
 #if    defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
-               sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
+               sdirEntry->d_fileno =
+                   (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
                FIXUPSTUPIDINODE(sdirEntry->d_fileno);
                sdirEntry->d_reclen = rlen = auio->afsio_resid;
                sdirEntry->d_namlen = o_slen;
                sdirEntry->d_off = origOffset;
-               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
+               AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
+                           auio, code);
                if (code == 0)
                    AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
                /* pad out the remaining characters with zeros */
                if (code == 0) {
-                   AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
+                   AFS_UIOMOVE(bufofzeros,
+                               ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
+                               UIO_READ, auio, code);
                }
                /* pad out the difference between rlen and slen... */
                if (NDIRSIZ_LEN(o_slen) < rlen) {
-                   while(NDIRSIZ_LEN(o_slen) < rlen) {
+                   while (NDIRSIZ_LEN(o_slen) < rlen) {
                        int minLen = rlen - NDIRSIZ_LEN(o_slen);
                        if (minLen > sizeof(bufofzeros))
                            minLen = sizeof(bufofzeros);
@@ -891,20 +1022,22 @@ tagain:
                    }
                }
 #else
-               code = afs_readdir_move(ode, avc, auio, o_slen,
-                               auio->afsio_resid, origOffset);
+               code =
+                   afs_readdir_move(ode, avc, auio, o_slen,
+                                    auio->afsio_resid, origOffset);
 #endif /* AFS_HPUX_ENV */
                /* this next line used to be AFSVFS40 or AIX 3.1, but is really generic */
                auio->afsio_offset = origOffset;
-               auio->afsio_resid = 0;  
-           } else { /* trouble, can't give anything to the user! */
+               auio->afsio_resid = 0;
+           } else {            /* trouble, can't give anything to the user! */
                /* even though he has given us a buffer, 
                 * even though we have something to give us,
                 * Looks like we lost something somewhere.
                 */
                code = EINVAL;
            }
-           if (ode) DRelease(ode, 0);
+           if (ode)
+               DRelease(ode, 0);
            goto dirend;
        }
 
@@ -914,21 +1047,25 @@ tagain:
         */
        if (len) {
 #if    defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
-           sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
+           sdirEntry->d_fileno =
+               (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
            FIXUPSTUPIDINODE(sdirEntry->d_fileno);
            sdirEntry->d_reclen = rlen = len;
            sdirEntry->d_namlen = o_slen;
            sdirEntry->d_off = origOffset;
-           AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
+           AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
+                       code);
            if (code == 0)
                AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
            /* pad out the remaining characters with zeros */
            if (code == 0) {
-               AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
+               AFS_UIOMOVE(bufofzeros,
+                           ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
+                           UIO_READ, auio, code);
            }
            /* pad out the difference between rlen and slen... */
            if (NDIRSIZ_LEN(o_slen) < rlen) {
-               while(NDIRSIZ_LEN(o_slen) < rlen) {
+               while (NDIRSIZ_LEN(o_slen) < rlen) {
                    int minLen = rlen - NDIRSIZ_LEN(o_slen);
                    if (minLen > sizeof(bufofzeros))
                        minLen = sizeof(bufofzeros);
@@ -937,24 +1074,28 @@ tagain:
                }
            }
 #else
-           code = afs_readdir_move (ode, avc, auio, o_slen, len, origOffset);
+           code = afs_readdir_move(ode, avc, auio, o_slen, len, origOffset);
 #endif /* AFS_HPUX_ENV */
        }
-       len = NDIRSIZ_LEN( o_slen = n_slen );
-       if (ode) DRelease(ode, 0);
+       len = NDIRSIZ_LEN(o_slen = n_slen);
+       if (ode)
+           DRelease(ode, 0);
        ode = nde;
        auio->afsio_offset = ((us + afs_dir_NameBlobs(nde->name)) << 5);
     }
-    if (ode) DRelease(ode, 0);
+    if (ode)
+       DRelease(ode, 0);
 
-dirend:
+  dirend:
+    ReleaseReadLock(&tdc->lock);
     afs_PutDCache(tdc);
     ReleaseReadLock(&avc->lock);
 
-done:
+  done:
 #if    defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
     osi_FreeSmallSpace((char *)sdirEntry);
 #endif
+    afs_PutFakeStat(&fakestate);
     code = afs_CheckCode(code, &treq, 29);
     return code;
 }