diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/open.c | 16 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 45 |
2 files changed, 43 insertions, 18 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6d559ac828..55970493fa 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -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); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 31a74ae482..9b1f2aa210 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -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); |