diff options
-rw-r--r-- | source3/include/smb.h | 1 | ||||
-rw-r--r-- | source3/libsmb/smb_share_modes.c | 2 | ||||
-rw-r--r-- | source3/locking/locking.c | 20 | ||||
-rw-r--r-- | source3/smbd/close.c | 4 | ||||
-rw-r--r-- | source3/smbd/open.c | 46 |
5 files changed, 44 insertions, 29 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 315eb3233a..ac268ea763 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -657,6 +657,7 @@ struct share_mode_lock { int num_share_modes; struct share_mode_entry *share_modes; BOOL delete_on_close; + BOOL initial_delete_on_close; BOOL fresh; BOOL modified; }; diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index 43f25cd378..86071ee2e9 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -123,6 +123,7 @@ struct locking_data { 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 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, 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); diff --git a/source3/locking/locking.c b/source3/locking/locking.c index e31ead30e4..e8309582fd 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -49,6 +49,7 @@ struct locking_data { 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 @@ static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) 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 @@ static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) 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 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, 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; @@ -1046,6 +1054,7 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, 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) @@ -1070,6 +1079,11 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) lck->modified = True; } + if (lck->initial_delete_on_close) { + lck->initial_delete_on_close = False; + lck->modified = True; + } + talloc_free(lck); return True; } diff --git a/source3/smbd/close.c b/source3/smbd/close.c index c0d87b1b21..d284c82f44 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -209,7 +209,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) 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 @@ static int close_directory(files_struct *fsp, BOOL normal_close) 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); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0ccac592d6..dd2731c897 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1660,32 +1660,28 @@ files_struct *open_file_ntcreate(connection_struct *conn, } 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); - 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; + /* 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; + } + /* 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 +1972,9 @@ files_struct *open_directory(connection_struct *conn, 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 +1983,7 @@ files_struct *open_directory(connection_struct *conn, return NULL; } - lck->delete_on_close = True; + lck->initial_delete_on_close = True; lck->modified = True; } |