Windows: RDR_DeleteFileEntry test for empty directory
authorJeffrey Altman <jaltman@your-file-system.com>
Fri, 12 Apr 2013 05:14:39 +0000 (01:14 -0400)
committerJeffrey Altman <jaltman@your-file-system.com>
Wed, 17 Apr 2013 16:44:59 +0000 (09:44 -0700)
RDR_DeleteFileEntry should check to see that a directory entry
that is a directory is in fact empty.  The most frequent use of
RDR_DeleteFileEntry is to check whether the object can be deleted
prior to setting the DeletePending state which in turn results in
the object being deleted during Cleanup.  If the directory is not
empty during Cleanup it is too late for the error to be seen by
the application.

Change-Id: I3207bab0527406e3003e97bccf4195abeed31423
Reviewed-on: http://gerrit.openafs.org/9779
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/user/RDRFunction.c

index fca4332..0ecfdae 100644 (file)
@@ -2327,6 +2327,37 @@ RDR_DeleteFileEntry( IN cm_user_t *userp,
         return;
     }
 
+    if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+        cm_dirOp_t dirop;
+
+        lock_ReleaseWrite(&scp->rw);
+
+        code = cm_BeginDirOp(scp, userp, &req, CM_DIRLOCK_READ,
+                             CM_DIROP_FLAG_NONE, &dirop);
+        if (code == 0) {
+            /* is the directory empty? if not, CM_ERROR_NOTEMPTY */
+            afs_uint32 bEmpty;
+
+            code = cm_BPlusDirIsEmpty(&dirop, &bEmpty);
+            if (code == 0 && !bEmpty)
+                code = CM_ERROR_NOTEMPTY;
+
+            cm_EndDirOp(&dirop);
+        }
+
+        if (code) {
+            smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+            (*ResultCB)->ResultStatus = status;
+            (*ResultCB)->ResultBufferLength = 0;
+            cm_ReleaseSCache(scp);
+            cm_ReleaseSCache(dscp);
+            osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
+                     scp, code, status);
+            return;
+        }
+        lock_ObtainWrite(&scp->rw);
+    }
+
     if (!bCheckOnly) {
         /* Drop all locks since the file is being deleted */
         code = cm_SyncOp(scp, NULL, userp, &req, 0,