r20883: W00t! I now understand how "delete on close" really
authorJeremy Allison <jra@samba.org>
Thu, 18 Jan 2007 21:51:52 +0000 (21:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:17:18 +0000 (12:17 -0500)
works - even with the strange "initial delete on close"
semantics. The "initial delete on close" flag isn't
committed to the share mode db until the handle is
closed, and is discarded if any real "delete on close"
was set. This allows me to remove the "initial_delete_on_close"
flag from the share db, and move it into a BOOL in files_struct.
Warning ! You must do a make clean after this. Cope with
the wrinkle in directory delete on close which is done
differently from files. We now pass all Samba4 smbtortute
BASE-DELETE tests except for the one checking that files
can't be created in a directory which has the delete on
close set (possibly expensive to fix).
Jeremy.
(This used to be commit f2df77a1497958c1ea791f1d2f4446b5fc3389b3)

source3/include/smb.h
source3/libsmb/smb_share_modes.c
source3/locking/locking.c
source3/smbd/close.c
source3/smbd/open.c

index cf754b5c1f91fba153c840406ce7390309556fdb..df4f47f12c061b3717d3255594dff222fe62adbb 100644 (file)
@@ -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. */
index b62240ce508b3dbc9104d820591813e807ef2b27..b8c7a7e66b4bd4466838c669f459e6caebcfbf3f 100644 (file)
@@ -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);
index 111fc98bbe218a03666764135aec296656ed685b..56d18a63efaebc2360726b68b403f5175492b035 100644 (file)
@@ -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;
index fe5e5eccf2c5fa200a14289b6c2e456d78ff3cb4..8958878433cfe6dffdb20ed4c8b6b0f63b762ef2 100644 (file)
@@ -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;
index c0638c0039da814bdd543943c3cb49c32282155d..a5a8eacda00f973af5315c682201110746396bf9 100644 (file)
@@ -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;
                }
        }