summaryrefslogtreecommitdiff
path: root/source4/ntvfs/common
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-10-24 08:31:41 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:02:25 -0500
commit3d5f3e39e5786612a2aa24ec98264c52907e67f2 (patch)
tree5f68660703faa135b79b025fcae765323ef8acd5 /source4/ntvfs/common
parentc785ca65040d985599bba6736af55240eae894aa (diff)
downloadsamba-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.c139
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;
+}