Index: smbd/open.c =================================================================== --- smbd/open.c (revision 13272) +++ smbd/open.c (working copy) @@ -1646,6 +1646,8 @@ *pinfo = info; } + DEBUG(10,("open_file_ntcreate: info was %d for file %s\n", info, fname)); + /* * Setup the oplock info in both the shared memory and * file structs. @@ -1660,32 +1662,28 @@ } set_share_mode(lck, fsp, 0, fsp->oplock_type); - if (create_options & FILE_DELETE_ON_CLOSE) { - uint32 dosattr= existing_dos_attributes; - NTSTATUS result; - - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) { - dosattr = new_dos_attributes; - } - result = can_set_delete_on_close(fsp, True, dosattr); + /* Handle strange delete on close create semantics. */ + if (create_options & FILE_DELETE_ON_CLOSE) { + NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes); - if (!NT_STATUS_IS_OK(result)) { - /* Remember to delete the mode we just added. */ - del_share_mode(lck, fsp); - talloc_free(lck); - fd_close(conn,fsp); - file_free(fsp); - set_saved_ntstatus(result); - return NULL; + if (!NT_STATUS_IS_OK(result)) { + /* Remember to delete the mode we just added. */ + del_share_mode(lck, fsp); + talloc_free(lck); + fd_close(conn,fsp); + file_free(fsp); + set_saved_ntstatus(result); + return NULL; + } + /* Note that here we set the *inital* delete on close flag, + not the regular one. */ + lck->initial_delete_on_close = True; + lck->modified = True; } - lck->delete_on_close = True; - lck->modified = True; - } - if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || - info == FILE_WAS_SUPERSEDED) { /* Files should be initially set as archive */ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) { @@ -1976,7 +1974,9 @@ set_share_mode(lck, fsp, 0, NO_OPLOCK); - if (create_options & FILE_DELETE_ON_CLOSE) { + if ((create_options & FILE_DELETE_ON_CLOSE) && + (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || + info == FILE_WAS_SUPERSEDED)) { status = can_set_delete_on_close(fsp, True, 0); if (!NT_STATUS_IS_OK(status)) { set_saved_ntstatus(status); @@ -1985,7 +1985,7 @@ return NULL; } - lck->delete_on_close = True; + lck->initial_delete_on_close = True; lck->modified = True; } Index: smbd/close.c =================================================================== --- smbd/close.c (revision 13272) +++ smbd/close.c (working copy) @@ -209,7 +209,7 @@ DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name)); } - delete_file = lck->delete_on_close; + delete_file = (lck->delete_on_close | lck->initial_delete_on_close); if (delete_file) { int i; @@ -345,7 +345,7 @@ DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name)); } - delete_dir = lck->delete_on_close; + delete_dir = (lck->delete_on_close | lck->initial_delete_on_close); talloc_free(lck); Index: libsmb/smb_share_modes.c =================================================================== --- libsmb/smb_share_modes.c (revision 13272) +++ libsmb/smb_share_modes.c (working copy) @@ -123,6 +123,7 @@ struct { int num_share_mode_entries; BOOL delete_on_close; + BOOL initial_delete_on_close; } s; struct share_mode_entry dummy; /* Needed for alignment. */ } u; @@ -282,6 +283,7 @@ ld = (struct locking_data *)db_data.dptr; ld->u.s.num_share_mode_entries = 1; ld->u.s.delete_on_close = 0; + ld->u.s.initial_delete_on_close = 0; shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry)); create_share_mode_entry(shares, new_entry); Index: include/smb.h =================================================================== --- include/smb.h (revision 13272) +++ include/smb.h (working copy) @@ -696,6 +696,7 @@ int num_share_modes; struct share_mode_entry *share_modes; BOOL delete_on_close; + BOOL initial_delete_on_close; BOOL fresh; BOOL modified; }; Index: locking/locking.c =================================================================== --- locking/locking.c (revision 13272) +++ locking/locking.c (working copy) @@ -49,6 +49,7 @@ struct { int num_share_mode_entries; BOOL delete_on_close; + BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */ } s; struct share_mode_entry dummy; /* Needed for alignment. */ } u; @@ -435,11 +436,15 @@ data = (struct locking_data *)dbuf.dptr; lck->delete_on_close = data->u.s.delete_on_close; + lck->initial_delete_on_close = data->u.s.initial_delete_on_close; lck->num_share_modes = data->u.s.num_share_mode_entries; DEBUG(10, ("parse_share_modes: delete_on_close: %d, " - "num_share_modes: %d\n", lck->delete_on_close, - lck->num_share_modes)); + "initial_delete_on_close: %d, " + "num_share_modes: %d\n", + lck->delete_on_close, + lck->initial_delete_on_close, + lck->num_share_modes)); if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { DEBUG(0, ("invalid number of share modes: %d\n", @@ -535,8 +540,10 @@ ZERO_STRUCTP(data); data->u.s.num_share_mode_entries = lck->num_share_modes; data->u.s.delete_on_close = lck->delete_on_close; - DEBUG(10, ("unparse_share_modes: del: %d, num: %d\n", + data->u.s.initial_delete_on_close = lck->initial_delete_on_close; + DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, num: %d\n", data->u.s.delete_on_close, + data->u.s.initial_delete_on_close, data->u.s.num_share_mode_entries)); memcpy(result.dptr + sizeof(*data), lck->share_modes, sizeof(struct share_mode_entry)*lck->num_share_modes); @@ -613,6 +620,7 @@ lck->num_share_modes = 0; lck->share_modes = NULL; lck->delete_on_close = False; + lck->initial_delete_on_close = False; lck->fresh = False; lck->modified = False; @@ -962,6 +970,7 @@ changed the delete on close flag. This will be noticed in the close code, the last closer will delete the file if flag is set. + Note that setting this to any value clears the initial_delete_on_close flag. ****************************************************************************/ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) @@ -986,6 +995,11 @@ lck->modified = True; } + if (lck->initial_delete_on_close) { + lck->initial_delete_on_close = False; + lck->modified = True; + } + talloc_free(lck); return True; }