summaryrefslogtreecommitdiff
path: root/source3/smbd/open.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-03-30 08:57:24 +0000
committerJeremy Allison <jra@samba.org>2001-03-30 08:57:24 +0000
commit6e7f03f9b920d1b81056959cca8c0b27ada4ee2d (patch)
treebf6426290c5aae2012dc4769158b3495cbbc031f /source3/smbd/open.c
parent9874ebc3d3355465f884f3aad4d69914a4e1f0c5 (diff)
downloadsamba-6e7f03f9b920d1b81056959cca8c0b27ada4ee2d.tar.gz
samba-6e7f03f9b920d1b81056959cca8c0b27ada4ee2d.tar.bz2
samba-6e7f03f9b920d1b81056959cca8c0b27ada4ee2d.zip
This is a big, rather ugly patch. Whilst investigating the files not truncated
when copying to a full disk problem, I discovered that we were not allowing the delete on close flag to be set properly, this led to other things, and after investigation of the proper delete on close semantics and their relationship to the file_share_delete flag I discovered there were some cases where we weren't doing the deny modes properly. And this after only 5 years working on them..... :-) :-). So here's the latest attempt. I realised the delete on close flag needs to be set across all smbds with a dev/ino pair open - in addition, the delete on close flag, allow share delete and delete access requested all need to be stored in the share mode tdb. The "delete_on_close" entry in the fsp struct is now redundant and should really be removed. This may also mean we can get rid of the "iterate_fsp" calls that I didn't like adding in the first place. Whilst doing this patch, I also discovered we needed to do the se_map_generic() call for file opens and POSIX ACL mapping, so I added that also. This code, although ugly, now passes the deny mode torture tests plus the delete on close tests I added. I do need to add one more multiple connection delete on close test to make sure I got the semantics exactly right, plus we should also (as Andrew suggested) move to random testing here. The good news is that NT should now correctly delete the file on disk full error when copying to a disk :-). Jeremy. (This used to be commit 51987684bd231c744da2e5f3705fd236d5616173)
Diffstat (limited to 'source3/smbd/open.c')
-rw-r--r--source3/smbd/open.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index c601121459..5f8657262a 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -341,18 +341,19 @@ static int access_table(int new_deny,int old_deny,int old_mode,
check if we can open a file with a share mode
****************************************************************************/
-static int check_share_mode( share_mode_entry *share, int deny_mode,
+static int check_share_mode( share_mode_entry *share, int share_mode,
const char *fname, BOOL fcbopen, int *flags)
{
+ int deny_mode = GET_DENY_MODE(share_mode);
int old_open_mode = GET_OPEN_MODE(share->share_mode);
int old_deny_mode = GET_DENY_MODE(share->share_mode);
/*
- * Don't allow any open once the delete on close flag has been
+ * Don't allow any opens once the delete on close flag has been
* set.
*/
- if(GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) {
+ if (GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) {
DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
fname ));
unix_ERR_class = ERRDOS;
@@ -360,6 +361,35 @@ static int check_share_mode( share_mode_entry *share, int deny_mode,
return False;
}
+ /*
+ * If delete access was requested and the existing share mode doesn't have
+ * ALLOW_SHARE_DELETE then deny.
+ */
+
+ if (GET_DELETE_ACCESS_REQUESTED(share_mode) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) {
+ DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n",
+ fname ));
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadshare;
+
+ return False;
+ }
+
+ /*
+ * The inverse of the above.
+ * If delete access was granted and the new share mode doesn't have
+ * ALLOW_SHARE_DELETE then deny.
+ */
+
+ if (GET_DELETE_ACCESS_REQUESTED(share->share_mode) && !GET_ALLOW_SHARE_DELETE(share_mode)) {
+ DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n",
+ fname ));
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadshare;
+
+ return False;
+ }
+
{
int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
(share->pid == sys_getpid()),is_executable(fname));
@@ -405,7 +435,6 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T
int oplock_contention_count = 0;
share_mode_entry *old_shares = 0;
BOOL fcbopen = False;
- int deny_mode = GET_DENY_MODE(share_mode);
BOOL broke_oplock;
if(GET_OPEN_MODE(share_mode) == DOS_OPEN_FCB)
@@ -473,7 +502,7 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou
/* someone else has a share lock on it, check to see
if we can too */
- if(check_share_mode(share_entry, deny_mode, fname, fcbopen, p_flags) == False) {
+ if(check_share_mode(share_entry, share_mode, fname, fcbopen, p_flags) == False) {
free((char *)old_shares);
errno = EACCES;
return -1;
@@ -532,6 +561,7 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
int flags2=0;
int deny_mode = GET_DENY_MODE(share_mode);
BOOL allow_share_delete = GET_ALLOW_SHARE_DELETE(share_mode);
+ BOOL delete_access_requested = GET_DELETE_ACCESS_REQUESTED(share_mode);
BOOL file_existed = VALID_STAT(*psbuf);
BOOL fcbopen = False;
SMB_DEV_T dev = 0;
@@ -768,7 +798,10 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
fsp->share_mode = SET_DENY_MODE(deny_mode) |
SET_OPEN_MODE(open_mode) |
- SET_ALLOW_SHARE_DELETE(allow_share_delete);
+ SET_ALLOW_SHARE_DELETE(allow_share_delete) |
+ SET_DELETE_ACCESS_REQUESTED(delete_access_requested);
+
+ DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode ));
if (Access)
(*Access) = open_mode;