[SCM] Samba Shared Repository - branch master updated - c0b98297b4064812d9a6572d56d98ddab9181446

Tim Prouty tprouty at samba.org
Mon Jan 5 03:46:53 GMT 2009


The branch, master has been updated
       via  c0b98297b4064812d9a6572d56d98ddab9181446 (commit)
       via  7ae992b622af62e9cfcbc9077f23eff8c2fe0d15 (commit)
       via  3e0e756104dc77059843bcef4a8d44981df28a18 (commit)
       via  2ddaebb2e11ba13ff7428e45dbfdc90b1bf2d630 (commit)
      from  d22adc14a91b7be323ff79c1b464e2b0bf400478 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c0b98297b4064812d9a6572d56d98ddab9181446
Author: Tim Prouty <tprouty at samba.org>
Date:   Sun Jan 4 19:27:06 2009 -0800

    s3: Remove a few unnecessary checks from the streams depot module and fix to work with NTRENAME
    
    Handling of error codes when renaming a file to a stream and a stream
    to a file is now done in rename_internals_fsp.
    
    The NTRENAME stream path only passes in the stream name, so the new
    base can now be different from the old base.

commit 7ae992b622af62e9cfcbc9077f23eff8c2fe0d15
Author: Tim Prouty <tprouty at samba.org>
Date:   Sun Jan 4 17:36:36 2009 -0800

    s3: Remove a few unnecessary checks from the streams xattr module
    
    Handling of error codes when renaming a file to a stream and a stream
    to a file is now done in rename_internals_fsp.
    
    The NTRENAME stream path only passes in the stream name, so the new
    base can now be different from the old base.

commit 3e0e756104dc77059843bcef4a8d44981df28a18
Author: Tim Prouty <tprouty at samba.org>
Date:   Sun Jan 4 10:45:34 2009 -0800

    s3: Allow renames of streams via NTRENAME and fix stream error codes on rename
    
    The test_streams_rename2 test in RAW-STREAMS verifies these changes

commit 2ddaebb2e11ba13ff7428e45dbfdc90b1bf2d630
Author: Tim Prouty <tprouty at samba.org>
Date:   Thu Dec 18 21:03:01 2008 -0800

    s4 torture: Add more rename tests to RAW-STREAMS
    
    There is one part of the new rename tests that passes against windows,
    but doesn't pass against samba3 right now.  Windows allow renaming a
    stream to the default stream, but none of the current streams module
    support this.  When this ability is added the check for samba can be
    removed from this test.
    
    This patch also adds a missing unlink in the cleanup of
    test_stream_delete and changes the order that the tests are run to be
    consistent with the physical order in the file.

-----------------------------------------------------------------------

Summary of changes:
 source3/modules/vfs_streams_depot.c |   30 +++--
 source3/modules/vfs_streams_xattr.c |   11 --
 source3/smbd/nttrans.c              |   14 ++--
 source3/smbd/reply.c                |   25 +++--
 source4/torture/raw/streams.c       |  201 ++++++++++++++++++++++++++++++++++-
 5 files changed, 238 insertions(+), 43 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c
index 69d3494..54c17db 100644
--- a/source3/modules/vfs_streams_depot.c
+++ b/source3/modules/vfs_streams_depot.c
@@ -525,6 +525,7 @@ static int streams_depot_rename(vfs_handle_struct *handle,
 	char *nsname = NULL;
 	char *ostream_fname = NULL;
 	char *nstream_fname = NULL;
+	char *newname_full = NULL;
 
 	DEBUG(10, ("streams_depot_rename called for %s => %s\n",
 		   oldname, newname));
@@ -536,11 +537,6 @@ static int streams_depot_rename(vfs_handle_struct *handle,
 		return SMB_VFS_NEXT_RENAME(handle, oldname, newname);
 	}
 
-	if (!(old_is_stream && new_is_stream)) {
-		errno = ENOSYS;
-		return -1;
-	}
-
 	frame = talloc_stackframe();
 
 	if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), oldname,
@@ -549,7 +545,7 @@ static int streams_depot_rename(vfs_handle_struct *handle,
 		goto done;
 	}
 
-	if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), oldname,
+	if (!NT_STATUS_IS_OK(split_ntfs_stream_name(talloc_tos(), newname,
 						    &nbase, &nsname))) {
 		errno = ENOMEM;
 		goto done;
@@ -561,17 +557,27 @@ static int streams_depot_rename(vfs_handle_struct *handle,
 		goto done;
 	}
 
-	if (StrCaseCmp(obase, nbase) != 0) {
-		errno = ENOSYS;
-		goto done;
-	}
-
 	ostream_fname = stream_name(handle, oldname, false);
 	if (ostream_fname == NULL) {
 		return -1;
 	}
 
-	nstream_fname = stream_name(handle, newname, false);
+	/*
+	 * Handle passing in a stream name without the base file.  This is
+	 * exercised by the NTRENAME streams rename path.
+	 */
+	if (StrCaseCmp(nbase, "./") == 0) {
+		newname_full = talloc_asprintf(talloc_tos(), "%s:%s", obase,
+					       nsname);
+		if (newname_full == NULL) {
+			errno = ENOMEM;
+			goto done;
+		}
+	}
+
+	nstream_fname = stream_name(handle,
+				    newname_full ? newname_full : newname,
+				    false);
 	if (nstream_fname == NULL) {
 		return -1;
 	}
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
index ecfc319..7124c57 100644
--- a/source3/modules/vfs_streams_xattr.c
+++ b/source3/modules/vfs_streams_xattr.c
@@ -511,11 +511,6 @@ static int streams_xattr_rename(vfs_handle_struct *handle,
 		return SMB_VFS_NEXT_RENAME(handle, oldname, newname);
 	}
 
-	if (!(o_is_stream && n_is_stream)) {
-		errno = ENOSYS;
-		goto fail;
-	}
-
 	frame = talloc_stackframe();
 	if (!frame) {
 		goto fail;
@@ -544,12 +539,6 @@ static int streams_xattr_rename(vfs_handle_struct *handle,
 		goto fail;
 	}
 
-	/* the new base should be empty */
-	if (StrCaseCmp(obase, nbase) != 0) {
-		errno = ENOSYS;
-		goto fail;
-	}
-
 	if (StrCaseCmp(ostream, nstream) == 0) {
 		goto done;
 	}
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 9bfc566..a793e61 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1310,13 +1310,6 @@ void reply_ntrename(struct smb_request *req)
 		return;
 	}
 
-	if( is_ntfs_stream_name(oldname)) {
-		/* Can't rename a stream. */
-		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
-		END_PROFILE(SMBntrename);
-		return;
-	}
-
 	if (ms_has_wild(oldname)) {
 		reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
 		END_PROFILE(SMBntrename);
@@ -1364,6 +1357,13 @@ void reply_ntrename(struct smb_request *req)
 		return;
 	}
 
+	/* The new name must begin with a ':' if the old name is a stream. */
+	if (is_ntfs_stream_name(oldname) && (newname[0] != ':')) {
+		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+		END_PROFILE(SMBntrename);
+		return;
+	}
+
 	DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
 
 	switch(rename_type) {
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 2133a30..593558e 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -5439,7 +5439,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 	SMB_STRUCT_STAT sbuf, sbuf1;
 	NTSTATUS status = NT_STATUS_OK;
 	struct share_mode_lock *lck = NULL;
-	bool dst_exists;
+	bool dst_exists, old_is_stream, new_is_stream;
 
 	ZERO_STRUCT(sbuf);
 
@@ -5508,6 +5508,18 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 		return NT_STATUS_OK;
 	}
 
+	old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
+	new_is_stream = is_ntfs_stream_name(newname);
+
+	/* Return the correct error code if both names aren't streams. */
+	if (!old_is_stream && new_is_stream) {
+		return NT_STATUS_OBJECT_NAME_INVALID;
+	}
+
+	if (old_is_stream && !new_is_stream) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
 	/*
 	 * Have vfs_object_exist also fill sbuf1
 	 */
@@ -5519,18 +5531,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
 		return NT_STATUS_OBJECT_NAME_COLLISION;
 	}
 
-	if(replace_if_exists && dst_exists) {
-		/* Ensure both or neither are stream names. */
-		if (is_ntfs_stream_name(fsp->fsp_name) !=
-				is_ntfs_stream_name(newname)) {
-			return NT_STATUS_INVALID_PARAMETER;
-		}
-	}
-
 	if (dst_exists) {
 		struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
 		files_struct *dst_fsp = file_find_di_first(fileid);
-		if (dst_fsp) {
+		/* The file can be open when renaming a stream */
+		if (dst_fsp && !new_is_stream) {
 			DEBUG(3, ("rename_internals_fsp: Target file open\n"));
 			return NT_STATUS_ACCESS_DENIED;
 		}
diff --git a/source4/torture/raw/streams.c b/source4/torture/raw/streams.c
index ba74530..1898fe9 100644
--- a/source4/torture/raw/streams.c
+++ b/source4/torture/raw/streams.c
@@ -640,6 +640,7 @@ static bool test_stream_delete(struct torture_context *tctx,
 	CHECK_STATUS(status, NT_STATUS_OK);
 done:
 	smbcli_close(cli->tree, fnum);
+	smbcli_unlink(cli->tree, fname);
 	return ret;
 }
 
@@ -1112,6 +1113,198 @@ done:
 	return ret;
 }
 
+static bool test_stream_rename2(struct torture_context *tctx,
+			       struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
+{
+	NTSTATUS status;
+	union smb_open io;
+	const char *fname1 = BASEDIR "\\stream.txt";
+	const char *fname2 = BASEDIR "\\stream2.txt";
+	const char *stream_name1 = ":Stream One:$DATA";
+	const char *stream_name2 = ":Stream Two:$DATA";
+	const char *stream_name_default = "::$DATA";
+	const char *sname1;
+	const char *sname2;
+	bool ret = true;
+	int fnum = -1;
+	union smb_setfileinfo sinfo;
+	union smb_rename rio;
+
+	sname1 = talloc_asprintf(mem_ctx, "%s:%s", fname1, "Stream One");
+	sname2 = talloc_asprintf(mem_ctx, "%s:%s", fname1, "Stream Two");
+
+	io.generic.level = RAW_OPEN_NTCREATEX;
+	io.ntcreatex.in.root_fid = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = (SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|
+	    SEC_STD_DELETE|SEC_FILE_APPEND_DATA|SEC_STD_READ_CONTROL);
+	io.ntcreatex.in.create_options = 0;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access = (NTCREATEX_SHARE_ACCESS_READ |
+					NTCREATEX_SHARE_ACCESS_WRITE |
+					NTCREATEX_SHARE_ACCESS_DELETE);
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = sname1;
+
+	/* Open/create new stream. */
+	status = smb_raw_open(cli->tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
+
+	/*
+	 * Check raw rename with <base>:<stream>.
+	 */
+	printf("(%s) Checking NTRENAME of a stream using <base>:<stream>\n",
+	       __location__);
+	rio.generic.level = RAW_RENAME_NTRENAME;
+	rio.ntrename.in.old_name = sname1;
+	rio.ntrename.in.new_name = sname2;
+	rio.ntrename.in.attrib = 0;
+	rio.ntrename.in.cluster_size = 0;
+	rio.ntrename.in.flags = RENAME_FLAG_RENAME;
+	status = smb_raw_rename(cli->tree, &rio);
+	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+	/*
+	 * Check raw rename to the default stream using :<stream>.
+	 */
+	printf("(%s) Checking NTRENAME to default stream using :<stream>\n",
+	       __location__);
+	rio.ntrename.in.new_name = stream_name_default;
+	status = smb_raw_rename(cli->tree, &rio);
+	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
+
+	/*
+	 * Check raw rename using :<stream>.
+	 */
+	printf("(%s) Checking NTRENAME of a stream using :<stream>\n",
+	       __location__);
+	rio.ntrename.in.new_name = stream_name2;
+	status = smb_raw_rename(cli->tree, &rio);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*
+	 * Check raw rename of a stream to a file.
+	 */
+	printf("(%s) Checking NTRENAME of a stream to a file\n",
+	       __location__);
+	rio.ntrename.in.old_name = sname2;
+	rio.ntrename.in.new_name = fname2;
+	status = smb_raw_rename(cli->tree, &rio);
+	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
+
+	/*
+	 * Check raw rename of a file to a stream.
+	 */
+	printf("(%s) Checking NTRENAME of a file to a stream\n",
+	       __location__);
+
+	/* Create the file. */
+	io.ntcreatex.in.fname = fname2;
+	status = smb_raw_open(cli->tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
+
+	/* Try the rename. */
+	rio.ntrename.in.old_name = fname2;
+	rio.ntrename.in.new_name = sname1;
+	status = smb_raw_rename(cli->tree, &rio);
+	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
+
+	/*
+	 * Reopen the stream for trans2 renames.
+	 */
+	io.ntcreatex.in.fname = sname2;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+	status = smb_raw_open(cli->tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/*
+	 * Check trans2 rename of a stream using :<stream>.
+	 */
+	printf("(%s) Checking trans2 rename of a stream using :<stream>\n",
+	       __location__);
+	ZERO_STRUCT(sinfo);
+	sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+	sinfo.rename_information.in.file.fnum = fnum;
+	sinfo.rename_information.in.overwrite = 1;
+	sinfo.rename_information.in.root_fid = 0;
+	sinfo.rename_information.in.new_name = stream_name1;
+	status = smb_raw_setfileinfo(cli->tree, &sinfo);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*
+	 * Check trans2 rename of an overwriting stream using :<stream>.
+	 */
+	printf("(%s) Checking trans2 rename of an overwriting stream using "
+	       ":<stream>\n", __location__);
+
+	/* Create second stream. */
+	io.ntcreatex.in.fname = sname2;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	status = smb_raw_open(cli->tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
+
+	/* Rename the first stream onto the second. */
+	sinfo.rename_information.in.file.fnum = fnum;
+	sinfo.rename_information.in.new_name = stream_name2;
+	status = smb_raw_setfileinfo(cli->tree, &sinfo);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	smbcli_close(cli->tree, fnum);
+
+	/*
+	 * Reopen the stream with the new name.
+	 */
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+	io.ntcreatex.in.fname = sname2;
+	status = smb_raw_open(cli->tree, mem_ctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	fnum = io.ntcreatex.out.file.fnum;
+
+	/*
+	 * Check trans2 rename of a stream using <base>:<stream>.
+	 */
+	printf("(%s) Checking trans2 rename of a stream using "
+	       "<base>:<stream>\n", __location__);
+	sinfo.rename_information.in.file.fnum = fnum;
+	sinfo.rename_information.in.new_name = sname1;
+	status = smb_raw_setfileinfo(cli->tree, &sinfo);
+	CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED);
+
+	/*
+	 * Samba3 doesn't currently support renaming a stream to the default
+	 * stream.  This test does pass on windows.
+	 */
+	if (torture_setting_bool(tctx, "samba3", false)) {
+		goto done;
+	}
+
+	/*
+	 * Check trans2 rename to the default stream using :<stream>.
+	 */
+	printf("(%s) Checking trans2 rename to defaualt stream using "
+	       ":<stream>\n", __location__);
+	sinfo.rename_information.in.file.fnum = fnum;
+	sinfo.rename_information.in.new_name = stream_name_default;
+	status = smb_raw_setfileinfo(cli->tree, &sinfo);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	smbcli_close(cli->tree, fnum);
+
+ done:
+	smbcli_close(cli->tree, fnum);
+	status = smbcli_unlink(cli->tree, fname1);
+	status = smbcli_unlink(cli->tree, fname2);
+	return ret;
+}
+
 
 /* 
    basic testing of streams calls
@@ -1131,15 +1324,17 @@ bool torture_raw_streams(struct torture_context *torture,
 	smb_raw_exit(cli->session);
 	ret &= test_stream_sharemodes(torture, cli, torture);
 	smb_raw_exit(cli->session);
+	if (!torture_setting_bool(torture, "samba4", false)) {
+		ret &= test_stream_delete(torture, cli, torture);
+	}
 	ret &= test_stream_names(torture, cli, torture);
 	smb_raw_exit(cli->session);
 	ret &= test_stream_names2(torture, cli, torture);
 	smb_raw_exit(cli->session);
 	ret &= test_stream_rename(torture, cli, torture);
 	smb_raw_exit(cli->session);
-	if (!torture_setting_bool(torture, "samba4", false)) {
-		ret &= test_stream_delete(torture, cli, torture);
-	}
+	ret &= test_stream_rename2(torture, cli, torture);
+	smb_raw_exit(cli->session);
 
 	smb_raw_exit(cli->session);
 	smbcli_deltree(cli->tree, BASEDIR);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list