diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-10-24 08:31:41 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:02:25 -0500 |
commit | 3d5f3e39e5786612a2aa24ec98264c52907e67f2 (patch) | |
tree | 5f68660703faa135b79b025fcae765323ef8acd5 /source4/ntvfs/common | |
parent | c785ca65040d985599bba6736af55240eae894aa (diff) | |
download | samba-3d5f3e39e5786612a2aa24ec98264c52907e67f2.tar.gz samba-3d5f3e39e5786612a2aa24ec98264c52907e67f2.tar.bz2 samba-3d5f3e39e5786612a2aa24ec98264c52907e67f2.zip |
r3147: added basic share modes support for pvfs (or more precisely, ntcreatex
share_access support). This is enough for us to pass the BASE-DENY2
test, but is a long way from fully correct share modes.
(This used to be commit b5a6dd3cbf28a3a3b3a3656042ac8f50fca29e1c)
Diffstat (limited to 'source4/ntvfs/common')
-rw-r--r-- | source4/ntvfs/common/opendb.c | 139 |
1 files changed, 138 insertions, 1 deletions
diff --git a/source4/ntvfs/common/opendb.c b/source4/ntvfs/common/opendb.c index 3b80145414..f074c31f6e 100644 --- a/source4/ntvfs/common/opendb.c +++ b/source4/ntvfs/common/opendb.c @@ -56,8 +56,8 @@ struct odb_entry { uint16_t tid; uint16_t fnum; uint32_t share_access; - uint32_t desired_access; uint32_t create_options; + uint32_t access_mask; }; @@ -144,3 +144,140 @@ 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); + + if ((m1 & m2) != m1) { + return True; + } + + 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); + + if ((m1 & m2) != m1) { + return True; + } + + return False; +} + +/* + register an open file in the open files database. This implements the share_access + rules +*/ +NTSTATUS odb_open_file(struct odb_lock *lck, uint16_t fnum, + uint32_t share_access, uint32_t create_options, + uint32_t access_mask) +{ + struct odb_context *odb = lck->odb; + TDB_DATA dbuf; + struct odb_entry e; + char *tp; + int i, count; + struct odb_entry *elist; + + dbuf = tdb_fetch(odb->w->tdb, lck->key); + + e.server = odb->server; + e.tid = odb->tid; + e.fnum = fnum; + e.share_access = share_access; + e.create_options = create_options; + e.access_mask = access_mask; + + /* check the existing file opens to see if they + conflict */ + elist = (struct odb_entry *)dbuf.dptr; + count = dbuf.dsize / sizeof(struct odb_entry); + + for (i=0;i<count;i++) { + if (share_conflict(elist+i, &e)) { + if (dbuf.dptr) free(dbuf.dptr); + return NT_STATUS_SHARING_VIOLATION; + } + } + + tp = Realloc(dbuf.dptr, (count+1) * sizeof(struct odb_entry)); + if (tp == NULL) { + if (dbuf.dptr) free(dbuf.dptr); + return NT_STATUS_NO_MEMORY; + } + + dbuf.dptr = tp; + dbuf.dsize = (count+1) * sizeof(struct odb_entry); + + memcpy(dbuf.dptr + (count*sizeof(struct odb_entry)), + &e, sizeof(struct odb_entry)); + + if (tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE) != 0) { + free(dbuf.dptr); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + free(dbuf.dptr); + return NT_STATUS_OK; +} + + +/* + remove a opendb entry +*/ +NTSTATUS odb_close_file(struct odb_lock *lck, uint16_t fnum) +{ + struct odb_context *odb = lck->odb; + TDB_DATA dbuf; + struct odb_entry *elist; + int i, count; + NTSTATUS status; + + dbuf = tdb_fetch(odb->w->tdb, lck->key); + + if (dbuf.dptr == NULL) { + return NT_STATUS_UNSUCCESSFUL; + } + + elist = (struct odb_entry *)dbuf.dptr; + count = dbuf.dsize / sizeof(struct odb_entry); + + /* find the entry, and delete it */ + for (i=0;i<count;i++) { + if (fnum == elist[i].fnum && + odb->server == elist[i].server && + odb->tid == elist[i].tid) { + if (i < count-1) { + memmove(elist+i, elist+i+1, count - (i+1)); + } + break; + } + } + + status = NT_STATUS_OK; + + if (i == count) { + status = NT_STATUS_UNSUCCESSFUL; + } else if (count == 1) { + if (tdb_delete(odb->w->tdb, lck->key) != 0) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + } + } else { + dbuf.dsize = (count-1) * sizeof(struct odb_entry); + if (tdb_store(odb->w->tdb, lck->key, dbuf, TDB_REPLACE) != 0) { + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + } + } + + free(dbuf.dptr); + + return status; +} |