summaryrefslogtreecommitdiff
path: root/source3/smbd/close.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-05-17 23:15:53 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:17:06 -0500
commitcc9ea93456e594432e203e6d2d2f4dbcaac9a3dd (patch)
tree7bf722a9a742cf7986f31f454bfd17a4a8415ec0 /source3/smbd/close.c
parentc91a675ac108f48046ce72287c6d70a1a54ef65f (diff)
downloadsamba-cc9ea93456e594432e203e6d2d2f4dbcaac9a3dd.tar.gz
samba-cc9ea93456e594432e203e6d2d2f4dbcaac9a3dd.tar.bz2
samba-cc9ea93456e594432e203e6d2d2f4dbcaac9a3dd.zip
r15668: DOS or FCB opens share one share mode entry from different
fsp pointers. Ensure we cope with this to pass Samba4 DENY tests (we used to pass these, there must have been a regression with newer code). We now pass them. Jeremy (This used to be commit fd6fa1d4eaf61783df74ee2da50d331477f06998)
Diffstat (limited to 'source3/smbd/close.c')
-rw-r--r--source3/smbd/close.c138
1 files changed, 73 insertions, 65 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index f2d54445b9..8a63d3b227 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -143,54 +143,15 @@ static void notify_deferred_opens(struct share_mode_lock *lck)
}
/****************************************************************************
- Close a file.
-
- close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
- printing and magic scripts are only run on normal close.
- delete on close is done on normal and shutdown close.
+ Deal with removing a share mode on last close.
****************************************************************************/
-static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
+static int close_remove_share_mode(files_struct *fsp, enum file_close_type close_type)
{
- BOOL delete_file = False;
connection_struct *conn = fsp->conn;
- int saved_errno = 0;
- int err = 0;
- int err1 = 0;
+ BOOL delete_file = False;
struct share_mode_lock *lck;
- remove_pending_lock_requests_by_fid(fsp);
-
- if (fsp->aio_write_behind) {
- /*
- * If we're finishing write behind on a close we can get a write
- * error here, we must remember this.
- */
- int ret = wait_for_aio_completion(fsp);
- if (ret) {
- saved_errno = ret;
- err1 = -1;
- }
- } else {
- cancel_aio_by_fsp(fsp);
- }
-
- /*
- * If we're flushing on a close we can get a write
- * error here, we must remember this.
- */
-
- if (close_filestruct(fsp) == -1) {
- saved_errno = errno;
- err1 = -1;
- }
-
- if (fsp->print_file) {
- print_fsp_end(fsp, close_type);
- file_free(fsp);
- return 0;
- }
-
/*
* Lock the share entries, and determine if we should delete
* on close. If so delete whilst the lock is still in effect.
@@ -200,12 +161,12 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
- DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name));
+ DEBUG(0, ("close_remove_share_mode: Could not get share mode lock for file %s\n", fsp->fsp_name));
return EINVAL;
}
if (!del_share_mode(lck, fsp)) {
- DEBUG(0, ("close_file: Could not delete share entry for file %s\n", fsp->fsp_name));
+ DEBUG(0, ("close_remove_share_mode: Could not delete share entry for file %s\n", fsp->fsp_name));
}
delete_file = (lck->delete_on_close | lck->initial_delete_on_close);
@@ -236,13 +197,13 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
lck->delete_token) {
SMB_STRUCT_STAT sbuf;
- DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n",
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set - deleting file.\n",
fsp->fsp_name));
/* Become the user who requested the delete. */
if (!push_sec_ctx()) {
- smb_panic("close_file: file %s. failed to push sec_ctx.\n");
+ smb_panic("close_remove_share_mode: file %s. failed to push sec_ctx.\n");
}
set_sec_ctx(lck->delete_token->uid,
@@ -253,17 +214,17 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
/* We can only delete the file if the name we have
is still valid and hasn't been renamed. */
-
+
if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) {
- DEBUG(5,("close_file: file %s. Delete on close was set "
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
"and stat failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
} else {
if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) {
- DEBUG(5,("close_file: file %s. Delete on close was set and "
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set and "
"dev and/or inode does not match\n",
fsp->fsp_name ));
- DEBUG(5,("close_file: file %s. stored dev = %x, inode = %.0f "
+ DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, inode = %.0f "
"stat dev = %x, inode = %.0f\n",
fsp->fsp_name,
(unsigned int)fsp->dev, (double)fsp->inode,
@@ -277,21 +238,80 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
* we log this but not at debug level zero.
*/
- DEBUG(5,("close_file: file %s. Delete on close was set "
+ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
"and unlink failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
}
}
/* unbecome user. */
pop_sec_ctx();
-
+
process_pending_change_notify_queue((time_t)0);
}
TALLOC_FREE(lck);
+ return 0;
+}
+
+/****************************************************************************
+ Close a file.
+
+ close_type can be NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE.
+ printing and magic scripts are only run on normal close.
+ delete on close is done on normal and shutdown close.
+****************************************************************************/
+
+static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
+{
+ connection_struct *conn = fsp->conn;
+ int saved_errno = 0;
+ int err = 0;
+ int err1 = 0;
- if(fsp->oplock_type)
+ remove_pending_lock_requests_by_fid(fsp);
+
+ if (fsp->aio_write_behind) {
+ /*
+ * If we're finishing write behind on a close we can get a write
+ * error here, we must remember this.
+ */
+ int ret = wait_for_aio_completion(fsp);
+ if (ret) {
+ saved_errno = ret;
+ err1 = -1;
+ }
+ } else {
+ cancel_aio_by_fsp(fsp);
+ }
+
+ /*
+ * If we're flushing on a close we can get a write
+ * error here, we must remember this.
+ */
+
+ if (close_filestruct(fsp) == -1) {
+ saved_errno = errno;
+ err1 = -1;
+ }
+
+ if (fsp->print_file) {
+ print_fsp_end(fsp, close_type);
+ file_free(fsp);
+ return 0;
+ }
+
+ /* If this is an old DOS or FCB open and we have multiple opens on
+ the same handle we only have one share mode. Ensure we only remove
+ the share mode on the last close. */
+
+ if (fsp->fh->ref_count == 1) {
+ /* Should we return on error here... ? */
+ close_remove_share_mode(fsp, close_type);
+ }
+
+ if(fsp->oplock_type) {
release_file_oplock(fsp);
+ }
locking_close_file(fsp);
@@ -323,9 +343,6 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
conn->num_files_open,
(err == -1 || err1 == -1) ? strerror(saved_errno) : ""));
- if (fsp->fsp_name)
- string_free(&fsp->fsp_name);
-
file_free(fsp);
if (err == -1 || err1 == -1) {
@@ -410,11 +427,6 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
* Do the code common to files and directories.
*/
close_filestruct(fsp);
-
- if (fsp->fsp_name) {
- string_free(&fsp->fsp_name);
- }
-
file_free(fsp);
return 0;
}
@@ -429,10 +441,6 @@ static int close_stat(files_struct *fsp)
* Do the code common to files and directories.
*/
close_filestruct(fsp);
-
- if (fsp->fsp_name)
- string_free(&fsp->fsp_name);
-
file_free(fsp);
return 0;
}