r11341: Put directory opens into the share mode db so we
authorJeremy Allison <jra@samba.org>
Thu, 27 Oct 2005 22:35:08 +0000 (22:35 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:05:13 +0000 (11:05 -0500)
can treat them similarly to file opens (delete on
close, share mode violations etc.). This fixes bug
#3216 I will up the default hash size on the locking
db in a later commit as this means more entries.
Jeremy.
(This used to be commit 1134abbbb3fd8e8b88e1a5817aae106476a4c126)

source3/locking/locking.c
source3/smbd/close.c
source3/smbd/open.c

index e3131e26a2a4da688a5aabeae9a8655fe7e767aa..aad254f276cfdee58dfb3149144df0c49da56260 100644 (file)
@@ -960,8 +960,9 @@ BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
                  delete_on_close ? "Adding" : "Removing", fsp->fnum,
                  fsp->fsp_name ));
 
-       if (fsp->is_directory || fsp->is_stat)
+       if (fsp->is_stat) {
                return True;
+       }
 
        lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
        if (lck == NULL) {
index becca003b64df3241a1f37acf86eef2efafc217e..44ab168a3af721d2052f63ff5789eb482dd73d44 100644 (file)
@@ -195,12 +195,12 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
        lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name);
 
        if (lck == NULL) {
-               DEBUG(0, ("Could not get share mode lock\n"));
+               DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name));
                return EINVAL;
        }
 
        if (!del_share_mode(lck, fsp)) {
-               DEBUG(0, ("Could not delete share entry\n"));
+               DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name));
        }
 
        delete_file = lck->delete_on_close;
@@ -297,6 +297,9 @@ with error %s\n", fsp->fsp_name, strerror(errno) ));
   
 static int close_directory(files_struct *fsp, BOOL normal_close)
 {
+       struct share_mode_lock *lck = 0;
+       BOOL delete_dir = False;
+
        remove_pending_change_notify_requests_by_fid(fsp);
 
        /*
@@ -304,8 +307,33 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
         * reference to a directory also.
         */
 
-       if (normal_close &&
-           get_delete_on_close_flag(fsp->dev, fsp->inode, fsp->fsp_name)) {
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name);
+
+       if (lck == NULL) {
+               DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
+               return EINVAL;
+       }
+
+       if (!del_share_mode(lck, fsp)) {
+               DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
+       }
+
+       delete_dir = lck->delete_on_close;
+
+       if (delete_dir) {
+               int i;
+               /* See if others still have the file open. If this is the
+                * case, then don't delete */
+               for (i=0; i<lck->num_share_modes; i++) {
+                       if (is_valid_share_mode_entry(&lck->share_modes[i])) {
+                               delete_dir = False;
+                               break;
+                       }
+               }
+       }
+
+
+       if (normal_close && delete_dir) {
                BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
                DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
                        fsp->fsp_name, ok ? "succeeded" : "failed" ));
@@ -321,6 +349,8 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
                process_pending_change_notify_queue((time_t)0);
        }
 
+       talloc_free(lck);
+
        /*
         * Do the code common to files and directories.
         */
index 70687ff5805c1673d575f89321a5c4400125df22..42e1da839fbde88348a50f09710508ca98b5c61a 100644 (file)
@@ -1536,7 +1536,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                lck = get_share_mode_lock(NULL, dev, inode, fname);
 
                if (lck == NULL) {
-                       DEBUG(0, ("Coult not get share mode lock\n"));
+                       DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
                        fd_close(conn, fsp);
                        file_free(fsp);
                        set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
@@ -1801,6 +1801,8 @@ files_struct *open_directory(connection_struct *conn,
        files_struct *fsp = NULL;
        BOOL dir_existed = VALID_STAT(*psbuf) ? True : False;
        BOOL create_dir = False;
+       struct share_mode_lock *lck = NULL;
+       NTSTATUS status;
        int info = 0;
 
        DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
@@ -1883,7 +1885,7 @@ files_struct *open_directory(connection_struct *conn,
 
                /* We know bad_path is false as it's caught earlier. */
 
-               NTSTATUS status = mkdir_internal(conn, fname, False);
+               status = mkdir_internal(conn, fname, False);
 
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(2,("open_directory: unable to create %s. "
@@ -1938,14 +1940,43 @@ files_struct *open_directory(connection_struct *conn,
        fsp->is_stat = False;
        string_set(&fsp->fsp_name,fname);
 
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fname);
+
+       if (lck == NULL) {
+               DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname));
+               file_free(fsp);
+               set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
+               return NULL;
+       }
+
+       status = open_mode_check(conn, fname, lck,
+                               access_mask, share_access,
+                               create_options, &dir_existed);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               set_saved_ntstatus(status);
+               talloc_free(lck);
+               file_free(fsp);
+               return NULL;
+       }
+
+       set_share_mode(lck, fsp, 0, NO_OPLOCK);
+
        if (create_options & FILE_DELETE_ON_CLOSE) {
-               NTSTATUS status = can_set_delete_on_close(fsp, True, 0);
+               status = can_set_delete_on_close(fsp, True, 0);
                if (!NT_STATUS_IS_OK(status)) {
+                       set_saved_ntstatus(status);
+                       talloc_free(lck);
                        file_free(fsp);
                        return NULL;
                }
+
+               lck->delete_on_close = True;
+               lck->modified = True;
        }
 
+       talloc_free(lck);
+
        /* Change the owner if required. */
        if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) {
                change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf);