diff options
author | Jeremy Allison <jra@samba.org> | 2001-03-30 08:57:24 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2001-03-30 08:57:24 +0000 |
commit | 6e7f03f9b920d1b81056959cca8c0b27ada4ee2d (patch) | |
tree | bf6426290c5aae2012dc4769158b3495cbbc031f /source3/smbd/close.c | |
parent | 9874ebc3d3355465f884f3aad4d69914a4e1f0c5 (diff) | |
download | samba-6e7f03f9b920d1b81056959cca8c0b27ada4ee2d.tar.gz samba-6e7f03f9b920d1b81056959cca8c0b27ada4ee2d.tar.xz 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/close.c')
-rw-r--r-- | source3/smbd/close.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 56aad643914..c290ee6f894 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -99,7 +99,9 @@ static int close_filestruct(files_struct *fsp) static int close_normal_file(files_struct *fsp, BOOL normal_close) { - BOOL delete_on_close = fsp->delete_on_close; + share_mode_entry *share_entry = NULL; + size_t share_entry_count = 0; + BOOL delete_on_close = False; connection_struct *conn = fsp->conn; int err = 0; int err1 = 0; @@ -120,21 +122,25 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) return 0; } - lock_share_entry_fsp(fsp); - del_share_mode(fsp); - unlock_share_entry_fsp(fsp); + /* + * Lock the share entries, and determine if we should delete + * on close. If so delete whilst the lock is still in effect. + * This prevents race conditions with the file being created. JRA. + */ - if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - release_file_oplock(fsp); + lock_share_entry_fsp(fsp); + share_entry_count = del_share_mode(fsp, &share_entry); - locking_close_file(fsp); + /* + * We delete on close if it's the last open, and the + * delete on close flag was set in the entry we just deleted. + */ - err = fd_close(conn, fsp); + if ((share_entry_count == 0) && share_entry && + GET_DELETE_ON_CLOSE_FLAG(share_entry->share_mode) ) + delete_on_close = True; - /* check for magic scripts */ - if (normal_close) { - check_magic(fsp,conn); - } + safe_free(share_entry); /* * NT can set delete_on_close of the last open @@ -157,6 +163,21 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); } } + unlock_share_entry_fsp(fsp); + + if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + release_file_oplock(fsp); + + locking_close_file(fsp); + + err = fd_close(conn, fsp); + + /* check for magic scripts */ + if (normal_close) { + check_magic(fsp,conn); + } + + DEBUG(2,("%s closed file %s (numopen=%d) %s\n", conn->user,fsp->fsp_name, conn->num_files_open, err ? strerror(err) : "")); |