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 *up, long rights,
45 if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
50 tfid.cell = scp->fid.cell;
51 tfid.volume = scp->fid.volume;
52 tfid.vnode = scp->parentVnode;
53 tfid.unique = scp->parentUnique;
54 aclScp = cm_FindSCache(&tfid);
55 if (!aclScp) return 0;
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) {
85 /* we have to check the specific rights info */
86 code = cm_FindACLCache(aclScp, up, &trights);
91 *outRightsp = trights;
95 if (!(scp->unixModeBits & 0400))
96 *outRightsp &= ~PRSFS_READ;
97 if (!(scp->unixModeBits & 0200))
98 *outRightsp &= ~PRSFS_WRITE;
105 lock_ReleaseMutex(&aclScp->mx);
106 cm_ReleaseSCache(aclScp);
110 /* called with locked scp; ensures that we have an ACL cache entry for the
111 * user specified by the parameter "up."
112 * In pathological race conditions, this function may return success without
113 * having loaded the entry properly (due to a racing callback revoke), so this
114 * function must also be called in a while loop to make sure that we eventually
117 long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *up,
124 /* pretty easy: just force a pass through the fetch status code */
126 osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, up);
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 code = cm_SyncOp(scp, NULL, up, reqp, 0, CM_SCACHESYNC_GETSTATUS
132 | CM_SCACHESYNC_NEEDCALLBACK);
134 if (code) return code;
136 if (scp->fileType != CM_SCACHETYPE_DIRECTORY) {
137 /* not a dir, use parent dir's acl */
138 tfid.cell = scp->fid.cell;
139 tfid.volume = scp->fid.volume;
140 tfid.vnode = scp->parentVnode;
141 tfid.unique = scp->parentUnique;
142 lock_ReleaseMutex(&scp->mx);
143 code = cm_GetSCache(&tfid, &aclScp, up, reqp);
145 lock_ObtainMutex(&scp->mx);
149 osi_Log1(afsd_logp, "GetAccess parent %x", aclScp);
150 lock_ObtainMutex(&aclScp->mx);
151 code = cm_GetCallback(aclScp, up, reqp, 1);
152 lock_ReleaseMutex(&aclScp->mx);
153 cm_ReleaseSCache(aclScp);
154 lock_ObtainMutex(&scp->mx);
157 code = cm_GetCallback(scp, up, reqp, 1);