summaryrefslogtreecommitdiff
path: root/source4/ntvfs/common
diff options
context:
space:
mode:
Diffstat (limited to 'source4/ntvfs/common')
-rw-r--r--source4/ntvfs/common/opendb.c74
1 files changed, 50 insertions, 24 deletions
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<count;i++) {
+ if (share_conflict(elist+i, &e)) {
+ if (dbuf.dptr) free(dbuf.dptr);
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+ }
+
free(dbuf.dptr);
- return True;
+ return NT_STATUS_OK;
}