avoid-leaking-stat-info-20050424
[openafs.git] / src / afs / VNOPS / afs_vnop_lookup.c
index f377ea6..c82496a 100644 (file)
@@ -67,7 +67,7 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
     char *cpos, *volnamep;
     char type, *buf;
     afs_int32 prefetch;                /* 1=>None  2=>RO  3=>BK */
-    afs_int32 mtptCell, assocCell, hac = 0;
+    afs_int32 mtptCell, assocCell = 0, hac = 0;
     afs_int32 samecell, roname, len;
 
     AFS_STATCNT(EvalMountPoint);
@@ -400,45 +400,55 @@ afs_ENameOK(register char *aname)
     return 1;
 }
 
-int
+static int
 afs_getsysname(register struct vrequest *areq, register struct vcache *adp,
-              register char *bufp)
+              register char *bufp, int *num, char **sysnamelist[])
 {
     register struct unixuser *au;
     register afs_int32 error;
 
-    if (!afs_nfsexporter) {
-       strcpy(bufp, afs_sysname);
-       return 0;
-    }
     AFS_STATCNT(getsysname);
-    au = afs_GetUser(areq->uid, adp->fid.Cell, 0);
-    afs_PutUser(au, 0);
-    if (au->exporter) {
-       error = EXP_SYSNAME(au->exporter, NULL, bufp);
-       if (error)
-           strcpy(bufp, "@sys");
-       return -1;
-    } else {
-       strcpy(bufp, afs_sysname);
-       return 0;
+
+    *sysnamelist = afs_sysnamelist;
+
+    if (!afs_nfsexporter)
+       strcpy(bufp, (*sysnamelist)[0]);
+    else {
+       au = afs_GetUser(areq->uid, adp->fid.Cell, 0);
+       if (au->exporter) {
+           error = EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num);
+           if (error) {
+               strcpy(bufp, "@sys");
+               afs_PutUser(au, 0);
+               return -1;
+           } else {
+               strcpy(bufp, (*sysnamelist)[0]);
+           }
+       } else
+           strcpy(bufp, afs_sysname);
+       afs_PutUser(au, 0);
     }
+    return 0;
 }
 
 void
 Check_AtSys(register struct vcache *avc, const char *aname,
            struct sysname_info *state, struct vrequest *areq)
 {
+    int num = 0;
+    char **sysnamelist[MAXSYSNAME];
+
     if (AFS_EQ_ATSYS(aname)) {
        state->offset = 0;
        state->name = (char *)osi_AllocLargeSpace(AFS_SMALLOCSIZ);
        state->allocked = 1;
-       state->index = afs_getsysname(areq, avc, state->name);
+       state->index =
+           afs_getsysname(areq, avc, state->name, &num, sysnamelist);
     } else {
        state->offset = -1;
        state->allocked = 0;
        state->index = 0;
-       state->name = aname;
+       state->name = (char *)aname;
     }
 }
 
@@ -446,48 +456,58 @@ int
 Next_AtSys(register struct vcache *avc, struct vrequest *areq,
           struct sysname_info *state)
 {
+    int num = afs_sysnamecount;
+    char **sysnamelist[MAXSYSNAME];
+
     if (state->index == -1)
        return 0;               /* No list */
 
     /* Check for the initial state of aname != "@sys" in Check_AtSys */
     if (state->offset == -1 && state->allocked == 0) {
        register char *tname;
+
        /* Check for .*@sys */
        for (tname = state->name; *tname; tname++)
            /*Move to the end of the string */ ;
+
        if ((tname > state->name + 4) && (AFS_EQ_ATSYS(tname - 4))) {
            state->offset = (tname - 4) - state->name;
            tname = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
            strncpy(tname, state->name, state->offset);
            state->name = tname;
            state->allocked = 1;
+           num = 0;
            state->index =
-               afs_getsysname(areq, avc, state->name + state->offset);
+               afs_getsysname(areq, avc, state->name + state->offset, &num,
+                              sysnamelist);
            return 1;
        } else
            return 0;           /* .*@sys doesn't match either */
-    } else if (++(state->index) >= afs_sysnamecount
-              || !afs_sysnamelist[(int)state->index])
-       return 0;               /* end of list */
-    strcpy(state->name + state->offset, afs_sysnamelist[(int)state->index]);
+    } else {
+       register struct unixuser *au;
+       register afs_int32 error;
+
+       *sysnamelist = afs_sysnamelist;
+
+       if (afs_nfsexporter) {
+           au = afs_GetUser(areq->uid, avc->fid.Cell, 0);
+           if (au->exporter) {
+               error =
+                   EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num);
+               if (error) {
+                   return 0;
+               }
+           }
+           afs_PutUser(au, 0);
+       }
+       if (++(state->index) >= num || !(*sysnamelist)[(unsigned int)state->index])
+           return 0;           /* end of list */
+    }
+    strcpy(state->name + state->offset, (*sysnamelist)[(unsigned int)state->index]);
     return 1;
 }
 
-#if (defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV))
-extern int BlobScan(ino64_t * afile, afs_int32 ablob);
-#else
-#if defined(AFS_HPUX1123_ENV)
-/* DEE should use the new afs_inode_t  for all */
-extern int BlobScan(ino_t *afile, afs_int32 ablob);
-#else
-#if defined AFS_LINUX_64BIT_KERNEL
-extern int BlobScan(long *afile, afs_int32 ablob);
-#else
-extern int BlobScan(afs_int32 * afile, afs_int32 ablob);
-#endif
-#endif
-#endif
-
+extern int BlobScan(struct dcache * afile, afs_int32 ablob);
 
 /* called with an unlocked directory and directory cookie.  Areqp
  * describes who is making the call.
@@ -526,14 +546,14 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     struct afs_q *tq;          /* temp queue variable */
     AFSCBFids fidParm;         /* file ID parm for bulk stat */
     AFSBulkStats statParm;     /* stat info parm for bulk stat */
-    int fidIndex;              /* which file were stating */
-    struct conn *tcp;          /* conn for call */
+    int fidIndex = 0;          /* which file were stating */
+    struct conn *tcp = 0;      /* conn for call */
     AFSCBs cbParm;             /* callback parm for bulk stat */
     struct server *hostp = 0;  /* host we got callback from */
     long startTime;            /* time we started the call,
                                 * for callback expiration base
                                 */
-    afs_size_t statSeqNo;      /* Valued of file size to detect races */
+    afs_size_t statSeqNo = 0;  /* Valued of file size to detect races */
     int code;                  /* error code */
     long newIndex;             /* new index in the dir */
     struct DirEntry *dirEntryp;        /* dir entry we are examining */
@@ -544,15 +564,15 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     long volStates;            /* flags from vol structure */
     struct volume *volp = 0;   /* volume ptr */
     struct VenusFid dotdot;
-    int flagIndex;             /* First file with bulk fetch flag set */
+    int flagIndex = 0;         /* First file with bulk fetch flag set */
     int inlinebulk = 0;                /* Did we use InlineBulk RPC or not? */
-    XSTATS_DECLS
-       /* first compute some basic parameters.  We dont want to prefetch more
-        * than a fraction of the cache in any given call, and we want to preserve
-        * a portion of the LRU queue in any event, so as to avoid thrashing
-        * the entire stat cache (we will at least leave some of it alone).
-        * presently dont stat more than 1/8 the cache in any one call.      */
-       nentries = afs_cacheStats / 8;
+    XSTATS_DECLS;
+    /* first compute some basic parameters.  We dont want to prefetch more
+     * than a fraction of the cache in any given call, and we want to preserve
+     * a portion of the LRU queue in any event, so as to avoid thrashing
+     * the entire stat cache (we will at least leave some of it alone).
+     * presently dont stat more than 1/8 the cache in any one call.      */
+    nentries = afs_cacheStats / 8;
 
     /* dont bother prefetching more than one calls worth of info */
     if (nentries > AFSCBMAX)
@@ -586,12 +606,12 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
   tagain:
     code = afs_VerifyVCache(adp, areqp);
     if (code)
-       goto done;
+       goto done2;
 
     dcp = afs_GetDCache(adp, (afs_size_t) 0, areqp, &temp, &temp, 1);
     if (!dcp) {
        code = ENOENT;
-       goto done;
+       goto done2;
     }
 
     /* lock the directory cache entry */
@@ -640,7 +660,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
        /* look for first safe entry to examine in the directory.  BlobScan
         * looks for a the 1st allocated dir after the dirCookie slot.
         */
-       newIndex = BlobScan(&dcp->f.inode, (dirCookie >> 5));
+       newIndex = BlobScan(dcp, (dirCookie >> 5));
        if (newIndex == 0)
            break;
 
@@ -649,7 +669,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 
        /* get a ptr to the dir entry */
        dirEntryp =
-           (struct DirEntry *)afs_dir_GetBlob(&dcp->f.inode, newIndex);
+           (struct DirEntry *)afs_dir_GetBlob(dcp, newIndex);
        if (!dirEntryp)
            break;
 
@@ -1047,6 +1067,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     } else {
        code = 0;
     }
+  done2:
     osi_FreeLargeSpace(statMemp);
     osi_FreeLargeSpace(cbfMemp);
     return code;
@@ -1056,36 +1077,16 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 static int AFSDOBULK = 1;
 
 int
-#ifdef AFS_OSF_ENV
-afs_lookup(adp, ndp)
-     struct vcache *adp;
-     struct nameidata *ndp;
-{
-    char aname[MAXNAMLEN + 1]; /* XXX */
-    struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
-    struct ucred *acred = ndp->ni_cred;
-    int wantparent = ndp->ni_nameiop & WANTPARENT;
-    int opflag = ndp->ni_nameiop & OPFLAG;
-#else                          /* AFS_OSF_ENV */
-#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-afs_lookup(OSI_VC_ARG(adp), aname, avcp, pnp, flags, rdir, acred)
-     struct pathname *pnp;
-     int flags;
-     struct vnode *rdir;
-#else
-#if defined(UKERNEL)
-afs_lookup(adp, aname, avcp, acred, flags)
-     int flags;
+#ifdef AFS_OSF_ENV
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred, int opflag, int wantparent)
+#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct pathname *pnp, int flags, struct vnode *rdir, struct AFS_UCRED *acred)
+#elif defined(UKERNEL)
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred, int flags)
 #else
-afs_lookup(adp, aname, avcp, acred)
-#endif                         /* UKERNEL */
-#endif                         /* SUN5 || SGI */
-OSI_VC_DECL(adp);
-     struct vcache **avcp;
-     char *aname;
-     struct AFS_UCRED *acred;
-{
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred)
 #endif
+{
     struct vrequest treq;
     char *tname = NULL;
     register struct vcache *tvc = 0;
@@ -1094,13 +1095,13 @@ OSI_VC_DECL(adp);
     int pass = 0, hit = 0;
     long dirCookie;
     extern afs_int32 afs_mariner;      /*Writing activity to log? */
-    OSI_VC_CONVERT(adp)
     afs_hyper_t versionNo;
     int no_read_access = 0;
     struct sysname_info sysState;      /* used only for @sys checking */
     int dynrootRetry = 1;
     struct afs_fakestat_state fakestate;
     int tryEvalOnly = 0;
+    OSI_VC_CONVERT(adp);
 
     AFS_STATCNT(afs_lookup);
     afs_InitFakeStat(&fakestate);
@@ -1110,8 +1111,6 @@ OSI_VC_DECL(adp);
 
 #ifdef AFS_OSF_ENV
     ndp->ni_dvp = AFSTOV(adp);
-    memcpy(aname, ndp->ni_ptr, ndp->ni_namelen);
-    aname[ndp->ni_namelen] = '\0';
 #endif /* AFS_OSF_ENV */
 
 #if defined(AFS_DARWIN_ENV)
@@ -1199,7 +1198,7 @@ OSI_VC_DECL(adp);
 
     /* Check for read access as well.  We need read access in order to
      * stat files, but not to stat subdirectories. */
-    if (!afs_AccessOK(adp, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS))
+    if (!afs_AccessOK(adp, PRSFS_READ, &treq, CHECK_MODE_BITS))
        no_read_access = 1;
 
     /* special case lookup of ".".  Can we check for it sooner in this code,
@@ -1242,7 +1241,7 @@ OSI_VC_DECL(adp);
        }
 #ifdef AFS_LINUX22_ENV
        if (tvc->mvstat == 2) { /* we don't trust the dnlc for root vcaches */
-           AFS_RELE(tvc);
+           AFS_RELE(AFSTOV(tvc));
            *avcp = 0;
        } else {
            code = 0;
@@ -1259,7 +1258,6 @@ OSI_VC_DECL(adp);
     {                          /* sub-block just to reduce stack usage */
        register struct dcache *tdc;
        afs_size_t dirOffset, dirLen;
-       ino_t theDir;
        struct VenusFid tfid;
 
        /* now we have to lookup the next fid */
@@ -1317,15 +1315,14 @@ OSI_VC_DECL(adp);
 
        /* lookup the name in the appropriate dir, and return a cache entry
         * on the resulting fid */
-       theDir = tdc->f.inode;
        code =
-           afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
+           afs_dir_LookupOffset(tdc, sysState.name, &tfid.Fid,
                                 &dirCookie);
 
        /* If the first lookup doesn't succeed, maybe it's got @sys in the name */
        while (code == ENOENT && Next_AtSys(adp, &treq, &sysState))
            code =
-               afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
+               afs_dir_LookupOffset(tdc, sysState.name, &tfid.Fid,
                                     &dirCookie);
        tname = sysState.name;