2 * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
4 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
5 * LICENSED MATERIALS - PROPERTY OF IBM
10 #include <afs/param.h>
23 /* called with scp write-locked, check to see if we have the ACL info we need
24 * and can get it w/o blocking for any locks.
26 * Never drops the scp lock, but may fail if the access control info comes from
27 * the parent directory, and the parent's scache entry can't be found, or it
28 * can't be locked. Thus, this must always be called in a while loop to stabilize
29 * things, since we can always lose the race condition getting to the parent vnode.
31 int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *up, long rights,
41 if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
46 tfid.cell = scp->fid.cell;
47 tfid.volume = scp->fid.volume;
48 tfid.vnode = scp->parentVnode;
49 tfid.unique = scp->parentUnique;
50 aclScp = cm_FindSCache(&tfid);
51 if (!aclScp) return 0;
53 code = lock_TryMutex(&aclScp->mx);
55 /* can't get lock safely and easily */
56 cm_ReleaseSCache(aclScp);
60 /* check that we have a callback, too */
61 if (!cm_HaveCallback(aclScp)) {
63 lock_ReleaseMutex(&aclScp->mx);
64 cm_ReleaseSCache(aclScp);
71 lock_AssertMutex(&aclScp->mx);
73 /* now if rights is a subset of the public rights, we're done.
74 * Otherwise, if we an explicit acl entry, we're also in good shape,
75 * and can definitively answer.
77 if ((~aclScp->anyAccess & rights) == 0) {
81 /* we have to check the specific rights info */
82 code = cm_FindACLCache(aclScp, up, &trights);
87 *outRightsp = trights;
91 if (!(scp->unixModeBits & 0400))
92 *outRightsp &= ~PRSFS_READ;
93 if (!(scp->unixModeBits & 0200))
94 *outRightsp &= ~PRSFS_WRITE;
100 if (didLock) lock_ReleaseMutex(&aclScp->mx);
101 cm_ReleaseSCache(aclScp);
105 /* called with locked scp; ensures that we have an ACL cache entry for the
106 * user specified by the parameter "up."
107 * In pathological race conditions, this function may return success without
108 * having loaded the entry properly (due to a racing callback revoke), so this
109 * function must also be called in a while loop to make sure that we eventually
112 long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *up,
119 /* pretty easy: just force a pass through the fetch status code */
121 osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, up);
123 /* first, start by finding out whether we have a directory or something
124 * else, so we can find what object's ACL we need.
126 code = cm_SyncOp(scp, NULL, up, reqp, 0, CM_SCACHESYNC_GETSTATUS
127 | CM_SCACHESYNC_NEEDCALLBACK);
129 if (code) return code;
131 if (scp->fileType != CM_SCACHETYPE_DIRECTORY) {
132 /* not a dir, use parent dir's acl */
133 tfid.cell = scp->fid.cell;
134 tfid.volume = scp->fid.volume;
135 tfid.vnode = scp->parentVnode;
136 tfid.unique = scp->parentUnique;
137 lock_ReleaseMutex(&scp->mx);
138 code = cm_GetSCache(&tfid, &aclScp, up, reqp);
140 lock_ObtainMutex(&scp->mx);
144 osi_Log1(afsd_logp, "GetAccess parent %x", aclScp);
145 lock_ObtainMutex(&aclScp->mx);
146 code = cm_GetCallback(aclScp, up, reqp, 1);
147 lock_ReleaseMutex(&aclScp->mx);
148 cm_ReleaseSCache(aclScp);
149 lock_ObtainMutex(&scp->mx);
152 code = cm_GetCallback(scp, up, reqp, 1);