fixed create_action for truncated files
[kai/samba.git] / source4 / ntvfs / posix / pvfs_open.c
index cc4f0add27ccc96427b6e7f973dd21a0040517bf..a1c5571258686368de53946d58baabe3be4d6f6d 100644 (file)
@@ -182,12 +182,19 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
        bool del_on_close;
        uint32_t create_options;
        uint32_t share_access;
+       bool forced;
 
        create_options = io->generic.in.create_options;
        share_access   = io->generic.in.share_access;
 
+       forced = (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)?true:false;
+
        if (name->stream_name) {
-               return NT_STATUS_NOT_A_DIRECTORY;
+               if (forced) {
+                       return NT_STATUS_NOT_A_DIRECTORY;
+               } else {
+                       return NT_STATUS_FILE_IS_A_DIRECTORY;
+               }
        }
 
        /* if the client says it must be a directory, and it isn't,
@@ -196,6 +203,13 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
                return NT_STATUS_NOT_A_DIRECTORY;
        }
 
+       /* found with gentest */
+       if (io->ntcreatex.in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED &&
+           (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) &&
+           (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       
        switch (io->generic.in.open_disposition) {
        case NTCREATEX_DISP_OPEN_IF:
                break;
@@ -551,12 +565,16 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
        if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) {
                return NT_STATUS_INVALID_PARAMETER;
        }
+
+       if (io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_ENCRYPTED) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
            
        if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) &&
            (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
                return NT_STATUS_CANNOT_DELETE;
        }
-       
+
        status = pvfs_access_check_create(pvfs, req, name, &access_mask);
        NT_STATUS_NOT_OK_RETURN(status);
 
@@ -616,6 +634,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
                return status;
        }
 
+       /* support initial alloc sizes */
+       name->dos.alloc_size = io->ntcreatex.in.alloc_size;
        name->dos.attrib = attrib;
        status = pvfs_dosattrib_save(pvfs, name, fd);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1102,6 +1122,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
        uint32_t create_options;
        uint32_t share_access;
        uint32_t access_mask;
+       uint32_t create_action = NTCREATEX_ACTION_EXISTED;
        bool del_on_close;
        bool stream_existed, stream_truncate=false;
        uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
@@ -1114,6 +1135,48 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                return ntvfs_map_open(ntvfs, req, io);
        }
 
+       create_options = io->generic.in.create_options;
+       share_access   = io->generic.in.share_access;
+       access_mask    = io->generic.in.access_mask;
+
+       if (share_access & ~NTCREATEX_SHARE_ACCESS_MASK) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* some create options are not supported */
+       if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) {
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
+       /* other create options are not allowed */
+       if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
+           !(access_mask & SEC_STD_DELETE)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (access_mask & SEC_MASK_INVALID) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       /* what does this bit really mean?? */
+       if (req->ctx->protocol == PROTOCOL_SMB2 &&
+           access_mask == SEC_STD_SYNCHRONIZE) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE|
+                                         FILE_ATTRIBUTE_VOLUME| 
+                                         (~FILE_ATTRIBUTE_ALL_MASK))) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* we ignore some file_attr bits */
+       io->ntcreatex.in.file_attr &= ~(FILE_ATTRIBUTE_NONINDEXED | 
+                                       FILE_ATTRIBUTE_COMPRESSED |
+                                       FILE_ATTRIBUTE_REPARSE_POINT |
+                                       FILE_ATTRIBUTE_SPARSE |
+                                       FILE_ATTRIBUTE_NORMAL);
+
        /* resolve the cifs name to a posix name */
        status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 
                                   PVFS_RESOLVE_STREAMS, &name);
@@ -1145,16 +1208,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
           open doesn't match */
        io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY;
 
-       create_options = io->generic.in.create_options;
-       share_access   = io->generic.in.share_access;
-       access_mask    = io->generic.in.access_mask;
-
-       /* certain create options are not allowed */
-       if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
-           !(access_mask & SEC_STD_DELETE)) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
        flags = 0;
 
        switch (io->generic.in.open_disposition) {
@@ -1165,6 +1218,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                } else {
                        stream_truncate = true;
                }
+               create_action = NTCREATEX_ACTION_TRUNCATED;
                break;
 
        case NTCREATEX_DISP_OPEN:
@@ -1183,6 +1237,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                } else {
                        stream_truncate = true;
                }
+               create_action = NTCREATEX_ACTION_TRUNCATED;
                break;
 
        case NTCREATEX_DISP_CREATE:
@@ -1421,6 +1476,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
                        talloc_free(lck);
                        return pvfs_map_errno(pvfs, errno);
                }
+               name->dos.alloc_size = io->ntcreatex.in.alloc_size;
                name->dos.attrib = attrib;
                status = pvfs_dosattrib_save(pvfs, name, fd);
                if (!NT_STATUS_IS_OK(status)) {
@@ -1441,7 +1497,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
        io->generic.out.oplock_level  = oplock_granted;
        io->generic.out.file.ntvfs    = h;
        io->generic.out.create_action = stream_existed?
-               NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED;
+               create_action:NTCREATEX_ACTION_CREATED;
+       
        io->generic.out.create_time   = name->dos.create_time;
        io->generic.out.access_time   = name->dos.access_time;
        io->generic.out.write_time    = name->dos.write_time;
@@ -1471,21 +1528,44 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
                return NT_STATUS_DOS(ERRSRV, ERRerror);
        }
 
-       if (io->generic.level != RAW_CLOSE_CLOSE) {
+       if (io->generic.level != RAW_CLOSE_GENERIC) {
                return ntvfs_map_close(ntvfs, req, io);
        }
 
-       f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs);
+       f = pvfs_find_fd(pvfs, req, io->generic.in.file.ntvfs);
        if (!f) {
                return NT_STATUS_INVALID_HANDLE;
        }
 
-       if (!null_time(io->close.in.write_time)) {
+       if (!null_time(io->generic.in.write_time)) {
                unix_times.actime = 0;
                unix_times.modtime = io->close.in.write_time;
                utime(f->handle->name->full_name, &unix_times);
        }
 
+       if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) {
+               struct pvfs_filename *name;
+               NTSTATUS status;
+               struct pvfs_file_handle *h = f->handle;
+
+               status = pvfs_resolve_name_handle(pvfs, h);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               name = h->name;
+
+               io->generic.out.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
+               io->generic.out.create_time = name->dos.create_time;
+               io->generic.out.access_time = name->dos.access_time;
+               io->generic.out.write_time  = name->dos.write_time;
+               io->generic.out.change_time = name->dos.change_time;
+               io->generic.out.alloc_size  = name->dos.alloc_size;
+               io->generic.out.size        = name->st.st_size;
+               io->generic.out.file_attr   = name->dos.attrib;         
+       } else {
+               ZERO_STRUCT(io->generic.out);
+       }
+
        talloc_free(f);
 
        return NT_STATUS_OK;