r3002: Fix for bug #1886 - prevent delete on close being set
authorJeremy Allison <jra@samba.org>
Sat, 16 Oct 2004 03:04:40 +0000 (03:04 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:52:59 +0000 (10:52 -0500)
for readonly files (and return the correct error code).
We now pass the Samba4 test suite on this.
Jeremy.
(This used to be commit 6ae417f12cc6f8d2ad00bea27ce0a20242f76325)

source3/smbd/open.c
source3/smbd/trans2.c

index 6d559ac828022b1234d8a18da7c7fde54ca7eaf3..55970493fa16edf644cdb020590440426962c7d0 100644 (file)
@@ -1409,9 +1409,17 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
        }
 
        if (delete_on_close) {
-               NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close);
+               uint32 dosmode = existing_dos_mode;
+               NTSTATUS result;
+
+               if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) {
+                       dosmode = new_dos_mode;
+               }
+               result = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
 
                if (NT_STATUS_V(result) !=  NT_STATUS_V(NT_STATUS_OK)) {
+                       uint8 u_e_c;
+                       uint32 u_e_code;
                        /* Remember to delete the mode we just added. */
                        if (add_share_mode) {
                                del_share_mode(fsp, NULL);
@@ -1419,6 +1427,10 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
                        unlock_share_entry_fsp(fsp);
                        fd_close(conn,fsp);
                        file_free(fsp);
+                       ntstatus_to_dos(result, &u_e_c, &u_e_code);
+                        unix_ERR_ntstatus = result;
+                        unix_ERR_class = u_e_c;
+                        unix_ERR_code = u_e_code;
                        return NULL;
                }
        }
@@ -1651,7 +1663,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST
        string_set(&fsp->fsp_name,fname);
 
        if (delete_on_close) {
-               NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close);
+               NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close, 0);
 
                if (NT_STATUS_V(result) !=  NT_STATUS_V(NT_STATUS_OK)) {
                        file_free(fsp);
index 31a74ae482fa396708e95a4ab7488020899b30ee..9b1f2aa21051369208959f2a0ef88b498725e47b 100644 (file)
@@ -2811,25 +2811,38 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
  open_file_shared. JRA.
 ****************************************************************************/
 
-NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
+NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
 {
-       /*
-        * Only allow delete on close for writable shares.
-        */
+       if (delete_on_close) {
+               /*
+                * Only allow delete on close for writable files.
+                */
 
-       if (delete_on_close && !CAN_WRITE(fsp->conn)) {
-               DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
+               if (dosmode & aRONLY) {
+                       DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
                                fsp->fsp_name ));
-                               return NT_STATUS_ACCESS_DENIED;
-       }
-       /*
-        * Only allow delete on close for files/directories opened with delete intent.
-        */
+                       return NT_STATUS_CANNOT_DELETE;
+               }
+
+               /*
+                * Only allow delete on close for writable shares.
+                */
 
-       if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
-               DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
+               if (!CAN_WRITE(fsp->conn)) {
+                       DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
                                fsp->fsp_name ));
-                               return NT_STATUS_ACCESS_DENIED;
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+
+               /*
+                * Only allow delete on close for files/directories opened with delete intent.
+                */
+
+               if (!(fsp->desired_access & DELETE_ACCESS)) {
+                       DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
+                               fsp->fsp_name ));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
        }
 
        if(fsp->is_directory) {
@@ -2866,7 +2879,7 @@ NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
                return NT_STATUS_ACCESS_DENIED;
 
        if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
-               DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
+               DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
                        fsp->fsp_name ));
                unlock_share_entry_fsp(fsp);
                return NT_STATUS_ACCESS_DENIED;
@@ -3286,7 +3299,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                        if (fsp == NULL)
                                return(UNIXERROR(ERRDOS,ERRbadfid));
 
-                       status = set_delete_on_close_internal(fsp, delete_on_close);
+                       status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
  
                        if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
                                return ERROR_NT(status);