dread-do-validation-20041012
[openafs.git] / src / afs / VNOPS / afs_vnop_lookup.c
index e9d760a..8add8d8 100644 (file)
@@ -64,11 +64,11 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
     struct volume *tvp = 0;
     struct VenusFid tfid;
     struct cell *tcell;
-    char   *cpos, *volnamep;
-    char   type, *buf;
-    afs_int32  prefetch;          /* 1=>None  2=>RO  3=>BK */
-    afs_int32  mtptCell, assocCell, hac = 0;
-    afs_int32  samecell, roname, len;
+    char *cpos, *volnamep;
+    char type, *buf;
+    afs_int32 prefetch;                /* 1=>None  2=>RO  3=>BK */
+    afs_int32 mtptCell, assocCell, hac = 0;
+    afs_int32 samecell, roname, len;
 
     AFS_STATCNT(EvalMountPoint);
 #ifdef notdef
@@ -121,14 +121,14 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
      *   want to prefetch the RO volume.
      */
     if ((type == '#') && !roname) {
-       if (afs_bkvolpref && samecell && (avc->states & CBackup))
-           prefetch = 3; /* Prefetch the BK */
-       else if (!samecell || (avc->states & CRO))
-           prefetch = 2; /* Prefetch the RO */
-       else
-           prefetch = 1; /* Do not prefetch */
+       if (afs_bkvolpref && samecell && (avc->states & CBackup))
+           prefetch = 3;       /* Prefetch the BK */
+       else if (!samecell || (avc->states & CRO))
+           prefetch = 2;       /* Prefetch the RO */
+       else
+           prefetch = 1;       /* Do not prefetch */
     } else {
-       prefetch = 1; /* Do not prefetch */
+       prefetch = 1;           /* Do not prefetch */
     }
 
     /* Get the volume struct. Unless this volume name has ".readonly" or
@@ -139,7 +139,7 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
 
     /* If no volume was found in this cell, try the associated linked cell */
     if (!tvp && hac && areq->volumeError) {
-       tvp =
+       tvp =
            afs_GetVolumeByName(volnamep, assocCell, prefetch, areq,
                                WRITE_LOCK);
     }
@@ -148,8 +148,8 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
      * doesn't exist? Try adding ".readonly" to volname and look for that.
      * Don't know why we do this. Would have still found it in above call - jpm.
      */
-    if (!tvp && (prefetch == 2)) {
-       buf = (char *)osi_AllocSmallSpace(strlen(volnamep) + 10);
+    if (!tvp && (prefetch == 2) && len < AFS_SMALLOCSIZ - 10) {
+       buf = (char *)osi_AllocSmallSpace(len + 10);
 
        strcpy(buf, volnamep);
        afs_strcat(buf, ".readonly");
@@ -191,7 +191,7 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
        afs_PutVolume(tvp, WRITE_LOCK); /* release old volume */
        tvp = afs_GetVolume(&tfid, areq, WRITE_LOCK);   /* get the new one */
        if (!tvp)
-          return ENODEV;       /* oops, can't do it */
+           return ENODEV;      /* oops, can't do it */
     }
 
     if (avc->mvid == 0)
@@ -400,40 +400,50 @@ 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,
+Check_AtSys(register struct vcache *avc, 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;
@@ -446,42 +456,71 @@ 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)[state->index])
+           return 0;           /* end of list */
+    }
+    strcpy(state->name + state->offset, (*sysnamelist)[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
 
 
 /* called with an unlocked directory and directory cookie.  Areqp
@@ -541,13 +580,13 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     struct VenusFid dotdot;
     int flagIndex;             /* 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)
@@ -635,7 +674,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->f, (dirCookie >> 5));
        if (newIndex == 0)
            break;
 
@@ -644,7 +683,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->f, newIndex);
        if (!dirEntryp)
            break;
 
@@ -1075,7 +1114,7 @@ afs_lookup(adp, aname, avcp, acred, flags)
 afs_lookup(adp, aname, avcp, acred)
 #endif                         /* UKERNEL */
 #endif                         /* SUN5 || SGI */
-OSI_VC_DECL(adp);
+     OSI_VC_DECL(adp);
      struct vcache **avcp;
      char *aname;
      struct AFS_UCRED *acred;
@@ -1089,13 +1128,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);
@@ -1254,7 +1293,7 @@ OSI_VC_DECL(adp);
     {                          /* sub-block just to reduce stack usage */
        register struct dcache *tdc;
        afs_size_t dirOffset, dirLen;
-       ino_t theDir;
+       struct fcache *theDir;
        struct VenusFid tfid;
 
        /* now we have to lookup the next fid */
@@ -1291,6 +1330,8 @@ OSI_VC_DECL(adp);
            ReleaseReadLock(&tdc->lock);
            ReleaseReadLock(&adp->lock);
            afs_PutDCache(tdc);
+           if (tname && tname != aname)
+               osi_FreeLargeSpace(tname);
            goto redo;
        }
 
@@ -1310,15 +1351,15 @@ OSI_VC_DECL(adp);
 
        /* lookup the name in the appropriate dir, and return a cache entry
         * on the resulting fid */
-       theDir = tdc->f.inode;
+       theDir = &tdc->f;
        code =
-           afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
+           afs_dir_LookupOffset(theDir, 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(theDir, sysState.name, &tfid.Fid,
                                     &dirCookie);
        tname = sysState.name;