Second part of the fix for bug #5903 - vfs_streams_xattr breaks contents of the file
authorJeremy Allison <jra@samba.org>
Fri, 21 Nov 2008 23:42:03 +0000 (15:42 -0800)
committerJeremy Allison <jra@samba.org>
Fri, 21 Nov 2008 23:42:03 +0000 (15:42 -0800)
(also fix a bad merge of the previous patch from 3.3).
Jeremy.

source3/modules/vfs_streams_xattr.c
source3/smbd/open.c

index b74c4f7902e75382e5f61b022e2b5d8e1a4c6a5c..9df88e5e19b430947b7872963231c6a29cbc6ea0 100644 (file)
@@ -624,7 +624,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
                (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
        struct ea_struct ea;
        NTSTATUS status;
-        size_t length, overlap;
+       size_t length, overlap;
 
        if (sio == NULL) {
                return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
@@ -651,6 +651,63 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
         return overlap;
 }
 
+static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
+                                       struct files_struct *fsp,
+                                       SMB_OFF_T offset)
+{
+       int ret;
+       uint8 *tmp;
+       struct ea_struct ea;
+       NTSTATUS status;
+        struct stream_io *sio =
+               (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+
+       DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n",
+               fsp->fsp_name,
+               (double)offset ));
+
+       if (sio == NULL) {
+               return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset);
+       }
+
+       status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
+                             sio->base, sio->xattr_name, &ea);
+       if (!NT_STATUS_IS_OK(status)) {
+               return -1;
+       }
+
+       tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), ea.value.data, uint8,
+                                  offset + 1);
+
+       if (tmp == NULL) {
+               TALLOC_FREE(ea.value.data);
+               errno = ENOMEM;
+               return -1;
+       }
+
+       /* Did we expand ? */
+       if (ea.value.length < offset + 1) {
+               memset(&tmp[ea.value.length], '\0',
+                       offset + 1 - ea.value.length);
+       }
+
+       ea.value.data = tmp;
+       ea.value.length = offset + 1;
+       ea.value.data[offset] = 0;
+
+       ret = SMB_VFS_SETXATTR(fsp->conn, fsp->base_fsp->fsp_name,
+                               sio->xattr_name,
+                               ea.value.data, ea.value.length, 0);
+
+       TALLOC_FREE(ea.value.data);
+
+       if (ret == -1) {
+               return -1;
+       }
+
+       return 0;
+}
+
 /* VFS operations structure */
 
 static vfs_op_tuple streams_xattr_ops[] = {
@@ -672,6 +729,8 @@ static vfs_op_tuple streams_xattr_ops[] = {
         SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(streams_xattr_unlink), SMB_VFS_OP_UNLINK,
         SMB_VFS_LAYER_TRANSPARENT},
+        {SMB_VFS_OP(streams_xattr_ftruncate),  SMB_VFS_OP_FTRUNCATE,
+         SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(streams_xattr_streaminfo), SMB_VFS_OP_STREAMINFO,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
index aca64917b56c19951683d549f68daac89b97944e..a6867e077c4093912c2121da8cbf8b5e655a8709 100644 (file)
@@ -1651,7 +1651,7 @@ static NTSTATUS open_file_ntcreate_internal(connection_struct *conn,
                                                        share_access,
                                                        create_options);
 
-                               if (!NT_STATUS_IS_OK(status)) {
+                               if (NT_STATUS_IS_OK(status)) {
                                        TALLOC_FREE(lck);
                                        if (pinfo) {
                                                *pinfo = FILE_WAS_OPENED;
@@ -2878,10 +2878,42 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
                 * Ordinary file case.
                 */
 
-               status = open_file_ntcreate(
-                       conn, req, fname, &sbuf, access_mask, share_access,
-                       create_disposition, create_options, file_attributes,
-                       oplock_request, &info, &fsp);
+               if (base_fsp) {
+                       /*
+                        * We're opening the stream element of a base_fsp
+                        * we already opened. We need to initialize
+                        * the fsp first, and set up the base_fsp pointer.
+                        */
+                       status = file_new(req, conn, &fsp);
+                       if(!NT_STATUS_IS_OK(status)) {
+                               goto fail;
+                       }
+
+                       fsp->base_fsp = base_fsp;
+
+                       status = open_file_ntcreate_internal(conn,
+                                               req,
+                                               fname,
+                                               &sbuf,
+                                               access_mask,
+                                               share_access,
+                                               create_disposition,
+                                               create_options,
+                                               file_attributes,
+                                               oplock_request,
+                                               &info,
+                                               fsp);
+
+                       if(!NT_STATUS_IS_OK(status)) {
+                               file_free(req, fsp);
+                               fsp = NULL;
+                       }
+               } else {
+                       status = open_file_ntcreate(
+                               conn, req, fname, &sbuf, access_mask, share_access,
+                               create_disposition, create_options, file_attributes,
+                               oplock_request, &info, &fsp);
+               }
 
                if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
 
@@ -2908,6 +2940,8 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
                goto fail;
        }
 
+       fsp->base_fsp = base_fsp;
+
        /*
         * According to the MS documentation, the only time the security
         * descriptor is applied to the opened file is iff we *created* the
@@ -2994,16 +3028,6 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
 
        DEBUG(10, ("create_file_unixpath: info=%d\n", info));
 
-       /*
-        * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In
-        * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would
-        * also close fsp->base_fsp which we have to also do explicitly in
-        * this routine here, as not in all "goto fail:" we have the fsp set
-        * up already to be initialized with the base_fsp.
-        */
-
-       fsp->base_fsp = base_fsp;
-
        *result = fsp;
        if (pinfo != NULL) {
                *pinfo = info;
@@ -3022,6 +3046,13 @@ NTSTATUS create_file_unixpath(connection_struct *conn,
        DEBUG(10, ("create_file_unixpath: %s\n", nt_errstr(status)));
 
        if (fsp != NULL) {
+               if (base_fsp && fsp->base_fsp == base_fsp) {
+                       /*
+                        * The close_file below will close
+                        * fsp->base_fsp.
+                        */
+                       base_fsp = NULL;
+               }
                close_file(req, fsp, ERROR_CLOSE);
                fsp = NULL;
        }