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;
104 if (didLock) 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 "up."
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 *up,
123 /* pretty easy: just force a pass through the fetch status code */
125 osi_Log2(afsd_logp, "GetAccess scp %x user %x", scp, up);
127 /* first, start by finding out whether we have a directory or something
128 * else, so we can find what object's ACL we need.
130 code = cm_SyncOp(scp, NULL, up, reqp, 0, CM_SCACHESYNC_GETSTATUS
131 | CM_SCACHESYNC_NEEDCALLBACK);
133 if (code) return code;
135 if (scp->fileType != CM_SCACHETYPE_DIRECTORY) {
136 /* not a dir, use parent dir's acl */
137 tfid.cell = scp->fid.cell;
138 tfid.volume = scp->fid.volume;
139 tfid.vnode = scp->parentVnode;
140 tfid.unique = scp->parentUnique;
141 lock_ReleaseMutex(&scp->mx);
142 code = cm_GetSCache(&tfid, &aclScp, up, reqp);
144 lock_ObtainMutex(&scp->mx);
148 osi_Log1(afsd_logp, "GetAccess parent %x", aclScp);
149 lock_ObtainMutex(&aclScp->mx);
150 code = cm_GetCallback(aclScp, up, reqp, 1);
151 lock_ReleaseMutex(&aclScp->mx);
152 cm_ReleaseSCache(aclScp);
153 lock_ObtainMutex(&scp->mx);
156 code = cm_GetCallback(scp, up, reqp, 1);