From 3d5f3e39e5786612a2aa24ec98264c52907e67f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Oct 2004 08:31:41 +0000 Subject: 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) --- source4/ntvfs/posix/pvfs_open.c | 131 +++++++++++++++++++++++++++------------ source4/ntvfs/posix/pvfs_read.c | 4 ++ source4/ntvfs/posix/pvfs_write.c | 4 ++ source4/ntvfs/posix/vfs_posix.h | 4 ++ 4 files changed, 103 insertions(+), 40 deletions(-) (limited to 'source4/ntvfs/posix') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 482f71b9a3..90de303a9d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -78,30 +78,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NOT_A_DIRECTORY; } - f = talloc_p(req, struct pvfs_file); - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } - - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); - if (fnum == -1) { - talloc_free(f); - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - f->fnum = fnum; - f->fd = -1; - f->name = talloc_steal(f, name); - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; - f->locking_key = data_blob(NULL, 0); - - /* setup a destructor to avoid leaks on abnormal termination */ - talloc_set_destructor(f, pvfs_dir_fd_destructor); - switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_OPEN_IF: break; @@ -125,6 +101,38 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INVALID_PARAMETER; } + f = talloc_p(req, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + f->fnum = fnum; + f->fd = -1; + f->name = talloc_steal(f, name); + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->locking_key = data_blob(NULL, 0); + f->create_options = io->generic.in.create_options; + f->share_access = io->generic.in.share_access; + + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + talloc_free(f); + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + + DLIST_ADD(pvfs->open_files, f); + + /* TODO: should we check in the opendb? Do directory opens + follow the share_access rules? */ + + + /* setup a destructor to avoid leaks on abnormal termination */ + talloc_set_destructor(f, pvfs_dir_fd_destructor); + if (!name->exists) { if (mkdir(name->full_name, 0755) == -1) { return pvfs_map_errno(pvfs,errno); @@ -143,8 +151,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - DLIST_ADD(pvfs->open_files, f); - /* the open succeeded, keep this handle permanently */ talloc_steal(pvfs, f); @@ -174,6 +180,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; + struct odb_lock *lck; + NTSTATUS status; DLIST_REMOVE(f->pvfs->open_files, f); @@ -186,6 +194,18 @@ static int pvfs_fd_destructor(void *p) idr_remove(f->pvfs->idtree_fnum, f->fnum); + lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key); + if (lck == NULL) { + DEBUG(0,("Unabled to lock opendb for close\n")); + return 0; + } + + status = odb_close_file(lck, f->fnum); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unabled to remove opendb entry for '%s' - %s\n", + f->name->full_name, nt_errstr(status))); + } + return 0; } @@ -228,7 +248,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, NTSTATUS status; int flags, fnum, fd; struct odb_lock *lck; - + uint32_t create_options = io->generic.in.create_options; + uint32_t share_access = io->generic.in.share_access; + uint32_t access_mask = io->generic.in.access_mask; + flags = O_RDWR; f = talloc_p(req, struct pvfs_file); @@ -252,6 +275,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); + close(fd); return status; } @@ -260,6 +284,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_locking_key(name, f, &f->locking_key); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); + close(fd); return status; } @@ -271,9 +296,18 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* we were supposed to do a blocking lock, so something is badly wrong! */ idr_remove(pvfs->idtree_fnum, fnum); + close(fd); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + status = odb_open_file(lck, fnum, share_access, create_options, access_mask); + if (!NT_STATUS_IS_OK(status)) { + /* bad news, we must have hit a race */ + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; + } + f->fnum = fnum; f->fd = fd; f->name = talloc_steal(f, name); @@ -282,6 +316,9 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; + f->create_options = io->generic.in.create_options; + f->share_access = io->generic.in.share_access; + f->access_mask = io->generic.in.access_mask; DLIST_ADD(pvfs->open_files, f); @@ -306,10 +343,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* success - keep the file handle */ talloc_steal(pvfs, f); - /* release the opendb lock (in case a chained request - blocks) */ - talloc_free(lck); - return NT_STATUS_OK; } @@ -327,6 +360,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, NTSTATUS status; int fnum; struct odb_lock *lck; + uint32_t create_options; + uint32_t share_access; + uint32_t access_mask; /* use the generic mapping code to avoid implementing all the different open calls. This won't allow openx to work @@ -420,10 +456,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } + /* allocate a fnum */ + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f, &f->locking_key); if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); return status; } @@ -434,9 +477,21 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ + idr_remove(pvfs->idtree_fnum, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + create_options = io->generic.in.create_options; + share_access = io->generic.in.share_access; + access_mask = io->generic.in.access_mask; + + /* see if we are allowed to open at the same time as existing opens */ + status = odb_open_file(lck, fnum, share_access, create_options, access_mask); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + return status; + } + /* do the actual open */ fd = open(name->full_name, flags); if (fd == -1) { @@ -446,15 +501,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { + close(fd); + idr_remove(pvfs->idtree_fnum, fnum); return status; } - /* allocate a fnum */ - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - f->fnum = fnum; f->fd = fd; f->name = talloc_steal(f, name); @@ -463,6 +514,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; + f->create_options = io->generic.in.create_options; + f->share_access = io->generic.in.share_access; + f->access_mask = io->generic.in.access_mask; DLIST_ADD(pvfs->open_files, f); @@ -487,9 +541,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* success - keep the file handle */ talloc_steal(pvfs, f); - /* unlock the locking database */ - talloc_free(lck); - return NT_STATUS_OK; } diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c index 7256fd8e16..530fb82798 100644 --- a/source4/ntvfs/posix/pvfs_read.c +++ b/source4/ntvfs/posix/pvfs_read.c @@ -47,6 +47,10 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs, return NT_STATUS_FILE_IS_A_DIRECTORY; } + if (!(f->access_mask & SA_RIGHT_FILE_READ_DATA)) { + return NT_STATUS_ACCESS_VIOLATION; + } + status = pvfs_check_lock(pvfs, f, req->smbpid, rd->readx.in.offset, rd->readx.in.maxcnt, diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c index 8bbb4f8605..a7b7084a08 100644 --- a/source4/ntvfs/posix/pvfs_write.c +++ b/source4/ntvfs/posix/pvfs_write.c @@ -48,6 +48,10 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, return NT_STATUS_FILE_IS_A_DIRECTORY; } + if (!(f->access_mask & SA_RIGHT_FILE_WRITE_DATA)) { + return NT_STATUS_ACCESS_VIOLATION; + } + status = pvfs_check_lock(pvfs, f, req->smbpid, wr->writex.in.offset, wr->writex.in.count, diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 59924b0b1b..0bd01f5377 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -121,6 +121,10 @@ struct pvfs_file { /* a count of active locks - used to avoid calling brl_close on file close */ uint64_t lock_count; + + uint32_t create_options; + uint32_t share_access; + uint32_t access_mask; }; -- cgit