Windows: Freelance HaveAccessRights
[openafs.git] / src / WINNT / afsd / cm_access.c
index da1593c..79692b1 100644 (file)
@@ -1,13 +1,16 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
+#include <afsconfig.h>
 #include <afs/param.h>
+#include <roken.h>
+
 #include <afs/stds.h>
 
 #include <windows.h>
@@ -20,6 +23,7 @@
 #include "afsd.h"
 
 int cm_deleteReadOnly = 0;
+int cm_accessPerFileCheck = 0;
 
 /* called with scp write-locked, check to see if we have the ACL info we need
  * and can get it w/o blocking for any locks.
@@ -29,7 +33,8 @@ int cm_deleteReadOnly = 0;
  * can't be locked.  Thus, this must always be called in a while loop to stabilize
  * things, since we can always lose the race condition getting to the parent vnode.
  */
-int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, afs_uint32 rights,
+int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, cm_req_t *reqp,
+                        afs_uint32 rights,
                         afs_uint32 *outRightsp)
 {
     cm_scache_t *aclScp;
@@ -39,27 +44,20 @@ int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, afs_uint32
     long trights;
     int release = 0;    /* Used to avoid a call to cm_HoldSCache in the directory case */
 
-#if 0
-    if (scp->flags & CM_SCACHEFLAG_EACCESS) {
-       *outRightsp = 0;
-       return 1;
-    }
-#endif
     didLock = 0;
-    if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY || cm_accessPerFileCheck) {
         aclScp = scp;   /* not held, not released */
     } else {
         cm_SetFid(&tfid, scp->fid.cell, scp->fid.volume, scp->parentVnode, scp->parentUnique);
         aclScp = cm_FindSCache(&tfid);
-        if (!aclScp) 
+        if (!aclScp)
             return 0;
         if (aclScp != scp) {
-            code = lock_TryRead(&aclScp->rw);
-            if (code == 0) {
-                /* can't get lock safely and easily */
-                cm_ReleaseSCache(aclScp);
-                return 0;
-            }
+            if (aclScp->fid.vnode < scp->fid.vnode)
+                lock_ReleaseWrite(&scp->rw);
+            lock_ObtainRead(&aclScp->rw);
+            if (aclScp->fid.vnode < scp->fid.vnode)
+                lock_ObtainWrite(&scp->rw);
 
            /* check that we have a callback, too */
             if (!cm_HaveCallback(aclScp)) {
@@ -74,13 +72,15 @@ int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, afs_uint32
     }
 
     lock_AssertAny(&aclScp->rw);
-        
+
     /* now if rights is a subset of the public rights, we're done.
      * Otherwise, if we an explicit acl entry, we're also in good shape,
      * and can definitively answer.
      */
 #ifdef AFS_FREELANCE_CLIENT
-    if (cm_freelanceEnabled && aclScp == cm_data.rootSCachep)
+    if (cm_freelanceEnabled &&
+        aclScp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+        aclScp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
     {
        *outRightsp = aclScp->anyAccess;
     } else
@@ -100,17 +100,17 @@ int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, afs_uint32
     if (scp->fileType > 0 && scp->fileType != CM_SCACHETYPE_DIRECTORY) {
        /* check mode bits */
        if ((scp->unixModeBits & 0400) == 0) {
-           osi_Log2(afsd_logp,"cm_HaveAccessRights UnixMode removing READ scp 0x%p unix 0x%x", 
+           osi_Log2(afsd_logp,"cm_HaveAccessRights UnixMode removing READ scp 0x%p unix 0%o",
                      scp, scp->unixModeBits);
            *outRightsp &= ~PRSFS_READ;
        }
        if ((scp->unixModeBits & 0200) == 0 && (rights != (PRSFS_WRITE | PRSFS_LOCK))) {
-           osi_Log2(afsd_logp,"cm_HaveAccessRights UnixMode removing WRITE scp 0x%p unix 0%o", 
+           osi_Log2(afsd_logp,"cm_HaveAccessRights UnixMode removing WRITE scp 0x%p unix 0%o",
                      scp, scp->unixModeBits);
            *outRightsp &= ~PRSFS_WRITE;
        }
-       if ((scp->unixModeBits & 0200) == 0 && !cm_deleteReadOnly) {
-           osi_Log2(afsd_logp,"cm_HaveAccessRights UnixMode removing DELETE scp 0x%p unix 0%o", 
+       if ((scp->unixModeBits & 0200) == 0 && !cm_deleteReadOnly && (reqp->flags & CM_REQ_SOURCE_SMB)) {
+           osi_Log2(afsd_logp,"cm_HaveAccessRights UnixMode removing DELETE scp 0x%p unix 0%o",
                      scp, scp->unixModeBits);
            *outRightsp &= ~PRSFS_DELETE;
        }
@@ -133,7 +133,7 @@ int cm_HaveAccessRights(struct cm_scache *scp, struct cm_user *userp, afs_uint32
     /* fall through */
 
   done:
-    if (didLock) 
+    if (didLock)
         lock_ReleaseRead(&aclScp->rw);
     if (release)
         cm_ReleaseSCache(aclScp);
@@ -156,34 +156,38 @@ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp,
     int got_cb = 0;
 
     /* pretty easy: just force a pass through the fetch status code */
-        
-    osi_Log2(afsd_logp, "GetAccess scp 0x%p user 0x%p", scp, userp);
+
+    osi_Log2(afsd_logp, "GetAccessRights scp 0x%p user 0x%p", scp, userp);
 
     /* first, start by finding out whether we have a directory or something
      * else, so we can find what object's ACL we need.
      */
-    if (scp->fileType == CM_SCACHETYPE_DIRECTORY ) {
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY || cm_accessPerFileCheck) {
        code = cm_SyncOp(scp, NULL, userp, reqp, 0,
                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB);
-       if (!code) 
+       if (!code)
            cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    else
+        osi_Log3(afsd_logp, "GetAccessRights syncop failure scp %x user %x code %x", scp, userp, code);
     } else {
         /* not a dir, use parent dir's acl */
         cm_SetFid(&tfid, scp->fid.cell, scp->fid.volume, scp->parentVnode, scp->parentUnique);
         lock_ReleaseWrite(&scp->rw);
-        code = cm_GetSCache(&tfid, &aclScp, userp, reqp);
+        code = cm_GetSCache(&tfid, NULL, &aclScp, userp, reqp);
         if (code) {
             lock_ObtainWrite(&scp->rw);
            goto _done;
-        }       
-                
-        osi_Log2(afsd_logp, "GetAccess parent scp %x user %x", aclScp, userp);
+        }
+
+        osi_Log2(afsd_logp, "GetAccessRights parent scp %x user %x", aclScp, userp);
        lock_ObtainWrite(&aclScp->rw);
        code = cm_SyncOp(aclScp, NULL, userp, reqp, 0,
                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB);
        if (!code)
-           cm_SyncOpDone(aclScp, NULL, 
+           cm_SyncOpDone(aclScp, NULL,
                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        else
+            osi_Log3(afsd_logp, "GetAccessRights parent syncop failure scp %x user %x code %x", aclScp, userp, code);
        lock_ReleaseWrite(&aclScp->rw);
         cm_ReleaseSCache(aclScp);
         lock_ObtainWrite(&scp->rw);