summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/libsmb/smb_share_modes.c2
-rw-r--r--source3/locking/locking.c20
-rw-r--r--source3/smbd/close.c4
-rw-r--r--source3/smbd/open.c46
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;
}