[OpenAFS-devel] Corrected patch: enhancements for AFS web interface

Jeff Riegel riegel@almaden.ibm.com
Fri, 15 Jun 2001 17:37:15 -0700


Sorry for the code duplication of afs_lookup and uafs_LookupName in my
previous submission.  Here is a corrected patch (again, based on 5/1/2001
snapshot).

Jeff Riegel
riegel@almaden.ibm.com

diff -Nur --exclude-from=exclude orig-src/afs/UKERNEL/afs_usrops.c src/afs/UKERNEL/afs_usrops.c
--- orig-src/afs/UKERNEL/afs_usrops.c	Sat Apr 14 10:27:43 2001
+++ src/afs/UKERNEL/afs_usrops.c	Fri Jun 15 17:12:10 2001
@@ -637,7 +637,7 @@
     struct usr_inode *ip;
     struct usr_vnode *vp;
 
-    usr_assert(followlink == 0);
+    /*usr_assert(followlink == 0);*/
     usr_assert(dirvpp == NULL);
 
     /*
@@ -645,7 +645,7 @@
      */
     if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
 	AFS_GLOCK();
-	code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0);
+	code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
 	AFS_GUNLOCK();
 	return code;
     }
@@ -2174,7 +2174,8 @@
     char *path,
     struct usr_vnode *parentVp,
     struct usr_vnode **vpp,
-    int follow)
+    int follow,
+    int no_eval_mtpt)
 {
     int code;
     int linkCount;
@@ -2251,7 +2252,14 @@
 	     * subdirectory since we hold the global lock
 	     */
 	    nextVp = NULL;
-	    code = afs_lookup(vp, pathP, &nextVp, u.u_cred);
+#ifdef AFS_WEB_ENHANCEMENTS
+            if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
+              code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
+            else
+              code = afs_lookup(vp, pathP, &nextVp, u.u_cred, AFS_LOOKUP_NOEVAL);
+#else
+            code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
+#endif /* AFS_WEB_ENHANCEMENTS */
 	    if (code != 0) {
 		VN_RELE(vp);
 		afs_osi_Free(tmpPath, strlen(path)+1);
@@ -2353,7 +2361,7 @@
     /*
      * Find the target of the symbolic link
      */
-    code = uafs_LookupName(pathP, parentVp, &linkVp, 1);
+    code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
     if (code) {
 	afs_osi_Free(pathP, MAX_OSI_PATH+1);
 	return code;
@@ -2417,7 +2425,7 @@
     /*
      * look up the parent
      */
-    code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1);
+    code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
     afs_osi_Free(pathP, len);
     if (code != 0) {
 	return code;
@@ -2471,7 +2479,7 @@
     int code;
     struct vnode *dirP;
 
-    code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1);
+    code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
     if (code != 0) {
 	errno = code;
 	return -1;
@@ -2661,7 +2669,7 @@
 	    }
 	} else {
 	    fileP = NULL;
-	    code = uafs_LookupName(nameP, dirP, &fileP, 1);
+	    code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
 	    VN_RELE(dirP);
 	    if (code != 0) {
 		errno = code;
@@ -2678,6 +2686,7 @@
 	    if (flags & (O_WRONLY|O_RDWR)) {
 		fileMode |= VWRITE;
 	    }
+         if (!fileMode) fileMode = VREAD;  /* since O_RDONLY is 0 */
 	    code = afs_access(fileP, fileMode, u.u_cred);
 	    if (code != 0) {
 		VN_RELE(fileP);
@@ -2973,7 +2982,7 @@
     int code;
     struct vnode *vp;
 
-    code = uafs_LookupName(path, afs_CurrentDir, &vp, 1);
+    code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
     if (code != 0) {
 	errno = code;
 	return -1;
@@ -3008,7 +3017,7 @@
     int code;
     struct vnode *vp;
 
-    code = uafs_LookupName(path, afs_CurrentDir, &vp, 0);
+    code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
     if (code != 0) {
 	errno = code;
 	return -1;
@@ -3079,7 +3088,7 @@
     struct vnode *vp;
     struct usr_vattr attrs;
 
-    code = uafs_LookupName(path, afs_CurrentDir, &vp, 1);
+    code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
     if (code != 0) {
 	errno = code;
 	return -1;
@@ -3154,7 +3163,7 @@
     struct vnode *vp;
     struct usr_vattr attrs;
 
-    code = uafs_LookupName(path, afs_CurrentDir, &vp, 1);
+    code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
     if (code != 0) {
 	errno = code;
 	return -1;
@@ -3366,7 +3375,7 @@
     /*
      * Look up the existing node.
      */
-    code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1);
+    code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
     if (code != 0) {
 	errno = code;
 	return -1;
@@ -3507,7 +3516,7 @@
     struct usr_uio uio;
     struct iovec iov[1];
 
-    code = uafs_LookupName(path, afs_CurrentDir, &vp, 0);
+    code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
     if (code != 0) {
 	errno = code;
 	return -1;
@@ -3807,6 +3816,7 @@
     char *path)
 {
     usr_DIR *dirp;
+    struct usr_vnode *fileP;
     int fd;
 
     /*
@@ -3817,6 +3827,17 @@
 	return NULL;
     }
 
+    fileP = afs_FileTable[fd];
+    if (fileP == NULL) {
+     return NULL;
+    }
+
+    if (fileP->v_type != VDIR) {
+      uafs_close_r(fd);
+      errno = ENOTDIR;
+      return NULL;
+    }
+
     /*
      * Set up the directory structures
      */
@@ -4106,5 +4127,187 @@
     }
     return NULL;
 }
+
+#ifdef AFS_WEB_ENHANCEMENTS
+/*
+ * uafs_klog_nopag
+ * klog but don't allocate a new pag
+ */
+int uafs_klog_nopag(
+    char *user,
+    char *cell,
+    char *passwd,
+    char **reason)
+{
+    int code;
+    afs_int32 password_expires = -1;
+
+    usr_mutex_lock(&osi_authenticate_lock);
+    code = ka_UserAuthenticateGeneral(
+      KA_USERAUTH_VERSION  /*+KA_USERAUTH_DOSETPAG2*/, user,
+          NULL, cell, passwd, 0, &password_expires,
+          0, reason);
+    usr_mutex_unlock(&osi_authenticate_lock);
+    return code;
+}
+
+/*
+ * uafs_getcellstatus
+ * get the cell status
+ */
+int uafs_getcellstatus(char *cell, afs_int32 *status)
+{
+  int rc;
+  struct afs_ioctl iob;
+
+  iob.in = cell;
+  iob.in_size = strlen(cell)+1;
+  iob.out = 0;
+  iob.out_size = 0;
+
+  rc = call_syscall(AFSCALL_PIOCTL, /*path*/0, _VICEIOCTL(35),
+                      (long)&iob, 0, 0);
+
+  if (rc < 0) {
+    errno = rc;
+    return -1;
+  }
+
+  *status = iob.out;
+  return 0;
+}
+
+/*
+ * uafs_getvolquota
+ * Get quota of volume associated with path
+ */
+int uafs_getvolquota(char *path, afs_int32 *BlocksInUse, afs_int32 *MaxQuota)
+{
+  int rc;
+  struct afs_ioctl iob;
+  VolumeStatus *status;
+  char buf[1024];
+
+  iob.in = 0;
+  iob.in_size = 0;
+  iob.out = buf;
+  iob.out_size = 1024;
+
+  rc = call_syscall(AFSCALL_PIOCTL, path, _VICEIOCTL(4),
+                      (long)&iob, 0, 0);
+
+  if (rc != 0) {
+    errno = rc;
+    return -1;
+  }
+
+  status = (VolumeStatus *) buf;
+  *BlocksInUse = status->BlocksInUse;
+  *MaxQuota = status->MaxQuota;
+  return 0;
+}
+
+/*
+ * uafs_setvolquota
+ * Set quota of volume associated with path
+ */
+int uafs_setvolquota(char *path, afs_int32 MaxQuota)
+{
+  int rc;
+  struct afs_ioctl iob;
+  VolumeStatus *status;
+  char buf[1024];
+
+  iob.in = buf;
+  iob.in_size = 1024;
+  iob.out = 0;
+  iob.out_size = 0;
+
+  memset(buf, 0, sizeof(VolumeStatus));
+  status = (VolumeStatus *) buf;
+  status->MaxQuota = MaxQuota;
+  status->MinQuota = -1;
+
+  rc = call_syscall(AFSCALL_PIOCTL, path, _VICEIOCTL(5),
+                      (long)&iob, 0, 0);
+
+  if (rc != 0) {
+    errno = rc;
+    return -1;
+  }
+
+  return 0;
+}
+
+/*
+ * uafs_statmountpoint
+ * Determine whether a dir. is a mount point or not
+ * return 1 if mount point, 0 if not
+ */
+int uafs_statmountpoint(char *path)
+{
+    int retval;
+    int code;
+    char buf[256];
+
+    AFS_GLOCK();
+    retval = uafs_statmountpoint_r(path);
+    AFS_GUNLOCK();
+    return retval;
+}
+
+int uafs_statmountpoint_r(char *path)
+{
+    int code;
+    struct vnode *vp;
+    struct vcache *avc;
+    struct vrequest treq;
+    int r;
+
+    code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
+    if (code != 0) {
+     errno = code;
+     return -1;
+    }
+
+    avc = (struct vcache *) vp;
+
+    r = avc->mvstat;
+    VN_RELE(vp);
+    return r;
+}
+
+/*
+ * uafs_getRights
+ * Get a list of rights for the current user on path.
+ */
+int uafs_getRights(char *path)
+{
+    int code, rc;
+    struct vnode *vp;
+    int afs_rights;
+
+    AFS_GLOCK();
+    code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
+    if (code != 0) {
+     errno = code;
+     AFS_GUNLOCK();
+     return -1;
+    }
+
+    afs_rights = PRSFS_READ |
+      PRSFS_WRITE |
+      PRSFS_INSERT |
+      PRSFS_LOOKUP |
+      PRSFS_DELETE |
+      PRSFS_LOCK |
+      PRSFS_ADMINISTER;
+
+    afs_rights = afs_getRights (vp, afs_rights, u.u_cred);
+
+    AFS_GUNLOCK();
+    return afs_rights;
+}
+#endif /* AFS_WEB_ENHANCEMENTS */
 
 #endif /* UKERNEL */
diff -Nur --exclude-from=exclude orig-src/afs/UKERNEL/afs_usrops.h src/afs/UKERNEL/afs_usrops.h
--- orig-src/afs/UKERNEL/afs_usrops.h	Sat Nov  4 02:03:29 2000
+++ src/afs/UKERNEL/afs_usrops.h	Thu Jun 14 20:15:52 2001
@@ -74,7 +74,8 @@
 extern int uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentP,
 			   struct usr_vnode **vpp);
 extern int uafs_LookupName(char *path, struct usr_vnode *parentP,
-			   struct usr_vnode **vpp, int follow);
+			   struct usr_vnode **vpp, int follow,
+                           int no_eval_mtpt);
 extern int uafs_LookupParent(char *path, struct usr_vnode **vpp);
 extern int uafs_GetAttr(struct usr_vnode *vp, struct stat *stats);
 
diff -Nur --exclude-from=exclude orig-src/afs/UKERNEL/sysincludes.h src/afs/UKERNEL/sysincludes.h
--- orig-src/afs/UKERNEL/sysincludes.h	Sat Apr 14 10:27:44 2001
+++ src/afs/UKERNEL/sysincludes.h	Thu Jun 14 19:42:36 2001
@@ -932,6 +932,8 @@
 #define usr_cond_signal(A)	assert(pthread_cond_signal(A) == 0)
 #define usr_cond_broadcast(A)	assert(pthread_cond_broadcast(A) == 0)
 #define usr_cond_wait(A,B)	pthread_cond_wait(A,B)
+#define usr_cond_timedwait(A,B,C)  pthread_cond_timedwait(A,B,C)
+
 #define usr_thread_create(A,B,C) \
     do { \
 	pthread_attr_t attr; \
@@ -1377,5 +1379,7 @@
 } usr_DIR;
 
 extern unsigned short usr_rx_port;
+
+#define AFS_LOOKUP_NOEVAL 1
 
 #endif /* __AFS_SYSINCLUDESH__  so idempotent */
diff -Nur --exclude-from=exclude orig-src/afs/VNOPS/afs_vnop_access.c src/afs/VNOPS/afs_vnop_access.c
--- orig-src/afs/VNOPS/afs_vnop_access.c	Sat Nov  4 02:03:29 2000
+++ src/afs/VNOPS/afs_vnop_access.c	Wed Jun 13 17:28:21 2001
@@ -273,3 +273,28 @@
     }
 }
 
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+/*
+ * afs_getRights
+ * This function is just an interface to afs_GetAccessBits
+ */
+int afs_getRights(OSI_VC_ARG(avc), arights, acred)
+    OSI_VC_DECL(avc);
+    register afs_int32 arights;
+    struct AFS_UCRED *acred;
+{
+    register afs_int32 code;
+    struct vrequest treq;
+    OSI_VC_CONVERT(avc)
+
+    if (code = afs_InitReq(&treq, acred)) return code;
+
+    code = afs_VerifyVCache(avc, &treq);
+    if (code) {
+      code = afs_CheckCode(code, &treq, 16);
+      return code; 
+    }
+
+    return afs_GetAccessBits(avc, arights, &treq);
+}
+#endif /* defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) */
diff -Nur --exclude-from=exclude orig-src/afs/VNOPS/afs_vnop_create.c src/afs/VNOPS/afs_vnop_create.c
--- orig-src/afs/VNOPS/afs_vnop_create.c	Mon Mar 26 23:06:38 2001
+++ src/afs/VNOPS/afs_vnop_create.c	Fri Jun  1 20:04:30 2001
@@ -177,6 +177,10 @@
 		if ((amode & VWRITE) || len != 0xffffffff) 
 #endif
 		  {
+              /* these lines are needed for write access check */
+              tvc->parentVnode = adp->fid.Fid.Vnode;
+              tvc->parentUnique = adp->fid.Fid.Unique;
+
 		    /* need write mode for these guys */
 		    if (!afs_AccessOK(tvc, PRSFS_WRITE, &treq, CHECK_MODE_BITS)) {
 			afs_PutVCache(tvc, READ_LOCK);
diff -Nur --exclude-from=exclude orig-src/afs/VNOPS/afs_vnop_lookup.c src/afs/VNOPS/afs_vnop_lookup.c
--- orig-src/afs/VNOPS/afs_vnop_lookup.c	Sat Feb 24 07:35:05 2001
+++ src/afs/VNOPS/afs_vnop_lookup.c	Fri Jun 15 17:16:04 2001
@@ -867,8 +867,13 @@
     int flags;
     struct vnode *rdir;
 #else
+#if defined(UKERNEL)
+afs_lookup(adp, aname, avcp, acred, flags)
+    int flags;
+#else    
 afs_lookup(adp, aname, avcp, acred)
-#endif
+#endif /* UKERNEL */
+#endif /* SUN5 || SGI */
     OSI_VC_DECL(adp);
     struct vcache **avcp;
     char *aname;
@@ -883,6 +888,7 @@
     extern afs_int32 afs_mariner;			/*Writing activity to log?*/
     OSI_VC_CONVERT(adp)
     afs_hyper_t versionNo;
+    int no_read_access = 0;
 
     AFS_STATCNT(afs_lookup);
 #ifdef	AFS_OSF_ENV
@@ -990,6 +996,10 @@
        else adp->last_looker = treq.uid;
     } 
 
+    /* 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_READ, &treq, CHECK_MODE_BITS))
+      no_read_access = 1;
 
     /* special case lookup of ".".  Can we check for it sooner in this code,
      * for instance, way up before "redo:" ??
@@ -1011,8 +1021,15 @@
 
     tvc = osi_dnlc_lookup (adp, tname, WRITE_LOCK);
     *avcp = tvc;  /* maybe wasn't initialized, but it is now */
-#ifdef AFS_LINUX22_ENV
     if (tvc) {
+      if (no_read_access && vType(tvc) != VDIR) {
+        /* need read access on dir to stat non-directory */
+        afs_PutVCache(tvc, WRITE_LOCK);
+        *avcp = (struct vcache *)0;
+        code = EACCES;
+        goto done;
+      }
+#ifdef AFS_LINUX22_ENV
       if (tvc->mvstat == 2) { /* we don't trust the dnlc for root vcaches */
 	AFS_RELE(tvc);
 	*avcp = 0;
@@ -1022,14 +1039,12 @@
 	hit = 1;
 	goto done;
       }
-    }
 #else /* non - LINUX */
-    if (tvc) {
       code = 0;
       hit = 1;
       goto done;
-    }
 #endif /* linux22 */
+    }
 
     {
     register struct dcache *tdc;
@@ -1155,6 +1170,11 @@
 	tvc->parentVnode = adp->fid.Fid.Vnode;
 	tvc->parentUnique = adp->fid.Fid.Unique;
 	tvc->states &= ~CBulkStat;
+
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+        if (!(flags & AFS_LOOKUP_NOEVAL))
+          /* don't eval mount points */
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
 	if (tvc->mvstat == 1) {
 	  /* a mt point, possibly unevaluated */
 	  struct volume *tvolp;
@@ -1263,6 +1283,14 @@
 
 	if (afs_mariner)
 	  afs_AddMarinerName(aname, tvc); 
+
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+        if (!(flags & AFS_LOOKUP_NOEVAL))
+	/* Here we don't enter the name into the DNLC because we want the
+        evaluated mount dir to be there (the vcache for the mounted volume)
+        rather than the vc of the mount point itself.  we can still find the
+        mount point's vc in the vcache by its fid. */
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
 	if (!hit) {
 	  osi_dnlc_enter (adp, aname, tvc, &versionNo);
 	}
diff -Nur --exclude-from=exclude orig-src/afs/afs_osi_pag.c src/afs/afs_osi_pag.c
--- orig-src/afs/afs_osi_pag.c	Sat Apr 14 10:27:32 2001
+++ src/afs/afs_osi_pag.c	Wed Jun 13 17:23:05 2001
@@ -33,7 +33,11 @@
 
 /* Exported variables */
 afs_uint32 pag_epoch;
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+afs_uint32 pagCounter = 1;
+#else
 afs_uint32 pagCounter = 0;
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
 
 /* Local variables */
 
@@ -61,14 +65,15 @@
  * anyway, so the pag is an alternative handle which is somewhat more
  * secure (although of course not absolutely secure).
 */
+#if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS)
 afs_uint32 genpag(void) {
     AFS_STATCNT(genpag);
 #ifdef AFS_LINUX20_ENV
     /* Ensure unique PAG's (mod 200 days) when reloading the client. */
     return (('A' << 24) + ((pag_epoch + pagCounter++) & 0xffffff));
-#else
+#else /* AFS_LINUX20_ENV */
     return (('A' << 24) + (pagCounter++ & 0xffffff));
-#endif
+#endif /* AFS_LINUX20_ENV */
 }
 
 afs_uint32 getpag(void) {
@@ -81,6 +86,30 @@
 #endif
 }
 
+#else
+
+/* Web enhancement: we don't need to restrict pags to 41XXXXXX since
+ * we are not sharing the space with anyone.  So we use the full 32 bits. */
+
+afs_uint32 genpag(void) {
+    AFS_STATCNT(genpag);
+#ifdef AFS_LINUX20_ENV
+    return (pag_epoch + pagCounter++);
+#else
+    return (pagCounter++);
+#endif /* AFS_LINUX20_ENV */
+}
+
+afs_uint32 getpag(void) {
+    AFS_STATCNT(getpag);
+#ifdef AFS_LINUX20_ENV
+    /* Ensure unique PAG's (mod 200 days) when reloading the client. */
+    return (pag_epoch + pagCounter);
+#else
+    return (pagCounter);
+#endif
+}
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
 
 /* used to require 10 seconds between each setpag to guarantee that
  * PAGs never wrap - which would be a security hole.  If we presume
@@ -182,6 +211,115 @@
 #endif
 }
 
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+/*
+ * afs_setpag_val
+ * This function is like setpag but sets the current thread's pag id to a
+ * caller-provided value instead of calling genpag().  This implements a
+ * form of token caching since the caller can recall a particular pag value
+ * for the thread to restore tokens, rather than reauthenticating.
+ */
+int
+#if	defined(AFS_SUN5_ENV)
+afs_setpag_val (struct AFS_UCRED **credpp, int pagval)
+#elif  defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+afs_setpag_val (struct proc *p, void *args, int *retval, int pagval)
+#else
+afs_setpag_val (int pagval) 
+#endif
+{
+    int code = 0;
+
+#if defined(AFS_SGI53_ENV) && defined(MP)
+    /* This is our first chance to get the global lock. */
+    AFS_GLOCK();
+#endif /* defined(AFS_SGI53_ENV) && defined(MP) */    
+
+    AFS_STATCNT(afs_setpag);
+#ifdef AFS_SUN5_ENV
+    if (!afs_suser(*credpp))
+#else
+    if (!afs_suser())
+#endif
+    {
+	while (osi_Time() - pag_epoch < pagCounter ) {
+	    afs_osi_Wait(1000, (struct afs_osi_WaitHandle *) 0, 0);
+	}	
+    }
+
+#if	defined(AFS_SUN5_ENV)
+    code = AddPag(pagval, credpp);
+#elif	defined(AFS_OSF_ENV) || defined(AFS_FBSD_ENV)
+    code = AddPag(p, pagval, &p->p_rcred);
+#elif	defined(AFS_AIX41_ENV)
+    {
+	struct ucred *credp;
+	struct ucred *credp0;
+	
+	credp = crref();
+	credp0 = credp;
+	code = AddPag(pagval, &credp);
+	/* If AddPag() didn't make a new cred, then free our cred ref */
+	if (credp == credp0) {
+	    crfree(credp);
+	}
+    }
+#elif	defined(AFS_HPUX110_ENV)
+    {
+	struct ucred *credp = p_cred(u.u_procp);
+	code = AddPag(pagval, &credp);
+    }
+#elif	defined(AFS_SGI_ENV)
+    {
+	cred_t *credp;
+	credp = OSI_GET_CURRENT_CRED();
+	code = AddPag(pagval, &credp);
+    }
+#elif	defined(AFS_LINUX20_ENV)
+    {
+	struct AFS_UCRED *credp = crref();
+	code = AddPag(pagval, &credp);
+	crfree(credp);
+    }
+#elif defined(AFS_DARWIN_ENV)  || defined(AFS_FBSD_ENV)
+    {
+       struct ucred *credp=crdup(p->p_cred->pc_ucred);
+       code=AddPag(p, pagval, &credp);
+       crfree(credp);
+    }
+#else
+    code = AddPag(pagval, &u.u_cred);
+#endif
+
+    afs_Trace1(afs_iclSetp, CM_TRACE_SETPAG, ICL_TYPE_INT32, code);
+#if	defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+#if defined(AFS_SGI53_ENV) && defined(MP)
+    AFS_GUNLOCK();
+#endif /* defined(AFS_SGI53_ENV) && defined(MP) */    
+    return (code);
+#else
+    if (!getuerror())
+ 	setuerror(code);
+    return (code);
+#endif
+}
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
+
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+int afs_getpag_val()
+{
+  int pagvalue;
+  struct AFS_UCRED *credp = u.u_cred;
+  int gidset0, gidset1;
+
+  gidset0 = credp->cr_groups[0];
+  gidset1 = credp->cr_groups[1];
+  pagvalue=afs_get_pag_from_groups(gidset0, gidset1);
+  return pagvalue;
+}
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
+
+
 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
 int AddPag(struct proc *p, afs_int32 aval, struct AFS_UCRED **credpp)
 #else	/* AFS_OSF_ENV || AFS_FBSD_ENV */
@@ -244,11 +382,15 @@
 	h = (g0 >> 14);
 	h = (g1 >> 14) + h + h + h;
 	ret = ((h << 28) | l);
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+	return ret;
+#else
 	/* Additional testing */
 	if (((ret >> 24) & 0xff) == 'A')
 	    return ret;
 	else
 	    return NOPAG;
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
     }
     return NOPAG;
 }
@@ -260,7 +402,9 @@
 
 
     AFS_STATCNT(afs_get_groups_from_pag);
+#if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS)
     pag &= 0x7fffffff;
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
     g0 = 0x3fff & (pag >> 14);
     g1 = 0x3fff & pag;
     g0 |= ((pag >> 28) / 3) << 14;
diff -Nur --exclude-from=exclude orig-src/afs/afs_pioctl.c src/afs/afs_pioctl.c
--- orig-src/afs/afs_pioctl.c	Mon Apr 30 15:08:40 2001
+++ src/afs/afs_pioctl.c	Fri Jun  1 20:00:47 2001
@@ -1845,6 +1845,13 @@
 	    afs_ResetUserConns(tu);
 	    tu->refCount--;
 	    ObtainWriteLock(&afs_xuser,228);
+#ifdef UKERNEL
+            /* set the expire times to 0, causes
+             * afs_GCUserData to remove this entry
+             */
+            tu->ct.EndTimestamp = 0;
+            tu->tokenTime = 0;
+#endif  /* UKERNEL */
 	}
     }
     ReleaseWriteLock(&afs_xuser);