summaryrefslogtreecommitdiff
path: root/source3/locking
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/locking
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/locking')
-rw-r--r--source3/locking/locking.c71
1 files changed, 39 insertions, 32 deletions
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 118d59cc10..5824287e91 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -331,19 +331,24 @@ int get_share_modes(connection_struct *conn,
}
/*******************************************************************
- Del the share mode of a file for this process
+ Del the share mode of a file for this process. Return the number
+ of entries left, and a memdup'ed copy of the entry deleted.
********************************************************************/
-void del_share_mode(files_struct *fsp)
+
+size_t del_share_mode(files_struct *fsp, share_mode_entry **ppse)
{
TDB_DATA dbuf;
struct locking_data *data;
int i, del_count=0;
share_mode_entry *shares;
pid_t pid = sys_getpid();
+ size_t count;
+
+ *ppse = NULL;
/* read in the existing share modes */
dbuf = tdb_fetch(tdb, locking_key_fsp(fsp));
- if (!dbuf.dptr) return;
+ if (!dbuf.dptr) return 0;
data = (struct locking_data *)dbuf.dptr;
shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
@@ -354,6 +359,7 @@ void del_share_mode(files_struct *fsp)
if (shares[i].pid == pid &&
memcmp(&shares[i].time,
&fsp->open_time,sizeof(struct timeval)) == 0) {
+ *ppse = memdup(&shares[i], sizeof(*shares));
data->num_share_mode_entries--;
memmove(&shares[i], &shares[i+1],
dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
@@ -366,6 +372,8 @@ void del_share_mode(files_struct *fsp)
/* the record has shrunk a bit */
dbuf.dsize -= del_count * sizeof(*shares);
+ count = data->num_share_mode_entries;
+
/* store it back in the database */
if (data->num_share_mode_entries == 0) {
tdb_delete(tdb, locking_key_fsp(fsp));
@@ -374,6 +382,7 @@ void del_share_mode(files_struct *fsp)
}
free(dbuf.dptr);
+ return count;
}
/*******************************************************************
@@ -529,42 +538,40 @@ BOOL downgrade_share_oplock(files_struct *fsp)
return mod_share_mode(fsp, downgrade_share_oplock_fn, NULL);
}
-
/*******************************************************************
- Static function that actually does the work for the generic function
- below.
+ Get/Set the delete on close flag in a set of share modes.
+ Return False on fail, True on success.
********************************************************************/
-struct mod_val {
- int new_share_mode;
- uint16 new_oplock;
-};
-static void modify_share_mode_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode,
- void *param)
+BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
{
- struct mod_val *mvp = (struct mod_val *)param;
-
- DEBUG(10,("modify_share_mode_fn: changing share mode info from %x to %x for entry dev=%x ino=%.0f\n",
- entry->share_mode, mvp->new_share_mode, (unsigned int)dev, (double)inode ));
- DEBUG(10,("modify_share_mode_fn: changing oplock state from %x to %x for entry dev=%x ino=%.0f\n",
- entry->op_type, (int)mvp->new_oplock, (unsigned int)dev, (double)inode ));
- /* Change the share mode info. */
- entry->share_mode = mvp->new_share_mode;
- entry->op_type = mvp->new_oplock;
-}
+ TDB_DATA dbuf;
+ struct locking_data *data;
+ int i;
+ share_mode_entry *shares;
-/*******************************************************************
- Modify a share mode on a file. Used by the delete open file code.
- Return False on fail, True on success.
-********************************************************************/
-BOOL modify_share_mode(files_struct *fsp, int new_mode, uint16 new_oplock)
-{
- struct mod_val mv;
+ /* read in the existing share modes */
+ dbuf = tdb_fetch(tdb, locking_key(dev, inode));
+ if (!dbuf.dptr) return False;
+
+ data = (struct locking_data *)dbuf.dptr;
+ shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
- mv.new_share_mode = new_mode;
- mv.new_oplock = new_oplock;
+ /* Set/Unset the delete on close element. */
+ for (i=0;i<data->num_share_mode_entries;i++,shares++) {
+ shares->share_mode = (delete_on_close ?
+ (shares->share_mode | DELETE_ON_CLOSE_FLAG) :
+ (shares->share_mode & ~DELETE_ON_CLOSE_FLAG) );
+ }
- return mod_share_mode(fsp, modify_share_mode_fn, (void *)&mv);
+ /* store it back */
+ if (data->num_share_mode_entries) {
+ if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1)
+ return False;
+ }
+
+ free(dbuf.dptr);
+ return True;
}