From 5c95896499dd6f72c8fc9be84b0da880571731da Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 04:24:58 +0000 Subject: r3189: improved the share_conflict() logic (both in terms of readability and correctness). pvfs now passes the BASE-RENAME test. (This used to be commit 4cf3f65a5c19fdad62a0bdef225b2d9002cf8c8b) --- source4/ntvfs/common/opendb.c | 74 +++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 24 deletions(-) (limited to 'source4/ntvfs/common/opendb.c') diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c index 5c962fbad0..a3924daf8e 100644 --- a/source4/ntvfs/common/opendb.c +++ b/source4/ntvfs/common/opendb.c @@ -145,41 +145,38 @@ struct odb_lock *odb_lock(TALLOC_CTX *mem_ctx, return lck; } - /* determine if two odb_entry structures conflict */ static BOOL share_conflict(struct odb_entry *e1, struct odb_entry *e2) { - uint32_t m1, m2; - - m1 = e1->access_mask & (SA_RIGHT_FILE_WRITE_DATA | SA_RIGHT_FILE_READ_DATA); - m2 = e2->share_access & - (NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_READ); +#define CHECK_MASK(am, sa, right, share) if (((am) & (right)) && !((sa) & (share))) return True - if ((m1 & m2) != m1) { - return True; + /* if either open involves no read.write or delete access then + it can't conflict */ + if (!(e1->access_mask & (SA_RIGHT_FILE_WRITE_DATA | SA_RIGHT_FILE_READ_DATA | STD_RIGHT_DELETE_ACCESS))) { + return False; + } + if (!(e2->access_mask & (SA_RIGHT_FILE_WRITE_DATA | SA_RIGHT_FILE_READ_DATA | STD_RIGHT_DELETE_ACCESS))) { + return False; } - m1 = e2->access_mask & (SA_RIGHT_FILE_WRITE_DATA | SA_RIGHT_FILE_READ_DATA); - m2 = e1->share_access & - (NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_READ); + /* check the basic share access */ + CHECK_MASK(e1->access_mask, e2->share_access, SA_RIGHT_FILE_WRITE_DATA, NTCREATEX_SHARE_ACCESS_WRITE); + CHECK_MASK(e2->access_mask, e1->share_access, SA_RIGHT_FILE_WRITE_DATA, NTCREATEX_SHARE_ACCESS_WRITE); - if ((m1 & m2) != m1) { - return True; - } + CHECK_MASK(e1->access_mask, e2->share_access, SA_RIGHT_FILE_READ_DATA, NTCREATEX_SHARE_ACCESS_READ); + CHECK_MASK(e2->access_mask, e1->share_access, SA_RIGHT_FILE_READ_DATA, NTCREATEX_SHARE_ACCESS_READ); + CHECK_MASK(e1->access_mask, e2->share_access, STD_RIGHT_DELETE_ACCESS, NTCREATEX_SHARE_ACCESS_DELETE); + CHECK_MASK(e2->access_mask, e1->share_access, STD_RIGHT_DELETE_ACCESS, NTCREATEX_SHARE_ACCESS_DELETE); + + /* if a delete is pending then a second open is not allowed */ if ((e1->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) || (e2->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return True; } - if ((e1->access_mask & STD_RIGHT_DELETE_ACCESS) && - !(e2->share_access & NTCREATEX_SHARE_ACCESS_DELETE)) { - return True; - } - - return False; } @@ -338,20 +335,49 @@ NTSTATUS odb_set_create_options(struct odb_lock *lck, /* - determine if a file is open + determine if a file can be opened with the given share_access, + create_options and access_mask */ -BOOL odb_is_open(struct odb_context *odb, DATA_BLOB *key) +NTSTATUS odb_can_open(struct odb_context *odb, DATA_BLOB *key, + uint32_t share_access, uint32_t create_options, + uint32_t access_mask) { TDB_DATA dbuf; TDB_DATA kbuf; + struct odb_entry *elist; + int i, count; + struct odb_entry e; kbuf.dptr = key->data; kbuf.dsize = key->length; dbuf = tdb_fetch(odb->w->tdb, kbuf); if (dbuf.dptr == NULL) { - return False; + return NT_STATUS_OK; } + + elist = (struct odb_entry *)dbuf.dptr; + count = dbuf.dsize / sizeof(struct odb_entry); + + if (count == 0) { + free(dbuf.dptr); + return NT_STATUS_OK; + } + + e.server = odb->server; + e.tid = odb->tid; + e.fnum = -1; + e.share_access = share_access; + e.create_options = create_options; + e.access_mask = access_mask; + + for (i=0;i