Index: server/doc/openafs-diff.num
===================================================================
--- server/doc/openafs-diff.num	(revision 18)
+++ server/doc/openafs-diff.num	(revision 18)
@@ -0,0 +1,1092 @@
+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/openafs-diff.pag
===================================================================
--- server/doc/openafs-diff.pag	(revision 17)
+++ 	(revision )
@@ -1,1092 +1,0 @@
-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      }
