Windows: Do not issue RXAFS change RPCs on known RO volumes
[openafs.git] / src / WINNT / afsd / cm_vnodeops.c
index bc2628d..b1668d1 100644 (file)
@@ -189,17 +189,17 @@ long cm_CheckNTOpen(cm_scache_t *scp, unsigned int desiredAccess,
                    cm_lock_data_t **ldpp)
 {
     long rights;
-    long code;
+    long code = 0;
 
     osi_assertx(ldpp != NULL, "null cm_lock_data_t");
     *ldpp = NULL;
 
     /* Always allow delete; the RPC will tell us if it's OK */
-    if (desiredAccess == DELETE)
-        return 0;
-
     rights = 0;
 
+    if (desiredAccess == DELETE)
+        goto done_2;
+
     if (desiredAccess & (AFS_ACCESS_READ|AFS_ACCESS_EXECUTE))
         rights |= (scp->fileType == CM_SCACHETYPE_DIRECTORY ? PRSFS_LOOKUP : PRSFS_READ);
 
@@ -210,6 +210,9 @@ long cm_CheckNTOpen(cm_scache_t *scp, unsigned int desiredAccess,
     if (desiredAccess & AFS_ACCESS_WRITE)
         rights |= PRSFS_WRITE;
 
+    if (desiredAccess & DELETE)
+        rights |= PRSFS_DELETE;
+
     lock_ObtainWrite(&scp->rw);
 
     code = cm_SyncOp(scp, NULL, userp, reqp, rights,
@@ -291,6 +294,7 @@ long cm_CheckNTOpen(cm_scache_t *scp, unsigned int desiredAccess,
  _done:
     lock_ReleaseWrite(&scp->rw);
 
+ done_2:
     osi_Log3(afsd_logp,"cm_CheckNTOpen scp 0x%p ldp 0x%p code 0x%x", scp, *ldpp, code);
     return code;
 }
@@ -671,6 +675,15 @@ long cm_ApplyDir(cm_scache_t *scp, cm_DirFuncp_t funcp, void *parmp,
         tp = bufferp->datap + entryInBuffer;
         dep = (cm_dirEntry_t *) tp;    /* now points to AFS3 dir entry */
 
+        /*
+         * here are some consistency checks
+         */
+        if (dep->flag != CM_DIR_FFIRST ||
+            strlen(dep->name) > 256) {
+            code = CM_ERROR_INVAL;
+            break;
+        }
+
         /* while we're here, compute the next entry's location, too,
          * since we'll need it when writing out the cookie into the
          * dir listing stream.
@@ -1616,6 +1629,14 @@ long cm_Unlink(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t * cnamep,
 #endif  
 
     code = cm_Lookup(dscp, cnamep, CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
+    if (code)
+        goto done;
+
+    /* Check for RO volume */
+    if (dscp->flags & CM_SCACHEFLAG_RO) {
+        code = CM_ERROR_READONLY;
+        goto done;
+    }
 
     /* make sure we don't screw up the dir status during the merge */
     code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_NONE,
@@ -1813,8 +1834,8 @@ long cm_AssembleLink(cm_scache_t *linkScp, fschar_t *pathSuffixp,
             StringCbCopyA((char *) tsp->data, sizeof(tsp->data), linkp+cm_mountRootLen+1);
         else
             tsp->data[0] = 0;
-        *newRootScpp = cm_data.rootSCachep;
-        cm_HoldSCache(cm_data.rootSCachep);
+        *newRootScpp = cm_RootSCachep(userp, reqp);
+        cm_HoldSCache(*newRootScpp);
     } else if (linkp[0] == '\\' && linkp[1] == '\\') {
         if (!strnicmp(&linkp[2], cm_NetbiosName, (len = (long)strlen(cm_NetbiosName)))) 
         {
@@ -1827,8 +1848,8 @@ long cm_AssembleLink(cm_scache_t *linkScp, fschar_t *pathSuffixp,
                 if (*p == '\\')
                     *p = '/';
             }
-            *newRootScpp = cm_data.rootSCachep;
-            cm_HoldSCache(cm_data.rootSCachep);
+            *newRootScpp = cm_RootSCachep(userp, reqp);
+            cm_HoldSCache(*newRootScpp);
         } else {
             linkScp->fileType = CM_SCACHETYPE_DFSLINK;
             StringCchCopyA(tsp->data,lengthof(tsp->data), linkp);
@@ -1845,8 +1866,8 @@ long cm_AssembleLink(cm_scache_t *linkScp, fschar_t *pathSuffixp,
          * but this seems to create problems.  instead, we will just
          * reject the link */
         StringCchCopyA(tsp->data,lengthof(tsp->data), linkp+1);
-        *newRootScpp = cm_data.rootSCachep;
-        cm_HoldSCache(cm_data.rootSCachep);
+        *newRootScpp = cm_RootSCachep(userp, reqp);
+        cm_HoldSCache(*newRootScpp);
 #else
         /* we still copy the link data into the response so that 
          * the user can see what the link points to
@@ -2421,6 +2442,7 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
                 case VOFFLINE:
                 case VSALVAGE:
                 case VNOSERVICE:
+                case VIO:
                     code = (&bbp->stats[0])->errorCode;
                     break;
                 default:
@@ -2711,6 +2733,13 @@ long cm_SetAttr(cm_scache_t *scp, cm_attr_t *attrp, cm_user_t *userp,
         return cm_SetLength(scp, &attrp->length, userp, reqp);
 
     lock_ObtainWrite(&scp->rw);
+    /* Check for RO volume */
+    if (scp->flags & CM_SCACHEFLAG_RO) {
+        code = CM_ERROR_READONLY;
+       lock_ReleaseWrite(&scp->rw);
+        return code;
+    }
+
     /* otherwise, we have to make an RPC to get the status */
     code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_STORESTATUS);
     if (code) {
@@ -2802,6 +2831,10 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
     }
 #endif /* AFS_FREELANCE_CLIENT */
 
+    /* Check for RO volume */
+    if (dscp->flags & CM_SCACHEFLAG_RO)
+        return CM_ERROR_READONLY;
+
     /* before starting the RPC, mark that we're changing the file data, so
      * that someone who does a chmod will know to wait until our call
      * completes.
@@ -2980,6 +3013,10 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
     }
 #endif /* AFS_FREELANCE_CLIENT */
 
+    /* Check for RO volume */
+    if (dscp->flags & CM_SCACHEFLAG_RO)
+        return CM_ERROR_READONLY;
+
     /* before starting the RPC, mark that we're changing the directory
      * data, so that someone who does a chmod on the dir will wait until
      * our call completes.
@@ -3107,6 +3144,10 @@ long cm_Link(cm_scache_t *dscp, clientchar_t *cnamep, cm_scache_t *sscp, long fl
         return CM_ERROR_CROSSDEVLINK;
     }
 
+    /* Check for RO volume */
+    if (dscp->flags & CM_SCACHEFLAG_RO)
+        return CM_ERROR_READONLY;
+
     cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_NONE, CM_DIROP_FLAG_NONE,
                   &dirop);
     lock_ObtainWrite(&dscp->rw);
@@ -3200,6 +3241,10 @@ long cm_SymLink(cm_scache_t *dscp, clientchar_t *cnamep, fschar_t *contentsp, lo
     cm_dirOp_t dirop;
     fschar_t *fnamep = NULL;
 
+    /* Check for RO volume */
+    if (dscp->flags & CM_SCACHEFLAG_RO)
+        return CM_ERROR_READONLY;
+
     memset(&volSync, 0, sizeof(volSync));
 
     /* before starting the RPC, mark that we're changing the directory data,
@@ -3349,6 +3394,12 @@ long cm_RemoveDir(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t *cnamep, cm_
     if (code)
         goto done;
 
+    /* Check for RO volume */
+    if (dscp->flags & CM_SCACHEFLAG_RO) {
+        code = CM_ERROR_READONLY;
+        goto done;
+    }
+
     /* before starting the RPC, mark that we're changing the directory data,
      * so that someone who does a chmod on the dir will wait until our
      * call completes.
@@ -3527,6 +3578,13 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
     } else {
         code = 0;
     }
+
+    /* Check for RO volume */
+    if (code == 0 &&
+        (oldDscp->flags & CM_SCACHEFLAG_RO) || (newDscp->flags & CM_SCACHEFLAG_RO)) {
+        code = CM_ERROR_READONLY;
+    }
+
     if (code) 
         goto done;