2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
27 /* called with scp write-locked, check to see if we have the ACL info we need
28 * and can get it w/o blocking for any locks.
30 * Never drops the scp lock, but may fail if the access control info comes from
31 * the parent directory, and the parent's scache entry can't be found, or it
32 * can't be locked. Thus, this must always be called in a while loop to stabilize
33 * things, since we can always lose the race condition getting to the parent vnode.
35 int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, afs_uint32 rights,
36 afs_uint32 *outRightsp)
45 if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
49 tfid.cell = scp->fid.cell;
50 tfid.volume = scp->fid.volume;
51 tfid.vnode = scp->parentVnode;
52 tfid.unique = scp->parentUnique;
53 aclScp = cm_FindSCache(&tfid);
57 code = lock_TryMutex(&aclScp->mx);
59 /* can't get lock safely and easily */
60 cm_ReleaseSCache(aclScp);
64 /* check that we have a callback, too */
65 if (!cm_HaveCallback(aclScp)) {
67 lock_ReleaseMutex(&aclScp->mx);
68 cm_ReleaseSCache(aclScp);
75 lock_AssertMutex(&aclScp->mx);
77 /* now if rights is a subset of the public rights, we're done.
78 * Otherwise, if we an explicit acl entry, we're also in good shape,
79 * and can definitively answer.
81 if ((~aclScp->anyAccess & rights) == 0) {
84 /* we have to check the specific rights info */
85 code = cm_FindACLCache(aclScp, userp, &trights);
90 *outRightsp = trights;
94 if (!(scp->unixModeBits & 0400))
95 *outRightsp &= ~PRSFS_READ;
96 if (!(scp->unixModeBits & 0200))
97 *outRightsp &= ~PRSFS_WRITE;
104 lock_ReleaseMutex(&aclScp->mx);
105 cm_ReleaseSCache(aclScp);
109 /* called with locked scp; ensures that we have an ACL cache entry for the
110 * user specified by the parameter "userp."
111 * In pathological race conditions, this function may return success without
112 * having loaded the entry properly (due to a racing callback revoke), so this
113 * function must also be called in a while loop to make sure that we eventually
116 long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
124 /* pretty easy: just force a pass through the fetch status code */
126 osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, userp);
128 /* first, start by finding out whether we have a directory or something
129 * else, so we can find what object's ACL we need.
131 if (!cm_HaveCallback(scp)) {
132 code = cm_SyncOp(scp, NULL, userp, reqp, 0,
133 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
140 if (scp->fileType != CM_SCACHETYPE_DIRECTORY) {
141 /* not a dir, use parent dir's acl */
142 tfid.cell = scp->fid.cell;
143 tfid.volume = scp->fid.volume;
144 tfid.vnode = scp->parentVnode;
145 tfid.unique = scp->parentUnique;
146 lock_ReleaseMutex(&scp->mx);
147 code = cm_GetSCache(&tfid, &aclScp, userp, reqp);
149 lock_ObtainMutex(&scp->mx);
153 osi_Log2(afsd_logp, "GetAccess parent scp %x user %x", aclScp, userp);
154 lock_ObtainMutex(&aclScp->mx);
156 code = cm_GetCallback(aclScp, userp, reqp, 1);
157 lock_ReleaseMutex(&aclScp->mx);
158 cm_ReleaseSCache(aclScp);
159 lock_ObtainMutex(&scp->mx);
160 } else if (!got_cb) {
161 code = cm_GetCallback(scp, userp, reqp, 1);