summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2005-10-27 22:35:08 +0000
committerJeremy Allison <jra@samba.org>2005-10-27 22:35:08 +0000
commit5aeb69924b303177bd4edc820f9ec8f71a2b8daa (patch)
tree77bd7094ed02e62fced3251904b97de6e3205a44 /source
parent2c8ac0d737db890177e28a082f419cd7db2cc1ef (diff)
downloadsamba-5aeb69924b303177bd4edc820f9ec8f71a2b8daa.tar.gz
samba-5aeb69924b303177bd4edc820f9ec8f71a2b8daa.tar.xz
samba-5aeb69924b303177bd4edc820f9ec8f71a2b8daa.zip
r11341: Put directory opens into the share mode db so we
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.
Diffstat (limited to 'source')
-rw-r--r--source/locking/locking.c3
-rw-r--r--source/smbd/close.c38
-rw-r--r--source/smbd/open.c37
3 files changed, 70 insertions, 8 deletions
diff --git a/source/locking/locking.c b/source/locking/locking.c
index e3131e26a2a..aad254f276c 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -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) {
diff --git a/source/smbd/close.c b/source/smbd/close.c
index becca003b64..44ab168a3af 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -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.
*/
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 70687ff5805..42e1da839fb 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -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);