Merge branch 'master' of ssh://git.samba.org/data/git/samba into master-devel
authorAndrew Bartlett <abartlet@samba.org>
Fri, 7 Aug 2009 03:08:35 +0000 (13:08 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 7 Aug 2009 03:08:35 +0000 (13:08 +1000)
source3/smbd/files.c
source4/torture/raw/rename.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;
 }
 
 /****************************************************************************
index e91c3b2319adcb5439f0447390863bc1e538881f..15fed0e3d8f6b6ddbf50c753d196fb8940fbaff3 100644 (file)
@@ -529,6 +529,7 @@ static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *c
         const char *dname1 = BASEDIR "\\dir_for_rename";
         const char *dname2 = BASEDIR "\\renamed_dir";
         const char *fname = BASEDIR "\\dir_for_rename\\file.txt";
+       const char *sname = BASEDIR "\\dir_for_rename:a stream:$DATA";
        bool ret = true;
        int fnum = -1;
 
@@ -593,6 +594,55 @@ static bool test_dir_rename(struct torture_context *tctx, struct smbcli_state *c
        status = smb_raw_rename(cli->tree, &ren_io);
        CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
 
+       /* Close the file and try the rename. */
+       smbcli_close(cli->tree, fnum);
+
+       status = smb_raw_rename(cli->tree, &ren_io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       /*
+        * Now try just holding a second handle on the directory and holding
+        * it open across a rename.  This should be allowed.
+        */
+       io.ntcreatex.in.fname = dname2;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+
+       io.ntcreatex.in.access_mask = SEC_STD_READ_CONTROL |
+           SEC_FILE_READ_ATTRIBUTE | SEC_FILE_READ_EA | SEC_FILE_READ_DATA;
+
+       status = smb_raw_open(cli->tree, tctx, &io);
+        CHECK_STATUS(status, NT_STATUS_OK);
+        fnum = io.ntcreatex.out.file.fnum;
+
+       ren_io.generic.level = RAW_RENAME_RENAME;
+       ren_io.rename.in.pattern1 = dname2;
+       ren_io.rename.in.pattern2 = dname1;
+       ren_io.rename.in.attrib = 0;
+
+       status = smb_raw_rename(cli->tree, &ren_io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
+       /* close our handle to the directory. */
+       smbcli_close(cli->tree, fnum);
+
+       /*
+        * Now try opening a stream on the directory and holding it open
+        * across a rename.  This should be allowed.
+        */
+       io.ntcreatex.in.fname = sname;
+
+       status = smb_raw_open(cli->tree, tctx, &io);
+        CHECK_STATUS(status, NT_STATUS_OK);
+        fnum = io.ntcreatex.out.file.fnum;
+
+       ren_io.generic.level = RAW_RENAME_RENAME;
+       ren_io.rename.in.pattern1 = dname1;
+       ren_io.rename.in.pattern2 = dname2;
+       ren_io.rename.in.attrib = 0;
+
+       status = smb_raw_rename(cli->tree, &ren_io);
+       CHECK_STATUS(status, NT_STATUS_OK);
+
 done:
        
        if (fnum != -1) {