#include <afsconfig.h>
#include "afs/param.h"
-RCSID
- ("$Header$");
#include "afs/sysincludes.h" /* Standard vendor system headers */
#include "afsincludes.h" /* Afs-based standard headers */
{
AFS_STATCNT(afs_GetAccessBits);
/* see if anyuser has the required access bits */
- if ((arights & avc->anyAccess) == arights) {
+ if ((arights & avc->f.anyAccess) == arights) {
return arights;
}
}
}
- if (!(avc->states & CForeign)) {
+ if (!(avc->f.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);
+ tu = afs_FindUser(areq->uid, avc->f.fid.Cell, READ_LOCK);
if (!tu) {
- return (arights & avc->anyAccess);
+ return (arights & avc->f.anyAccess);
}
if ((tu->vid == UNDEFVID) || !(tu->states & UHasTokens)
|| (tu->states & UTokensBad)) {
afs_PutUser(tu, READ_LOCK);
- return (arights & avc->anyAccess);
+ return (arights & avc->f.anyAccess);
} else {
afs_PutUser(tu, READ_LOCK);
}
}
+ if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
+ /* If we get this far, we have to ask the network. But we can't, so
+ * they're out of luck... */
+ return 0;
+ } else
{ /* Ok, user has valid tokens, go ask the server. */
struct AFSFetchStatus OutStatus;
afs_int32 code;
- code = afs_FetchStatus(avc, &avc->fid, areq, &OutStatus);
+ code = afs_FetchStatus(avc, &avc->f.fid, areq, &OutStatus);
return (code ? 0 : OutStatus.CallerAccess & arights);
}
}
AFS_STATCNT(afs_AccessOK);
- if ((vType(avc) == VDIR) || (avc->states & CForeign)) {
+ if ((vType(avc) == VDIR) || (avc->f.states & CForeign)) {
/* rights are just those from acl */
if (afs_InReadDir(avc)) {
/* if we are already in readdir, then they may have read and
* 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;
+ if (avc->f.parent.vnode) {
+ dirFid.Cell = avc->f.fid.Cell;
+ dirFid.Fid.Volume = avc->f.fid.Fid.Volume;
+ dirFid.Fid.Vnode = avc->f.parent.vnode;
+ dirFid.Fid.Unique = avc->f.parent.unique;
/* Avoid this GetVCache call */
tvc = afs_GetVCache(&dirFid, areq, NULL, NULL);
if (tvc) {
- dirBits = afs_GetAccessBits(tvc, arights, areq);
+ if ((arights & (PRSFS_READ | PRSFS_WRITE))) {
+ /* we may need to grant implicit 'rw' rights if we have
+ * 'i' on the parent dir and we are the owner, so check
+ * for 'i' rights in addition, here */
+ dirBits = afs_GetAccessBits(tvc, arights | PRSFS_INSERT, areq);
+ } else {
+ dirBits = afs_GetAccessBits(tvc, arights, areq);
+ }
afs_PutVCache(tvc);
}
} else
dirBits = 0xffffffff; /* assume OK; this is a race condition */
- if (arights & PRSFS_ADMINISTER)
+ if (arights & PRSFS_ADMINISTER) {
fileBits = afs_GetAccessBits(avc, arights, areq);
- else
+
+ } else if ((dirBits & PRSFS_INSERT) &&
+ ((arights & (PRSFS_READ | PRSFS_WRITE)) & dirBits) !=
+ (arights & (PRSFS_READ | PRSFS_WRITE))) {
+
+ /* if we have 'i' rights in the directory, and we are requesting
+ * read or write access, AND the directory ACL (dirBits) does not
+ * already give us the requested read or write access, we need to
+ * find out if we are the owner for the file ('A' bit), for the
+ * "throw in R and W if we have I and A" check below */
+
+ fileBits = afs_GetAccessBits(avc, arights | PRSFS_ADMINISTER, areq);
+
+ } else {
fileBits = 0; /* don't make call if results don't matter */
+ }
/* compute basic rights in fileBits, taking A from file bits */
fileBits =
/* 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)) ==
+ /* note that we know vType(avc) != VDIR from the top-level 'else' */
+ if ((fileBits & (PRSFS_ADMINISTER | PRSFS_INSERT)) ==
(PRSFS_ADMINISTER | PRSFS_INSERT))
fileBits |= (PRSFS_READ | PRSFS_WRITE);
* 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 */
+ mask = (avc->f.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)
+ if (avc->f.m.Mode & 0100)
fileBits |= PRSFS_READ;
}
}
#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)
+ afs_ucred_t *acred)
#else
int
afs_access(OSI_VC_DECL(avc), register afs_int32 amode,
- struct AFS_UCRED *acred)
+ afs_ucred_t *acred)
#endif
{
register afs_int32 code;
AFS_STATCNT(afs_access);
afs_Trace3(afs_iclSetp, CM_TRACE_ACCESS, ICL_TYPE_POINTER, avc,
ICL_TYPE_INT32, amode, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
+ ICL_HANDLE_OFFSET(avc->f.m.Length));
afs_InitFakeStat(&fakestate);
if ((code = afs_InitReq(&treq, acred)))
return code;
+ AFS_DISCON_LOCK();
+
if (afs_fakestat_enable && avc->mvstat == 1) {
code = afs_TryEvalFakeStat(&avc, &fakestate, &treq);
if (code == 0 && avc->mvstat == 1) {
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return 0;
}
} else {
if (code) {
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return code;
}
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 16);
- return code;
+ if (vType(avc) != VDIR || !afs_InReadDir(avc)) {
+ code = afs_VerifyVCache(avc, &treq);
+ if (code) {
+ afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
+ 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)) {
+ if ((amode & VWRITE) && (avc->f.states & CRO)) {
afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
return EROFS;
}
+
+ /* If we're looking for write access, and we're disconnected without logging, forget it */
+ if ((amode & VWRITE) && (AFS_IS_DISCONNECTED && !AFS_IS_DISCON_RW)) {
+ afs_PutFakeStat(&fakestate);
+ AFS_DISCON_UNLOCK();
+ printf("Network is down in afs_vnop_access\n");
+ return ENETDOWN;
+ }
+
code = 1; /* Default from here on in is access ok. */
- if (avc->states & CForeign) {
+ if (avc->f.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 (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)
+ if ((avc->f.m.Mode & 0100) == 0)
code = 0;
- } else if (avc->m.Mode & 0100)
+ } else if (avc->f.m.Mode & 0100)
code = 1;
}
if (code && (amode & VWRITE)) {
** call returns failure. hence, we retry without any file
** mode bit checking */
if (!code && AFS_NFSXLATORREQ(acred)
- && avc->m.Owner == ANONYMOUSID)
+ && avc->f.m.Owner == ANONYMOUSID)
code =
afs_AccessOK(avc, PRSFS_WRITE, &treq,
DONT_CHECK_MODE_BITS);
}
}
afs_PutFakeStat(&fakestate);
+
+ AFS_DISCON_UNLOCK();
+
if (code) {
return 0; /* if access is ok */
} else {
*/
int
afs_getRights(OSI_VC_DECL(avc), register afs_int32 arights,
- struct AFS_UCRED *acred)
+ afs_ucred_t *acred)
{
register afs_int32 code;
struct vrequest treq;
OSI_VC_CONVERT(avc);
- if (code = afs_InitReq(&treq, acred))
+ if ((code = afs_InitReq(&treq, acred)))
return code;
code = afs_VerifyVCache(avc, &treq);