r13274: Fix for bug #3467. Not a show stopper.
authorJeremy Allison <jra@samba.org>
Wed, 1 Feb 2006 04:14:07 +0000 (04:14 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:06:20 +0000 (11:06 -0500)
jason qian <jason@infrant.com> was a *fantastic*
help in tracking this down.
Jeremy.
(This used to be commit 9f4a9c70fa232047868e5d8a3f132a2dd6bfee82)

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

index 315eb3233a8c038064224bc8d0e32baea20ff3f9..ac268ea763ff55366b7e9e1aaa1a036b20c680fb 100644 (file)
@@ -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;
 };
index 43f25cd37872fdeba8f87045ca7c30045209ad98..86071ee2e9190d9edbec3998cf85c61d12a69672 100644 (file)
@@ -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);
 
index e31ead30e4e920419c2fa320401d916f6bd65273..e8309582fd9dff613de1d3415f9448f75bef1036 100644 (file)
@@ -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;
 }
index c0d87b1b212bf373530aa0e7772281dc6975eecb..d284c82f4425ad1bde78d67d9bb36b816e3d6a1d 100644 (file)
@@ -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);
 
index 0ccac592d619bd09e22b5397788426206fd97317..dd2731c897305a79e80583bb3c3914a6b5fcaa5e 100644 (file)
@@ -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;
        }