summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-07-17 18:48:39 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:28:46 -0500
commit14826b0a794fb321cee43df0aadf3a34460dbfcc (patch)
tree06bcbee71c98d03855c295ea0979b686d0b191b6
parent00b27d2d6933e29d9d89652e4f193562bb204f39 (diff)
downloadsamba-14826b0a794fb321cee43df0aadf3a34460dbfcc.tar.gz
samba-14826b0a794fb321cee43df0aadf3a34460dbfcc.tar.bz2
samba-14826b0a794fb321cee43df0aadf3a34460dbfcc.zip
r23935: We were lying to the client in the case of POSIX_UNLINK
if a Windows client had the file open. We were setting delete on close and returning "ok". The POSIX client then believed the file was gone (and it wasn't). Fix this to return SHARING_VIOLATION if there is an existing NTcreateX open on the file and someone calls POSIX_UNLINK. Still one more Cthon test to fix but getting closer now. Should be in 3.0.25c also. Jeremy. (This used to be commit 24e625a615447c025b73fed2d3db03c1f11ae596)
-rw-r--r--source3/smbd/trans2.c67
1 files changed, 51 insertions, 16 deletions
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 080eb36b42..2d7d96e8b3 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5723,7 +5723,10 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
uint16 flags = 0;
+ char del = 1;
int info = 0;
+ int i;
+ struct share_mode_lock *lck = NULL;
if (total_data < 2) {
return NT_STATUS_INVALID_PARAMETER;
@@ -5751,12 +5754,11 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
DELETE_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
- FILE_DELETE_ON_CLOSE,
+ 0,
FILE_FLAG_POSIX_SEMANTICS|0777,
- &info,
+ &info,
&fsp);
} else {
- char del = 1;
status = open_file_ntcreate(conn, req,
fname,
@@ -5769,26 +5771,59 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
0, /* No oplock, but break existing ones. */
&info,
&fsp);
- /*
- * For file opens we must set the delete on close
- * after the open.
- */
+ }
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- status = smb_set_file_disposition_info(conn,
- &del,
- 1,
- fsp,
- fname,
- psbuf);
+ /*
+ * Don't lie to client. If we can't really delete due to
+ * non-POSIX opens return SHARING_VIOLATION.
+ */
+
+ lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+ if (lck == NULL) {
+ DEBUG(0, ("smb_posix_unlink: Could not get share mode "
+ "lock for file %s\n", fsp->fsp_name));
+ close_file(fsp, NORMAL_CLOSE);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /*
+ * See if others still have the file open. If this is the case, then
+ * don't delete. If all opens are POSIX delete we can set the delete
+ * on close disposition.
+ */
+ for (i=0; i<lck->num_share_modes; i++) {
+ struct share_mode_entry *e = &lck->share_modes[i];
+ if (is_valid_share_mode_entry(e)) {
+ if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
+ continue;
+ }
+ /* Fail with sharing violation. */
+ close_file(fsp, NORMAL_CLOSE);
+ TALLOC_FREE(lck);
+ return NT_STATUS_SHARING_VIOLATION;
+ }
}
+ /*
+ * Set the delete on close.
+ */
+ status = smb_set_file_disposition_info(conn,
+ &del,
+ 1,
+ fsp,
+ fname,
+ psbuf);
+
if (!NT_STATUS_IS_OK(status)) {
+ close_file(fsp, NORMAL_CLOSE);
+ TALLOC_FREE(lck);
return status;
}
+ TALLOC_FREE(lck);
return close_file(fsp, NORMAL_CLOSE);
}