s3: Fix a bug in renames of directories
authorTim Prouty <tprouty@samba.org>
Thu, 6 Aug 2009 22:53:33 +0000 (15:53 -0700)
committerTim Prouty <tprouty@samba.org>
Fri, 7 Aug 2009 00:07:50 +0000 (17:07 -0700)
Recently code was added to match windows semantics of denying the
rename of a directory if there are open files underneath it.  This
does partly match windows semantics, but it turns out the rename
should be allowed if the open file handle is for the directory being
renamed, or for a stream on the directory being renamed.  This patch
refines the check to better follow these rename semantics.

source3/smbd/files.c

index a170f774fe64ecc6c8308b5db2bba9a66e326273..146d80973874101742dd6c25f373fdd36a479fd0 100644 (file)
@@ -404,14 +404,15 @@ bool file_find_subpath(files_struct *dir_fsp)
 {
        files_struct *fsp;
        size_t dlen;
-       char *d_fullname;
+       char *d_fullname = NULL;
+       bool ret = false;
 
        d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
                                     dir_fsp->conn->connectpath,
                                     dir_fsp->fsp_name->base_name);
 
        if (!d_fullname) {
-               return false;
+               goto out;
        }
 
        dlen = strlen(d_fullname);
@@ -429,15 +430,27 @@ bool file_find_subpath(files_struct *dir_fsp)
                                        fsp->fsp_name->base_name);
 
                if (strnequal(d_fullname, d1_fullname, dlen)) {
-                       TALLOC_FREE(d_fullname);
+                       int d1_len = strlen(d1_fullname);
+
+                       /*
+                        * If the open file is a second file handle to the
+                        * same name or is a stream on the original file, then
+                        * don't return true.
+                        */
+                       if (d1_len == dlen) {
+                               TALLOC_FREE(d1_fullname);
+                               continue;
+                       }
+
                        TALLOC_FREE(d1_fullname);
-                       return true;
+                       ret = true;
+                       goto out;
                }
                TALLOC_FREE(d1_fullname);
        } 
-
+ out:
        TALLOC_FREE(d_fullname);
-       return false;
+       return ret;
 }
 
 /****************************************************************************