summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/libsmb/smb_share_modes.c1
-rw-r--r--source3/locking/locking.c39
-rw-r--r--source3/smbd/close.c39
-rw-r--r--source3/smbd/open.c12
5 files changed, 59 insertions, 35 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index cf754b5c1f..df4f47f12c 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -506,6 +506,7 @@ typedef struct files_struct {
BOOL is_stat;
BOOL aio_write_behind;
BOOL lockdb_clean;
+ BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */
char *fsp_name;
struct vfs_fsp_data *vfs_extension;
@@ -773,7 +774,6 @@ struct share_mode_lock {
struct share_mode_entry *share_modes;
UNIX_USER_TOKEN *delete_token;
BOOL delete_on_close;
- BOOL initial_delete_on_close;
BOOL fresh;
BOOL modified;
};
@@ -788,7 +788,6 @@ 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. */
uint32 delete_token_size; /* Only valid if either of
the two previous fields
are True. */
diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c
index b62240ce50..b8c7a7e66b 100644
--- a/source3/libsmb/smb_share_modes.c
+++ b/source3/libsmb/smb_share_modes.c
@@ -274,7 +274,6 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
memset(ld, '\0', sizeof(struct locking_data));
ld->u.s.num_share_mode_entries = 1;
ld->u.s.delete_on_close = 0;
- ld->u.s.initial_delete_on_close = 0;
ld->u.s.delete_token_size = 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 111fc98bbe..56d18a63ef 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -473,14 +473,11 @@ 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, "
- "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)) {
@@ -635,11 +632,9 @@ 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;
- data->u.s.initial_delete_on_close = lck->initial_delete_on_close;
data->u.s.delete_token_size = delete_token_size;
- DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, tok = %u, num: %d\n",
+ DEBUG(10, ("unparse_share_modes: del: %d, tok = %u, num: %d\n",
data->u.s.delete_on_close,
- data->u.s.initial_delete_on_close,
(unsigned int)data->u.s.delete_token_size,
data->u.s.num_share_mode_entries));
memcpy(result.dptr + sizeof(*data), lck->share_modes,
@@ -734,7 +729,6 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
lck->share_modes = NULL;
lck->delete_token = NULL;
lck->delete_on_close = False;
- lck->initial_delete_on_close = False;
lck->fresh = False;
lck->modified = False;
@@ -1251,11 +1245,22 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok
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.
- If delete_on_close is True this makes a copy of any UNIX_USER_TOKEN into the
- lck entry.
+ This makes a copy of any UNIX_USER_TOKEN into the
+ lck entry. This function is used when the lock is already granted.
****************************************************************************/
+void set_delete_on_close_lck(struct share_mode_lock *lck, BOOL delete_on_close, UNIX_USER_TOKEN *tok)
+{
+ if (lck->delete_on_close != delete_on_close) {
+ set_delete_on_close_token(lck, tok);
+ lck->delete_on_close = delete_on_close;
+ if (delete_on_close) {
+ SMB_ASSERT(lck->delete_token != NULL);
+ }
+ lck->modified = True;
+ }
+}
+
BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok)
{
struct share_mode_lock *lck;
@@ -1274,19 +1279,7 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKE
return False;
}
- if (lck->delete_on_close != delete_on_close) {
- set_delete_on_close_token(lck, tok);
- lck->delete_on_close = delete_on_close;
- if (delete_on_close) {
- SMB_ASSERT(lck->delete_token != NULL);
- }
- lck->modified = True;
- }
-
- if (lck->initial_delete_on_close) {
- lck->initial_delete_on_close = False;
- lck->modified = True;
- }
+ set_delete_on_close_lck(lck, delete_on_close, tok);
TALLOC_FREE(lck);
return True;
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index fe5e5eccf2..8958878433 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -22,6 +22,8 @@
#include "includes.h"
+extern struct current_user current_user;
+
/****************************************************************************
Run a file if it is a magic script.
****************************************************************************/
@@ -172,7 +174,23 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
"entry for file %s\n", fsp->fsp_name));
}
- delete_file = (lck->delete_on_close | lck->initial_delete_on_close);
+ if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
+ BOOL became_user = False;
+
+ /* Initial delete on close was set and no one else
+ * wrote a real delete on close. */
+
+ if (current_user.vuid != fsp->vuid) {
+ become_user(conn, fsp->vuid);
+ became_user = True;
+ }
+ set_delete_on_close_lck(lck, True, &current_user.ut);
+ if (became_user) {
+ unbecome_user();
+ }
+ }
+
+ delete_file = lck->delete_on_close;
if (delete_file) {
int i;
@@ -402,7 +420,24 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
}
- delete_dir = (lck->delete_on_close | lck->initial_delete_on_close);
+ if (fsp->initial_delete_on_close) {
+ BOOL became_user = False;
+
+ /* Initial delete on close was set - for
+ * directories we don't care if anyone else
+ * wrote a real delete on close. */
+
+ if (current_user.vuid != fsp->vuid) {
+ become_user(fsp->conn, fsp->vuid);
+ became_user = True;
+ }
+ set_delete_on_close_lck(lck, True, &current_user.ut);
+ if (became_user) {
+ unbecome_user();
+ }
+ }
+
+ delete_dir = lck->delete_on_close;
if (delete_dir) {
int i;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index c0638c0039..a5a8eacda0 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1761,10 +1761,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
return status;
}
/* Note that here we set the *inital* delete on close flag,
- not the regular one. */
- set_delete_on_close_token(lck, &current_user.ut);
- lck->initial_delete_on_close = True;
- lck->modified = True;
+ not the regular one. The magic gets handled in close. */
+ fsp->initial_delete_on_close = True;
}
/* Files should be initially set as archive */
@@ -2117,9 +2115,9 @@ NTSTATUS open_directory(connection_struct *conn,
}
if (NT_STATUS_IS_OK(status)) {
- set_delete_on_close_token(lck, &current_user.ut);
- lck->initial_delete_on_close = True;
- lck->modified = True;
+ /* Note that here we set the *inital* delete on close flag,
+ not the regular one. The magic gets handled in close. */
+ fsp->initial_delete_on_close = True;
}
}