s3: Allow renames of streams via NTRENAME and fix stream error codes on rename
authorTim Prouty <tprouty@samba.org>
Sun, 4 Jan 2009 18:45:34 +0000 (10:45 -0800)
committerTim Prouty <tprouty@samba.org>
Mon, 5 Jan 2009 03:31:30 +0000 (19:31 -0800)
The test_streams_rename2 test in RAW-STREAMS verifies these changes

source3/smbd/nttrans.c
source3/smbd/reply.c

index 9bfc5664101aeb8f59741a20cf420c8608569370..a793e614afffaea509d13a7f6970066fe6b81113 100644 (file)
@@ -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) {
index 2133a30dc651c7cf5cc1d653488aabaa6614a1bb..593558e3992aea0a4f87d679dc56cd646669d435 100644 (file)
@@ -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;
                }