s4-streams: fixed handling of stream rename and overwrite
authorAndrew Tridgell <tridge@samba.org>
Sun, 18 Oct 2009 03:19:27 +0000 (14:19 +1100)
committerAndrew Tridgell <tridge@samba.org>
Sun, 18 Oct 2009 04:06:13 +0000 (15:06 +1100)
source4/ntvfs/posix/pvfs_rename.c
source4/ntvfs/posix/pvfs_setfileinfo.c
source4/ntvfs/posix/pvfs_streams.c

index 0616d38bee59e226e05ad0c6c8c909fd6885c7c2..d963357cbabd2ad4d0cd18537d6ae153c2746689 100644 (file)
@@ -515,7 +515,8 @@ static NTSTATUS pvfs_rename_stream(struct ntvfs_module_context *ntvfs,
        NT_STATUS_NOT_OK_RETURN(status);
 
        status = pvfs_stream_rename(pvfs, name1, -1, 
        NT_STATUS_NOT_OK_RETURN(status);
 
        status = pvfs_stream_rename(pvfs, name1, -1, 
-                                   ren->ntrename.in.new_name+1);
+                                   ren->ntrename.in.new_name+1, 
+                                   true);
        NT_STATUS_NOT_OK_RETURN(status);
        
        return NT_STATUS_OK;
        NT_STATUS_NOT_OK_RETURN(status);
        
        return NT_STATUS_OK;
index c70b44def05839736158aacee4537e0836e08cd7..b40ae9c9ded2d3662b058ef2f9b9805230989171 100644 (file)
@@ -108,7 +108,8 @@ static NTSTATUS pvfs_setfileinfo_rename_stream(struct pvfs_state *pvfs,
 
 
        status = pvfs_stream_rename(pvfs, name, fd, 
 
 
        status = pvfs_stream_rename(pvfs, name, fd, 
-                                   info->rename_information.in.new_name+1);
+                                   info->rename_information.in.new_name+1,
+                                   info->rename_information.in.overwrite);
        return status;
 }
 
        return status;
 }
 
index 6b39fb6066656dafefa01ea84e144f83b3a765a5..4da95432c1ff46c8842d91a871de822669a9910d 100644 (file)
@@ -240,7 +240,7 @@ static NTSTATUS pvfs_stream_update_size(struct pvfs_state *pvfs, struct pvfs_fil
   rename a stream
 */
 NTSTATUS pvfs_stream_rename(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
   rename a stream
 */
 NTSTATUS pvfs_stream_rename(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,
-                           const char *new_name)
+                           const char *new_name, bool overwrite)
 {
        struct xattr_DosStreams *streams;
        int i, found_old, found_new;
 {
        struct xattr_DosStreams *streams;
        int i, found_old, found_new;
@@ -289,17 +289,27 @@ NTSTATUS pvfs_stream_rename(struct pvfs_state *pvfs, struct pvfs_filename *name,
                struct xattr_DosStream *s = &streams->streams[found_old];
                s->name = new_name;
        } else {
                struct xattr_DosStream *s = &streams->streams[found_old];
                s->name = new_name;
        } else {
-               /* remove the old one and replace with the new one */
-               streams->streams[found_old].name = new_name;
-               memmove(&streams->streams[found_new],
-                       &streams->streams[found_new+1],
-                       sizeof(streams->streams[0]) *
-                       (streams->num_streams - (found_new+1)));
+               if (!overwrite) {
+                       return NT_STATUS_OBJECT_NAME_COLLISION;
+               }
+               if (found_old != found_new) {
+                       /* remove the old one and replace with the new one */
+                       streams->streams[found_old].name = new_name;
+                       memmove(&streams->streams[found_new],
+                               &streams->streams[found_new+1],
+                               sizeof(streams->streams[0]) *
+                               (streams->num_streams - (found_new+1)));
+                       streams->num_streams--;
+               }
        }
 
        status = pvfs_streams_save(pvfs, name, fd, streams);
        talloc_free(streams);
 
        }
 
        status = pvfs_streams_save(pvfs, name, fd, streams);
        talloc_free(streams);
 
+       /* update the in-memory copy of the name of the open file */
+       talloc_free(name->stream_name);
+       name->stream_name = talloc_strdup(name, new_name);
+
        return status;
 }
 
        return status;
 }