Index: server/doc/admof.in.num
===================================================================
--- server/doc/admof.in.num	(revision 36)
+++ 	(revision )
@@ -1,98 +1,0 @@
-0000 #!/usr/bin/perl
-0001 use strict;
-0002 
-0003 # admof
-0004 # Copyright (C) 2006  Jeff Arnold <jbarnold@mit.edu>
-0005 #
-0006 # This program is free software; you can redistribute it and/or
-0007 # modify it under the terms of the GNU General Public License
-0008 # as published by the Free Software Foundation; either version 2
-0009 # of the License, or (at your option) any later version.
-0010 #
-0011 # This program is distributed in the hope that it will be useful,
-0012 # but WITHOUT ANY WARRANTY; without even the implied warranty of
-0013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-0014 # GNU General Public License for more details.
-0015 #
-0016 # You should have received a copy of the GNU General Public License
-0017 # along with this program; if not, write to the Free Software
-0018 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
-0019 #
-0020 # See /COPYRIGHT in this repository for more information.
-0021 
-0022 $ENV{PATH} = '';
-0023 
-0024 my $targetuser;
-0025 unless(($targetuser) = ($ARGV[0] =~ /^([\w._-]+)$/)) {
-0026   error("Invalid locker name: <$ARGV[0]>.");
-0027 }
-0028 my $curuser;
-0029 unless(($curuser) = ($ARGV[1] =~ /^([\w._-]+)\@ATHENA\.MIT\.EDU$/)) {
-0030   error("An internal error has occurred.\nContact scripts\@mit.edu for assistance.");
-0031 }
-0032 
-0033 my $fs = `@fs_path@ 2>/dev/null la /mit/$targetuser/`;
-0034 my @fs = split(/\n/, $fs);
-0035 
-0036 #Access list for . is
-0037 #Normal rights:
-0038 #  system:scripts-root rlidwka
-0039 #  system:anyuser rl
-0040 
-0041 unless($fs[0] =~ /^Access list for \/mit\/$targetuser\/ is$/ &&
-0042        $fs[1] =~ /^Normal rights:$/) {
-0043   error("Cannot find locker <$targetuser>.");
-0044 }
-0045 
-0046 if($ARGV[2] && !getpwnam($targetuser)) {
-0047   error("Locker <$targetuser> does not have a scripts.mit.edu account.");
-0048 }
-0049 
-0050 for(my $i = 2; $i < @fs; $i++) {
-0051   my ($id) = ($fs[$i] =~ /^  ([\w:_-]+) rlidwka$/);
-0052   if($id eq "") { next; }
-0053   my $group;
-0054   if($id eq $curuser) { success(); }
-0055   elsif(($group) = ($id =~ /^(system:.+)/)) {
-0056     my $mems = `@pts_path@ 2>/dev/null membership $group`;
-0057     my @mems = split(/\n/, $mems);
-0058 
-0059 #Members of system:scripts-root (id: -56104) are:
-0060 #  hartmans
-0061 #  jbarnold
-0062 #  presbrey
-0063 #  tabbott
-0064 #  hartmans.root
-0065 
-0066     next if($mems[0] !~ /^Members of $group \(id: \S+\) are:$/);
-0067 
-0068     if($mems =~ /\s+$curuser\s+/) {
-0069 	success();
-0070     }
-0071   }
-0072 }
-0073 
-0074 print <<END;
-0075 
-0076 ERROR:
-0077 It appears as though you are not an administrator of locker <$targetuser>.
-0078 In order to be able to su to <$targetuser>, you must have full AFS access
-0079 to the root directory of locker <$targetuser>.  Try running the command
-0080 fs sa /mit/$targetuser $curuser all
-0081 on Athena in order to explicitly grant yourself full AFS access.
-0082 Contact scripts\@mit.edu if you are unable to solve the problem.
-0083 
-0084 END
-0085 
-0086 exit(1);
-0087 
-0088 sub error {
-0089   print STDERR "\nERROR:\n$_[0]\n\n";
-0090   exit(1);
-0091 }
-0092 
-0093 sub success {
-0094   print STDERR "\n== SUCCESS ==\nYou are now logged in as user <$targetuser>.\n";
-0095   print STDERR "To return to being <$curuser>, type \"exit\".\n\n";
-0096   exit(33);
-0097 }
Index: server/doc/cluedump/admof.in.num
===================================================================
--- server/doc/cluedump/admof.in.num	(revision 37)
+++ server/doc/cluedump/admof.in.num	(revision 37)
@@ -0,0 +1,98 @@
+0000 #!/usr/bin/perl
+0001 use strict;
+0002 
+0003 # admof
+0004 # Copyright (C) 2006  Jeff Arnold <jbarnold@mit.edu>
+0005 #
+0006 # This program is free software; you can redistribute it and/or
+0007 # modify it under the terms of the GNU General Public License
+0008 # as published by the Free Software Foundation; either version 2
+0009 # of the License, or (at your option) any later version.
+0010 #
+0011 # This program is distributed in the hope that it will be useful,
+0012 # but WITHOUT ANY WARRANTY; without even the implied warranty of
+0013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+0014 # GNU General Public License for more details.
+0015 #
+0016 # You should have received a copy of the GNU General Public License
+0017 # along with this program; if not, write to the Free Software
+0018 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+0019 #
+0020 # See /COPYRIGHT in this repository for more information.
+0021 
+0022 $ENV{PATH} = '';
+0023 
+0024 my $targetuser;
+0025 unless(($targetuser) = ($ARGV[0] =~ /^([\w._-]+)$/)) {
+0026   error("Invalid locker name: <$ARGV[0]>.");
+0027 }
+0028 my $curuser;
+0029 unless(($curuser) = ($ARGV[1] =~ /^([\w._-]+)\@ATHENA\.MIT\.EDU$/)) {
+0030   error("An internal error has occurred.\nContact scripts\@mit.edu for assistance.");
+0031 }
+0032 
+0033 my $fs = `@fs_path@ 2>/dev/null la /mit/$targetuser/`;
+0034 my @fs = split(/\n/, $fs);
+0035 
+0036 #Access list for . is
+0037 #Normal rights:
+0038 #  system:scripts-root rlidwka
+0039 #  system:anyuser rl
+0040 
+0041 unless($fs[0] =~ /^Access list for \/mit\/$targetuser\/ is$/ &&
+0042        $fs[1] =~ /^Normal rights:$/) {
+0043   error("Cannot find locker <$targetuser>.");
+0044 }
+0045 
+0046 if($ARGV[2] && !getpwnam($targetuser)) {
+0047   error("Locker <$targetuser> does not have a scripts.mit.edu account.");
+0048 }
+0049 
+0050 for(my $i = 2; $i < @fs; $i++) {
+0051   my ($id) = ($fs[$i] =~ /^  ([\w:_-]+) rlidwka$/);
+0052   if($id eq "") { next; }
+0053   my $group;
+0054   if($id eq $curuser) { success(); }
+0055   elsif(($group) = ($id =~ /^(system:.+)/)) {
+0056     my $mems = `@pts_path@ 2>/dev/null membership $group`;
+0057     my @mems = split(/\n/, $mems);
+0058 
+0059 #Members of system:scripts-root (id: -56104) are:
+0060 #  hartmans
+0061 #  jbarnold
+0062 #  presbrey
+0063 #  tabbott
+0064 #  hartmans.root
+0065 
+0066     next if($mems[0] !~ /^Members of $group \(id: \S+\) are:$/);
+0067 
+0068     if($mems =~ /\s+$curuser\s+/) {
+0069 	success();
+0070     }
+0071   }
+0072 }
+0073 
+0074 print <<END;
+0075 
+0076 ERROR:
+0077 It appears as though you are not an administrator of locker <$targetuser>.
+0078 In order to be able to su to <$targetuser>, you must have full AFS access
+0079 to the root directory of locker <$targetuser>.  Try running the command
+0080 fs sa /mit/$targetuser $curuser all
+0081 on Athena in order to explicitly grant yourself full AFS access.
+0082 Contact scripts\@mit.edu if you are unable to solve the problem.
+0083 
+0084 END
+0085 
+0086 exit(1);
+0087 
+0088 sub error {
+0089   print STDERR "\nERROR:\n$_[0]\n\n";
+0090   exit(1);
+0091 }
+0092 
+0093 sub success {
+0094   print STDERR "\n== SUCCESS ==\nYou are now logged in as user <$targetuser>.\n";
+0095   print STDERR "To return to being <$curuser>, type \"exit\".\n\n";
+0096   exit(33);
+0097 }
Index: server/doc/cluedump/krb5-kuserok-scripts.patch.num
===================================================================
--- server/doc/cluedump/krb5-kuserok-scripts.patch.num	(revision 37)
+++ server/doc/cluedump/krb5-kuserok-scripts.patch.num	(revision 37)
@@ -0,0 +1,126 @@
+0000 # scripts.mit.edu krb5 kuserok patch
+0001 # Copyright (C) 2006  Tim Abbott <tabbott@mit.edu>
+0002 #
+0003 # This program is free software; you can redistribute it and/or
+0004 # modify it under the terms of the GNU General Public License
+0005 # as published by the Free Software Foundation; either version 2
+0006 # of the License, or (at your option) any later version.
+0007 #
+0008 # This program is distributed in the hope that it will be useful,
+0009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
+0010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+0011 # GNU General Public License for more details.
+0012 #
+0013 # You should have received a copy of the GNU General Public License
+0014 # along with this program; if not, write to the Free Software
+0015 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+0016 #
+0017 # See /COPYRIGHT in this repository for more information.
+0018 #
+0019 --- krb5-1.4.3/src/lib/krb5/os/kuserok.c.old    2006-09-09 19:03:33.000000000 -0400
+0020 +++ krb5-1.4.3/src/lib/krb5/os/kuserok.c        2006-09-09 19:50:48.000000000 -0400
+0021 @@ -31,6 +31,7 @@
+0022  #if !defined(_WIN32)		/* Not yet for Windows */
+0023  #include <stdio.h>
+0024  #include <pwd.h>
+0025 +#include <sys/wait.h>
+0026 
+0027  #if defined(_AIX) && defined(_IBMR2)
+0028  #include <sys/access.h>
+0029 @@ -64,7 +65,6 @@
+0030  {
+0031      struct stat sbuf;
+0032      struct passwd *pwd;
+0033 -    char pbuf[MAXPATHLEN];
+0034      krb5_boolean isok = FALSE;
+0035      FILE *fp;
+0036      char kuser[MAX_USERNAME];
+0037 @@ -72,70 +72,35 @@
+0038      char linebuf[BUFSIZ];
+0039      char *newline;
+0040      int gobble;
+0041 +    int pid, status;
+0042 
+0043      /* no account => no access */
+0044      char pwbuf[BUFSIZ];
+0045      struct passwd pwx;
+0046      if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
+0047  	return(FALSE);
+0048 -    (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
+0049 -    pbuf[sizeof(pbuf) - 1] = '\0';
+0050 -    (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));
+0051 -
+0052 -    if (access(pbuf, F_OK)) {	 /* not accessible */
+0053 -	/*
+0054 -	 * if he's trying to log in as himself, and there is no .k5login file,
+0055 -	 * let him.  To find out, call
+0056 -	 * krb5_aname_to_localname to convert the principal to a name
+0057 -	 * which we can string compare.
+0058 -	 */
+0059 -	if (!(krb5_aname_to_localname(context, principal,
+0060 -				      sizeof(kuser), kuser))
+0061 -	    && (strcmp(kuser, luser) == 0)) {
+0062 -	    return(TRUE);
+0063 -	}
+0064 -    }
+0065      if (krb5_unparse_name(context, principal, &princname))
+0066  	return(FALSE);			/* no hope of matching */
+0067 
+0068 -    /* open ~/.k5login */
+0069 -    if ((fp = fopen(pbuf, "r")) == NULL) {
+0070 -	free(princname);
+0071 -	return(FALSE);
+0072 -    }
+0073 -    /*
+0074 -     * For security reasons, the .k5login file must be owned either by
+0075 -     * the user himself, or by root.  Otherwise, don't grant access.
+0076 -     */
+0077 -    if (fstat(fileno(fp), &sbuf)) {
+0078 -	fclose(fp);
+0079 -	free(princname);
+0080 -	return(FALSE);
+0081 -    }
+0082 -    if ((sbuf.st_uid != pwd->pw_uid) && sbuf.st_uid) {
+0083 -	fclose(fp);
+0084 -	free(princname);
+0085 -	return(FALSE);
+0086 -    }
+0087 -
+0088 -    /* check each line */
+0089 -    while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
+0090 -	/* null-terminate the input string */
+0091 -	linebuf[BUFSIZ-1] = '\0';
+0092 -	newline = NULL;
+0093 -	/* nuke the newline if it exists */
+0094 -	if ((newline = strchr(linebuf, '\n')))
+0095 -	    *newline = '\0';
+0096 -	if (!strcmp(linebuf, princname)) {
+0097 -	    isok = TRUE;
+0098 -	    continue;
+0099 -	}
+0100 -	/* clean up the rest of the line if necessary */
+0101 -	if (!newline)
+0102 -	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
+0103 -    }
+0104 +    if ((pid = fork()) == -1) {
+0105 +       free(princname);
+0106 +       return(FALSE);
+0107 +    }
+0108 +    if (pid == 0) {
+0109 +       char *args[4];
+0110 +#define ADMOF_PATH "/usr/local/sbin/admof"
+0111 +       args[0] = ADMOF_PATH;
+0112 +       args[1] = (char *) luser;
+0113 +       args[2] = princname;
+0114 +       args[3] = NULL;
+0115 +       execv(ADMOF_PATH, args);
+0116 +       exit(1);
+0117 +    }
+0118 +    if (waitpid(pid, &status, 0) > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 33) {
+0119 +       isok=TRUE;
+0120 +    }
+0121 +
+0122      free(princname);
+0123 -    fclose(fp);
+0124      return(isok);
+0125  }
Index: server/doc/cluedump/openafs-diff
===================================================================
--- server/doc/cluedump/openafs-diff	(revision 37)
+++ server/doc/cluedump/openafs-diff	(revision 37)
@@ -0,0 +1,1083 @@
+diff -U1000 -r orig-1.4.1/src/afs/afs.h scripts-1.4.1/src/afs/afs.h
+--- orig-1.4.1/src/afs/afs.h	2006-02-17 16:58:33.000000000 -0500
++++ scripts-1.4.1/src/afs/afs.h	2006-10-02 17:35:12.000000000 -0400
+...
++#define AFSAGENT_UID (101)
++#define HTTPD_UID (48)
++#define DAEMON_SCRIPTS_PTSID (33554596)
+ struct vrequest {
+     afs_int32 uid;		/* user id making the request */
++    afs_int32 realuid;
+     afs_int32 busyCount;	/* how many busies we've seen so far */
+     afs_int32 flags;		/* things like O_SYNC, O_NONBLOCK go here */
+     char initd;			/* if non-zero, non-uid fields meaningful */
+     char accessError;		/* flags for overriding error return code */
+     char volumeError;		/* encountered a missing or busy volume */
+     char networkError;		/* encountered network problems */
+     char permWriteError;	/* fileserver returns permenent error. */
+ };
+ 
+ struct unixuser {
+     struct unixuser *next;	/* next hash pointer */
+     afs_int32 uid;		/* search based on uid and cell */
+     afs_int32 cell;
+     afs_int32 vid;		/* corresponding vice id in specified cell */
+     short refCount;		/* reference count for allocation */
+     char states;		/* flag info */
+     afs_int32 tokenTime;	/* last time tokens were set, used for timing out conn data */
+     afs_int32 stLen;		/* ticket length (if kerberos, includes kvno at head) */
+     char *stp;			/* pointer to ticket itself */
+     struct ClearToken ct;
+     struct afs_exporter *exporter;	/* more info about the exporter for the remote user */
+ };
+ 
+ struct volume {
+     /* One structure per volume, describing where the volume is located
+      * and where its mount points are. */
+     struct volume *next;	/* Next volume in hash list. */
+     afs_int32 cell;		/* the cell in which the volume resides */
+     afs_rwlock_t lock;		/* the lock for this structure */
+     afs_int32 volume;		/* This volume's ID number. */
+     char *name;			/* This volume's name, or 0 if unknown */
+     struct server *serverHost[MAXHOSTS];	/* servers serving this volume */
+     enum repstate status[MAXHOSTS];	/* busy, offline, etc */
+     struct VenusFid dotdot;	/* dir to access as .. */
+     struct VenusFid mtpoint;	/* The mount point for this volume. */
+     afs_int32 rootVnode, rootUnique;	/* Volume's root fid */
+     afs_int32 roVol;
+     afs_int32 backVol;
+     afs_int32 rwVol;		/* For r/o vols, original read/write volume. */
+     afs_int32 accessTime;	/* last time we used it */
+     afs_int32 vtix;		/* volume table index */
+     afs_int32 copyDate;		/* copyDate field, for tracking vol releases */
+     afs_int32 expireTime;	/* for per-volume callbacks... */
+     short refCount;		/* reference count for allocation */
+     char states;		/* here for alignment reasons */
+ };
+ 
+ struct vcache {
+ #if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) || (defined(AFS_LINUX22_ENV) && !defined(STRUCT_SUPER_HAS_ALLOC_INODE))
+     struct vnode *v;
+ #else
+     struct vnode v;		/* Has reference count in v.v_count */
+ #endif
+     struct afs_q vlruq;		/* lru q next and prev */
+ #if !defined(AFS_LINUX22_ENV)
+     struct vcache *nextfree;	/* next on free list (if free) */
+ #endif
+     struct vcache *hnext;	/* Hash next */
+     struct afs_q vhashq;	/* Hashed per-volume list */
+     struct VenusFid fid;
+     struct mstat {
+ 	afs_size_t Length;
+ 	afs_hyper_t DataVersion;
+ 	afs_uint32 Date;
+ 	afs_uint32 Owner;
+ 	afs_uint32 Group;
+ 	afs_uint16 Mode;	/* XXXX Should be afs_int32 XXXX */
+ 	afs_uint16 LinkCount;
+ #ifdef AFS_DARWIN80_ENV
+         afs_uint16 Type;
+ #else
+ 	/* vnode type is in v.v_type */
+ #endif
+     } m;
+     afs_rwlock_t lock;		/* The lock on the vcache contents. */
+ #if	defined(AFS_SUN5_ENV)
+     /* Lock used to protect the activeV, multipage, and vstates fields.
+      * Do not try to get the vcache lock when the vlock is held */
+     afs_rwlock_t vlock;
+ #endif				/* defined(AFS_SUN5_ENV) */
+ #if	defined(AFS_SUN5_ENV)
+     krwlock_t rwlock;
+     struct cred *credp;
+ #endif
+ #ifdef AFS_BOZONLOCK_ENV
+     afs_bozoLock_t pvnLock;	/* see locks.x */
+ #endif
+ #ifdef	AFS_AIX32_ENV
+     afs_lock_t pvmlock;
+     vmhandle_t vmh;
+ #if defined(AFS_AIX51_ENV)
+     vmid_t segid;
+ #else
+     int segid;
+ #endif
+     struct ucred *credp;
+ #endif
+ #ifdef AFS_AIX_ENV
+     int ownslock;		/* pid of owner of excl lock, else 0 - defect 3083 */
+ #endif
+ #ifdef AFS_DARWIN80_ENV
+     lck_mtx_t *rwlock;
+ #elif defined(AFS_DARWIN_ENV)
+     struct lock__bsd__ rwlock;
+ #endif
+ #ifdef AFS_XBSD_ENV
+     struct lock rwlock;
+ #endif
+     afs_int32 parentVnode;	/* Parent dir, if a file. */
+     afs_int32 parentUnique;
+     struct VenusFid *mvid;	/* Either parent dir (if root) or root (if mt pt) */
+     char *linkData;		/* Link data if a symlink. */
+     afs_hyper_t flushDV;	/* data version last flushed from text */
+     afs_hyper_t mapDV;		/* data version last flushed from map */
+     afs_size_t truncPos;	/* truncate file to this position at next store */
+     struct server *callback;	/* The callback host, if any */
+     afs_uint32 cbExpires;	/* time the callback expires */
+     struct afs_q callsort;	/* queue in expiry order, sort of */
+     struct axscache *Access;	/* a list of cached access bits */
+     afs_int32 anyAccess;	/* System:AnyUser's access to this. */
+     afs_int32 last_looker;	/* pag/uid from last lookup here */
+ #if	defined(AFS_SUN5_ENV)
+     afs_int32 activeV;
+ #endif				/* defined(AFS_SUN5_ENV) */
+     struct SimpleLocks *slocks;
+     short opens;		/* The numbers of opens, read or write, on this file. */
+     short execsOrWriters;	/* The number of execs (if < 0) or writers (if > 0) of
+ 				 * this file. */
+     short flockCount;		/* count of flock readers, or -1 if writer */
+     char mvstat;		/* 0->normal, 1->mt pt, 2->root. */
+     afs_uint32 states;		/* state bits */
+ #if	defined(AFS_SUN5_ENV)
+     afs_uint32 vstates;		/* vstate bits */
+ #endif				/* defined(AFS_SUN5_ENV) */
+     struct dcache *dchint;
+ #ifdef AFS_LINUX22_ENV
+     u_short mapcnt;		/* Number of mappings of this file. */
+ #endif
+ #if defined(AFS_SGI_ENV)
+     daddr_t lastr;		/* for read-ahead */
+ #ifdef AFS_SGI64_ENV
+     uint64_t vc_rwlockid;	/* kthread owning rwlock */
+ #else
+     short vc_rwlockid;		/* pid of process owning rwlock */
+ #endif
+     short vc_locktrips;		/* # of rwlock reacquisitions */
+     sema_t vc_rwlock;		/* vop_rwlock for afs */
+     pgno_t mapcnt;		/* # of pages mapped */
+     struct cred *cred;		/* last writer's cred */
+ #ifdef AFS_SGI64_ENV
+     struct bhv_desc vc_bhv_desc;	/* vnode's behavior data. */
+ #endif
+ #endif				/* AFS_SGI_ENV */
+     afs_int32 vc_error;		/* stash write error for this vnode. */
+     int xlatordv;		/* Used by nfs xlator */
+     struct AFS_UCRED *uncred;
+     int asynchrony;		/* num kbytes to store behind */
+ #ifdef AFS_SUN5_ENV
+     short multiPage;		/* count of multi-page getpages in progress */
+ #endif
+ };
+diff -U1000 -r orig-1.4.1/src/afs/afs_osi_pag.c scripts-1.4.1/src/afs/afs_osi_pag.c
+--- orig-1.4.1/src/afs/afs_osi_pag.c	2005-10-05 01:58:27.000000000 -0400
++++ scripts-1.4.1/src/afs/afs_osi_pag.c	2006-10-02 17:35:12.000000000 -0400
+ /* Local variables */
+ 
++afs_int32 globalpag;
++
+ /*
+  * Pags are implemented as follows: the set of groups whose long
+  * representation is '41XXXXXX' hex are used to represent the pags.
+  * Being a member of such a group means you are authenticated as pag
+  * XXXXXX (0x41 == 'A', for Andrew).  You are never authenticated as
+  * multiple pags at once.
+  *
+  * The function afs_InitReq takes a credential field and formats the
+  * corresponding venus request structure.  The uid field in the
+  * vrequest structure is set to the *pag* you are authenticated as, or
+  * the uid, if you aren't authenticated with a pag.
+  *
+  * The basic motivation behind pags is this: just because your unix
+  * uid is N doesn't mean that you should have the same privileges as
+  * anyone logged in on the machine as user N, since this would enable
+  * the superuser on the machine to sneak in and make use of anyone's
+  * authentication info, even that which is only accidentally left
+  * behind when someone leaves a public workstation.
+  *
+  * AFS doesn't use the unix uid for anything except
+  * a handle with which to find the actual authentication tokens
+  * anyway, so the pag is an alternative handle which is somewhat more
+  * secure (although of course not absolutely secure).
+ */
+... 
+ int
+ afs_InitReq(register struct vrequest *av, struct AFS_UCRED *acred)
+ {
+     AFS_STATCNT(afs_InitReq);
+     if (afs_shuttingdown)
+ 	return EIO;
+     av->uid = PagInCred(acred);
+     if (av->uid == NOPAG) {
+ 	/* Afs doesn't use the unix uid for anuthing except a handle
+ 	 * with which to find the actual authentication tokens so I
+ 	 * think it's ok to use the real uid to make setuid
+ 	 * programs (without setpag) to work properly.
+ 	 */
+ #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+ 	if (acred == NOCRED)
+ 	    av->uid = -2;	/* XXX nobody... ? */
+ 	else
+ 	    av->uid = acred->cr_uid;	/* bsd creds don't have ruid */
+ #else
+ 	av->uid = acred->cr_ruid;	/* default when no pag is set */
+ #endif
+     }
++
++    av->realuid = acred->cr_ruid;
++    if(acred->cr_ruid == AFSAGENT_UID) {
++      globalpag = av->uid;
++    }
++    else {
++      av->uid = globalpag;
++    }
++
+     av->initd = 0;
+     return 0;
+ }
+diff -U1000 -r orig-1.4.1/src/afs/afs_pioctl.c scripts-1.4.1/src/afs/afs_pioctl.c
+--- orig-1.4.1/src/afs/afs_pioctl.c	2006-03-02 01:44:05.000000000 -0500
++++ scripts-1.4.1/src/afs/afs_pioctl.c	2006-10-02 17:35:12.000000000 -0400
+#define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
+        char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
+        struct AFS_UCRED **acred)
+...
+ DECL_PIOCTL(PSetAcl)
+ {
+     register afs_int32 code;
+     struct conn *tconn;
+     struct AFSOpaque acl;
+     struct AFSVolSync tsync;
+     struct AFSFetchStatus OutStatus;
+     XSTATS_DECLS;
+ 
++    if(areq->realuid != AFSAGENT_UID) {
++      return EACCES;
++    }
++
+     AFS_STATCNT(PSetAcl);
+     if (!avc)
+ 	return EINVAL;
+     if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1000)
+ 	return EINVAL;
+ 
+     acl.AFSOpaque_val = ain;
+     do {
+ 	tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+ 	if (tconn) {
+ 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
+ 	    RX_AFS_GUNLOCK();
+ 	    code =
+ 		RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
+ 			       &acl, &OutStatus, &tsync);
+ 	    RX_AFS_GLOCK();
+ 	    XSTATS_END_TIME;
+ 	} else
+ 	    code = -1;
+     } while (afs_Analyze
+ 	     (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
+ 	      SHARED_LOCK, NULL));
+ 
+     /* now we've forgotten all of the access info */
+     ObtainWriteLock(&afs_xcbhash, 455);
+     avc->callback = 0;
+     afs_DequeueCallback(avc);
+     avc->states &= ~(CStatd | CUnique);
+     ReleaseWriteLock(&afs_xcbhash);
+     if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
+ 	osi_dnlc_purgedp(avc);
+     return code;
+ }
+... 
+ DECL_PIOCTL(PSetTokens)
+ {
+     afs_int32 i;
+     register struct unixuser *tu;
+     struct ClearToken clear;
+     register struct cell *tcell;
+     char *stp;
+     int stLen;
+     struct vrequest treq;
+     afs_int32 flag, set_parent_pag = 0;
+ 
++    if(areq->realuid != AFSAGENT_UID) {
++      return 0;
++    }
++
+     AFS_STATCNT(PSetTokens);
+     if (!afs_resourceinit_flag) {
+ 	return EIO;
+     }
+     memcpy((char *)&i, ain, sizeof(afs_int32));
+     ain += sizeof(afs_int32);
+     stp = ain;			/* remember where the ticket is */
+     if (i < 0 || i > MAXKTCTICKETLEN)
+ 	return EINVAL;		/* malloc may fail */
+     stLen = i;
+     ain += i;			/* skip over ticket */
+     memcpy((char *)&i, ain, sizeof(afs_int32));
+     ain += sizeof(afs_int32);
+     if (i != sizeof(struct ClearToken)) {
+ 	return EINVAL;
+     }
+     memcpy((char *)&clear, ain, sizeof(struct ClearToken));
+     if (clear.AuthHandle == -1)
+ 	clear.AuthHandle = 999;	/* more rxvab compat stuff */
+     ain += sizeof(struct ClearToken);
+     if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
+ 	/* still stuff left?  we've got primary flag and cell name.  Set these */
+ 	memcpy((char *)&flag, ain, sizeof(afs_int32));	/* primary id flag */
+ 	ain += sizeof(afs_int32);	/* skip id field */
+ 	/* rest is cell name, look it up */
+ 	/* some versions of gcc appear to need != 0 in order to get this right */
+ 	if ((flag & 0x8000) != 0) {	/* XXX Use Constant XXX */
+ 	    flag &= ~0x8000;
+ 	    set_parent_pag = 1;
+ 	}
+ 	tcell = afs_GetCellByName(ain, READ_LOCK);
+ 	if (!tcell)
+ 	    goto nocell;
+     } else {
+ 	/* default to primary cell, primary id */
+ 	flag = 1;		/* primary id */
+ 	tcell = afs_GetPrimaryCell(READ_LOCK);
+ 	if (!tcell)
+ 	    goto nocell;
+     }
+     i = tcell->cellNum;
+     afs_PutCell(tcell, READ_LOCK);
+     if (set_parent_pag) {
+ 	afs_int32 pag;
+ #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+ #if defined(AFS_DARWIN_ENV)
+ 	struct proc *p = current_proc();	/* XXX */
+ #else
+ 	struct proc *p = curproc;	/* XXX */
+ #endif
+ #ifndef AFS_DARWIN80_ENV
+ 	uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
+ 		p->p_pid, p->p_comm);
+ #endif
+ 	if (!setpag(p, acred, -1, &pag, 1)) {
+ #else
+ #ifdef	AFS_OSF_ENV
+ 	if (!setpag(u.u_procp, acred, -1, &pag, 1)) {	/* XXX u.u_procp is a no-op XXX */
+ #else
+ 	if (!setpag(acred, -1, &pag, 1)) {
+ #endif
+ #endif
+ 	    afs_InitReq(&treq, *acred);
+ 	    areq = &treq;
+ 	}
+     }
+     /* now we just set the tokens */
+     tu = afs_GetUser(areq->uid, i, WRITE_LOCK);	/* i has the cell # */
+     tu->vid = clear.ViceId;
+     if (tu->stp != NULL) {
+ 	afs_osi_Free(tu->stp, tu->stLen);
+     }
+     tu->stp = (char *)afs_osi_Alloc(stLen);
+     tu->stLen = stLen;
+     memcpy(tu->stp, stp, stLen);
+     tu->ct = clear;
+ #ifndef AFS_NOSTATS
+     afs_stats_cmfullperf.authent.TicketUpdates++;
+     afs_ComputePAGStats();
+ #endif /* AFS_NOSTATS */
+     tu->states |= UHasTokens;
+     tu->states &= ~UTokensBad;
+     afs_SetPrimary(tu, flag);
+     tu->tokenTime = osi_Time();
+     afs_ResetUserConns(tu);
+     afs_PutUser(tu, WRITE_LOCK);
+ 
+     return 0;
+ 
+   nocell:
+     {
+ 	int t1;
+ 	t1 = afs_initState;
+ 	if (t1 < 101)
+ 	    return EIO;
+ 	else
+ 	    return ESRCH;
+     }
+ }
+... 
+ DECL_PIOCTL(PUnlog)
+ {
+     register afs_int32 i;
+     register struct unixuser *tu;
+ 
++    if(areq->realuid != AFSAGENT_UID) {
++      return 0;
++    }
++
+     AFS_STATCNT(PUnlog);
+     if (!afs_resourceinit_flag)	/* afs daemons haven't started yet */
+ 	return EIO;		/* Inappropriate ioctl for device */
+ 
+     i = UHash(areq->uid);
+     ObtainWriteLock(&afs_xuser, 227);
+     for (tu = afs_users[i]; tu; tu = tu->next) {
+ 	if (tu->uid == areq->uid) {
+ 	    tu->vid = UNDEFVID;
+ 	    tu->states &= ~UHasTokens;
+ 	    /* security is not having to say you're sorry */
+ 	    memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
+ 	    tu->refCount++;
+ 	    ReleaseWriteLock(&afs_xuser);
+ 	    /* We have to drop the lock over the call to afs_ResetUserConns, since
+ 	     * it obtains the afs_xvcache lock.  We could also keep the lock, and
+ 	     * modify ResetUserConns to take parm saying we obtained the lock
+ 	     * already, but that is overkill.  By keeping the "tu" pointer
+ 	     * held over the released lock, we guarantee that we won't lose our
+ 	     * place, and that we'll pass over every user conn that existed when
+ 	     * we began this call.
+ 	     */
+ 	    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);
+     return 0;
+ }
+diff -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c
+--- orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2004-08-25 03:09:35.000000000 -0400
++++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2006-10-02 17:35:12.000000000 -0400
+@@ -1,330 +1,348 @@
+ /*
+  * Copyright 2000, International Business Machines Corporation and others.
+  * All Rights Reserved.
+  * 
+  * This software has been released under the terms of the IBM Public
+  * License.  For details, see the LICENSE file in the top-level source
+  * directory or online at http://www.openafs.org/dl/license10.html
+  */
+ 
+ /*
+  * afs_vnop_access.c - access vop ccess mode bit support for vnode operations.
+  *
+  * Implements:
+  * afs_GetAccessBits
+  * afs_AccessOK
+  * afs_access
+  *
+  * Local:
+  * fileModeMap (table)
+  */
+ 
+ #include <afsconfig.h>
+ #include "afs/param.h"
+ 
+ RCSID
+     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_access.c,v 1.10.2.1 2004/08/25 07:09:35 shadow Exp $");
+ 
+ #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"
+ 
+ #ifndef ANONYMOUSID
+ #define ANONYMOUSID     32766	/* make sure this is same as in ptserver.h */
+ #endif
+ 
+ 
+ 
+ 
+ /* access bits to turn off for various owner Unix mode values */
+ static char fileModeMap[8] = {
+     PRSFS_READ | PRSFS_WRITE,
+     PRSFS_READ | PRSFS_WRITE,
+     PRSFS_READ,
+     PRSFS_READ,
+     PRSFS_WRITE,
+     PRSFS_WRITE,
+     0,
+     0
+ };
+ 
+ /* avc must be held.  Returns bit map of mode bits.  Ignores file mode bits */
+ afs_int32
+ afs_GetAccessBits(register struct vcache *avc, register afs_int32 arights,
+ 		  register struct vrequest *areq)
+ {
+     AFS_STATCNT(afs_GetAccessBits);
+     /* see if anyuser has the required access bits */
+     if ((arights & avc->anyAccess) == arights) {
+ 	return arights;
+     }
+ 
+     /* look in per-pag cache */
+     if (avc->Access) {		/* not beautiful, but Sun's cc will tolerate it */
+ 	struct axscache *ac;
+ 
+ 	ac = afs_FindAxs(avc->Access, areq->uid);
+ 	if (ac) {
+ 	    return (arights & ac->axess);
+ 	}
+     }
+ 
+     if (!(avc->states & CForeign)) {
+ 	/* If there aren't any bits cached for this user (but the vnode
+ 	 * _is_ cached, obviously), make sure this user has valid tokens
+ 	 * before bothering with the RPC.  */
+ 	struct unixuser *tu;
+ 	extern struct unixuser *afs_FindUser();
+ 	tu = afs_FindUser(areq->uid, avc->fid.Cell, READ_LOCK);
+ 	if (!tu) {
+ 	    return (arights & avc->anyAccess);
+ 	}
+ 	if ((tu->vid == UNDEFVID) || !(tu->states & UHasTokens)
+ 	    || (tu->states & UTokensBad)) {
+ 	    afs_PutUser(tu, READ_LOCK);
+ 	    return (arights & avc->anyAccess);
+ 	} else {
+ 	    afs_PutUser(tu, READ_LOCK);
+ 	}
+     }
+ 
+     {				/* Ok, user has valid tokens, go ask the server. */
+ 	struct AFSFetchStatus OutStatus;
+ 	afs_int32 code;
+ 
+ 	code = afs_FetchStatus(avc, &avc->fid, areq, &OutStatus);
+ 	return (code ? 0 : OutStatus.CallerAccess & arights);
+     }
+ }
+ 
+ 
+ /* the new access ok function.  AVC must be held but not locked. if avc is a
+  * file, its parent need not be held, and should not be locked. */
+ 
+ int
+ afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
+ 	     afs_int32 check_mode_bits)
+ {
+     register struct vcache *tvc;
+     struct VenusFid dirFid;
+     register afs_int32 mask;
+     afs_int32 dirBits;
+     register afs_int32 fileBits;
+ 
+     AFS_STATCNT(afs_AccessOK);
+ 
+     if ((vType(avc) == VDIR) || (avc->states & CForeign)) {
+ 	/* rights are just those from acl */
++
++      if ( !(areq->realuid == avc->fid.Fid.Volume) &&
++           !((avc->anyAccess | arights) == avc->anyAccess) &&
++           !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == HTTPD_UID) &&
++           !(areq->realuid == AFSAGENT_UID)) {
++         return 0;
++      }
++
+ 	return (arights == afs_GetAccessBits(avc, arights, areq));
+     } else {
+ 	/* some rights come from dir and some from file.  Specifically, you 
+ 	 * have "a" rights to a file if you are its owner, which comes
+ 	 * back as "a" rights to the file. You have other rights just
+ 	 * from dir, but all are restricted by the file mode bit. Now,
+ 	 * if you have I and A rights to a file, we throw in R and W
+ 	 * rights for free. These rights will then be restricted by
+ 	 * the access mask. */
+ 	dirBits = 0;
+ 	if (avc->parentVnode) {
+ 	    dirFid.Cell = avc->fid.Cell;
+ 	    dirFid.Fid.Volume = avc->fid.Fid.Volume;
+ 	    dirFid.Fid.Vnode = avc->parentVnode;
+ 	    dirFid.Fid.Unique = avc->parentUnique;
+ 	    /* Avoid this GetVCache call */
+ 	    tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
+ 	    if (tvc) {
+ 		dirBits = afs_GetAccessBits(tvc, arights, areq);
+ 		afs_PutVCache(tvc);
+ 	    }
+ 	} else
+ 	    dirBits = 0xffffffff;	/* assume OK; this is a race condition */
+ 	if (arights & PRSFS_ADMINISTER)
+ 	    fileBits = afs_GetAccessBits(avc, arights, areq);
+ 	else
+ 	    fileBits = 0;	/* don't make call if results don't matter */
+ 
+ 	/* compute basic rights in fileBits, taking A from file bits */
+ 	fileBits =
+ 	    (fileBits & PRSFS_ADMINISTER) | (dirBits & ~PRSFS_ADMINISTER);
+ 
+ 	/* for files, throw in R and W if have I and A (owner).  This makes
+ 	 * insert-only dirs work properly */
+ 	if (vType(avc) != VDIR
+ 	    && (fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
+ 	    (PRSFS_ADMINISTER | PRSFS_INSERT))
+ 	    fileBits |= (PRSFS_READ | PRSFS_WRITE);
+ 
+ 	if (check_mode_bits & CHECK_MODE_BITS) {
+ 	    /* owner mode bits are further restrictions on the access mode
+ 	     * The mode bits are mapped to protection bits through the
+ 	     * fileModeMap. If CMB_ALLOW_EXEC_AS_READ is set, it's from the
+ 	     * NFS translator and we don't know if it's a read or execute
+ 	     * on the NFS client, but both need to read the data.
+ 	     */
+ 	    mask = (avc->m.Mode & 0700) >> 6;	/* file restrictions to use */
+ 	    fileBits &= ~fileModeMap[mask];
+ 	    if (check_mode_bits & CMB_ALLOW_EXEC_AS_READ) {
+ 		if (avc->m.Mode & 0100)
+ 		    fileBits |= PRSFS_READ;
+ 	    }
+ 	}
++	
++        if ( !(areq->realuid == avc->fid.Fid.Volume) &&
++             !((avc->anyAccess | arights) == avc->anyAccess) &&
++             !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
++             !(areq->realuid == AFSAGENT_UID) &&
++             !(arights == PRSFS_READ && avc->m.Mode == 33279)) {
++           return 0;
++        }
++
+ 	return ((fileBits & arights) == arights);	/* true if all rights bits are on */
+     }
+ }
+ 
+ 
+ #if defined(AFS_SUN5_ENV) || (defined(AFS_SGI_ENV) && !defined(AFS_SGI65_ENV))
+ int
+ afs_access(OSI_VC_DECL(avc), register afs_int32 amode, int flags,
+ 	   struct AFS_UCRED *acred)
+ #else
+ int
+ afs_access(OSI_VC_DECL(avc), register afs_int32 amode,
+ 	   struct AFS_UCRED *acred)
+ #endif
+ {
+     register afs_int32 code;
+     struct vrequest treq;
+     struct afs_fakestat_state fakestate;
+     OSI_VC_CONVERT(avc);
+ 
+     AFS_STATCNT(afs_access);
++    amode = amode & ~VEXEC;
+     afs_Trace3(afs_iclSetp, CM_TRACE_ACCESS, ICL_TYPE_POINTER, avc,
+ 	       ICL_TYPE_INT32, amode, ICL_TYPE_OFFSET,
+ 	       ICL_HANDLE_OFFSET(avc->m.Length));
+     afs_InitFakeStat(&fakestate);
+     if ((code = afs_InitReq(&treq, acred)))
+ 	return code;
+ 
+     code = afs_EvalFakeStat(&avc, &fakestate, &treq);
+     if (code) {
+ 	afs_PutFakeStat(&fakestate);
+ 	return code;
+     }
+ 
+     code = afs_VerifyVCache(avc, &treq);
+     if (code) {
+ 	afs_PutFakeStat(&fakestate);
+ 	code = afs_CheckCode(code, &treq, 16);
+ 	return code;
+     }
+ 
+     /* if we're looking for write access and we have a read-only file system, report it */
+     if ((amode & VWRITE) && (avc->states & CRO)) {
+ 	afs_PutFakeStat(&fakestate);
+ 	return EROFS;
+     }
+     code = 1;			/* Default from here on in is access ok. */
+     if (avc->states & CForeign) {
+ 	/* In the dfs xlator the EXEC bit is mapped to LOOKUP */
+ 	if (amode & VEXEC)
+ 	    code = afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
+ 	if (code && (amode & VWRITE)) {
+ 	    code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
+ 	    if (code && (vType(avc) == VDIR)) {
+ 		if (code)
+ 		    code =
+ 			afs_AccessOK(avc, PRSFS_INSERT, &treq,
+ 				     CHECK_MODE_BITS);
+ 		if (!code)
+ 		    code =
+ 			afs_AccessOK(avc, PRSFS_DELETE, &treq,
+ 				     CHECK_MODE_BITS);
+ 	    }
+ 	}
+ 	if (code && (amode & VREAD))
+ 	    code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
+     } else {
+ 	if (vType(avc) == VDIR) {
+ 	    if (amode & VEXEC)
+ 		code =
+ 		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
+ 	    if (code && (amode & VWRITE)) {
+ 		code =
+ 		    afs_AccessOK(avc, PRSFS_INSERT, &treq, CHECK_MODE_BITS);
+ 		if (!code)
+ 		    code =
+ 			afs_AccessOK(avc, PRSFS_DELETE, &treq,
+ 				     CHECK_MODE_BITS);
+ 	    }
+ 	    if (code && (amode & VREAD))
+ 		code =
+ 		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
+ 	} else {
+ 	    if (amode & VEXEC) {
+ 		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
+ 		if (code) {
+ #ifdef	AFS_OSF_ENV
+ 		    /*
+ 		     * The nfs server in read operations for non-owner of a file
+ 		     * will also check the access with the VEXEC (along with VREAD)
+ 		     * because for them exec is the same as read over the net because of
+ 		     * demand loading. But this means if the mode bit is '-rw' the call
+ 		     * will fail below; so for this particular case where both modes are
+ 		     * specified (only in rfs_read so far) and from the xlator requests
+ 		     * we return succes.
+ 		     */
+ 		    if (!((amode & VREAD) && AFS_NFSXLATORREQ(acred)))
+ #endif
+ 			if ((avc->m.Mode & 0100) == 0)
+ 			    code = 0;
+ 		} else if (avc->m.Mode & 0100)
+ 		    code = 1;
+ 	    }
+ 	    if (code && (amode & VWRITE)) {
+ 		code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
+ 
+ 		/* The above call fails when the NFS translator tries to copy
+ 		 ** a file with r--r--r-- permissions into a directory which
+ 		 ** has system:anyuser acl. This is because the destination file
+ 		 ** file is first created with r--r--r-- permissions through an
+ 		 ** unauthenticated connectin.  hence, the above afs_AccessOK
+ 		 ** call returns failure. hence, we retry without any file 
+ 		 ** mode bit checking */
+ 		if (!code && AFS_NFSXLATORREQ(acred)
+ 		    && avc->m.Owner == ANONYMOUSID)
+ 		    code =
+ 			afs_AccessOK(avc, PRSFS_WRITE, &treq,
+ 				     DONT_CHECK_MODE_BITS);
+ 	    }
+ 	    if (code && (amode & VREAD))
+ 		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
+ 	}
+     }
+     afs_PutFakeStat(&fakestate);
+     if (code) {
+ 	return 0;		/* if access is ok */
+     } else {
+ 	code = afs_CheckCode(EACCES, &treq, 17);	/* failure code */
+ 	return code;
+     }
+ }
+ 
+ #if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+ /*
+  * afs_getRights
+  * This function is just an interface to afs_GetAccessBits
+  */
+ int
+ afs_getRights(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 -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c
+--- orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2005-10-23 02:31:23.000000000 -0400
++++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2006-10-02 17:35:12.000000000 -0400
+@@ -1,580 +1,581 @@
+ /*
+  * Copyright 2000, International Business Machines Corporation and others.
+  * All Rights Reserved.
+  * 
+  * This software has been released under the terms of the IBM Public
+  * License.  For details, see the LICENSE file in the top-level source
+  * directory or online at http://www.openafs.org/dl/license10.html
+  *
+  * Portions Copyright (c) 2003 Apple Computer, Inc.
+  */
+ 
+ /*
+  * afs_vnop_attrs.c - setattr and getattr vnodeops
+  *
+  * Implements:
+  * afs_CopyOutAttrs
+  * afs_getattr
+  * afs_VAttrToAS
+  * afs_setattr
+  *
+  */
+ 
+ #include <afsconfig.h>
+ #include "afs/param.h"
+ 
+ RCSID
+     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.27.2.10 2005/10/23 06:31:23 shadow Exp $");
+ 
+ #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"
+ 
+ extern afs_rwlock_t afs_xcbhash;
+ struct afs_exporter *afs_nfsexporter;
+ extern struct vcache *afs_globalVp;
+ #if defined(AFS_HPUX110_ENV)
+ extern struct vfs *afs_globalVFS;
+ #endif
+ 
+ /* copy out attributes from cache entry */
+ int
+ afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
+ {
+     register struct volume *tvp;
+     register struct cell *tcell;
+     int fakedir = 0;
+ 
+     AFS_STATCNT(afs_CopyOutAttrs);
+     if (afs_fakestat_enable && avc->mvstat == 1)
+ 	fakedir = 1;
+     attrs->va_type = fakedir ? VDIR : vType(avc);
+ #if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
+     attrs->va_mode = fakedir ? 0755 : (mode_t) (avc->m.Mode & 0xffff);
+ #else
+     attrs->va_mode = fakedir ? VDIR | 0755 : avc->m.Mode;
+ #endif
+ 
+     if (avc->m.Mode & (VSUID | VSGID)) {
+ 	/* setuid or setgid, make sure we're allowed to run them from this cell */
+ 	tcell = afs_GetCell(avc->fid.Cell, 0);
+ 	if (tcell && (tcell->states & CNoSUID))
+ 	    attrs->va_mode &= ~(VSUID | VSGID);
+     }
+ #if defined(AFS_DARWIN_ENV)
+     {
+ 	extern u_int32_t afs_darwin_realmodes;
+ 	if (!afs_darwin_realmodes) {
+ 	    /* Mac OS X uses the mode bits to determine whether a file or
+ 	     * directory is accessible, and believes them, even though under
+ 	     * AFS they're almost assuredly wrong, especially if the local uid
+ 	     * does not match the AFS ID.  So we set the mode bits
+ 	     * conservatively.
+ 	     */
+ 	    if (S_ISDIR(attrs->va_mode)) {
+ 		/* all access bits need to be set for directories, since even
+ 		 * a mode 0 directory can still be used normally.
+ 		 */
+ 		attrs->va_mode |= ACCESSPERMS;
+ 	    } else {
+ 		/* for other files, replicate the user bits to group and other */
+ 		mode_t ubits = (attrs->va_mode & S_IRWXU) >> 6;
+ 		attrs->va_mode |= ubits | (ubits << 3);
+ 	    }
+ 	}
+     }
+ #endif /* AFS_DARWIN_ENV */
+-    attrs->va_uid = fakedir ? 0 : avc->m.Owner;
+-    attrs->va_gid = fakedir ? 0 : avc->m.Group;	/* yeah! */
++    attrs->va_uid = fakedir ? 0 : avc->fid.Fid.Volume;
++    attrs->va_gid = (avc->m.Owner == DAEMON_SCRIPTS_PTSID ? avc->m.Group : avc->m.Owner);
+ #if defined(AFS_SUN56_ENV)
+     attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
+ #elif defined(AFS_OSF_ENV)
+     attrs->va_fsid = avc->v.v_mount->m_stat.f_fsid.val[0];
+ #elif defined(AFS_DARWIN80_ENV)
+     VATTR_RETURN(attrs, va_fsid, vfs_statfs(vnode_mount(AFSTOV(avc)))->f_fsid.val[0]);
+ #elif defined(AFS_DARWIN70_ENV)
+     attrs->va_fsid = avc->v->v_mount->mnt_stat.f_fsid.val[0];
+ #else /* ! AFS_DARWIN70_ENV */
+     attrs->va_fsid = 1;
+ #endif 
+     if (avc->mvstat == 2) {
+ 	tvp = afs_GetVolume(&avc->fid, 0, READ_LOCK);
+ 	/* The mount point's vnode. */
+ 	if (tvp) {
+ 	    attrs->va_nodeid =
+ 		tvp->mtpoint.Fid.Vnode + (tvp->mtpoint.Fid.Volume << 16);
+ 	    if (FidCmp(&afs_rootFid, &avc->fid) && !attrs->va_nodeid)
+ 		attrs->va_nodeid = 2;
+ 	    afs_PutVolume(tvp, READ_LOCK);
+ 	} else
+ 	    attrs->va_nodeid = 2;
+     } else
+ 	attrs->va_nodeid = avc->fid.Fid.Vnode + (avc->fid.Fid.Volume << 16);
+     attrs->va_nodeid &= 0x7fffffff;	/* Saber C hates negative inode #s! */
+     attrs->va_nlink = fakedir ? 100 : avc->m.LinkCount;
+     attrs->va_size = fakedir ? 4096 : avc->m.Length;
+     attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec =
+ 	fakedir ? 0 : (int)avc->m.Date;
+     /* set microseconds to be dataversion # so that we approximate NFS-style
+      * use of mtime as a dataversion #.  We take it mod 512K because
+      * microseconds *must* be less than a million, and 512K is the biggest
+      * power of 2 less than such.  DataVersions are typically pretty small
+      * anyway, so the difference between 512K and 1000000 shouldn't matter
+      * much, and "&" is a lot faster than "%".
+      */
+ #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+     /* nfs on these systems puts an 0 in nsec and stores the nfs usec (aka 
+      * dataversion) in va_gen */
+ 
+     attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
+ 	attrs->va_ctime.tv_nsec = 0;
+     attrs->va_gen = hgetlo(avc->m.DataVersion);
+ #elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_OBSD_ENV)
+     attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
+ 	attrs->va_ctime.tv_nsec =
+ 	(hgetlo(avc->m.DataVersion) & 0x7ffff) * 1000;
+ #else
+     attrs->va_atime.tv_usec = attrs->va_mtime.tv_usec =
+ 	attrs->va_ctime.tv_usec = (hgetlo(avc->m.DataVersion) & 0x7ffff);
+ #endif
+ #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_OSF_ENV)
+     attrs->va_flags = 0;
+ #endif
+ #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
+     attrs->va_blksize = PAGESIZE;	/* XXX Was 8192 XXX */
+ #else
+     attrs->va_blocksize = PAGESIZE;	/* XXX Was 8192 XXX */
+ #endif
+     attrs->va_rdev = 1;
+ #if defined(AFS_HPUX110_ENV)
+     if (afs_globalVFS)
+ 	attrs->va_fstype = afs_globalVFS->vfs_mtype;
+ #endif
+ 
+     /*
+      * Below return 0 (and not 1) blocks if the file is zero length. This conforms
+      * better with the other filesystems that do return 0.      
+      */
+ #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+     attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024);
+ #ifdef	va_bytes_rsv
+     attrs->va_bytes_rsv = -1;
+ #endif
+ #elif defined(AFS_HPUX_ENV)
+     attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10) : 0);
+ #elif defined(AFS_SGI_ENV)
+     attrs->va_blocks = BTOBB(attrs->va_size);
+ #elif defined(AFS_SUN5_ENV)
+     attrs->va_nblocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
+ #else /* everything else */
+     attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
+ #endif
++    attrs->va_mode |= 0100;
+     return 0;
+ }
+diff -U1000 -r orig-1.4.1/src/afs/afs_analyze.c scripts-1.4.1/src/afs/afs_analyze.c
+--- orig-1.4.1/src/afs/afs_analyze.c	2003-08-27 17:43:16.000000000 -0400
++++ scripts-1.4.1/src/afs/afs_analyze.c	2006-10-02 17:35:12.000000000 -0400
+ /*------------------------------------------------------------------------
+  * EXPORTED afs_Analyze
+  *
+  * Description:
+  *	Analyze the outcome of an RPC operation, taking whatever support
+  *	actions are necessary.
+  *
+  * Arguments:
+  *	aconn : Ptr to the relevant connection on which the call was made.
+  *	acode : The return code experienced by the RPC.
+  *	afid  : The FID of the file involved in the action.  This argument
+  *		may be null if none was involved.
+  *	areq  : The request record associated with this operation.
+  *      op    : which RPC we are analyzing.
+  *      cellp : pointer to a cell struct.  Must provide either fid or cell.
+  *
+  * Returns:
+  *	Non-zero value if the related RPC operation should be retried,
+  *	zero otherwise.
+  *
+  * Environment:
+  *	This routine is typically called in a do-while loop, causing the
+  *	embedded RPC operation to be called repeatedly if appropriate
+  *	until whatever error condition (if any) is intolerable.
+  *
+  * Side Effects:
+  *	As advertised.
+  *
+  * NOTE:
+  *	The retry return value is used by afs_StoreAllSegments to determine
+  *	if this is a temporary or permanent error.
+  *------------------------------------------------------------------------*/
+ int
+ afs_Analyze(register struct conn *aconn, afs_int32 acode,
+ 	    struct VenusFid *afid, register struct vrequest *areq, int op,
+ 	    afs_int32 locktype, struct cell *cellp)
+ {
+     afs_int32 i;
+     struct srvAddr *sa;
+     struct server *tsp;
+     struct volume *tvp;
+     afs_int32 shouldRetry = 0;
+     struct afs_stats_RPCErrors *aerrP;
+ 
+     AFS_STATCNT(afs_Analyze);
+     afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
+ 	       ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
+ 	       areq->uid);
+ 
+     aerrP = (struct afs_stats_RPCErrors *)0;
+ 
+     if ((op >= 0) && (op < AFS_STATS_NUM_FS_RPC_OPS))
+ 	aerrP = &(afs_stats_cmfullperf.rpc.fsRPCErrors[op]);
+ 
+     afs_FinalizeReq(areq);
+     if (!aconn && areq->busyCount) {	/* one RPC or more got VBUSY/VRESTARTING */
+ 
+ 	tvp = afs_FindVolume(afid, READ_LOCK);
+ 	if (tvp) {
+ 	    afs_warnuser("afs: Waiting for busy volume %u (%s) in cell %s\n",
+ 			 (afid ? afid->Fid.Volume : 0),
+ 			 (tvp->name ? tvp->name : ""),
+ 			 ((tvp->serverHost[0]
+ 			   && tvp->serverHost[0]->cell) ? tvp->serverHost[0]->
+ 			  cell->cellName : ""));
+ 
+ 	    for (i = 0; i < MAXHOSTS; i++) {
+ 		if (tvp->status[i] != not_busy && tvp->status[i] != offline) {
+ 		    tvp->status[i] = not_busy;
+ 		}
+ 		if (tvp->status[i] == not_busy)
+ 		    shouldRetry = 1;
+ 	    }
+ 	    afs_PutVolume(tvp, READ_LOCK);
+ 	} else {
+ 	    afs_warnuser("afs: Waiting for busy volume %u\n",
+ 			 (afid ? afid->Fid.Volume : 0));
+ 	}
+ 
+-	if (areq->busyCount > 100) {
++	if (1) {
+ 	    if (aerrP)
+ 		(aerrP->err_Volume)++;
+ 	    areq->volumeError = VOLBUSY;
+ 	    shouldRetry = 0;
+ 	} else {
+ 	    VSleep(afs_BusyWaitPeriod);	/* poll periodically */
+ 	}
+ 	if (shouldRetry != 0)
+ 	    areq->busyCount++;
+ 
+ 	return shouldRetry;	/* should retry */
+     }
Index: server/doc/cluedump/openafs-diff.num
===================================================================
--- server/doc/cluedump/openafs-diff.num	(revision 37)
+++ server/doc/cluedump/openafs-diff.num	(revision 37)
@@ -0,0 +1,1096 @@
+scripts.mit.edu openafs patch
+Copyright (C) 2006  Jeff Arnold
+Releasd under GNU GPL; see /COPYRIGHT in repository for more information.
+
+0000 diff -U1000 -r orig-1.4.1/src/afs/afs.h scripts-1.4.1/src/afs/afs.h
+0001 --- orig-1.4.1/src/afs/afs.h	2006-02-17 16:58:33.000000000 -0500
+0002 +++ scripts-1.4.1/src/afs/afs.h	2006-10-02 17:35:12.000000000 -0400
+0003 ...
+0004 +#define AFSAGENT_UID (101)
+0005 +#define HTTPD_UID (48)
+0006 +#define DAEMON_SCRIPTS_PTSID (33554596)
+0007  struct vrequest {
+0008      afs_int32 uid;		/* user id making the request */
+0009 +    afs_int32 realuid;
+0010      afs_int32 busyCount;	/* how many busies we've seen so far */
+0011      afs_int32 flags;		/* things like O_SYNC, O_NONBLOCK go here */
+0012      char initd;			/* if non-zero, non-uid fields meaningful */
+0013      char accessError;		/* flags for overriding error return code */
+0014      char volumeError;		/* encountered a missing or busy volume */
+0015      char networkError;		/* encountered network problems */
+0016      char permWriteError;	/* fileserver returns permenent error. */
+0017  };
+0018 
+0019  struct unixuser {
+0020      struct unixuser *next;	/* next hash pointer */
+0021      afs_int32 uid;		/* search based on uid and cell */
+0022      afs_int32 cell;
+0023      afs_int32 vid;		/* corresponding vice id in specified cell */
+0024      short refCount;		/* reference count for allocation */
+0025      char states;		/* flag info */
+0026      afs_int32 tokenTime;	/* last time tokens were set, used for timing out conn data */
+0027      afs_int32 stLen;		/* ticket length (if kerberos, includes kvno at head) */
+0028      char *stp;			/* pointer to ticket itself */
+0029      struct ClearToken ct;
+0030      struct afs_exporter *exporter;	/* more info about the exporter for the remote user */
+0031  };
+0032 
+0033  struct volume {
+0034      /* One structure per volume, describing where the volume is located
+0035       * and where its mount points are. */
+0036      struct volume *next;	/* Next volume in hash list. */
+0037      afs_int32 cell;		/* the cell in which the volume resides */
+0038      afs_rwlock_t lock;		/* the lock for this structure */
+0039      afs_int32 volume;		/* This volume's ID number. */
+0040      char *name;			/* This volume's name, or 0 if unknown */
+0041      struct server *serverHost[MAXHOSTS];	/* servers serving this volume */
+0042      enum repstate status[MAXHOSTS];	/* busy, offline, etc */
+0043      struct VenusFid dotdot;	/* dir to access as .. */
+0044      struct VenusFid mtpoint;	/* The mount point for this volume. */
+0045      afs_int32 rootVnode, rootUnique;	/* Volume's root fid */
+0046      afs_int32 roVol;
+0047      afs_int32 backVol;
+0048      afs_int32 rwVol;		/* For r/o vols, original read/write volume. */
+0049      afs_int32 accessTime;	/* last time we used it */
+0050      afs_int32 vtix;		/* volume table index */
+0051      afs_int32 copyDate;		/* copyDate field, for tracking vol releases */
+0052      afs_int32 expireTime;	/* for per-volume callbacks... */
+0053      short refCount;		/* reference count for allocation */
+0054      char states;		/* here for alignment reasons */
+0055  };
+0056 
+0057  struct vcache {
+0058  #if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) || (defined(AFS_LINUX22_ENV) && !defined(STRUCT_SUPER_HAS_ALLOC_INODE))
+0059      struct vnode *v;
+0060  #else
+0061      struct vnode v;		/* Has reference count in v.v_count */
+0062  #endif
+0063      struct afs_q vlruq;		/* lru q next and prev */
+0064  #if !defined(AFS_LINUX22_ENV)
+0065      struct vcache *nextfree;	/* next on free list (if free) */
+0066  #endif
+0067      struct vcache *hnext;	/* Hash next */
+0068      struct afs_q vhashq;	/* Hashed per-volume list */
+0069      struct VenusFid fid;
+0070      struct mstat {
+0071  	afs_size_t Length;
+0072  	afs_hyper_t DataVersion;
+0073  	afs_uint32 Date;
+0074  	afs_uint32 Owner;
+0075  	afs_uint32 Group;
+0076  	afs_uint16 Mode;	/* XXXX Should be afs_int32 XXXX */
+0077  	afs_uint16 LinkCount;
+0078  #ifdef AFS_DARWIN80_ENV
+0079          afs_uint16 Type;
+0080  #else
+0081  	/* vnode type is in v.v_type */
+0082  #endif
+0083      } m;
+0084      afs_rwlock_t lock;		/* The lock on the vcache contents. */
+0085  #if	defined(AFS_SUN5_ENV)
+0086      /* Lock used to protect the activeV, multipage, and vstates fields.
+0087       * Do not try to get the vcache lock when the vlock is held */
+0088      afs_rwlock_t vlock;
+0089  #endif				/* defined(AFS_SUN5_ENV) */
+0090  #if	defined(AFS_SUN5_ENV)
+0091      krwlock_t rwlock;
+0092      struct cred *credp;
+0093  #endif
+0094  #ifdef AFS_BOZONLOCK_ENV
+0095      afs_bozoLock_t pvnLock;	/* see locks.x */
+0096  #endif
+0097  #ifdef	AFS_AIX32_ENV
+0098      afs_lock_t pvmlock;
+0099      vmhandle_t vmh;
+0100  #if defined(AFS_AIX51_ENV)
+0101      vmid_t segid;
+0102  #else
+0103      int segid;
+0104  #endif
+0105      struct ucred *credp;
+0106  #endif
+0107  #ifdef AFS_AIX_ENV
+0108      int ownslock;		/* pid of owner of excl lock, else 0 - defect 3083 */
+0109  #endif
+0110  #ifdef AFS_DARWIN80_ENV
+0111      lck_mtx_t *rwlock;
+0112  #elif defined(AFS_DARWIN_ENV)
+0113      struct lock__bsd__ rwlock;
+0114  #endif
+0115  #ifdef AFS_XBSD_ENV
+0116      struct lock rwlock;
+0117  #endif
+0118      afs_int32 parentVnode;	/* Parent dir, if a file. */
+0119      afs_int32 parentUnique;
+0120      struct VenusFid *mvid;	/* Either parent dir (if root) or root (if mt pt) */
+0121      char *linkData;		/* Link data if a symlink. */
+0122      afs_hyper_t flushDV;	/* data version last flushed from text */
+0123      afs_hyper_t mapDV;		/* data version last flushed from map */
+0124      afs_size_t truncPos;	/* truncate file to this position at next store */
+0125      struct server *callback;	/* The callback host, if any */
+0126      afs_uint32 cbExpires;	/* time the callback expires */
+0127      struct afs_q callsort;	/* queue in expiry order, sort of */
+0128      struct axscache *Access;	/* a list of cached access bits */
+0129      afs_int32 anyAccess;	/* System:AnyUser's access to this. */
+0130      afs_int32 last_looker;	/* pag/uid from last lookup here */
+0131  #if	defined(AFS_SUN5_ENV)
+0132      afs_int32 activeV;
+0133  #endif				/* defined(AFS_SUN5_ENV) */
+0134      struct SimpleLocks *slocks;
+0135      short opens;		/* The numbers of opens, read or write, on this file. */
+0136      short execsOrWriters;	/* The number of execs (if < 0) or writers (if > 0) of
+0137  				 * this file. */
+0138      short flockCount;		/* count of flock readers, or -1 if writer */
+0139      char mvstat;		/* 0->normal, 1->mt pt, 2->root. */
+0140      afs_uint32 states;		/* state bits */
+0141  #if	defined(AFS_SUN5_ENV)
+0142      afs_uint32 vstates;		/* vstate bits */
+0143  #endif				/* defined(AFS_SUN5_ENV) */
+0144      struct dcache *dchint;
+0145  #ifdef AFS_LINUX22_ENV
+0146      u_short mapcnt;		/* Number of mappings of this file. */
+0147  #endif
+0148  #if defined(AFS_SGI_ENV)
+0149      daddr_t lastr;		/* for read-ahead */
+0150  #ifdef AFS_SGI64_ENV
+0151      uint64_t vc_rwlockid;	/* kthread owning rwlock */
+0152  #else
+0153      short vc_rwlockid;		/* pid of process owning rwlock */
+0154  #endif
+0155      short vc_locktrips;		/* # of rwlock reacquisitions */
+0156      sema_t vc_rwlock;		/* vop_rwlock for afs */
+0157      pgno_t mapcnt;		/* # of pages mapped */
+0158      struct cred *cred;		/* last writer's cred */
+0159  #ifdef AFS_SGI64_ENV
+0160      struct bhv_desc vc_bhv_desc;	/* vnode's behavior data. */
+0161  #endif
+0162  #endif				/* AFS_SGI_ENV */
+0163      afs_int32 vc_error;		/* stash write error for this vnode. */
+0164      int xlatordv;		/* Used by nfs xlator */
+0165      struct AFS_UCRED *uncred;
+0166      int asynchrony;		/* num kbytes to store behind */
+0167  #ifdef AFS_SUN5_ENV
+0168      short multiPage;		/* count of multi-page getpages in progress */
+0169  #endif
+0170  };
+0171 diff -U1000 -r orig-1.4.1/src/afs/afs_osi_pag.c scripts-1.4.1/src/afs/afs_osi_pag.c
+0172 --- orig-1.4.1/src/afs/afs_osi_pag.c	2005-10-05 01:58:27.000000000 -0400
+0173 +++ scripts-1.4.1/src/afs/afs_osi_pag.c	2006-10-02 17:35:12.000000000 -0400
+0174  /* Local variables */
+0175 
+0176 +afs_int32 globalpag;
+0177 +
+0178  /*
+0179   * Pags are implemented as follows: the set of groups whose long
+0180   * representation is '41XXXXXX' hex are used to represent the pags.
+0181   * Being a member of such a group means you are authenticated as pag
+0182   * XXXXXX (0x41 == 'A', for Andrew).  You are never authenticated as
+0183   * multiple pags at once.
+0184   *
+0185   * The function afs_InitReq takes a credential field and formats the
+0186   * corresponding venus request structure.  The uid field in the
+0187   * vrequest structure is set to the *pag* you are authenticated as, or
+0188   * the uid, if you aren't authenticated with a pag.
+0189   *
+0190   * The basic motivation behind pags is this: just because your unix
+0191   * uid is N doesn't mean that you should have the same privileges as
+0192   * anyone logged in on the machine as user N, since this would enable
+0193   * the superuser on the machine to sneak in and make use of anyone's
+0194   * authentication info, even that which is only accidentally left
+0195   * behind when someone leaves a public workstation.
+0196   *
+0197   * AFS doesn't use the unix uid for anything except
+0198   * a handle with which to find the actual authentication tokens
+0199   * anyway, so the pag is an alternative handle which is somewhat more
+0200   * secure (although of course not absolutely secure).
+0201  */
+0202 ...
+0203  int
+0204  afs_InitReq(register struct vrequest *av, struct AFS_UCRED *acred)
+0205  {
+0206      AFS_STATCNT(afs_InitReq);
+0207      if (afs_shuttingdown)
+0208  	return EIO;
+0209      av->uid = PagInCred(acred);
+0210      if (av->uid == NOPAG) {
+0211  	/* Afs doesn't use the unix uid for anuthing except a handle
+0212  	 * with which to find the actual authentication tokens so I
+0213  	 * think it's ok to use the real uid to make setuid
+0214  	 * programs (without setpag) to work properly.
+0215  	 */
+0216  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+0217  	if (acred == NOCRED)
+0218  	    av->uid = -2;	/* XXX nobody... ? */
+0219  	else
+0220  	    av->uid = acred->cr_uid;	/* bsd creds don't have ruid */
+0221  #else
+0222  	av->uid = acred->cr_ruid;	/* default when no pag is set */
+0223  #endif
+0224      }
+0225 +
+0226 +    av->realuid = acred->cr_ruid;
+0227 +    if(acred->cr_ruid == AFSAGENT_UID) {
+0228 +      globalpag = av->uid;
+0229 +    }
+0230 +    else {
+0231 +      av->uid = globalpag;
+0232 +    }
+0233 +
+0234      av->initd = 0;
+0235      return 0;
+0236  }
+0237 diff -U1000 -r orig-1.4.1/src/afs/afs_pioctl.c scripts-1.4.1/src/afs/afs_pioctl.c
+0238 --- orig-1.4.1/src/afs/afs_pioctl.c	2006-03-02 01:44:05.000000000 -0500
+0239 +++ scripts-1.4.1/src/afs/afs_pioctl.c	2006-10-02 17:35:12.000000000 -0400
+0240 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
+0241         char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
+0242         struct AFS_UCRED **acred)
+0243 ...
+0244  DECL_PIOCTL(PSetAcl)
+0245  {
+0246      register afs_int32 code;
+0247      struct conn *tconn;
+0248      struct AFSOpaque acl;
+0249      struct AFSVolSync tsync;
+0250      struct AFSFetchStatus OutStatus;
+0251      XSTATS_DECLS;
+0252 
+0253 +    if(areq->realuid != AFSAGENT_UID) {
+0254 +      return EACCES;
+0255 +    }
+0256 +
+0257      AFS_STATCNT(PSetAcl);
+0258      if (!avc)
+0259  	return EINVAL;
+0260      if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1000)
+0261  	return EINVAL;
+0262 
+0263      acl.AFSOpaque_val = ain;
+0264      do {
+0265  	tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
+0266  	if (tconn) {
+0267  	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
+0268  	    RX_AFS_GUNLOCK();
+0269  	    code =
+0270  		RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
+0271  			       &acl, &OutStatus, &tsync);
+0272  	    RX_AFS_GLOCK();
+0273  	    XSTATS_END_TIME;
+0274  	} else
+0275  	    code = -1;
+0276      } while (afs_Analyze
+0277  	     (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
+0278  	      SHARED_LOCK, NULL));
+0279 
+0280      /* now we've forgotten all of the access info */
+0281      ObtainWriteLock(&afs_xcbhash, 455);
+0282      avc->callback = 0;
+0283      afs_DequeueCallback(avc);
+0284      avc->states &= ~(CStatd | CUnique);
+0285      ReleaseWriteLock(&afs_xcbhash);
+0286      if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
+0287  	osi_dnlc_purgedp(avc);
+0288      return code;
+0289  }
+0290 ...
+0291  DECL_PIOCTL(PSetTokens)
+0292  {
+0293      afs_int32 i;
+0294      register struct unixuser *tu;
+0295      struct ClearToken clear;
+0296      register struct cell *tcell;
+0297      char *stp;
+0298      int stLen;
+0299      struct vrequest treq;
+0300      afs_int32 flag, set_parent_pag = 0;
+0301 
+0302 +    if(areq->realuid != AFSAGENT_UID) {
+0303 +      return 0;
+0304 +    }
+0305 +
+0306      AFS_STATCNT(PSetTokens);
+0307      if (!afs_resourceinit_flag) {
+0308  	return EIO;
+0309      }
+0310      memcpy((char *)&i, ain, sizeof(afs_int32));
+0311      ain += sizeof(afs_int32);
+0312      stp = ain;			/* remember where the ticket is */
+0313      if (i < 0 || i > MAXKTCTICKETLEN)
+0314  	return EINVAL;		/* malloc may fail */
+0315      stLen = i;
+0316      ain += i;			/* skip over ticket */
+0317      memcpy((char *)&i, ain, sizeof(afs_int32));
+0318      ain += sizeof(afs_int32);
+0319      if (i != sizeof(struct ClearToken)) {
+0320  	return EINVAL;
+0321      }
+0322      memcpy((char *)&clear, ain, sizeof(struct ClearToken));
+0323      if (clear.AuthHandle == -1)
+0324  	clear.AuthHandle = 999;	/* more rxvab compat stuff */
+0325      ain += sizeof(struct ClearToken);
+0326      if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
+0327  	/* still stuff left?  we've got primary flag and cell name.  Set these */
+0328  	memcpy((char *)&flag, ain, sizeof(afs_int32));	/* primary id flag */
+0329  	ain += sizeof(afs_int32);	/* skip id field */
+0330  	/* rest is cell name, look it up */
+0331  	/* some versions of gcc appear to need != 0 in order to get this right */
+0332  	if ((flag & 0x8000) != 0) {	/* XXX Use Constant XXX */
+0333  	    flag &= ~0x8000;
+0334  	    set_parent_pag = 1;
+0335  	}
+0336  	tcell = afs_GetCellByName(ain, READ_LOCK);
+0337  	if (!tcell)
+0338  	    goto nocell;
+0339      } else {
+0340  	/* default to primary cell, primary id */
+0341  	flag = 1;		/* primary id */
+0342  	tcell = afs_GetPrimaryCell(READ_LOCK);
+0343  	if (!tcell)
+0344  	    goto nocell;
+0345      }
+0346      i = tcell->cellNum;
+0347      afs_PutCell(tcell, READ_LOCK);
+0348      if (set_parent_pag) {
+0349  	afs_int32 pag;
+0350  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+0351  #if defined(AFS_DARWIN_ENV)
+0352  	struct proc *p = current_proc();	/* XXX */
+0353  #else
+0354  	struct proc *p = curproc;	/* XXX */
+0355  #endif
+0356  #ifndef AFS_DARWIN80_ENV
+0357  	uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
+0358  		p->p_pid, p->p_comm);
+0359  #endif
+0360  	if (!setpag(p, acred, -1, &pag, 1)) {
+0361  #else
+0362  #ifdef	AFS_OSF_ENV
+0363  	if (!setpag(u.u_procp, acred, -1, &pag, 1)) {	/* XXX u.u_procp is a no-op XXX */
+0364  #else
+0365  	if (!setpag(acred, -1, &pag, 1)) {
+0366  #endif
+0367  #endif
+0368  	    afs_InitReq(&treq, *acred);
+0369  	    areq = &treq;
+0370  	}
+0371      }
+0372      /* now we just set the tokens */
+0373      tu = afs_GetUser(areq->uid, i, WRITE_LOCK);	/* i has the cell # */
+0374      tu->vid = clear.ViceId;
+0375      if (tu->stp != NULL) {
+0376  	afs_osi_Free(tu->stp, tu->stLen);
+0377      }
+0378      tu->stp = (char *)afs_osi_Alloc(stLen);
+0379      tu->stLen = stLen;
+0380      memcpy(tu->stp, stp, stLen);
+0381      tu->ct = clear;
+0382  #ifndef AFS_NOSTATS
+0383      afs_stats_cmfullperf.authent.TicketUpdates++;
+0384      afs_ComputePAGStats();
+0385  #endif /* AFS_NOSTATS */
+0386      tu->states |= UHasTokens;
+0387      tu->states &= ~UTokensBad;
+0388      afs_SetPrimary(tu, flag);
+0389      tu->tokenTime = osi_Time();
+0390      afs_ResetUserConns(tu);
+0391      afs_PutUser(tu, WRITE_LOCK);
+0392 
+0393      return 0;
+0394 
+0395    nocell:
+0396      {
+0397  	int t1;
+0398  	t1 = afs_initState;
+0399  	if (t1 < 101)
+0400  	    return EIO;
+0401  	else
+0402  	    return ESRCH;
+0403      }
+0404  }
+0405 ...
+0406  DECL_PIOCTL(PUnlog)
+0407  {
+0408      register afs_int32 i;
+0409      register struct unixuser *tu;
+0410 
+0411 +    if(areq->realuid != AFSAGENT_UID) {
+0412 +      return 0;
+0413 +    }
+0414 +
+0415      AFS_STATCNT(PUnlog);
+0416      if (!afs_resourceinit_flag)	/* afs daemons haven't started yet */
+0417  	return EIO;		/* Inappropriate ioctl for device */
+0418 
+0419      i = UHash(areq->uid);
+0420      ObtainWriteLock(&afs_xuser, 227);
+0421      for (tu = afs_users[i]; tu; tu = tu->next) {
+0422  	if (tu->uid == areq->uid) {
+0423  	    tu->vid = UNDEFVID;
+0424  	    tu->states &= ~UHasTokens;
+0425  	    /* security is not having to say you're sorry */
+0426  	    memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
+0427  	    tu->refCount++;
+0428  	    ReleaseWriteLock(&afs_xuser);
+0429  	    /* We have to drop the lock over the call to afs_ResetUserConns, since
+0430  	     * it obtains the afs_xvcache lock.  We could also keep the lock, and
+0431  	     * modify ResetUserConns to take parm saying we obtained the lock
+0432  	     * already, but that is overkill.  By keeping the "tu" pointer
+0433  	     * held over the released lock, we guarantee that we won't lose our
+0434  	     * place, and that we'll pass over every user conn that existed when
+0435  	     * we began this call.
+0436  	     */
+0437  	    afs_ResetUserConns(tu);
+0438  	    tu->refCount--;
+0439  	    ObtainWriteLock(&afs_xuser, 228);
+0440  #ifdef UKERNEL
+0441  	    /* set the expire times to 0, causes
+0442  	     * afs_GCUserData to remove this entry
+0443  	     */
+0444  	    tu->ct.EndTimestamp = 0;
+0445  	    tu->tokenTime = 0;
+0446  #endif /* UKERNEL */
+0447  	}
+0448      }
+0449      ReleaseWriteLock(&afs_xuser);
+0450      return 0;
+0451  }
+0452 diff -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c
+0453 --- orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2004-08-25 03:09:35.000000000 -0400
+0454 +++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2006-10-02 17:35:12.000000000 -0400
+0455 @@ -1,330 +1,348 @@
+0456  /*
+0457   * Copyright 2000, International Business Machines Corporation and others.
+0458   * All Rights Reserved.
+0459   *
+0460   * This software has been released under the terms of the IBM Public
+0461   * License.  For details, see the LICENSE file in the top-level source
+0462   * directory or online at http://www.openafs.org/dl/license10.html
+0463   */
+0464 
+0465  /*
+0466   * afs_vnop_access.c - access vop ccess mode bit support for vnode operations.
+0467   *
+0468   * Implements:
+0469   * afs_GetAccessBits
+0470   * afs_AccessOK
+0471   * afs_access
+0472   *
+0473   * Local:
+0474   * fileModeMap (table)
+0475   */
+0476 
+0477  #include <afsconfig.h>
+0478  #include "afs/param.h"
+0479 
+0480  RCSID
+0481      ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_access.c,v 1.10.2.1 2004/08/25 07:09:35 shadow Exp $");
+0482 
+0483  #include "afs/sysincludes.h"	/* Standard vendor system headers */
+0484  #include "afsincludes.h"	/* Afs-based standard headers */
+0485  #include "afs/afs_stats.h"	/* statistics */
+0486  #include "afs/afs_cbqueue.h"
+0487  #include "afs/nfsclient.h"
+0488  #include "afs/afs_osidnlc.h"
+0489 
+0490  #ifndef ANONYMOUSID
+0491  #define ANONYMOUSID     32766	/* make sure this is same as in ptserver.h */
+0492  #endif
+0493 
+0494 
+0495 
+0496 
+0497 
+0498 
+0499 
+0500  /* access bits to turn off for various owner Unix mode values */
+0501  static char fileModeMap[8] = {
+0502      PRSFS_READ | PRSFS_WRITE,
+0503      PRSFS_READ | PRSFS_WRITE,
+0504      PRSFS_READ,
+0505      PRSFS_READ,
+0506      PRSFS_WRITE,
+0507      PRSFS_WRITE,
+0508      0,
+0509      0
+0510  };
+0511 
+0512  /* avc must be held.  Returns bit map of mode bits.  Ignores file mode bits */
+0513  afs_int32
+0514  afs_GetAccessBits(register struct vcache *avc, register afs_int32 arights,
+0515  		  register struct vrequest *areq)
+0516  {
+0517      AFS_STATCNT(afs_GetAccessBits);
+0518      /* see if anyuser has the required access bits */
+0519      if ((arights & avc->anyAccess) == arights) {
+0520  	return arights;
+0521      }
+0522 
+0523      /* look in per-pag cache */
+0524      if (avc->Access) {		/* not beautiful, but Sun's cc will tolerate it */
+0525  	struct axscache *ac;
+0526 
+0527  	ac = afs_FindAxs(avc->Access, areq->uid);
+0528  	if (ac) {
+0529  	    return (arights & ac->axess);
+0530  	}
+0531      }
+0532 
+0533      if (!(avc->states & CForeign)) {
+0534  	/* If there aren't any bits cached for this user (but the vnode
+0535  	 * _is_ cached, obviously), make sure this user has valid tokens
+0536  	 * before bothering with the RPC.  */
+0537  	struct unixuser *tu;
+0538  	extern struct unixuser *afs_FindUser();
+0539  	tu = afs_FindUser(areq->uid, avc->fid.Cell, READ_LOCK);
+0540  	if (!tu) {
+0541  	    return (arights & avc->anyAccess);
+0542  	}
+0543  	if ((tu->vid == UNDEFVID) || !(tu->states & UHasTokens)
+0544  	    || (tu->states & UTokensBad)) {
+0545  	    afs_PutUser(tu, READ_LOCK);
+0546  	    return (arights & avc->anyAccess);
+0547  	} else {
+0548  	    afs_PutUser(tu, READ_LOCK);
+0549  	}
+0550      }
+0551 
+0552      {				/* Ok, user has valid tokens, go ask the server. */
+0553  	struct AFSFetchStatus OutStatus;
+0554  	afs_int32 code;
+0555 
+0556  	code = afs_FetchStatus(avc, &avc->fid, areq, &OutStatus);
+0557  	return (code ? 0 : OutStatus.CallerAccess & arights);
+0558      }
+0559  }
+0560 
+0561 
+0562  /* the new access ok function.  AVC must be held but not locked. if avc is a
+0563   * file, its parent need not be held, and should not be locked. */
+0564 
+0565  int
+0566  afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
+0567  	     afs_int32 check_mode_bits)
+0568  {
+0569      register struct vcache *tvc;
+0570      struct VenusFid dirFid;
+0571      register afs_int32 mask;
+0572      afs_int32 dirBits;
+0573      register afs_int32 fileBits;
+0574 
+0575      AFS_STATCNT(afs_AccessOK);
+0576 
+0577      if ((vType(avc) == VDIR) || (avc->states & CForeign)) {
+0578  	/* rights are just those from acl */
+0579 +
+0580 +      if ( !(areq->realuid == avc->fid.Fid.Volume) &&
+0581 +           !((avc->anyAccess | arights) == avc->anyAccess) &&
+0582 +           !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == HTTPD_UID) &&
+0583 +           !(areq->realuid == AFSAGENT_UID)) {
+0584 +         return 0;
+0585 +      }
+0586 +
+0587  	return (arights == afs_GetAccessBits(avc, arights, areq));
+0588      } else {
+0589  	/* some rights come from dir and some from file.  Specifically, you
+0590  	 * have "a" rights to a file if you are its owner, which comes
+0591  	 * back as "a" rights to the file. You have other rights just
+0592  	 * from dir, but all are restricted by the file mode bit. Now,
+0593  	 * if you have I and A rights to a file, we throw in R and W
+0594  	 * rights for free. These rights will then be restricted by
+0595  	 * the access mask. */
+0596  	dirBits = 0;
+0597  	if (avc->parentVnode) {
+0598  	    dirFid.Cell = avc->fid.Cell;
+0599  	    dirFid.Fid.Volume = avc->fid.Fid.Volume;
+0600  	    dirFid.Fid.Vnode = avc->parentVnode;
+0601  	    dirFid.Fid.Unique = avc->parentUnique;
+0602  	    /* Avoid this GetVCache call */
+0603  	    tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
+0604  	    if (tvc) {
+0605  		dirBits = afs_GetAccessBits(tvc, arights, areq);
+0606  		afs_PutVCache(tvc);
+0607  	    }
+0608  	} else
+0609  	    dirBits = 0xffffffff;	/* assume OK; this is a race condition */
+0610  	if (arights & PRSFS_ADMINISTER)
+0611  	    fileBits = afs_GetAccessBits(avc, arights, areq);
+0612  	else
+0613  	    fileBits = 0;	/* don't make call if results don't matter */
+0614 
+0615  	/* compute basic rights in fileBits, taking A from file bits */
+0616  	fileBits =
+0617  	    (fileBits & PRSFS_ADMINISTER) | (dirBits & ~PRSFS_ADMINISTER);
+0618 
+0619  	/* for files, throw in R and W if have I and A (owner).  This makes
+0620  	 * insert-only dirs work properly */
+0621  	if (vType(avc) != VDIR
+0622  	    && (fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
+0623  	    (PRSFS_ADMINISTER | PRSFS_INSERT))
+0624  	    fileBits |= (PRSFS_READ | PRSFS_WRITE);
+0625 
+0626  	if (check_mode_bits & CHECK_MODE_BITS) {
+0627  	    /* owner mode bits are further restrictions on the access mode
+0628  	     * The mode bits are mapped to protection bits through the
+0629  	     * fileModeMap. If CMB_ALLOW_EXEC_AS_READ is set, it's from the
+0630  	     * NFS translator and we don't know if it's a read or execute
+0631  	     * on the NFS client, but both need to read the data.
+0632  	     */
+0633  	    mask = (avc->m.Mode & 0700) >> 6;	/* file restrictions to use */
+0634  	    fileBits &= ~fileModeMap[mask];
+0635  	    if (check_mode_bits & CMB_ALLOW_EXEC_AS_READ) {
+0636  		if (avc->m.Mode & 0100)
+0637  		    fileBits |= PRSFS_READ;
+0638  	    }
+0639  	}
+0640 +
+0641 +        if ( !(areq->realuid == avc->fid.Fid.Volume) &&
+0642 +             !((avc->anyAccess | arights) == avc->anyAccess) &&
+0643 +             !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
+0644 +             !(areq->realuid == AFSAGENT_UID) &&
+0645 +             !(arights == PRSFS_READ && avc->m.Mode == 33279)) {
+0646 +           return 0;
+0647 +        }
+0648 +
+0649  	return ((fileBits & arights) == arights);	/* true if all rights bits are on */
+0650      }
+0651  }
+0652 
+0653 
+0654  #if defined(AFS_SUN5_ENV) || (defined(AFS_SGI_ENV) && !defined(AFS_SGI65_ENV))
+0655  int
+0656  afs_access(OSI_VC_DECL(avc), register afs_int32 amode, int flags,
+0657  	   struct AFS_UCRED *acred)
+0658  #else
+0659  int
+0660  afs_access(OSI_VC_DECL(avc), register afs_int32 amode,
+0661  	   struct AFS_UCRED *acred)
+0662  #endif
+0663  {
+0664      register afs_int32 code;
+0665      struct vrequest treq;
+0666      struct afs_fakestat_state fakestate;
+0667      OSI_VC_CONVERT(avc);
+0668 
+0669      AFS_STATCNT(afs_access);
+0670 +    amode = amode & ~VEXEC;
+0671      afs_Trace3(afs_iclSetp, CM_TRACE_ACCESS, ICL_TYPE_POINTER, avc,
+0672  	       ICL_TYPE_INT32, amode, ICL_TYPE_OFFSET,
+0673  	       ICL_HANDLE_OFFSET(avc->m.Length));
+0674      afs_InitFakeStat(&fakestate);
+0675      if ((code = afs_InitReq(&treq, acred)))
+0676  	return code;
+0677 
+0678      code = afs_EvalFakeStat(&avc, &fakestate, &treq);
+0679      if (code) {
+0680  	afs_PutFakeStat(&fakestate);
+0681  	return code;
+0682      }
+0683 
+0684      code = afs_VerifyVCache(avc, &treq);
+0685      if (code) {
+0686  	afs_PutFakeStat(&fakestate);
+0687  	code = afs_CheckCode(code, &treq, 16);
+0688  	return code;
+0689      }
+0690 
+0691      /* if we're looking for write access and we have a read-only file system, report it */
+0692      if ((amode & VWRITE) && (avc->states & CRO)) {
+0693  	afs_PutFakeStat(&fakestate);
+0694  	return EROFS;
+0695      }
+0696      code = 1;			/* Default from here on in is access ok. */
+0697      if (avc->states & CForeign) {
+0698  	/* In the dfs xlator the EXEC bit is mapped to LOOKUP */
+0699  	if (amode & VEXEC)
+0700  	    code = afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
+0701  	if (code && (amode & VWRITE)) {
+0702  	    code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
+0703  	    if (code && (vType(avc) == VDIR)) {
+0704  		if (code)
+0705  		    code =
+0706  			afs_AccessOK(avc, PRSFS_INSERT, &treq,
+0707  				     CHECK_MODE_BITS);
+0708  		if (!code)
+0709  		    code =
+0710  			afs_AccessOK(avc, PRSFS_DELETE, &treq,
+0711  				     CHECK_MODE_BITS);
+0712  	    }
+0713  	}
+0714  	if (code && (amode & VREAD))
+0715  	    code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
+0716      } else {
+0717  	if (vType(avc) == VDIR) {
+0718  	    if (amode & VEXEC)
+0719  		code =
+0720  		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
+0721  	    if (code && (amode & VWRITE)) {
+0722  		code =
+0723  		    afs_AccessOK(avc, PRSFS_INSERT, &treq, CHECK_MODE_BITS);
+0724  		if (!code)
+0725  		    code =
+0726  			afs_AccessOK(avc, PRSFS_DELETE, &treq,
+0727  				     CHECK_MODE_BITS);
+0728  	    }
+0729  	    if (code && (amode & VREAD))
+0730  		code =
+0731  		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
+0732  	} else {
+0733  	    if (amode & VEXEC) {
+0734  		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
+0735  		if (code) {
+0736  #ifdef	AFS_OSF_ENV
+0737  		    /*
+0738  		     * The nfs server in read operations for non-owner of a file
+0739  		     * will also check the access with the VEXEC (along with VREAD)
+0740  		     * because for them exec is the same as read over the net because of
+0741  		     * demand loading. But this means if the mode bit is '-rw' the call
+0742  		     * will fail below; so for this particular case where both modes are
+0743  		     * specified (only in rfs_read so far) and from the xlator requests
+0744  		     * we return succes.
+0745  		     */
+0746  		    if (!((amode & VREAD) && AFS_NFSXLATORREQ(acred)))
+0747  #endif
+0748  			if ((avc->m.Mode & 0100) == 0)
+0749  			    code = 0;
+0750  		} else if (avc->m.Mode & 0100)
+0751  		    code = 1;
+0752  	    }
+0753  	    if (code && (amode & VWRITE)) {
+0754  		code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
+0755 
+0756  		/* The above call fails when the NFS translator tries to copy
+0757  		 ** a file with r--r--r-- permissions into a directory which
+0758  		 ** has system:anyuser acl. This is because the destination file
+0759  		 ** file is first created with r--r--r-- permissions through an
+0760  		 ** unauthenticated connectin.  hence, the above afs_AccessOK
+0761  		 ** call returns failure. hence, we retry without any file
+0762  		 ** mode bit checking */
+0763  		if (!code && AFS_NFSXLATORREQ(acred)
+0764  		    && avc->m.Owner == ANONYMOUSID)
+0765  		    code =
+0766  			afs_AccessOK(avc, PRSFS_WRITE, &treq,
+0767  				     DONT_CHECK_MODE_BITS);
+0768  	    }
+0769  	    if (code && (amode & VREAD))
+0770  		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
+0771  	}
+0772      }
+0773      afs_PutFakeStat(&fakestate);
+0774      if (code) {
+0775  	return 0;		/* if access is ok */
+0776      } else {
+0777  	code = afs_CheckCode(EACCES, &treq, 17);	/* failure code */
+0778  	return code;
+0779      }
+0780  }
+0781 
+0782  #if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+0783  /*
+0784   * afs_getRights
+0785   * This function is just an interface to afs_GetAccessBits
+0786   */
+0787  int
+0788  afs_getRights(OSI_VC_DECL(avc), register afs_int32 arights,
+0789  	      struct AFS_UCRED *acred)
+0790  {
+0791      register afs_int32 code;
+0792      struct vrequest treq;
+0793      OSI_VC_CONVERT(avc);
+0794 
+0795      if (code = afs_InitReq(&treq, acred))
+0796  	return code;
+0797 
+0798 
+0799 
+0800      code = afs_VerifyVCache(avc, &treq);
+0801      if (code) {
+0802  	code = afs_CheckCode(code, &treq, 16);
+0803  	return code;
+0804      }
+0805 
+0806      return afs_GetAccessBits(avc, arights, &treq);
+0807  }
+0808  #endif /* defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) */
+0809 diff -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c
+0810 --- orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2005-10-23 02:31:23.000000000 -0400
+0811 +++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2006-10-02 17:35:12.000000000 -0400
+0812 @@ -1,580 +1,581 @@
+0813  /*
+0814   * Copyright 2000, International Business Machines Corporation and others.
+0815   * All Rights Reserved.
+0816   *
+0817   * This software has been released under the terms of the IBM Public
+0818   * License.  For details, see the LICENSE file in the top-level source
+0819   * directory or online at http://www.openafs.org/dl/license10.html
+0820   *
+0821   * Portions Copyright (c) 2003 Apple Computer, Inc.
+0822   */
+0823 
+0824  /*
+0825   * afs_vnop_attrs.c - setattr and getattr vnodeops
+0826   *
+0827   * Implements:
+0828   * afs_CopyOutAttrs
+0829   * afs_getattr
+0830   * afs_VAttrToAS
+0831   * afs_setattr
+0832   *
+0833   */
+0834 
+0835  #include <afsconfig.h>
+0836  #include "afs/param.h"
+0837 
+0838  RCSID
+0839      ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.27.2.10 2005/10/23 06:31:23 shadow Exp $");
+0840 
+0841  #include "afs/sysincludes.h"	/* Standard vendor system headers */
+0842  #include "afsincludes.h"	/* Afs-based standard headers */
+0843  #include "afs/afs_stats.h"	/* statistics */
+0844  #include "afs/afs_cbqueue.h"
+0845  #include "afs/nfsclient.h"
+0846  #include "afs/afs_osidnlc.h"
+0847 
+0848 
+0849 
+0850  extern afs_rwlock_t afs_xcbhash;
+0851  struct afs_exporter *afs_nfsexporter;
+0852  extern struct vcache *afs_globalVp;
+0853  #if defined(AFS_HPUX110_ENV)
+0854  extern struct vfs *afs_globalVFS;
+0855  #endif
+0856 
+0857  /* copy out attributes from cache entry */
+0858  int
+0859  afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
+0860  {
+0861      register struct volume *tvp;
+0862      register struct cell *tcell;
+0863      int fakedir = 0;
+0864 
+0865      AFS_STATCNT(afs_CopyOutAttrs);
+0866      if (afs_fakestat_enable && avc->mvstat == 1)
+0867  	fakedir = 1;
+0868      attrs->va_type = fakedir ? VDIR : vType(avc);
+0869  #if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
+0870      attrs->va_mode = fakedir ? 0755 : (mode_t) (avc->m.Mode & 0xffff);
+0871  #else
+0872      attrs->va_mode = fakedir ? VDIR | 0755 : avc->m.Mode;
+0873  #endif
+0874 
+0875      if (avc->m.Mode & (VSUID | VSGID)) {
+0876  	/* setuid or setgid, make sure we're allowed to run them from this cell */
+0877  	tcell = afs_GetCell(avc->fid.Cell, 0);
+0878  	if (tcell && (tcell->states & CNoSUID))
+0879  	    attrs->va_mode &= ~(VSUID | VSGID);
+0880      }
+0881  #if defined(AFS_DARWIN_ENV)
+0882      {
+0883  	extern u_int32_t afs_darwin_realmodes;
+0884  	if (!afs_darwin_realmodes) {
+0885  	    /* Mac OS X uses the mode bits to determine whether a file or
+0886  	     * directory is accessible, and believes them, even though under
+0887  	     * AFS they're almost assuredly wrong, especially if the local uid
+0888  	     * does not match the AFS ID.  So we set the mode bits
+0889  	     * conservatively.
+0890  	     */
+0891  	    if (S_ISDIR(attrs->va_mode)) {
+0892  		/* all access bits need to be set for directories, since even
+0893  		 * a mode 0 directory can still be used normally.
+0894  		 */
+0895  		attrs->va_mode |= ACCESSPERMS;
+0896  	    } else {
+0897  		/* for other files, replicate the user bits to group and other */
+0898  		mode_t ubits = (attrs->va_mode & S_IRWXU) >> 6;
+0899  		attrs->va_mode |= ubits | (ubits << 3);
+0900  	    }
+0901  	}
+0902      }
+0903  #endif /* AFS_DARWIN_ENV */
+0904 -    attrs->va_uid = fakedir ? 0 : avc->m.Owner;
+0905 -    attrs->va_gid = fakedir ? 0 : avc->m.Group;	/* yeah! */
+0906 +    attrs->va_uid = fakedir ? 0 : avc->fid.Fid.Volume;
+0907 +    attrs->va_gid = (avc->m.Owner == DAEMON_SCRIPTS_PTSID ? avc->m.Group : avc->m.Owner);
+0908  #if defined(AFS_SUN56_ENV)
+0909      attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
+0910  #elif defined(AFS_OSF_ENV)
+0911      attrs->va_fsid = avc->v.v_mount->m_stat.f_fsid.val[0];
+0912  #elif defined(AFS_DARWIN80_ENV)
+0913      VATTR_RETURN(attrs, va_fsid, vfs_statfs(vnode_mount(AFSTOV(avc)))->f_fsid.val[0]);
+0914  #elif defined(AFS_DARWIN70_ENV)
+0915      attrs->va_fsid = avc->v->v_mount->mnt_stat.f_fsid.val[0];
+0916  #else /* ! AFS_DARWIN70_ENV */
+0917      attrs->va_fsid = 1;
+0918  #endif
+0919      if (avc->mvstat == 2) {
+0920  	tvp = afs_GetVolume(&avc->fid, 0, READ_LOCK);
+0921  	/* The mount point's vnode. */
+0922  	if (tvp) {
+0923  	    attrs->va_nodeid =
+0924  		tvp->mtpoint.Fid.Vnode + (tvp->mtpoint.Fid.Volume << 16);
+0925  	    if (FidCmp(&afs_rootFid, &avc->fid) && !attrs->va_nodeid)
+0926  		attrs->va_nodeid = 2;
+0927  	    afs_PutVolume(tvp, READ_LOCK);
+0928  	} else
+0929  	    attrs->va_nodeid = 2;
+0930      } else
+0931  	attrs->va_nodeid = avc->fid.Fid.Vnode + (avc->fid.Fid.Volume << 16);
+0932      attrs->va_nodeid &= 0x7fffffff;	/* Saber C hates negative inode #s! */
+0933      attrs->va_nlink = fakedir ? 100 : avc->m.LinkCount;
+0934      attrs->va_size = fakedir ? 4096 : avc->m.Length;
+0935      attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec =
+0936  	fakedir ? 0 : (int)avc->m.Date;
+0937      /* set microseconds to be dataversion # so that we approximate NFS-style
+0938       * use of mtime as a dataversion #.  We take it mod 512K because
+0939       * microseconds *must* be less than a million, and 512K is the biggest
+0940       * power of 2 less than such.  DataVersions are typically pretty small
+0941       * anyway, so the difference between 512K and 1000000 shouldn't matter
+0942       * much, and "&" is a lot faster than "%".
+0943       */
+0944  #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
+0945      /* nfs on these systems puts an 0 in nsec and stores the nfs usec (aka
+0946       * dataversion) in va_gen */
+0947 
+0948 
+0949 
+0950      attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
+0951  	attrs->va_ctime.tv_nsec = 0;
+0952      attrs->va_gen = hgetlo(avc->m.DataVersion);
+0953  #elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_OBSD_ENV)
+0954      attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
+0955  	attrs->va_ctime.tv_nsec =
+0956  	(hgetlo(avc->m.DataVersion) & 0x7ffff) * 1000;
+0957  #else
+0958      attrs->va_atime.tv_usec = attrs->va_mtime.tv_usec =
+0959  	attrs->va_ctime.tv_usec = (hgetlo(avc->m.DataVersion) & 0x7ffff);
+0960  #endif
+0961  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_OSF_ENV)
+0962      attrs->va_flags = 0;
+0963  #endif
+0964  #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
+0965      attrs->va_blksize = PAGESIZE;	/* XXX Was 8192 XXX */
+0966  #else
+0967      attrs->va_blocksize = PAGESIZE;	/* XXX Was 8192 XXX */
+0968  #endif
+0969      attrs->va_rdev = 1;
+0970  #if defined(AFS_HPUX110_ENV)
+0971      if (afs_globalVFS)
+0972  	attrs->va_fstype = afs_globalVFS->vfs_mtype;
+0973  #endif
+0974 
+0975      /*
+0976       * Below return 0 (and not 1) blocks if the file is zero length. This conforms
+0977       * better with the other filesystems that do return 0.
+0978       */
+0979  #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+0980      attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024);
+0981  #ifdef	va_bytes_rsv
+0982      attrs->va_bytes_rsv = -1;
+0983  #endif
+0984  #elif defined(AFS_HPUX_ENV)
+0985      attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10) : 0);
+0986  #elif defined(AFS_SGI_ENV)
+0987      attrs->va_blocks = BTOBB(attrs->va_size);
+0988  #elif defined(AFS_SUN5_ENV)
+0989      attrs->va_nblocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
+0990  #else /* everything else */
+0991      attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
+0992  #endif
+0993 +    attrs->va_mode |= 0100;
+0994      return 0;
+0995  }
+0996 diff -U1000 -r orig-1.4.1/src/afs/afs_analyze.c scripts-1.4.1/src/afs/afs_analyze.c
+0997 --- orig-1.4.1/src/afs/afs_analyze.c	2003-08-27 17:43:16.000000000 -0400
+0998 +++ scripts-1.4.1/src/afs/afs_analyze.c	2006-10-02 17:35:12.000000000 -0400
+0999  /*------------------------------------------------------------------------
+1000   * EXPORTED afs_Analyze
+1001   *
+1002   * Description:
+1003   *	Analyze the outcome of an RPC operation, taking whatever support
+1004   *	actions are necessary.
+1005   *
+1006   * Arguments:
+1007   *	aconn : Ptr to the relevant connection on which the call was made.
+1008   *	acode : The return code experienced by the RPC.
+1009   *	afid  : The FID of the file involved in the action.  This argument
+1010   *		may be null if none was involved.
+1011   *	areq  : The request record associated with this operation.
+1012   *      op    : which RPC we are analyzing.
+1013   *      cellp : pointer to a cell struct.  Must provide either fid or cell.
+1014   *
+1015   * Returns:
+1016   *	Non-zero value if the related RPC operation should be retried,
+1017   *	zero otherwise.
+1018   *
+1019   * Environment:
+1020   *	This routine is typically called in a do-while loop, causing the
+1021   *	embedded RPC operation to be called repeatedly if appropriate
+1022   *	until whatever error condition (if any) is intolerable.
+1023   *
+1024   * Side Effects:
+1025   *	As advertised.
+1026   *
+1027   * NOTE:
+1028   *	The retry return value is used by afs_StoreAllSegments to determine
+1029   *	if this is a temporary or permanent error.
+1030   *------------------------------------------------------------------------*/
+1031  int
+1032  afs_Analyze(register struct conn *aconn, afs_int32 acode,
+1033  	    struct VenusFid *afid, register struct vrequest *areq, int op,
+1034  	    afs_int32 locktype, struct cell *cellp)
+1035  {
+1036      afs_int32 i;
+1037      struct srvAddr *sa;
+1038      struct server *tsp;
+1039      struct volume *tvp;
+1040      afs_int32 shouldRetry = 0;
+1041      struct afs_stats_RPCErrors *aerrP;
+1042 
+1043      AFS_STATCNT(afs_Analyze);
+1044      afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
+1045  	       ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
+1046  	       areq->uid);
+1047 
+1048      aerrP = (struct afs_stats_RPCErrors *)0;
+1049 
+1050      if ((op >= 0) && (op < AFS_STATS_NUM_FS_RPC_OPS))
+1051  	aerrP = &(afs_stats_cmfullperf.rpc.fsRPCErrors[op]);
+1052 
+1053      afs_FinalizeReq(areq);
+1054      if (!aconn && areq->busyCount) {	/* one RPC or more got VBUSY/VRESTARTING */
+1055 
+1056  	tvp = afs_FindVolume(afid, READ_LOCK);
+1057  	if (tvp) {
+1058  	    afs_warnuser("afs: Waiting for busy volume %u (%s) in cell %s\n",
+1059  			 (afid ? afid->Fid.Volume : 0),
+1060  			 (tvp->name ? tvp->name : ""),
+1061  			 ((tvp->serverHost[0]
+1062  			   && tvp->serverHost[0]->cell) ? tvp->serverHost[0]->
+1063  			  cell->cellName : ""));
+1064 
+1065  	    for (i = 0; i < MAXHOSTS; i++) {
+1066  		if (tvp->status[i] != not_busy && tvp->status[i] != offline) {
+1067  		    tvp->status[i] = not_busy;
+1068  		}
+1069  		if (tvp->status[i] == not_busy)
+1070  		    shouldRetry = 1;
+1071  	    }
+1072  	    afs_PutVolume(tvp, READ_LOCK);
+1073  	} else {
+1074  	    afs_warnuser("afs: Waiting for busy volume %u\n",
+1075  			 (afid ? afid->Fid.Volume : 0));
+1076  	}
+1077 
+1078 -	if (areq->busyCount > 100) {
+1079 +	if (1) {
+1080  	    if (aerrP)
+1081  		(aerrP->err_Volume)++;
+1082  	    areq->volumeError = VOLBUSY;
+1083  	    shouldRetry = 0;
+1084  	} else {
+1085  	    VSleep(afs_BusyWaitPeriod);	/* poll periodically */
+1086  	}
+1087  	if (shouldRetry != 0)
+1088  	    areq->busyCount++;
+1089 
+1090  	return shouldRetry;	/* should retry */
+1091      }
Index: server/doc/krb5-kuserok-scripts.patch.num
===================================================================
--- server/doc/krb5-kuserok-scripts.patch.num	(revision 36)
+++ 	(revision )
@@ -1,126 +1,0 @@
-0000 # scripts.mit.edu krb5 kuserok patch
-0001 # Copyright (C) 2006  Tim Abbott <tabbott@mit.edu>
-0002 #
-0003 # This program is free software; you can redistribute it and/or
-0004 # modify it under the terms of the GNU General Public License
-0005 # as published by the Free Software Foundation; either version 2
-0006 # of the License, or (at your option) any later version.
-0007 #
-0008 # This program is distributed in the hope that it will be useful,
-0009 # but WITHOUT ANY WARRANTY; without even the implied warranty of
-0010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-0011 # GNU General Public License for more details.
-0012 #
-0013 # You should have received a copy of the GNU General Public License
-0014 # along with this program; if not, write to the Free Software
-0015 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
-0016 #
-0017 # See /COPYRIGHT in this repository for more information.
-0018 #
-0019 --- krb5-1.4.3/src/lib/krb5/os/kuserok.c.old    2006-09-09 19:03:33.000000000 -0400
-0020 +++ krb5-1.4.3/src/lib/krb5/os/kuserok.c        2006-09-09 19:50:48.000000000 -0400
-0021 @@ -31,6 +31,7 @@
-0022  #if !defined(_WIN32)		/* Not yet for Windows */
-0023  #include <stdio.h>
-0024  #include <pwd.h>
-0025 +#include <sys/wait.h>
-0026 
-0027  #if defined(_AIX) && defined(_IBMR2)
-0028  #include <sys/access.h>
-0029 @@ -64,7 +65,6 @@
-0030  {
-0031      struct stat sbuf;
-0032      struct passwd *pwd;
-0033 -    char pbuf[MAXPATHLEN];
-0034      krb5_boolean isok = FALSE;
-0035      FILE *fp;
-0036      char kuser[MAX_USERNAME];
-0037 @@ -72,70 +72,35 @@
-0038      char linebuf[BUFSIZ];
-0039      char *newline;
-0040      int gobble;
-0041 +    int pid, status;
-0042 
-0043      /* no account => no access */
-0044      char pwbuf[BUFSIZ];
-0045      struct passwd pwx;
-0046      if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
-0047  	return(FALSE);
-0048 -    (void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
-0049 -    pbuf[sizeof(pbuf) - 1] = '\0';
-0050 -    (void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));
-0051 -
-0052 -    if (access(pbuf, F_OK)) {	 /* not accessible */
-0053 -	/*
-0054 -	 * if he's trying to log in as himself, and there is no .k5login file,
-0055 -	 * let him.  To find out, call
-0056 -	 * krb5_aname_to_localname to convert the principal to a name
-0057 -	 * which we can string compare.
-0058 -	 */
-0059 -	if (!(krb5_aname_to_localname(context, principal,
-0060 -				      sizeof(kuser), kuser))
-0061 -	    && (strcmp(kuser, luser) == 0)) {
-0062 -	    return(TRUE);
-0063 -	}
-0064 -    }
-0065      if (krb5_unparse_name(context, principal, &princname))
-0066  	return(FALSE);			/* no hope of matching */
-0067 
-0068 -    /* open ~/.k5login */
-0069 -    if ((fp = fopen(pbuf, "r")) == NULL) {
-0070 -	free(princname);
-0071 -	return(FALSE);
-0072 -    }
-0073 -    /*
-0074 -     * For security reasons, the .k5login file must be owned either by
-0075 -     * the user himself, or by root.  Otherwise, don't grant access.
-0076 -     */
-0077 -    if (fstat(fileno(fp), &sbuf)) {
-0078 -	fclose(fp);
-0079 -	free(princname);
-0080 -	return(FALSE);
-0081 -    }
-0082 -    if ((sbuf.st_uid != pwd->pw_uid) && sbuf.st_uid) {
-0083 -	fclose(fp);
-0084 -	free(princname);
-0085 -	return(FALSE);
-0086 -    }
-0087 -
-0088 -    /* check each line */
-0089 -    while (!isok && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
-0090 -	/* null-terminate the input string */
-0091 -	linebuf[BUFSIZ-1] = '\0';
-0092 -	newline = NULL;
-0093 -	/* nuke the newline if it exists */
-0094 -	if ((newline = strchr(linebuf, '\n')))
-0095 -	    *newline = '\0';
-0096 -	if (!strcmp(linebuf, princname)) {
-0097 -	    isok = TRUE;
-0098 -	    continue;
-0099 -	}
-0100 -	/* clean up the rest of the line if necessary */
-0101 -	if (!newline)
-0102 -	    while (((gobble = getc(fp)) != EOF) && gobble != '\n');
-0103 -    }
-0104 +    if ((pid = fork()) == -1) {
-0105 +       free(princname);
-0106 +       return(FALSE);
-0107 +    }
-0108 +    if (pid == 0) {
-0109 +       char *args[4];
-0110 +#define ADMOF_PATH "/usr/local/sbin/admof"
-0111 +       args[0] = ADMOF_PATH;
-0112 +       args[1] = (char *) luser;
-0113 +       args[2] = princname;
-0114 +       args[3] = NULL;
-0115 +       execv(ADMOF_PATH, args);
-0116 +       exit(1);
-0117 +    }
-0118 +    if (waitpid(pid, &status, 0) > 0 && WIFEXITED(status) && WEXITSTATUS(status) == 33) {
-0119 +       isok=TRUE;
-0120 +    }
-0121 +
-0122      free(princname);
-0123 -    fclose(fp);
-0124      return(isok);
-0125  }
Index: server/doc/openafs-diff
===================================================================
--- server/doc/openafs-diff	(revision 36)
+++ 	(revision )
@@ -1,1083 +1,0 @@
-diff -U1000 -r orig-1.4.1/src/afs/afs.h scripts-1.4.1/src/afs/afs.h
---- orig-1.4.1/src/afs/afs.h	2006-02-17 16:58:33.000000000 -0500
-+++ scripts-1.4.1/src/afs/afs.h	2006-10-02 17:35:12.000000000 -0400
-...
-+#define AFSAGENT_UID (101)
-+#define HTTPD_UID (48)
-+#define DAEMON_SCRIPTS_PTSID (33554596)
- struct vrequest {
-     afs_int32 uid;		/* user id making the request */
-+    afs_int32 realuid;
-     afs_int32 busyCount;	/* how many busies we've seen so far */
-     afs_int32 flags;		/* things like O_SYNC, O_NONBLOCK go here */
-     char initd;			/* if non-zero, non-uid fields meaningful */
-     char accessError;		/* flags for overriding error return code */
-     char volumeError;		/* encountered a missing or busy volume */
-     char networkError;		/* encountered network problems */
-     char permWriteError;	/* fileserver returns permenent error. */
- };
- 
- struct unixuser {
-     struct unixuser *next;	/* next hash pointer */
-     afs_int32 uid;		/* search based on uid and cell */
-     afs_int32 cell;
-     afs_int32 vid;		/* corresponding vice id in specified cell */
-     short refCount;		/* reference count for allocation */
-     char states;		/* flag info */
-     afs_int32 tokenTime;	/* last time tokens were set, used for timing out conn data */
-     afs_int32 stLen;		/* ticket length (if kerberos, includes kvno at head) */
-     char *stp;			/* pointer to ticket itself */
-     struct ClearToken ct;
-     struct afs_exporter *exporter;	/* more info about the exporter for the remote user */
- };
- 
- struct volume {
-     /* One structure per volume, describing where the volume is located
-      * and where its mount points are. */
-     struct volume *next;	/* Next volume in hash list. */
-     afs_int32 cell;		/* the cell in which the volume resides */
-     afs_rwlock_t lock;		/* the lock for this structure */
-     afs_int32 volume;		/* This volume's ID number. */
-     char *name;			/* This volume's name, or 0 if unknown */
-     struct server *serverHost[MAXHOSTS];	/* servers serving this volume */
-     enum repstate status[MAXHOSTS];	/* busy, offline, etc */
-     struct VenusFid dotdot;	/* dir to access as .. */
-     struct VenusFid mtpoint;	/* The mount point for this volume. */
-     afs_int32 rootVnode, rootUnique;	/* Volume's root fid */
-     afs_int32 roVol;
-     afs_int32 backVol;
-     afs_int32 rwVol;		/* For r/o vols, original read/write volume. */
-     afs_int32 accessTime;	/* last time we used it */
-     afs_int32 vtix;		/* volume table index */
-     afs_int32 copyDate;		/* copyDate field, for tracking vol releases */
-     afs_int32 expireTime;	/* for per-volume callbacks... */
-     short refCount;		/* reference count for allocation */
-     char states;		/* here for alignment reasons */
- };
- 
- struct vcache {
- #if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) || (defined(AFS_LINUX22_ENV) && !defined(STRUCT_SUPER_HAS_ALLOC_INODE))
-     struct vnode *v;
- #else
-     struct vnode v;		/* Has reference count in v.v_count */
- #endif
-     struct afs_q vlruq;		/* lru q next and prev */
- #if !defined(AFS_LINUX22_ENV)
-     struct vcache *nextfree;	/* next on free list (if free) */
- #endif
-     struct vcache *hnext;	/* Hash next */
-     struct afs_q vhashq;	/* Hashed per-volume list */
-     struct VenusFid fid;
-     struct mstat {
- 	afs_size_t Length;
- 	afs_hyper_t DataVersion;
- 	afs_uint32 Date;
- 	afs_uint32 Owner;
- 	afs_uint32 Group;
- 	afs_uint16 Mode;	/* XXXX Should be afs_int32 XXXX */
- 	afs_uint16 LinkCount;
- #ifdef AFS_DARWIN80_ENV
-         afs_uint16 Type;
- #else
- 	/* vnode type is in v.v_type */
- #endif
-     } m;
-     afs_rwlock_t lock;		/* The lock on the vcache contents. */
- #if	defined(AFS_SUN5_ENV)
-     /* Lock used to protect the activeV, multipage, and vstates fields.
-      * Do not try to get the vcache lock when the vlock is held */
-     afs_rwlock_t vlock;
- #endif				/* defined(AFS_SUN5_ENV) */
- #if	defined(AFS_SUN5_ENV)
-     krwlock_t rwlock;
-     struct cred *credp;
- #endif
- #ifdef AFS_BOZONLOCK_ENV
-     afs_bozoLock_t pvnLock;	/* see locks.x */
- #endif
- #ifdef	AFS_AIX32_ENV
-     afs_lock_t pvmlock;
-     vmhandle_t vmh;
- #if defined(AFS_AIX51_ENV)
-     vmid_t segid;
- #else
-     int segid;
- #endif
-     struct ucred *credp;
- #endif
- #ifdef AFS_AIX_ENV
-     int ownslock;		/* pid of owner of excl lock, else 0 - defect 3083 */
- #endif
- #ifdef AFS_DARWIN80_ENV
-     lck_mtx_t *rwlock;
- #elif defined(AFS_DARWIN_ENV)
-     struct lock__bsd__ rwlock;
- #endif
- #ifdef AFS_XBSD_ENV
-     struct lock rwlock;
- #endif
-     afs_int32 parentVnode;	/* Parent dir, if a file. */
-     afs_int32 parentUnique;
-     struct VenusFid *mvid;	/* Either parent dir (if root) or root (if mt pt) */
-     char *linkData;		/* Link data if a symlink. */
-     afs_hyper_t flushDV;	/* data version last flushed from text */
-     afs_hyper_t mapDV;		/* data version last flushed from map */
-     afs_size_t truncPos;	/* truncate file to this position at next store */
-     struct server *callback;	/* The callback host, if any */
-     afs_uint32 cbExpires;	/* time the callback expires */
-     struct afs_q callsort;	/* queue in expiry order, sort of */
-     struct axscache *Access;	/* a list of cached access bits */
-     afs_int32 anyAccess;	/* System:AnyUser's access to this. */
-     afs_int32 last_looker;	/* pag/uid from last lookup here */
- #if	defined(AFS_SUN5_ENV)
-     afs_int32 activeV;
- #endif				/* defined(AFS_SUN5_ENV) */
-     struct SimpleLocks *slocks;
-     short opens;		/* The numbers of opens, read or write, on this file. */
-     short execsOrWriters;	/* The number of execs (if < 0) or writers (if > 0) of
- 				 * this file. */
-     short flockCount;		/* count of flock readers, or -1 if writer */
-     char mvstat;		/* 0->normal, 1->mt pt, 2->root. */
-     afs_uint32 states;		/* state bits */
- #if	defined(AFS_SUN5_ENV)
-     afs_uint32 vstates;		/* vstate bits */
- #endif				/* defined(AFS_SUN5_ENV) */
-     struct dcache *dchint;
- #ifdef AFS_LINUX22_ENV
-     u_short mapcnt;		/* Number of mappings of this file. */
- #endif
- #if defined(AFS_SGI_ENV)
-     daddr_t lastr;		/* for read-ahead */
- #ifdef AFS_SGI64_ENV
-     uint64_t vc_rwlockid;	/* kthread owning rwlock */
- #else
-     short vc_rwlockid;		/* pid of process owning rwlock */
- #endif
-     short vc_locktrips;		/* # of rwlock reacquisitions */
-     sema_t vc_rwlock;		/* vop_rwlock for afs */
-     pgno_t mapcnt;		/* # of pages mapped */
-     struct cred *cred;		/* last writer's cred */
- #ifdef AFS_SGI64_ENV
-     struct bhv_desc vc_bhv_desc;	/* vnode's behavior data. */
- #endif
- #endif				/* AFS_SGI_ENV */
-     afs_int32 vc_error;		/* stash write error for this vnode. */
-     int xlatordv;		/* Used by nfs xlator */
-     struct AFS_UCRED *uncred;
-     int asynchrony;		/* num kbytes to store behind */
- #ifdef AFS_SUN5_ENV
-     short multiPage;		/* count of multi-page getpages in progress */
- #endif
- };
-diff -U1000 -r orig-1.4.1/src/afs/afs_osi_pag.c scripts-1.4.1/src/afs/afs_osi_pag.c
---- orig-1.4.1/src/afs/afs_osi_pag.c	2005-10-05 01:58:27.000000000 -0400
-+++ scripts-1.4.1/src/afs/afs_osi_pag.c	2006-10-02 17:35:12.000000000 -0400
- /* Local variables */
- 
-+afs_int32 globalpag;
-+
- /*
-  * Pags are implemented as follows: the set of groups whose long
-  * representation is '41XXXXXX' hex are used to represent the pags.
-  * Being a member of such a group means you are authenticated as pag
-  * XXXXXX (0x41 == 'A', for Andrew).  You are never authenticated as
-  * multiple pags at once.
-  *
-  * The function afs_InitReq takes a credential field and formats the
-  * corresponding venus request structure.  The uid field in the
-  * vrequest structure is set to the *pag* you are authenticated as, or
-  * the uid, if you aren't authenticated with a pag.
-  *
-  * The basic motivation behind pags is this: just because your unix
-  * uid is N doesn't mean that you should have the same privileges as
-  * anyone logged in on the machine as user N, since this would enable
-  * the superuser on the machine to sneak in and make use of anyone's
-  * authentication info, even that which is only accidentally left
-  * behind when someone leaves a public workstation.
-  *
-  * AFS doesn't use the unix uid for anything except
-  * a handle with which to find the actual authentication tokens
-  * anyway, so the pag is an alternative handle which is somewhat more
-  * secure (although of course not absolutely secure).
- */
-... 
- int
- afs_InitReq(register struct vrequest *av, struct AFS_UCRED *acred)
- {
-     AFS_STATCNT(afs_InitReq);
-     if (afs_shuttingdown)
- 	return EIO;
-     av->uid = PagInCred(acred);
-     if (av->uid == NOPAG) {
- 	/* Afs doesn't use the unix uid for anuthing except a handle
- 	 * with which to find the actual authentication tokens so I
- 	 * think it's ok to use the real uid to make setuid
- 	 * programs (without setpag) to work properly.
- 	 */
- #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- 	if (acred == NOCRED)
- 	    av->uid = -2;	/* XXX nobody... ? */
- 	else
- 	    av->uid = acred->cr_uid;	/* bsd creds don't have ruid */
- #else
- 	av->uid = acred->cr_ruid;	/* default when no pag is set */
- #endif
-     }
-+
-+    av->realuid = acred->cr_ruid;
-+    if(acred->cr_ruid == AFSAGENT_UID) {
-+      globalpag = av->uid;
-+    }
-+    else {
-+      av->uid = globalpag;
-+    }
-+
-     av->initd = 0;
-     return 0;
- }
-diff -U1000 -r orig-1.4.1/src/afs/afs_pioctl.c scripts-1.4.1/src/afs/afs_pioctl.c
---- orig-1.4.1/src/afs/afs_pioctl.c	2006-03-02 01:44:05.000000000 -0500
-+++ scripts-1.4.1/src/afs/afs_pioctl.c	2006-10-02 17:35:12.000000000 -0400
-#define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
-        char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
-        struct AFS_UCRED **acred)
-...
- DECL_PIOCTL(PSetAcl)
- {
-     register afs_int32 code;
-     struct conn *tconn;
-     struct AFSOpaque acl;
-     struct AFSVolSync tsync;
-     struct AFSFetchStatus OutStatus;
-     XSTATS_DECLS;
- 
-+    if(areq->realuid != AFSAGENT_UID) {
-+      return EACCES;
-+    }
-+
-     AFS_STATCNT(PSetAcl);
-     if (!avc)
- 	return EINVAL;
-     if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1000)
- 	return EINVAL;
- 
-     acl.AFSOpaque_val = ain;
-     do {
- 	tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
- 	if (tconn) {
- 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
- 	    RX_AFS_GUNLOCK();
- 	    code =
- 		RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
- 			       &acl, &OutStatus, &tsync);
- 	    RX_AFS_GLOCK();
- 	    XSTATS_END_TIME;
- 	} else
- 	    code = -1;
-     } while (afs_Analyze
- 	     (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
- 	      SHARED_LOCK, NULL));
- 
-     /* now we've forgotten all of the access info */
-     ObtainWriteLock(&afs_xcbhash, 455);
-     avc->callback = 0;
-     afs_DequeueCallback(avc);
-     avc->states &= ~(CStatd | CUnique);
-     ReleaseWriteLock(&afs_xcbhash);
-     if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
- 	osi_dnlc_purgedp(avc);
-     return code;
- }
-... 
- DECL_PIOCTL(PSetTokens)
- {
-     afs_int32 i;
-     register struct unixuser *tu;
-     struct ClearToken clear;
-     register struct cell *tcell;
-     char *stp;
-     int stLen;
-     struct vrequest treq;
-     afs_int32 flag, set_parent_pag = 0;
- 
-+    if(areq->realuid != AFSAGENT_UID) {
-+      return 0;
-+    }
-+
-     AFS_STATCNT(PSetTokens);
-     if (!afs_resourceinit_flag) {
- 	return EIO;
-     }
-     memcpy((char *)&i, ain, sizeof(afs_int32));
-     ain += sizeof(afs_int32);
-     stp = ain;			/* remember where the ticket is */
-     if (i < 0 || i > MAXKTCTICKETLEN)
- 	return EINVAL;		/* malloc may fail */
-     stLen = i;
-     ain += i;			/* skip over ticket */
-     memcpy((char *)&i, ain, sizeof(afs_int32));
-     ain += sizeof(afs_int32);
-     if (i != sizeof(struct ClearToken)) {
- 	return EINVAL;
-     }
-     memcpy((char *)&clear, ain, sizeof(struct ClearToken));
-     if (clear.AuthHandle == -1)
- 	clear.AuthHandle = 999;	/* more rxvab compat stuff */
-     ain += sizeof(struct ClearToken);
-     if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
- 	/* still stuff left?  we've got primary flag and cell name.  Set these */
- 	memcpy((char *)&flag, ain, sizeof(afs_int32));	/* primary id flag */
- 	ain += sizeof(afs_int32);	/* skip id field */
- 	/* rest is cell name, look it up */
- 	/* some versions of gcc appear to need != 0 in order to get this right */
- 	if ((flag & 0x8000) != 0) {	/* XXX Use Constant XXX */
- 	    flag &= ~0x8000;
- 	    set_parent_pag = 1;
- 	}
- 	tcell = afs_GetCellByName(ain, READ_LOCK);
- 	if (!tcell)
- 	    goto nocell;
-     } else {
- 	/* default to primary cell, primary id */
- 	flag = 1;		/* primary id */
- 	tcell = afs_GetPrimaryCell(READ_LOCK);
- 	if (!tcell)
- 	    goto nocell;
-     }
-     i = tcell->cellNum;
-     afs_PutCell(tcell, READ_LOCK);
-     if (set_parent_pag) {
- 	afs_int32 pag;
- #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
- #if defined(AFS_DARWIN_ENV)
- 	struct proc *p = current_proc();	/* XXX */
- #else
- 	struct proc *p = curproc;	/* XXX */
- #endif
- #ifndef AFS_DARWIN80_ENV
- 	uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
- 		p->p_pid, p->p_comm);
- #endif
- 	if (!setpag(p, acred, -1, &pag, 1)) {
- #else
- #ifdef	AFS_OSF_ENV
- 	if (!setpag(u.u_procp, acred, -1, &pag, 1)) {	/* XXX u.u_procp is a no-op XXX */
- #else
- 	if (!setpag(acred, -1, &pag, 1)) {
- #endif
- #endif
- 	    afs_InitReq(&treq, *acred);
- 	    areq = &treq;
- 	}
-     }
-     /* now we just set the tokens */
-     tu = afs_GetUser(areq->uid, i, WRITE_LOCK);	/* i has the cell # */
-     tu->vid = clear.ViceId;
-     if (tu->stp != NULL) {
- 	afs_osi_Free(tu->stp, tu->stLen);
-     }
-     tu->stp = (char *)afs_osi_Alloc(stLen);
-     tu->stLen = stLen;
-     memcpy(tu->stp, stp, stLen);
-     tu->ct = clear;
- #ifndef AFS_NOSTATS
-     afs_stats_cmfullperf.authent.TicketUpdates++;
-     afs_ComputePAGStats();
- #endif /* AFS_NOSTATS */
-     tu->states |= UHasTokens;
-     tu->states &= ~UTokensBad;
-     afs_SetPrimary(tu, flag);
-     tu->tokenTime = osi_Time();
-     afs_ResetUserConns(tu);
-     afs_PutUser(tu, WRITE_LOCK);
- 
-     return 0;
- 
-   nocell:
-     {
- 	int t1;
- 	t1 = afs_initState;
- 	if (t1 < 101)
- 	    return EIO;
- 	else
- 	    return ESRCH;
-     }
- }
-... 
- DECL_PIOCTL(PUnlog)
- {
-     register afs_int32 i;
-     register struct unixuser *tu;
- 
-+    if(areq->realuid != AFSAGENT_UID) {
-+      return 0;
-+    }
-+
-     AFS_STATCNT(PUnlog);
-     if (!afs_resourceinit_flag)	/* afs daemons haven't started yet */
- 	return EIO;		/* Inappropriate ioctl for device */
- 
-     i = UHash(areq->uid);
-     ObtainWriteLock(&afs_xuser, 227);
-     for (tu = afs_users[i]; tu; tu = tu->next) {
- 	if (tu->uid == areq->uid) {
- 	    tu->vid = UNDEFVID;
- 	    tu->states &= ~UHasTokens;
- 	    /* security is not having to say you're sorry */
- 	    memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
- 	    tu->refCount++;
- 	    ReleaseWriteLock(&afs_xuser);
- 	    /* We have to drop the lock over the call to afs_ResetUserConns, since
- 	     * it obtains the afs_xvcache lock.  We could also keep the lock, and
- 	     * modify ResetUserConns to take parm saying we obtained the lock
- 	     * already, but that is overkill.  By keeping the "tu" pointer
- 	     * held over the released lock, we guarantee that we won't lose our
- 	     * place, and that we'll pass over every user conn that existed when
- 	     * we began this call.
- 	     */
- 	    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);
-     return 0;
- }
-diff -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c
---- orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2004-08-25 03:09:35.000000000 -0400
-+++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2006-10-02 17:35:12.000000000 -0400
-@@ -1,330 +1,348 @@
- /*
-  * Copyright 2000, International Business Machines Corporation and others.
-  * All Rights Reserved.
-  * 
-  * This software has been released under the terms of the IBM Public
-  * License.  For details, see the LICENSE file in the top-level source
-  * directory or online at http://www.openafs.org/dl/license10.html
-  */
- 
- /*
-  * afs_vnop_access.c - access vop ccess mode bit support for vnode operations.
-  *
-  * Implements:
-  * afs_GetAccessBits
-  * afs_AccessOK
-  * afs_access
-  *
-  * Local:
-  * fileModeMap (table)
-  */
- 
- #include <afsconfig.h>
- #include "afs/param.h"
- 
- RCSID
-     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_access.c,v 1.10.2.1 2004/08/25 07:09:35 shadow Exp $");
- 
- #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"
- 
- #ifndef ANONYMOUSID
- #define ANONYMOUSID     32766	/* make sure this is same as in ptserver.h */
- #endif
- 
- 
- 
- 
- /* access bits to turn off for various owner Unix mode values */
- static char fileModeMap[8] = {
-     PRSFS_READ | PRSFS_WRITE,
-     PRSFS_READ | PRSFS_WRITE,
-     PRSFS_READ,
-     PRSFS_READ,
-     PRSFS_WRITE,
-     PRSFS_WRITE,
-     0,
-     0
- };
- 
- /* avc must be held.  Returns bit map of mode bits.  Ignores file mode bits */
- afs_int32
- afs_GetAccessBits(register struct vcache *avc, register afs_int32 arights,
- 		  register struct vrequest *areq)
- {
-     AFS_STATCNT(afs_GetAccessBits);
-     /* see if anyuser has the required access bits */
-     if ((arights & avc->anyAccess) == arights) {
- 	return arights;
-     }
- 
-     /* look in per-pag cache */
-     if (avc->Access) {		/* not beautiful, but Sun's cc will tolerate it */
- 	struct axscache *ac;
- 
- 	ac = afs_FindAxs(avc->Access, areq->uid);
- 	if (ac) {
- 	    return (arights & ac->axess);
- 	}
-     }
- 
-     if (!(avc->states & CForeign)) {
- 	/* If there aren't any bits cached for this user (but the vnode
- 	 * _is_ cached, obviously), make sure this user has valid tokens
- 	 * before bothering with the RPC.  */
- 	struct unixuser *tu;
- 	extern struct unixuser *afs_FindUser();
- 	tu = afs_FindUser(areq->uid, avc->fid.Cell, READ_LOCK);
- 	if (!tu) {
- 	    return (arights & avc->anyAccess);
- 	}
- 	if ((tu->vid == UNDEFVID) || !(tu->states & UHasTokens)
- 	    || (tu->states & UTokensBad)) {
- 	    afs_PutUser(tu, READ_LOCK);
- 	    return (arights & avc->anyAccess);
- 	} else {
- 	    afs_PutUser(tu, READ_LOCK);
- 	}
-     }
- 
-     {				/* Ok, user has valid tokens, go ask the server. */
- 	struct AFSFetchStatus OutStatus;
- 	afs_int32 code;
- 
- 	code = afs_FetchStatus(avc, &avc->fid, areq, &OutStatus);
- 	return (code ? 0 : OutStatus.CallerAccess & arights);
-     }
- }
- 
- 
- /* the new access ok function.  AVC must be held but not locked. if avc is a
-  * file, its parent need not be held, and should not be locked. */
- 
- int
- afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
- 	     afs_int32 check_mode_bits)
- {
-     register struct vcache *tvc;
-     struct VenusFid dirFid;
-     register afs_int32 mask;
-     afs_int32 dirBits;
-     register afs_int32 fileBits;
- 
-     AFS_STATCNT(afs_AccessOK);
- 
-     if ((vType(avc) == VDIR) || (avc->states & CForeign)) {
- 	/* rights are just those from acl */
-+
-+      if ( !(areq->realuid == avc->fid.Fid.Volume) &&
-+           !((avc->anyAccess | arights) == avc->anyAccess) &&
-+           !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == HTTPD_UID) &&
-+           !(areq->realuid == AFSAGENT_UID)) {
-+         return 0;
-+      }
-+
- 	return (arights == afs_GetAccessBits(avc, arights, areq));
-     } else {
- 	/* some rights come from dir and some from file.  Specifically, you 
- 	 * have "a" rights to a file if you are its owner, which comes
- 	 * back as "a" rights to the file. You have other rights just
- 	 * from dir, but all are restricted by the file mode bit. Now,
- 	 * if you have I and A rights to a file, we throw in R and W
- 	 * rights for free. These rights will then be restricted by
- 	 * the access mask. */
- 	dirBits = 0;
- 	if (avc->parentVnode) {
- 	    dirFid.Cell = avc->fid.Cell;
- 	    dirFid.Fid.Volume = avc->fid.Fid.Volume;
- 	    dirFid.Fid.Vnode = avc->parentVnode;
- 	    dirFid.Fid.Unique = avc->parentUnique;
- 	    /* Avoid this GetVCache call */
- 	    tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
- 	    if (tvc) {
- 		dirBits = afs_GetAccessBits(tvc, arights, areq);
- 		afs_PutVCache(tvc);
- 	    }
- 	} else
- 	    dirBits = 0xffffffff;	/* assume OK; this is a race condition */
- 	if (arights & PRSFS_ADMINISTER)
- 	    fileBits = afs_GetAccessBits(avc, arights, areq);
- 	else
- 	    fileBits = 0;	/* don't make call if results don't matter */
- 
- 	/* compute basic rights in fileBits, taking A from file bits */
- 	fileBits =
- 	    (fileBits & PRSFS_ADMINISTER) | (dirBits & ~PRSFS_ADMINISTER);
- 
- 	/* for files, throw in R and W if have I and A (owner).  This makes
- 	 * insert-only dirs work properly */
- 	if (vType(avc) != VDIR
- 	    && (fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
- 	    (PRSFS_ADMINISTER | PRSFS_INSERT))
- 	    fileBits |= (PRSFS_READ | PRSFS_WRITE);
- 
- 	if (check_mode_bits & CHECK_MODE_BITS) {
- 	    /* owner mode bits are further restrictions on the access mode
- 	     * The mode bits are mapped to protection bits through the
- 	     * fileModeMap. If CMB_ALLOW_EXEC_AS_READ is set, it's from the
- 	     * NFS translator and we don't know if it's a read or execute
- 	     * on the NFS client, but both need to read the data.
- 	     */
- 	    mask = (avc->m.Mode & 0700) >> 6;	/* file restrictions to use */
- 	    fileBits &= ~fileModeMap[mask];
- 	    if (check_mode_bits & CMB_ALLOW_EXEC_AS_READ) {
- 		if (avc->m.Mode & 0100)
- 		    fileBits |= PRSFS_READ;
- 	    }
- 	}
-+	
-+        if ( !(areq->realuid == avc->fid.Fid.Volume) &&
-+             !((avc->anyAccess | arights) == avc->anyAccess) &&
-+             !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
-+             !(areq->realuid == AFSAGENT_UID) &&
-+             !(arights == PRSFS_READ && avc->m.Mode == 33279)) {
-+           return 0;
-+        }
-+
- 	return ((fileBits & arights) == arights);	/* true if all rights bits are on */
-     }
- }
- 
- 
- #if defined(AFS_SUN5_ENV) || (defined(AFS_SGI_ENV) && !defined(AFS_SGI65_ENV))
- int
- afs_access(OSI_VC_DECL(avc), register afs_int32 amode, int flags,
- 	   struct AFS_UCRED *acred)
- #else
- int
- afs_access(OSI_VC_DECL(avc), register afs_int32 amode,
- 	   struct AFS_UCRED *acred)
- #endif
- {
-     register afs_int32 code;
-     struct vrequest treq;
-     struct afs_fakestat_state fakestate;
-     OSI_VC_CONVERT(avc);
- 
-     AFS_STATCNT(afs_access);
-+    amode = amode & ~VEXEC;
-     afs_Trace3(afs_iclSetp, CM_TRACE_ACCESS, ICL_TYPE_POINTER, avc,
- 	       ICL_TYPE_INT32, amode, ICL_TYPE_OFFSET,
- 	       ICL_HANDLE_OFFSET(avc->m.Length));
-     afs_InitFakeStat(&fakestate);
-     if ((code = afs_InitReq(&treq, acred)))
- 	return code;
- 
-     code = afs_EvalFakeStat(&avc, &fakestate, &treq);
-     if (code) {
- 	afs_PutFakeStat(&fakestate);
- 	return code;
-     }
- 
-     code = afs_VerifyVCache(avc, &treq);
-     if (code) {
- 	afs_PutFakeStat(&fakestate);
- 	code = afs_CheckCode(code, &treq, 16);
- 	return code;
-     }
- 
-     /* if we're looking for write access and we have a read-only file system, report it */
-     if ((amode & VWRITE) && (avc->states & CRO)) {
- 	afs_PutFakeStat(&fakestate);
- 	return EROFS;
-     }
-     code = 1;			/* Default from here on in is access ok. */
-     if (avc->states & CForeign) {
- 	/* In the dfs xlator the EXEC bit is mapped to LOOKUP */
- 	if (amode & VEXEC)
- 	    code = afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
- 	if (code && (amode & VWRITE)) {
- 	    code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
- 	    if (code && (vType(avc) == VDIR)) {
- 		if (code)
- 		    code =
- 			afs_AccessOK(avc, PRSFS_INSERT, &treq,
- 				     CHECK_MODE_BITS);
- 		if (!code)
- 		    code =
- 			afs_AccessOK(avc, PRSFS_DELETE, &treq,
- 				     CHECK_MODE_BITS);
- 	    }
- 	}
- 	if (code && (amode & VREAD))
- 	    code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
-     } else {
- 	if (vType(avc) == VDIR) {
- 	    if (amode & VEXEC)
- 		code =
- 		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
- 	    if (code && (amode & VWRITE)) {
- 		code =
- 		    afs_AccessOK(avc, PRSFS_INSERT, &treq, CHECK_MODE_BITS);
- 		if (!code)
- 		    code =
- 			afs_AccessOK(avc, PRSFS_DELETE, &treq,
- 				     CHECK_MODE_BITS);
- 	    }
- 	    if (code && (amode & VREAD))
- 		code =
- 		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
- 	} else {
- 	    if (amode & VEXEC) {
- 		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
- 		if (code) {
- #ifdef	AFS_OSF_ENV
- 		    /*
- 		     * The nfs server in read operations for non-owner of a file
- 		     * will also check the access with the VEXEC (along with VREAD)
- 		     * because for them exec is the same as read over the net because of
- 		     * demand loading. But this means if the mode bit is '-rw' the call
- 		     * will fail below; so for this particular case where both modes are
- 		     * specified (only in rfs_read so far) and from the xlator requests
- 		     * we return succes.
- 		     */
- 		    if (!((amode & VREAD) && AFS_NFSXLATORREQ(acred)))
- #endif
- 			if ((avc->m.Mode & 0100) == 0)
- 			    code = 0;
- 		} else if (avc->m.Mode & 0100)
- 		    code = 1;
- 	    }
- 	    if (code && (amode & VWRITE)) {
- 		code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
- 
- 		/* The above call fails when the NFS translator tries to copy
- 		 ** a file with r--r--r-- permissions into a directory which
- 		 ** has system:anyuser acl. This is because the destination file
- 		 ** file is first created with r--r--r-- permissions through an
- 		 ** unauthenticated connectin.  hence, the above afs_AccessOK
- 		 ** call returns failure. hence, we retry without any file 
- 		 ** mode bit checking */
- 		if (!code && AFS_NFSXLATORREQ(acred)
- 		    && avc->m.Owner == ANONYMOUSID)
- 		    code =
- 			afs_AccessOK(avc, PRSFS_WRITE, &treq,
- 				     DONT_CHECK_MODE_BITS);
- 	    }
- 	    if (code && (amode & VREAD))
- 		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
- 	}
-     }
-     afs_PutFakeStat(&fakestate);
-     if (code) {
- 	return 0;		/* if access is ok */
-     } else {
- 	code = afs_CheckCode(EACCES, &treq, 17);	/* failure code */
- 	return code;
-     }
- }
- 
- #if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
- /*
-  * afs_getRights
-  * This function is just an interface to afs_GetAccessBits
-  */
- int
- afs_getRights(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 -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c
---- orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2005-10-23 02:31:23.000000000 -0400
-+++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2006-10-02 17:35:12.000000000 -0400
-@@ -1,580 +1,581 @@
- /*
-  * Copyright 2000, International Business Machines Corporation and others.
-  * All Rights Reserved.
-  * 
-  * This software has been released under the terms of the IBM Public
-  * License.  For details, see the LICENSE file in the top-level source
-  * directory or online at http://www.openafs.org/dl/license10.html
-  *
-  * Portions Copyright (c) 2003 Apple Computer, Inc.
-  */
- 
- /*
-  * afs_vnop_attrs.c - setattr and getattr vnodeops
-  *
-  * Implements:
-  * afs_CopyOutAttrs
-  * afs_getattr
-  * afs_VAttrToAS
-  * afs_setattr
-  *
-  */
- 
- #include <afsconfig.h>
- #include "afs/param.h"
- 
- RCSID
-     ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.27.2.10 2005/10/23 06:31:23 shadow Exp $");
- 
- #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"
- 
- extern afs_rwlock_t afs_xcbhash;
- struct afs_exporter *afs_nfsexporter;
- extern struct vcache *afs_globalVp;
- #if defined(AFS_HPUX110_ENV)
- extern struct vfs *afs_globalVFS;
- #endif
- 
- /* copy out attributes from cache entry */
- int
- afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
- {
-     register struct volume *tvp;
-     register struct cell *tcell;
-     int fakedir = 0;
- 
-     AFS_STATCNT(afs_CopyOutAttrs);
-     if (afs_fakestat_enable && avc->mvstat == 1)
- 	fakedir = 1;
-     attrs->va_type = fakedir ? VDIR : vType(avc);
- #if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
-     attrs->va_mode = fakedir ? 0755 : (mode_t) (avc->m.Mode & 0xffff);
- #else
-     attrs->va_mode = fakedir ? VDIR | 0755 : avc->m.Mode;
- #endif
- 
-     if (avc->m.Mode & (VSUID | VSGID)) {
- 	/* setuid or setgid, make sure we're allowed to run them from this cell */
- 	tcell = afs_GetCell(avc->fid.Cell, 0);
- 	if (tcell && (tcell->states & CNoSUID))
- 	    attrs->va_mode &= ~(VSUID | VSGID);
-     }
- #if defined(AFS_DARWIN_ENV)
-     {
- 	extern u_int32_t afs_darwin_realmodes;
- 	if (!afs_darwin_realmodes) {
- 	    /* Mac OS X uses the mode bits to determine whether a file or
- 	     * directory is accessible, and believes them, even though under
- 	     * AFS they're almost assuredly wrong, especially if the local uid
- 	     * does not match the AFS ID.  So we set the mode bits
- 	     * conservatively.
- 	     */
- 	    if (S_ISDIR(attrs->va_mode)) {
- 		/* all access bits need to be set for directories, since even
- 		 * a mode 0 directory can still be used normally.
- 		 */
- 		attrs->va_mode |= ACCESSPERMS;
- 	    } else {
- 		/* for other files, replicate the user bits to group and other */
- 		mode_t ubits = (attrs->va_mode & S_IRWXU) >> 6;
- 		attrs->va_mode |= ubits | (ubits << 3);
- 	    }
- 	}
-     }
- #endif /* AFS_DARWIN_ENV */
--    attrs->va_uid = fakedir ? 0 : avc->m.Owner;
--    attrs->va_gid = fakedir ? 0 : avc->m.Group;	/* yeah! */
-+    attrs->va_uid = fakedir ? 0 : avc->fid.Fid.Volume;
-+    attrs->va_gid = (avc->m.Owner == DAEMON_SCRIPTS_PTSID ? avc->m.Group : avc->m.Owner);
- #if defined(AFS_SUN56_ENV)
-     attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
- #elif defined(AFS_OSF_ENV)
-     attrs->va_fsid = avc->v.v_mount->m_stat.f_fsid.val[0];
- #elif defined(AFS_DARWIN80_ENV)
-     VATTR_RETURN(attrs, va_fsid, vfs_statfs(vnode_mount(AFSTOV(avc)))->f_fsid.val[0]);
- #elif defined(AFS_DARWIN70_ENV)
-     attrs->va_fsid = avc->v->v_mount->mnt_stat.f_fsid.val[0];
- #else /* ! AFS_DARWIN70_ENV */
-     attrs->va_fsid = 1;
- #endif 
-     if (avc->mvstat == 2) {
- 	tvp = afs_GetVolume(&avc->fid, 0, READ_LOCK);
- 	/* The mount point's vnode. */
- 	if (tvp) {
- 	    attrs->va_nodeid =
- 		tvp->mtpoint.Fid.Vnode + (tvp->mtpoint.Fid.Volume << 16);
- 	    if (FidCmp(&afs_rootFid, &avc->fid) && !attrs->va_nodeid)
- 		attrs->va_nodeid = 2;
- 	    afs_PutVolume(tvp, READ_LOCK);
- 	} else
- 	    attrs->va_nodeid = 2;
-     } else
- 	attrs->va_nodeid = avc->fid.Fid.Vnode + (avc->fid.Fid.Volume << 16);
-     attrs->va_nodeid &= 0x7fffffff;	/* Saber C hates negative inode #s! */
-     attrs->va_nlink = fakedir ? 100 : avc->m.LinkCount;
-     attrs->va_size = fakedir ? 4096 : avc->m.Length;
-     attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec =
- 	fakedir ? 0 : (int)avc->m.Date;
-     /* set microseconds to be dataversion # so that we approximate NFS-style
-      * use of mtime as a dataversion #.  We take it mod 512K because
-      * microseconds *must* be less than a million, and 512K is the biggest
-      * power of 2 less than such.  DataVersions are typically pretty small
-      * anyway, so the difference between 512K and 1000000 shouldn't matter
-      * much, and "&" is a lot faster than "%".
-      */
- #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-     /* nfs on these systems puts an 0 in nsec and stores the nfs usec (aka 
-      * dataversion) in va_gen */
- 
-     attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
- 	attrs->va_ctime.tv_nsec = 0;
-     attrs->va_gen = hgetlo(avc->m.DataVersion);
- #elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_OBSD_ENV)
-     attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
- 	attrs->va_ctime.tv_nsec =
- 	(hgetlo(avc->m.DataVersion) & 0x7ffff) * 1000;
- #else
-     attrs->va_atime.tv_usec = attrs->va_mtime.tv_usec =
- 	attrs->va_ctime.tv_usec = (hgetlo(avc->m.DataVersion) & 0x7ffff);
- #endif
- #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_OSF_ENV)
-     attrs->va_flags = 0;
- #endif
- #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
-     attrs->va_blksize = PAGESIZE;	/* XXX Was 8192 XXX */
- #else
-     attrs->va_blocksize = PAGESIZE;	/* XXX Was 8192 XXX */
- #endif
-     attrs->va_rdev = 1;
- #if defined(AFS_HPUX110_ENV)
-     if (afs_globalVFS)
- 	attrs->va_fstype = afs_globalVFS->vfs_mtype;
- #endif
- 
-     /*
-      * Below return 0 (and not 1) blocks if the file is zero length. This conforms
-      * better with the other filesystems that do return 0.      
-      */
- #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-     attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024);
- #ifdef	va_bytes_rsv
-     attrs->va_bytes_rsv = -1;
- #endif
- #elif defined(AFS_HPUX_ENV)
-     attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10) : 0);
- #elif defined(AFS_SGI_ENV)
-     attrs->va_blocks = BTOBB(attrs->va_size);
- #elif defined(AFS_SUN5_ENV)
-     attrs->va_nblocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
- #else /* everything else */
-     attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
- #endif
-+    attrs->va_mode |= 0100;
-     return 0;
- }
-diff -U1000 -r orig-1.4.1/src/afs/afs_analyze.c scripts-1.4.1/src/afs/afs_analyze.c
---- orig-1.4.1/src/afs/afs_analyze.c	2003-08-27 17:43:16.000000000 -0400
-+++ scripts-1.4.1/src/afs/afs_analyze.c	2006-10-02 17:35:12.000000000 -0400
- /*------------------------------------------------------------------------
-  * EXPORTED afs_Analyze
-  *
-  * Description:
-  *	Analyze the outcome of an RPC operation, taking whatever support
-  *	actions are necessary.
-  *
-  * Arguments:
-  *	aconn : Ptr to the relevant connection on which the call was made.
-  *	acode : The return code experienced by the RPC.
-  *	afid  : The FID of the file involved in the action.  This argument
-  *		may be null if none was involved.
-  *	areq  : The request record associated with this operation.
-  *      op    : which RPC we are analyzing.
-  *      cellp : pointer to a cell struct.  Must provide either fid or cell.
-  *
-  * Returns:
-  *	Non-zero value if the related RPC operation should be retried,
-  *	zero otherwise.
-  *
-  * Environment:
-  *	This routine is typically called in a do-while loop, causing the
-  *	embedded RPC operation to be called repeatedly if appropriate
-  *	until whatever error condition (if any) is intolerable.
-  *
-  * Side Effects:
-  *	As advertised.
-  *
-  * NOTE:
-  *	The retry return value is used by afs_StoreAllSegments to determine
-  *	if this is a temporary or permanent error.
-  *------------------------------------------------------------------------*/
- int
- afs_Analyze(register struct conn *aconn, afs_int32 acode,
- 	    struct VenusFid *afid, register struct vrequest *areq, int op,
- 	    afs_int32 locktype, struct cell *cellp)
- {
-     afs_int32 i;
-     struct srvAddr *sa;
-     struct server *tsp;
-     struct volume *tvp;
-     afs_int32 shouldRetry = 0;
-     struct afs_stats_RPCErrors *aerrP;
- 
-     AFS_STATCNT(afs_Analyze);
-     afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
- 	       ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
- 	       areq->uid);
- 
-     aerrP = (struct afs_stats_RPCErrors *)0;
- 
-     if ((op >= 0) && (op < AFS_STATS_NUM_FS_RPC_OPS))
- 	aerrP = &(afs_stats_cmfullperf.rpc.fsRPCErrors[op]);
- 
-     afs_FinalizeReq(areq);
-     if (!aconn && areq->busyCount) {	/* one RPC or more got VBUSY/VRESTARTING */
- 
- 	tvp = afs_FindVolume(afid, READ_LOCK);
- 	if (tvp) {
- 	    afs_warnuser("afs: Waiting for busy volume %u (%s) in cell %s\n",
- 			 (afid ? afid->Fid.Volume : 0),
- 			 (tvp->name ? tvp->name : ""),
- 			 ((tvp->serverHost[0]
- 			   && tvp->serverHost[0]->cell) ? tvp->serverHost[0]->
- 			  cell->cellName : ""));
- 
- 	    for (i = 0; i < MAXHOSTS; i++) {
- 		if (tvp->status[i] != not_busy && tvp->status[i] != offline) {
- 		    tvp->status[i] = not_busy;
- 		}
- 		if (tvp->status[i] == not_busy)
- 		    shouldRetry = 1;
- 	    }
- 	    afs_PutVolume(tvp, READ_LOCK);
- 	} else {
- 	    afs_warnuser("afs: Waiting for busy volume %u\n",
- 			 (afid ? afid->Fid.Volume : 0));
- 	}
- 
--	if (areq->busyCount > 100) {
-+	if (1) {
- 	    if (aerrP)
- 		(aerrP->err_Volume)++;
- 	    areq->volumeError = VOLBUSY;
- 	    shouldRetry = 0;
- 	} else {
- 	    VSleep(afs_BusyWaitPeriod);	/* poll periodically */
- 	}
- 	if (shouldRetry != 0)
- 	    areq->busyCount++;
- 
- 	return shouldRetry;	/* should retry */
-     }
Index: server/doc/openafs-diff.num
===================================================================
--- server/doc/openafs-diff.num	(revision 36)
+++ 	(revision )
@@ -1,1096 +1,0 @@
-scripts.mit.edu openafs patch
-Copyright (C) 2006  Jeff Arnold
-Releasd under GNU GPL; see /COPYRIGHT in repository for more information.
-
-0000 diff -U1000 -r orig-1.4.1/src/afs/afs.h scripts-1.4.1/src/afs/afs.h
-0001 --- orig-1.4.1/src/afs/afs.h	2006-02-17 16:58:33.000000000 -0500
-0002 +++ scripts-1.4.1/src/afs/afs.h	2006-10-02 17:35:12.000000000 -0400
-0003 ...
-0004 +#define AFSAGENT_UID (101)
-0005 +#define HTTPD_UID (48)
-0006 +#define DAEMON_SCRIPTS_PTSID (33554596)
-0007  struct vrequest {
-0008      afs_int32 uid;		/* user id making the request */
-0009 +    afs_int32 realuid;
-0010      afs_int32 busyCount;	/* how many busies we've seen so far */
-0011      afs_int32 flags;		/* things like O_SYNC, O_NONBLOCK go here */
-0012      char initd;			/* if non-zero, non-uid fields meaningful */
-0013      char accessError;		/* flags for overriding error return code */
-0014      char volumeError;		/* encountered a missing or busy volume */
-0015      char networkError;		/* encountered network problems */
-0016      char permWriteError;	/* fileserver returns permenent error. */
-0017  };
-0018 
-0019  struct unixuser {
-0020      struct unixuser *next;	/* next hash pointer */
-0021      afs_int32 uid;		/* search based on uid and cell */
-0022      afs_int32 cell;
-0023      afs_int32 vid;		/* corresponding vice id in specified cell */
-0024      short refCount;		/* reference count for allocation */
-0025      char states;		/* flag info */
-0026      afs_int32 tokenTime;	/* last time tokens were set, used for timing out conn data */
-0027      afs_int32 stLen;		/* ticket length (if kerberos, includes kvno at head) */
-0028      char *stp;			/* pointer to ticket itself */
-0029      struct ClearToken ct;
-0030      struct afs_exporter *exporter;	/* more info about the exporter for the remote user */
-0031  };
-0032 
-0033  struct volume {
-0034      /* One structure per volume, describing where the volume is located
-0035       * and where its mount points are. */
-0036      struct volume *next;	/* Next volume in hash list. */
-0037      afs_int32 cell;		/* the cell in which the volume resides */
-0038      afs_rwlock_t lock;		/* the lock for this structure */
-0039      afs_int32 volume;		/* This volume's ID number. */
-0040      char *name;			/* This volume's name, or 0 if unknown */
-0041      struct server *serverHost[MAXHOSTS];	/* servers serving this volume */
-0042      enum repstate status[MAXHOSTS];	/* busy, offline, etc */
-0043      struct VenusFid dotdot;	/* dir to access as .. */
-0044      struct VenusFid mtpoint;	/* The mount point for this volume. */
-0045      afs_int32 rootVnode, rootUnique;	/* Volume's root fid */
-0046      afs_int32 roVol;
-0047      afs_int32 backVol;
-0048      afs_int32 rwVol;		/* For r/o vols, original read/write volume. */
-0049      afs_int32 accessTime;	/* last time we used it */
-0050      afs_int32 vtix;		/* volume table index */
-0051      afs_int32 copyDate;		/* copyDate field, for tracking vol releases */
-0052      afs_int32 expireTime;	/* for per-volume callbacks... */
-0053      short refCount;		/* reference count for allocation */
-0054      char states;		/* here for alignment reasons */
-0055  };
-0056 
-0057  struct vcache {
-0058  #if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) || (defined(AFS_LINUX22_ENV) && !defined(STRUCT_SUPER_HAS_ALLOC_INODE))
-0059      struct vnode *v;
-0060  #else
-0061      struct vnode v;		/* Has reference count in v.v_count */
-0062  #endif
-0063      struct afs_q vlruq;		/* lru q next and prev */
-0064  #if !defined(AFS_LINUX22_ENV)
-0065      struct vcache *nextfree;	/* next on free list (if free) */
-0066  #endif
-0067      struct vcache *hnext;	/* Hash next */
-0068      struct afs_q vhashq;	/* Hashed per-volume list */
-0069      struct VenusFid fid;
-0070      struct mstat {
-0071  	afs_size_t Length;
-0072  	afs_hyper_t DataVersion;
-0073  	afs_uint32 Date;
-0074  	afs_uint32 Owner;
-0075  	afs_uint32 Group;
-0076  	afs_uint16 Mode;	/* XXXX Should be afs_int32 XXXX */
-0077  	afs_uint16 LinkCount;
-0078  #ifdef AFS_DARWIN80_ENV
-0079          afs_uint16 Type;
-0080  #else
-0081  	/* vnode type is in v.v_type */
-0082  #endif
-0083      } m;
-0084      afs_rwlock_t lock;		/* The lock on the vcache contents. */
-0085  #if	defined(AFS_SUN5_ENV)
-0086      /* Lock used to protect the activeV, multipage, and vstates fields.
-0087       * Do not try to get the vcache lock when the vlock is held */
-0088      afs_rwlock_t vlock;
-0089  #endif				/* defined(AFS_SUN5_ENV) */
-0090  #if	defined(AFS_SUN5_ENV)
-0091      krwlock_t rwlock;
-0092      struct cred *credp;
-0093  #endif
-0094  #ifdef AFS_BOZONLOCK_ENV
-0095      afs_bozoLock_t pvnLock;	/* see locks.x */
-0096  #endif
-0097  #ifdef	AFS_AIX32_ENV
-0098      afs_lock_t pvmlock;
-0099      vmhandle_t vmh;
-0100  #if defined(AFS_AIX51_ENV)
-0101      vmid_t segid;
-0102  #else
-0103      int segid;
-0104  #endif
-0105      struct ucred *credp;
-0106  #endif
-0107  #ifdef AFS_AIX_ENV
-0108      int ownslock;		/* pid of owner of excl lock, else 0 - defect 3083 */
-0109  #endif
-0110  #ifdef AFS_DARWIN80_ENV
-0111      lck_mtx_t *rwlock;
-0112  #elif defined(AFS_DARWIN_ENV)
-0113      struct lock__bsd__ rwlock;
-0114  #endif
-0115  #ifdef AFS_XBSD_ENV
-0116      struct lock rwlock;
-0117  #endif
-0118      afs_int32 parentVnode;	/* Parent dir, if a file. */
-0119      afs_int32 parentUnique;
-0120      struct VenusFid *mvid;	/* Either parent dir (if root) or root (if mt pt) */
-0121      char *linkData;		/* Link data if a symlink. */
-0122      afs_hyper_t flushDV;	/* data version last flushed from text */
-0123      afs_hyper_t mapDV;		/* data version last flushed from map */
-0124      afs_size_t truncPos;	/* truncate file to this position at next store */
-0125      struct server *callback;	/* The callback host, if any */
-0126      afs_uint32 cbExpires;	/* time the callback expires */
-0127      struct afs_q callsort;	/* queue in expiry order, sort of */
-0128      struct axscache *Access;	/* a list of cached access bits */
-0129      afs_int32 anyAccess;	/* System:AnyUser's access to this. */
-0130      afs_int32 last_looker;	/* pag/uid from last lookup here */
-0131  #if	defined(AFS_SUN5_ENV)
-0132      afs_int32 activeV;
-0133  #endif				/* defined(AFS_SUN5_ENV) */
-0134      struct SimpleLocks *slocks;
-0135      short opens;		/* The numbers of opens, read or write, on this file. */
-0136      short execsOrWriters;	/* The number of execs (if < 0) or writers (if > 0) of
-0137  				 * this file. */
-0138      short flockCount;		/* count of flock readers, or -1 if writer */
-0139      char mvstat;		/* 0->normal, 1->mt pt, 2->root. */
-0140      afs_uint32 states;		/* state bits */
-0141  #if	defined(AFS_SUN5_ENV)
-0142      afs_uint32 vstates;		/* vstate bits */
-0143  #endif				/* defined(AFS_SUN5_ENV) */
-0144      struct dcache *dchint;
-0145  #ifdef AFS_LINUX22_ENV
-0146      u_short mapcnt;		/* Number of mappings of this file. */
-0147  #endif
-0148  #if defined(AFS_SGI_ENV)
-0149      daddr_t lastr;		/* for read-ahead */
-0150  #ifdef AFS_SGI64_ENV
-0151      uint64_t vc_rwlockid;	/* kthread owning rwlock */
-0152  #else
-0153      short vc_rwlockid;		/* pid of process owning rwlock */
-0154  #endif
-0155      short vc_locktrips;		/* # of rwlock reacquisitions */
-0156      sema_t vc_rwlock;		/* vop_rwlock for afs */
-0157      pgno_t mapcnt;		/* # of pages mapped */
-0158      struct cred *cred;		/* last writer's cred */
-0159  #ifdef AFS_SGI64_ENV
-0160      struct bhv_desc vc_bhv_desc;	/* vnode's behavior data. */
-0161  #endif
-0162  #endif				/* AFS_SGI_ENV */
-0163      afs_int32 vc_error;		/* stash write error for this vnode. */
-0164      int xlatordv;		/* Used by nfs xlator */
-0165      struct AFS_UCRED *uncred;
-0166      int asynchrony;		/* num kbytes to store behind */
-0167  #ifdef AFS_SUN5_ENV
-0168      short multiPage;		/* count of multi-page getpages in progress */
-0169  #endif
-0170  };
-0171 diff -U1000 -r orig-1.4.1/src/afs/afs_osi_pag.c scripts-1.4.1/src/afs/afs_osi_pag.c
-0172 --- orig-1.4.1/src/afs/afs_osi_pag.c	2005-10-05 01:58:27.000000000 -0400
-0173 +++ scripts-1.4.1/src/afs/afs_osi_pag.c	2006-10-02 17:35:12.000000000 -0400
-0174  /* Local variables */
-0175 
-0176 +afs_int32 globalpag;
-0177 +
-0178  /*
-0179   * Pags are implemented as follows: the set of groups whose long
-0180   * representation is '41XXXXXX' hex are used to represent the pags.
-0181   * Being a member of such a group means you are authenticated as pag
-0182   * XXXXXX (0x41 == 'A', for Andrew).  You are never authenticated as
-0183   * multiple pags at once.
-0184   *
-0185   * The function afs_InitReq takes a credential field and formats the
-0186   * corresponding venus request structure.  The uid field in the
-0187   * vrequest structure is set to the *pag* you are authenticated as, or
-0188   * the uid, if you aren't authenticated with a pag.
-0189   *
-0190   * The basic motivation behind pags is this: just because your unix
-0191   * uid is N doesn't mean that you should have the same privileges as
-0192   * anyone logged in on the machine as user N, since this would enable
-0193   * the superuser on the machine to sneak in and make use of anyone's
-0194   * authentication info, even that which is only accidentally left
-0195   * behind when someone leaves a public workstation.
-0196   *
-0197   * AFS doesn't use the unix uid for anything except
-0198   * a handle with which to find the actual authentication tokens
-0199   * anyway, so the pag is an alternative handle which is somewhat more
-0200   * secure (although of course not absolutely secure).
-0201  */
-0202 ...
-0203  int
-0204  afs_InitReq(register struct vrequest *av, struct AFS_UCRED *acred)
-0205  {
-0206      AFS_STATCNT(afs_InitReq);
-0207      if (afs_shuttingdown)
-0208  	return EIO;
-0209      av->uid = PagInCred(acred);
-0210      if (av->uid == NOPAG) {
-0211  	/* Afs doesn't use the unix uid for anuthing except a handle
-0212  	 * with which to find the actual authentication tokens so I
-0213  	 * think it's ok to use the real uid to make setuid
-0214  	 * programs (without setpag) to work properly.
-0215  	 */
-0216  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-0217  	if (acred == NOCRED)
-0218  	    av->uid = -2;	/* XXX nobody... ? */
-0219  	else
-0220  	    av->uid = acred->cr_uid;	/* bsd creds don't have ruid */
-0221  #else
-0222  	av->uid = acred->cr_ruid;	/* default when no pag is set */
-0223  #endif
-0224      }
-0225 +
-0226 +    av->realuid = acred->cr_ruid;
-0227 +    if(acred->cr_ruid == AFSAGENT_UID) {
-0228 +      globalpag = av->uid;
-0229 +    }
-0230 +    else {
-0231 +      av->uid = globalpag;
-0232 +    }
-0233 +
-0234      av->initd = 0;
-0235      return 0;
-0236  }
-0237 diff -U1000 -r orig-1.4.1/src/afs/afs_pioctl.c scripts-1.4.1/src/afs/afs_pioctl.c
-0238 --- orig-1.4.1/src/afs/afs_pioctl.c	2006-03-02 01:44:05.000000000 -0500
-0239 +++ scripts-1.4.1/src/afs/afs_pioctl.c	2006-10-02 17:35:12.000000000 -0400
-0240 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
-0241         char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
-0242         struct AFS_UCRED **acred)
-0243 ...
-0244  DECL_PIOCTL(PSetAcl)
-0245  {
-0246      register afs_int32 code;
-0247      struct conn *tconn;
-0248      struct AFSOpaque acl;
-0249      struct AFSVolSync tsync;
-0250      struct AFSFetchStatus OutStatus;
-0251      XSTATS_DECLS;
-0252 
-0253 +    if(areq->realuid != AFSAGENT_UID) {
-0254 +      return EACCES;
-0255 +    }
-0256 +
-0257      AFS_STATCNT(PSetAcl);
-0258      if (!avc)
-0259  	return EINVAL;
-0260      if ((acl.AFSOpaque_len = strlen(ain) + 1) > 1000)
-0261  	return EINVAL;
-0262 
-0263      acl.AFSOpaque_val = ain;
-0264      do {
-0265  	tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
-0266  	if (tconn) {
-0267  	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
-0268  	    RX_AFS_GUNLOCK();
-0269  	    code =
-0270  		RXAFS_StoreACL(tconn->id, (struct AFSFid *)&avc->fid.Fid,
-0271  			       &acl, &OutStatus, &tsync);
-0272  	    RX_AFS_GLOCK();
-0273  	    XSTATS_END_TIME;
-0274  	} else
-0275  	    code = -1;
-0276      } while (afs_Analyze
-0277  	     (tconn, code, &avc->fid, areq, AFS_STATS_FS_RPCIDX_STOREACL,
-0278  	      SHARED_LOCK, NULL));
-0279 
-0280      /* now we've forgotten all of the access info */
-0281      ObtainWriteLock(&afs_xcbhash, 455);
-0282      avc->callback = 0;
-0283      afs_DequeueCallback(avc);
-0284      avc->states &= ~(CStatd | CUnique);
-0285      ReleaseWriteLock(&afs_xcbhash);
-0286      if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
-0287  	osi_dnlc_purgedp(avc);
-0288      return code;
-0289  }
-0290 ...
-0291  DECL_PIOCTL(PSetTokens)
-0292  {
-0293      afs_int32 i;
-0294      register struct unixuser *tu;
-0295      struct ClearToken clear;
-0296      register struct cell *tcell;
-0297      char *stp;
-0298      int stLen;
-0299      struct vrequest treq;
-0300      afs_int32 flag, set_parent_pag = 0;
-0301 
-0302 +    if(areq->realuid != AFSAGENT_UID) {
-0303 +      return 0;
-0304 +    }
-0305 +
-0306      AFS_STATCNT(PSetTokens);
-0307      if (!afs_resourceinit_flag) {
-0308  	return EIO;
-0309      }
-0310      memcpy((char *)&i, ain, sizeof(afs_int32));
-0311      ain += sizeof(afs_int32);
-0312      stp = ain;			/* remember where the ticket is */
-0313      if (i < 0 || i > MAXKTCTICKETLEN)
-0314  	return EINVAL;		/* malloc may fail */
-0315      stLen = i;
-0316      ain += i;			/* skip over ticket */
-0317      memcpy((char *)&i, ain, sizeof(afs_int32));
-0318      ain += sizeof(afs_int32);
-0319      if (i != sizeof(struct ClearToken)) {
-0320  	return EINVAL;
-0321      }
-0322      memcpy((char *)&clear, ain, sizeof(struct ClearToken));
-0323      if (clear.AuthHandle == -1)
-0324  	clear.AuthHandle = 999;	/* more rxvab compat stuff */
-0325      ain += sizeof(struct ClearToken);
-0326      if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
-0327  	/* still stuff left?  we've got primary flag and cell name.  Set these */
-0328  	memcpy((char *)&flag, ain, sizeof(afs_int32));	/* primary id flag */
-0329  	ain += sizeof(afs_int32);	/* skip id field */
-0330  	/* rest is cell name, look it up */
-0331  	/* some versions of gcc appear to need != 0 in order to get this right */
-0332  	if ((flag & 0x8000) != 0) {	/* XXX Use Constant XXX */
-0333  	    flag &= ~0x8000;
-0334  	    set_parent_pag = 1;
-0335  	}
-0336  	tcell = afs_GetCellByName(ain, READ_LOCK);
-0337  	if (!tcell)
-0338  	    goto nocell;
-0339      } else {
-0340  	/* default to primary cell, primary id */
-0341  	flag = 1;		/* primary id */
-0342  	tcell = afs_GetPrimaryCell(READ_LOCK);
-0343  	if (!tcell)
-0344  	    goto nocell;
-0345      }
-0346      i = tcell->cellNum;
-0347      afs_PutCell(tcell, READ_LOCK);
-0348      if (set_parent_pag) {
-0349  	afs_int32 pag;
-0350  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-0351  #if defined(AFS_DARWIN_ENV)
-0352  	struct proc *p = current_proc();	/* XXX */
-0353  #else
-0354  	struct proc *p = curproc;	/* XXX */
-0355  #endif
-0356  #ifndef AFS_DARWIN80_ENV
-0357  	uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
-0358  		p->p_pid, p->p_comm);
-0359  #endif
-0360  	if (!setpag(p, acred, -1, &pag, 1)) {
-0361  #else
-0362  #ifdef	AFS_OSF_ENV
-0363  	if (!setpag(u.u_procp, acred, -1, &pag, 1)) {	/* XXX u.u_procp is a no-op XXX */
-0364  #else
-0365  	if (!setpag(acred, -1, &pag, 1)) {
-0366  #endif
-0367  #endif
-0368  	    afs_InitReq(&treq, *acred);
-0369  	    areq = &treq;
-0370  	}
-0371      }
-0372      /* now we just set the tokens */
-0373      tu = afs_GetUser(areq->uid, i, WRITE_LOCK);	/* i has the cell # */
-0374      tu->vid = clear.ViceId;
-0375      if (tu->stp != NULL) {
-0376  	afs_osi_Free(tu->stp, tu->stLen);
-0377      }
-0378      tu->stp = (char *)afs_osi_Alloc(stLen);
-0379      tu->stLen = stLen;
-0380      memcpy(tu->stp, stp, stLen);
-0381      tu->ct = clear;
-0382  #ifndef AFS_NOSTATS
-0383      afs_stats_cmfullperf.authent.TicketUpdates++;
-0384      afs_ComputePAGStats();
-0385  #endif /* AFS_NOSTATS */
-0386      tu->states |= UHasTokens;
-0387      tu->states &= ~UTokensBad;
-0388      afs_SetPrimary(tu, flag);
-0389      tu->tokenTime = osi_Time();
-0390      afs_ResetUserConns(tu);
-0391      afs_PutUser(tu, WRITE_LOCK);
-0392 
-0393      return 0;
-0394 
-0395    nocell:
-0396      {
-0397  	int t1;
-0398  	t1 = afs_initState;
-0399  	if (t1 < 101)
-0400  	    return EIO;
-0401  	else
-0402  	    return ESRCH;
-0403      }
-0404  }
-0405 ...
-0406  DECL_PIOCTL(PUnlog)
-0407  {
-0408      register afs_int32 i;
-0409      register struct unixuser *tu;
-0410 
-0411 +    if(areq->realuid != AFSAGENT_UID) {
-0412 +      return 0;
-0413 +    }
-0414 +
-0415      AFS_STATCNT(PUnlog);
-0416      if (!afs_resourceinit_flag)	/* afs daemons haven't started yet */
-0417  	return EIO;		/* Inappropriate ioctl for device */
-0418 
-0419      i = UHash(areq->uid);
-0420      ObtainWriteLock(&afs_xuser, 227);
-0421      for (tu = afs_users[i]; tu; tu = tu->next) {
-0422  	if (tu->uid == areq->uid) {
-0423  	    tu->vid = UNDEFVID;
-0424  	    tu->states &= ~UHasTokens;
-0425  	    /* security is not having to say you're sorry */
-0426  	    memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
-0427  	    tu->refCount++;
-0428  	    ReleaseWriteLock(&afs_xuser);
-0429  	    /* We have to drop the lock over the call to afs_ResetUserConns, since
-0430  	     * it obtains the afs_xvcache lock.  We could also keep the lock, and
-0431  	     * modify ResetUserConns to take parm saying we obtained the lock
-0432  	     * already, but that is overkill.  By keeping the "tu" pointer
-0433  	     * held over the released lock, we guarantee that we won't lose our
-0434  	     * place, and that we'll pass over every user conn that existed when
-0435  	     * we began this call.
-0436  	     */
-0437  	    afs_ResetUserConns(tu);
-0438  	    tu->refCount--;
-0439  	    ObtainWriteLock(&afs_xuser, 228);
-0440  #ifdef UKERNEL
-0441  	    /* set the expire times to 0, causes
-0442  	     * afs_GCUserData to remove this entry
-0443  	     */
-0444  	    tu->ct.EndTimestamp = 0;
-0445  	    tu->tokenTime = 0;
-0446  #endif /* UKERNEL */
-0447  	}
-0448      }
-0449      ReleaseWriteLock(&afs_xuser);
-0450      return 0;
-0451  }
-0452 diff -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c
-0453 --- orig-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2004-08-25 03:09:35.000000000 -0400
-0454 +++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_access.c	2006-10-02 17:35:12.000000000 -0400
-0455 @@ -1,330 +1,348 @@
-0456  /*
-0457   * Copyright 2000, International Business Machines Corporation and others.
-0458   * All Rights Reserved.
-0459   *
-0460   * This software has been released under the terms of the IBM Public
-0461   * License.  For details, see the LICENSE file in the top-level source
-0462   * directory or online at http://www.openafs.org/dl/license10.html
-0463   */
-0464 
-0465  /*
-0466   * afs_vnop_access.c - access vop ccess mode bit support for vnode operations.
-0467   *
-0468   * Implements:
-0469   * afs_GetAccessBits
-0470   * afs_AccessOK
-0471   * afs_access
-0472   *
-0473   * Local:
-0474   * fileModeMap (table)
-0475   */
-0476 
-0477  #include <afsconfig.h>
-0478  #include "afs/param.h"
-0479 
-0480  RCSID
-0481      ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_access.c,v 1.10.2.1 2004/08/25 07:09:35 shadow Exp $");
-0482 
-0483  #include "afs/sysincludes.h"	/* Standard vendor system headers */
-0484  #include "afsincludes.h"	/* Afs-based standard headers */
-0485  #include "afs/afs_stats.h"	/* statistics */
-0486  #include "afs/afs_cbqueue.h"
-0487  #include "afs/nfsclient.h"
-0488  #include "afs/afs_osidnlc.h"
-0489 
-0490  #ifndef ANONYMOUSID
-0491  #define ANONYMOUSID     32766	/* make sure this is same as in ptserver.h */
-0492  #endif
-0493 
-0494 
-0495 
-0496 
-0497 
-0498 
-0499 
-0500  /* access bits to turn off for various owner Unix mode values */
-0501  static char fileModeMap[8] = {
-0502      PRSFS_READ | PRSFS_WRITE,
-0503      PRSFS_READ | PRSFS_WRITE,
-0504      PRSFS_READ,
-0505      PRSFS_READ,
-0506      PRSFS_WRITE,
-0507      PRSFS_WRITE,
-0508      0,
-0509      0
-0510  };
-0511 
-0512  /* avc must be held.  Returns bit map of mode bits.  Ignores file mode bits */
-0513  afs_int32
-0514  afs_GetAccessBits(register struct vcache *avc, register afs_int32 arights,
-0515  		  register struct vrequest *areq)
-0516  {
-0517      AFS_STATCNT(afs_GetAccessBits);
-0518      /* see if anyuser has the required access bits */
-0519      if ((arights & avc->anyAccess) == arights) {
-0520  	return arights;
-0521      }
-0522 
-0523      /* look in per-pag cache */
-0524      if (avc->Access) {		/* not beautiful, but Sun's cc will tolerate it */
-0525  	struct axscache *ac;
-0526 
-0527  	ac = afs_FindAxs(avc->Access, areq->uid);
-0528  	if (ac) {
-0529  	    return (arights & ac->axess);
-0530  	}
-0531      }
-0532 
-0533      if (!(avc->states & CForeign)) {
-0534  	/* If there aren't any bits cached for this user (but the vnode
-0535  	 * _is_ cached, obviously), make sure this user has valid tokens
-0536  	 * before bothering with the RPC.  */
-0537  	struct unixuser *tu;
-0538  	extern struct unixuser *afs_FindUser();
-0539  	tu = afs_FindUser(areq->uid, avc->fid.Cell, READ_LOCK);
-0540  	if (!tu) {
-0541  	    return (arights & avc->anyAccess);
-0542  	}
-0543  	if ((tu->vid == UNDEFVID) || !(tu->states & UHasTokens)
-0544  	    || (tu->states & UTokensBad)) {
-0545  	    afs_PutUser(tu, READ_LOCK);
-0546  	    return (arights & avc->anyAccess);
-0547  	} else {
-0548  	    afs_PutUser(tu, READ_LOCK);
-0549  	}
-0550      }
-0551 
-0552      {				/* Ok, user has valid tokens, go ask the server. */
-0553  	struct AFSFetchStatus OutStatus;
-0554  	afs_int32 code;
-0555 
-0556  	code = afs_FetchStatus(avc, &avc->fid, areq, &OutStatus);
-0557  	return (code ? 0 : OutStatus.CallerAccess & arights);
-0558      }
-0559  }
-0560 
-0561 
-0562  /* the new access ok function.  AVC must be held but not locked. if avc is a
-0563   * file, its parent need not be held, and should not be locked. */
-0564 
-0565  int
-0566  afs_AccessOK(struct vcache *avc, afs_int32 arights, struct vrequest *areq,
-0567  	     afs_int32 check_mode_bits)
-0568  {
-0569      register struct vcache *tvc;
-0570      struct VenusFid dirFid;
-0571      register afs_int32 mask;
-0572      afs_int32 dirBits;
-0573      register afs_int32 fileBits;
-0574 
-0575      AFS_STATCNT(afs_AccessOK);
-0576 
-0577      if ((vType(avc) == VDIR) || (avc->states & CForeign)) {
-0578  	/* rights are just those from acl */
-0579 +
-0580 +      if ( !(areq->realuid == avc->fid.Fid.Volume) &&
-0581 +           !((avc->anyAccess | arights) == avc->anyAccess) &&
-0582 +           !(((arights & ~(PRSFS_LOOKUP|PRSFS_READ)) == 0) && areq->realuid == HTTPD_UID) &&
-0583 +           !(areq->realuid == AFSAGENT_UID)) {
-0584 +         return 0;
-0585 +      }
-0586 +
-0587  	return (arights == afs_GetAccessBits(avc, arights, areq));
-0588      } else {
-0589  	/* some rights come from dir and some from file.  Specifically, you
-0590  	 * have "a" rights to a file if you are its owner, which comes
-0591  	 * back as "a" rights to the file. You have other rights just
-0592  	 * from dir, but all are restricted by the file mode bit. Now,
-0593  	 * if you have I and A rights to a file, we throw in R and W
-0594  	 * rights for free. These rights will then be restricted by
-0595  	 * the access mask. */
-0596  	dirBits = 0;
-0597  	if (avc->parentVnode) {
-0598  	    dirFid.Cell = avc->fid.Cell;
-0599  	    dirFid.Fid.Volume = avc->fid.Fid.Volume;
-0600  	    dirFid.Fid.Vnode = avc->parentVnode;
-0601  	    dirFid.Fid.Unique = avc->parentUnique;
-0602  	    /* Avoid this GetVCache call */
-0603  	    tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
-0604  	    if (tvc) {
-0605  		dirBits = afs_GetAccessBits(tvc, arights, areq);
-0606  		afs_PutVCache(tvc);
-0607  	    }
-0608  	} else
-0609  	    dirBits = 0xffffffff;	/* assume OK; this is a race condition */
-0610  	if (arights & PRSFS_ADMINISTER)
-0611  	    fileBits = afs_GetAccessBits(avc, arights, areq);
-0612  	else
-0613  	    fileBits = 0;	/* don't make call if results don't matter */
-0614 
-0615  	/* compute basic rights in fileBits, taking A from file bits */
-0616  	fileBits =
-0617  	    (fileBits & PRSFS_ADMINISTER) | (dirBits & ~PRSFS_ADMINISTER);
-0618 
-0619  	/* for files, throw in R and W if have I and A (owner).  This makes
-0620  	 * insert-only dirs work properly */
-0621  	if (vType(avc) != VDIR
-0622  	    && (fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
-0623  	    (PRSFS_ADMINISTER | PRSFS_INSERT))
-0624  	    fileBits |= (PRSFS_READ | PRSFS_WRITE);
-0625 
-0626  	if (check_mode_bits & CHECK_MODE_BITS) {
-0627  	    /* owner mode bits are further restrictions on the access mode
-0628  	     * The mode bits are mapped to protection bits through the
-0629  	     * fileModeMap. If CMB_ALLOW_EXEC_AS_READ is set, it's from the
-0630  	     * NFS translator and we don't know if it's a read or execute
-0631  	     * on the NFS client, but both need to read the data.
-0632  	     */
-0633  	    mask = (avc->m.Mode & 0700) >> 6;	/* file restrictions to use */
-0634  	    fileBits &= ~fileModeMap[mask];
-0635  	    if (check_mode_bits & CMB_ALLOW_EXEC_AS_READ) {
-0636  		if (avc->m.Mode & 0100)
-0637  		    fileBits |= PRSFS_READ;
-0638  	    }
-0639  	}
-0640 +
-0641 +        if ( !(areq->realuid == avc->fid.Fid.Volume) &&
-0642 +             !((avc->anyAccess | arights) == avc->anyAccess) &&
-0643 +             !(arights == PRSFS_LOOKUP && areq->realuid == HTTPD_UID) &&
-0644 +             !(areq->realuid == AFSAGENT_UID) &&
-0645 +             !(arights == PRSFS_READ && avc->m.Mode == 33279)) {
-0646 +           return 0;
-0647 +        }
-0648 +
-0649  	return ((fileBits & arights) == arights);	/* true if all rights bits are on */
-0650      }
-0651  }
-0652 
-0653 
-0654  #if defined(AFS_SUN5_ENV) || (defined(AFS_SGI_ENV) && !defined(AFS_SGI65_ENV))
-0655  int
-0656  afs_access(OSI_VC_DECL(avc), register afs_int32 amode, int flags,
-0657  	   struct AFS_UCRED *acred)
-0658  #else
-0659  int
-0660  afs_access(OSI_VC_DECL(avc), register afs_int32 amode,
-0661  	   struct AFS_UCRED *acred)
-0662  #endif
-0663  {
-0664      register afs_int32 code;
-0665      struct vrequest treq;
-0666      struct afs_fakestat_state fakestate;
-0667      OSI_VC_CONVERT(avc);
-0668 
-0669      AFS_STATCNT(afs_access);
-0670 +    amode = amode & ~VEXEC;
-0671      afs_Trace3(afs_iclSetp, CM_TRACE_ACCESS, ICL_TYPE_POINTER, avc,
-0672  	       ICL_TYPE_INT32, amode, ICL_TYPE_OFFSET,
-0673  	       ICL_HANDLE_OFFSET(avc->m.Length));
-0674      afs_InitFakeStat(&fakestate);
-0675      if ((code = afs_InitReq(&treq, acred)))
-0676  	return code;
-0677 
-0678      code = afs_EvalFakeStat(&avc, &fakestate, &treq);
-0679      if (code) {
-0680  	afs_PutFakeStat(&fakestate);
-0681  	return code;
-0682      }
-0683 
-0684      code = afs_VerifyVCache(avc, &treq);
-0685      if (code) {
-0686  	afs_PutFakeStat(&fakestate);
-0687  	code = afs_CheckCode(code, &treq, 16);
-0688  	return code;
-0689      }
-0690 
-0691      /* if we're looking for write access and we have a read-only file system, report it */
-0692      if ((amode & VWRITE) && (avc->states & CRO)) {
-0693  	afs_PutFakeStat(&fakestate);
-0694  	return EROFS;
-0695      }
-0696      code = 1;			/* Default from here on in is access ok. */
-0697      if (avc->states & CForeign) {
-0698  	/* In the dfs xlator the EXEC bit is mapped to LOOKUP */
-0699  	if (amode & VEXEC)
-0700  	    code = afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
-0701  	if (code && (amode & VWRITE)) {
-0702  	    code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
-0703  	    if (code && (vType(avc) == VDIR)) {
-0704  		if (code)
-0705  		    code =
-0706  			afs_AccessOK(avc, PRSFS_INSERT, &treq,
-0707  				     CHECK_MODE_BITS);
-0708  		if (!code)
-0709  		    code =
-0710  			afs_AccessOK(avc, PRSFS_DELETE, &treq,
-0711  				     CHECK_MODE_BITS);
-0712  	    }
-0713  	}
-0714  	if (code && (amode & VREAD))
-0715  	    code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
-0716      } else {
-0717  	if (vType(avc) == VDIR) {
-0718  	    if (amode & VEXEC)
-0719  		code =
-0720  		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
-0721  	    if (code && (amode & VWRITE)) {
-0722  		code =
-0723  		    afs_AccessOK(avc, PRSFS_INSERT, &treq, CHECK_MODE_BITS);
-0724  		if (!code)
-0725  		    code =
-0726  			afs_AccessOK(avc, PRSFS_DELETE, &treq,
-0727  				     CHECK_MODE_BITS);
-0728  	    }
-0729  	    if (code && (amode & VREAD))
-0730  		code =
-0731  		    afs_AccessOK(avc, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS);
-0732  	} else {
-0733  	    if (amode & VEXEC) {
-0734  		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
-0735  		if (code) {
-0736  #ifdef	AFS_OSF_ENV
-0737  		    /*
-0738  		     * The nfs server in read operations for non-owner of a file
-0739  		     * will also check the access with the VEXEC (along with VREAD)
-0740  		     * because for them exec is the same as read over the net because of
-0741  		     * demand loading. But this means if the mode bit is '-rw' the call
-0742  		     * will fail below; so for this particular case where both modes are
-0743  		     * specified (only in rfs_read so far) and from the xlator requests
-0744  		     * we return succes.
-0745  		     */
-0746  		    if (!((amode & VREAD) && AFS_NFSXLATORREQ(acred)))
-0747  #endif
-0748  			if ((avc->m.Mode & 0100) == 0)
-0749  			    code = 0;
-0750  		} else if (avc->m.Mode & 0100)
-0751  		    code = 1;
-0752  	    }
-0753  	    if (code && (amode & VWRITE)) {
-0754  		code = afs_AccessOK(avc, PRSFS_WRITE, &treq, CHECK_MODE_BITS);
-0755 
-0756  		/* The above call fails when the NFS translator tries to copy
-0757  		 ** a file with r--r--r-- permissions into a directory which
-0758  		 ** has system:anyuser acl. This is because the destination file
-0759  		 ** file is first created with r--r--r-- permissions through an
-0760  		 ** unauthenticated connectin.  hence, the above afs_AccessOK
-0761  		 ** call returns failure. hence, we retry without any file
-0762  		 ** mode bit checking */
-0763  		if (!code && AFS_NFSXLATORREQ(acred)
-0764  		    && avc->m.Owner == ANONYMOUSID)
-0765  		    code =
-0766  			afs_AccessOK(avc, PRSFS_WRITE, &treq,
-0767  				     DONT_CHECK_MODE_BITS);
-0768  	    }
-0769  	    if (code && (amode & VREAD))
-0770  		code = afs_AccessOK(avc, PRSFS_READ, &treq, CHECK_MODE_BITS);
-0771  	}
-0772      }
-0773      afs_PutFakeStat(&fakestate);
-0774      if (code) {
-0775  	return 0;		/* if access is ok */
-0776      } else {
-0777  	code = afs_CheckCode(EACCES, &treq, 17);	/* failure code */
-0778  	return code;
-0779      }
-0780  }
-0781 
-0782  #if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
-0783  /*
-0784   * afs_getRights
-0785   * This function is just an interface to afs_GetAccessBits
-0786   */
-0787  int
-0788  afs_getRights(OSI_VC_DECL(avc), register afs_int32 arights,
-0789  	      struct AFS_UCRED *acred)
-0790  {
-0791      register afs_int32 code;
-0792      struct vrequest treq;
-0793      OSI_VC_CONVERT(avc);
-0794 
-0795      if (code = afs_InitReq(&treq, acred))
-0796  	return code;
-0797 
-0798 
-0799 
-0800      code = afs_VerifyVCache(avc, &treq);
-0801      if (code) {
-0802  	code = afs_CheckCode(code, &treq, 16);
-0803  	return code;
-0804      }
-0805 
-0806      return afs_GetAccessBits(avc, arights, &treq);
-0807  }
-0808  #endif /* defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS) */
-0809 diff -U1000 -r orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c
-0810 --- orig-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2005-10-23 02:31:23.000000000 -0400
-0811 +++ scripts-1.4.1/src/afs/VNOPS/afs_vnop_attrs.c	2006-10-02 17:35:12.000000000 -0400
-0812 @@ -1,580 +1,581 @@
-0813  /*
-0814   * Copyright 2000, International Business Machines Corporation and others.
-0815   * All Rights Reserved.
-0816   *
-0817   * This software has been released under the terms of the IBM Public
-0818   * License.  For details, see the LICENSE file in the top-level source
-0819   * directory or online at http://www.openafs.org/dl/license10.html
-0820   *
-0821   * Portions Copyright (c) 2003 Apple Computer, Inc.
-0822   */
-0823 
-0824  /*
-0825   * afs_vnop_attrs.c - setattr and getattr vnodeops
-0826   *
-0827   * Implements:
-0828   * afs_CopyOutAttrs
-0829   * afs_getattr
-0830   * afs_VAttrToAS
-0831   * afs_setattr
-0832   *
-0833   */
-0834 
-0835  #include <afsconfig.h>
-0836  #include "afs/param.h"
-0837 
-0838  RCSID
-0839      ("$Header: /cvs/openafs/src/afs/VNOPS/afs_vnop_attrs.c,v 1.27.2.10 2005/10/23 06:31:23 shadow Exp $");
-0840 
-0841  #include "afs/sysincludes.h"	/* Standard vendor system headers */
-0842  #include "afsincludes.h"	/* Afs-based standard headers */
-0843  #include "afs/afs_stats.h"	/* statistics */
-0844  #include "afs/afs_cbqueue.h"
-0845  #include "afs/nfsclient.h"
-0846  #include "afs/afs_osidnlc.h"
-0847 
-0848 
-0849 
-0850  extern afs_rwlock_t afs_xcbhash;
-0851  struct afs_exporter *afs_nfsexporter;
-0852  extern struct vcache *afs_globalVp;
-0853  #if defined(AFS_HPUX110_ENV)
-0854  extern struct vfs *afs_globalVFS;
-0855  #endif
-0856 
-0857  /* copy out attributes from cache entry */
-0858  int
-0859  afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs)
-0860  {
-0861      register struct volume *tvp;
-0862      register struct cell *tcell;
-0863      int fakedir = 0;
-0864 
-0865      AFS_STATCNT(afs_CopyOutAttrs);
-0866      if (afs_fakestat_enable && avc->mvstat == 1)
-0867  	fakedir = 1;
-0868      attrs->va_type = fakedir ? VDIR : vType(avc);
-0869  #if defined(AFS_SGI_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
-0870      attrs->va_mode = fakedir ? 0755 : (mode_t) (avc->m.Mode & 0xffff);
-0871  #else
-0872      attrs->va_mode = fakedir ? VDIR | 0755 : avc->m.Mode;
-0873  #endif
-0874 
-0875      if (avc->m.Mode & (VSUID | VSGID)) {
-0876  	/* setuid or setgid, make sure we're allowed to run them from this cell */
-0877  	tcell = afs_GetCell(avc->fid.Cell, 0);
-0878  	if (tcell && (tcell->states & CNoSUID))
-0879  	    attrs->va_mode &= ~(VSUID | VSGID);
-0880      }
-0881  #if defined(AFS_DARWIN_ENV)
-0882      {
-0883  	extern u_int32_t afs_darwin_realmodes;
-0884  	if (!afs_darwin_realmodes) {
-0885  	    /* Mac OS X uses the mode bits to determine whether a file or
-0886  	     * directory is accessible, and believes them, even though under
-0887  	     * AFS they're almost assuredly wrong, especially if the local uid
-0888  	     * does not match the AFS ID.  So we set the mode bits
-0889  	     * conservatively.
-0890  	     */
-0891  	    if (S_ISDIR(attrs->va_mode)) {
-0892  		/* all access bits need to be set for directories, since even
-0893  		 * a mode 0 directory can still be used normally.
-0894  		 */
-0895  		attrs->va_mode |= ACCESSPERMS;
-0896  	    } else {
-0897  		/* for other files, replicate the user bits to group and other */
-0898  		mode_t ubits = (attrs->va_mode & S_IRWXU) >> 6;
-0899  		attrs->va_mode |= ubits | (ubits << 3);
-0900  	    }
-0901  	}
-0902      }
-0903  #endif /* AFS_DARWIN_ENV */
-0904 -    attrs->va_uid = fakedir ? 0 : avc->m.Owner;
-0905 -    attrs->va_gid = fakedir ? 0 : avc->m.Group;	/* yeah! */
-0906 +    attrs->va_uid = fakedir ? 0 : avc->fid.Fid.Volume;
-0907 +    attrs->va_gid = (avc->m.Owner == DAEMON_SCRIPTS_PTSID ? avc->m.Group : avc->m.Owner);
-0908  #if defined(AFS_SUN56_ENV)
-0909      attrs->va_fsid = avc->v.v_vfsp->vfs_fsid.val[0];
-0910  #elif defined(AFS_OSF_ENV)
-0911      attrs->va_fsid = avc->v.v_mount->m_stat.f_fsid.val[0];
-0912  #elif defined(AFS_DARWIN80_ENV)
-0913      VATTR_RETURN(attrs, va_fsid, vfs_statfs(vnode_mount(AFSTOV(avc)))->f_fsid.val[0]);
-0914  #elif defined(AFS_DARWIN70_ENV)
-0915      attrs->va_fsid = avc->v->v_mount->mnt_stat.f_fsid.val[0];
-0916  #else /* ! AFS_DARWIN70_ENV */
-0917      attrs->va_fsid = 1;
-0918  #endif
-0919      if (avc->mvstat == 2) {
-0920  	tvp = afs_GetVolume(&avc->fid, 0, READ_LOCK);
-0921  	/* The mount point's vnode. */
-0922  	if (tvp) {
-0923  	    attrs->va_nodeid =
-0924  		tvp->mtpoint.Fid.Vnode + (tvp->mtpoint.Fid.Volume << 16);
-0925  	    if (FidCmp(&afs_rootFid, &avc->fid) && !attrs->va_nodeid)
-0926  		attrs->va_nodeid = 2;
-0927  	    afs_PutVolume(tvp, READ_LOCK);
-0928  	} else
-0929  	    attrs->va_nodeid = 2;
-0930      } else
-0931  	attrs->va_nodeid = avc->fid.Fid.Vnode + (avc->fid.Fid.Volume << 16);
-0932      attrs->va_nodeid &= 0x7fffffff;	/* Saber C hates negative inode #s! */
-0933      attrs->va_nlink = fakedir ? 100 : avc->m.LinkCount;
-0934      attrs->va_size = fakedir ? 4096 : avc->m.Length;
-0935      attrs->va_atime.tv_sec = attrs->va_mtime.tv_sec = attrs->va_ctime.tv_sec =
-0936  	fakedir ? 0 : (int)avc->m.Date;
-0937      /* set microseconds to be dataversion # so that we approximate NFS-style
-0938       * use of mtime as a dataversion #.  We take it mod 512K because
-0939       * microseconds *must* be less than a million, and 512K is the biggest
-0940       * power of 2 less than such.  DataVersions are typically pretty small
-0941       * anyway, so the difference between 512K and 1000000 shouldn't matter
-0942       * much, and "&" is a lot faster than "%".
-0943       */
-0944  #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
-0945      /* nfs on these systems puts an 0 in nsec and stores the nfs usec (aka
-0946       * dataversion) in va_gen */
-0947 
-0948 
-0949 
-0950      attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
-0951  	attrs->va_ctime.tv_nsec = 0;
-0952      attrs->va_gen = hgetlo(avc->m.DataVersion);
-0953  #elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_OBSD_ENV)
-0954      attrs->va_atime.tv_nsec = attrs->va_mtime.tv_nsec =
-0955  	attrs->va_ctime.tv_nsec =
-0956  	(hgetlo(avc->m.DataVersion) & 0x7ffff) * 1000;
-0957  #else
-0958      attrs->va_atime.tv_usec = attrs->va_mtime.tv_usec =
-0959  	attrs->va_ctime.tv_usec = (hgetlo(avc->m.DataVersion) & 0x7ffff);
-0960  #endif
-0961  #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) || defined(AFS_OSF_ENV)
-0962      attrs->va_flags = 0;
-0963  #endif
-0964  #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
-0965      attrs->va_blksize = PAGESIZE;	/* XXX Was 8192 XXX */
-0966  #else
-0967      attrs->va_blocksize = PAGESIZE;	/* XXX Was 8192 XXX */
-0968  #endif
-0969      attrs->va_rdev = 1;
-0970  #if defined(AFS_HPUX110_ENV)
-0971      if (afs_globalVFS)
-0972  	attrs->va_fstype = afs_globalVFS->vfs_mtype;
-0973  #endif
-0974 
-0975      /*
-0976       * Below return 0 (and not 1) blocks if the file is zero length. This conforms
-0977       * better with the other filesystems that do return 0.
-0978       */
-0979  #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-0980      attrs->va_bytes = (attrs->va_size ? (attrs->va_size + 1023) : 1024);
-0981  #ifdef	va_bytes_rsv
-0982      attrs->va_bytes_rsv = -1;
-0983  #endif
-0984  #elif defined(AFS_HPUX_ENV)
-0985      attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10) : 0);
-0986  #elif defined(AFS_SGI_ENV)
-0987      attrs->va_blocks = BTOBB(attrs->va_size);
-0988  #elif defined(AFS_SUN5_ENV)
-0989      attrs->va_nblocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
-0990  #else /* everything else */
-0991      attrs->va_blocks = (attrs->va_size ? ((attrs->va_size + 1023)>>10)<<1:0);
-0992  #endif
-0993 +    attrs->va_mode |= 0100;
-0994      return 0;
-0995  }
-0996 diff -U1000 -r orig-1.4.1/src/afs/afs_analyze.c scripts-1.4.1/src/afs/afs_analyze.c
-0997 --- orig-1.4.1/src/afs/afs_analyze.c	2003-08-27 17:43:16.000000000 -0400
-0998 +++ scripts-1.4.1/src/afs/afs_analyze.c	2006-10-02 17:35:12.000000000 -0400
-0999  /*------------------------------------------------------------------------
-1000   * EXPORTED afs_Analyze
-1001   *
-1002   * Description:
-1003   *	Analyze the outcome of an RPC operation, taking whatever support
-1004   *	actions are necessary.
-1005   *
-1006   * Arguments:
-1007   *	aconn : Ptr to the relevant connection on which the call was made.
-1008   *	acode : The return code experienced by the RPC.
-1009   *	afid  : The FID of the file involved in the action.  This argument
-1010   *		may be null if none was involved.
-1011   *	areq  : The request record associated with this operation.
-1012   *      op    : which RPC we are analyzing.
-1013   *      cellp : pointer to a cell struct.  Must provide either fid or cell.
-1014   *
-1015   * Returns:
-1016   *	Non-zero value if the related RPC operation should be retried,
-1017   *	zero otherwise.
-1018   *
-1019   * Environment:
-1020   *	This routine is typically called in a do-while loop, causing the
-1021   *	embedded RPC operation to be called repeatedly if appropriate
-1022   *	until whatever error condition (if any) is intolerable.
-1023   *
-1024   * Side Effects:
-1025   *	As advertised.
-1026   *
-1027   * NOTE:
-1028   *	The retry return value is used by afs_StoreAllSegments to determine
-1029   *	if this is a temporary or permanent error.
-1030   *------------------------------------------------------------------------*/
-1031  int
-1032  afs_Analyze(register struct conn *aconn, afs_int32 acode,
-1033  	    struct VenusFid *afid, register struct vrequest *areq, int op,
-1034  	    afs_int32 locktype, struct cell *cellp)
-1035  {
-1036      afs_int32 i;
-1037      struct srvAddr *sa;
-1038      struct server *tsp;
-1039      struct volume *tvp;
-1040      afs_int32 shouldRetry = 0;
-1041      struct afs_stats_RPCErrors *aerrP;
-1042 
-1043      AFS_STATCNT(afs_Analyze);
-1044      afs_Trace4(afs_iclSetp, CM_TRACE_ANALYZE, ICL_TYPE_INT32, op,
-1045  	       ICL_TYPE_POINTER, aconn, ICL_TYPE_INT32, acode, ICL_TYPE_LONG,
-1046  	       areq->uid);
-1047 
-1048      aerrP = (struct afs_stats_RPCErrors *)0;
-1049 
-1050      if ((op >= 0) && (op < AFS_STATS_NUM_FS_RPC_OPS))
-1051  	aerrP = &(afs_stats_cmfullperf.rpc.fsRPCErrors[op]);
-1052 
-1053      afs_FinalizeReq(areq);
-1054      if (!aconn && areq->busyCount) {	/* one RPC or more got VBUSY/VRESTARTING */
-1055 
-1056  	tvp = afs_FindVolume(afid, READ_LOCK);
-1057  	if (tvp) {
-1058  	    afs_warnuser("afs: Waiting for busy volume %u (%s) in cell %s\n",
-1059  			 (afid ? afid->Fid.Volume : 0),
-1060  			 (tvp->name ? tvp->name : ""),
-1061  			 ((tvp->serverHost[0]
-1062  			   && tvp->serverHost[0]->cell) ? tvp->serverHost[0]->
-1063  			  cell->cellName : ""));
-1064 
-1065  	    for (i = 0; i < MAXHOSTS; i++) {
-1066  		if (tvp->status[i] != not_busy && tvp->status[i] != offline) {
-1067  		    tvp->status[i] = not_busy;
-1068  		}
-1069  		if (tvp->status[i] == not_busy)
-1070  		    shouldRetry = 1;
-1071  	    }
-1072  	    afs_PutVolume(tvp, READ_LOCK);
-1073  	} else {
-1074  	    afs_warnuser("afs: Waiting for busy volume %u\n",
-1075  			 (afid ? afid->Fid.Volume : 0));
-1076  	}
-1077 
-1078 -	if (areq->busyCount > 100) {
-1079 +	if (1) {
-1080  	    if (aerrP)
-1081  		(aerrP->err_Volume)++;
-1082  	    areq->volumeError = VOLBUSY;
-1083  	    shouldRetry = 0;
-1084  	} else {
-1085  	    VSleep(afs_BusyWaitPeriod);	/* poll periodically */
-1086  	}
-1087  	if (shouldRetry != 0)
-1088  	    areq->busyCount++;
-1089 
-1090  	return shouldRetry;	/* should retry */
-1091      }
Index: server/doc/perl
===================================================================
--- server/doc/perl	(revision 36)
+++ server/doc/perl	(revision 37)
@@ -1,3 +1,3 @@
-In order to transfer perl modules from one machine to another
+In order to transfer perl modules from one machine to another:
 
 $ perl -MCPAN -e shell
Index: server/doc/rpm
===================================================================
--- server/doc/rpm	(revision 36)
+++ server/doc/rpm	(revision 37)
@@ -1,3 +1,3 @@
 In order to transfer rpms from one machine to another:
 
-rpm -qa --queryformat "%{NAME}\n
+rpm -qa --queryformat "%{NAME} "
