diff options
Diffstat (limited to 'source4/ntvfs')
23 files changed, 538 insertions, 304 deletions
diff --git a/source4/ntvfs/cifs/vfs_cifs.c b/source4/ntvfs/cifs/vfs_cifs.c index e12fd3de2f..c669414e09 100644 --- a/source4/ntvfs/cifs/vfs_cifs.c +++ b/source4/ntvfs/cifs/vfs_cifs.c @@ -32,12 +32,19 @@ #include "ntvfs/ntvfs.h" #include "include/dlinklist.h" +struct cvfs_file { + struct cvfs_file *prev, *next; + uint16_t fnum; + struct ntvfs_handle *h; +}; + /* this is stored in ntvfs_private */ struct cvfs_private { struct smbcli_tree *tree; struct smbcli_transport *transport; struct ntvfs_module_context *ntvfs; struct async_info *pending; + struct cvfs_file *files; BOOL map_generic; BOOL map_trans2; }; @@ -49,11 +56,24 @@ struct async_info { struct cvfs_private *cvfs; struct ntvfs_request *req; struct smbcli_request *c_req; + struct cvfs_file *f; void *parms; }; #define SETUP_PID private->tree->session->pid = req->smbpid +#define SETUP_FILE do { \ + struct cvfs_file *f; \ + f = ntvfs_handle_get_backend_data(io->generic.in.file.ntvfs, ntvfs); \ + if (!f) return NT_STATUS_INVALID_HANDLE; \ + io->generic.in.file.fnum = f->fnum; \ +} while (0) + +#define SETUP_PID_AND_FILE do { \ + SETUP_PID; \ + SETUP_FILE; \ +} while (0) + /* a handler for oplock break events from the server - these need to be passed along to the client @@ -62,9 +82,22 @@ static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, uin { struct cvfs_private *private = p_private; NTSTATUS status; + struct ntvfs_handle *h = NULL; + struct cvfs_file *f; + + for (f=private->files; f; f=f->next) { + if (f->fnum != fnum) continue; + h = f->h; + break; + } + + if (!h) { + DEBUG(5,("vfs_cifs: ignoring oplock break level %d for fnum %d\n", level, fnum)); + return True; + } DEBUG(5,("vfs_cifs: sending oplock break level %d for fnum %d\n", level, fnum)); - status = ntvfs_send_oplock_break(private->ntvfs, fnum, level); + status = ntvfs_send_oplock_break(private->ntvfs, h, level); if (!NT_STATUS_IS_OK(status)) return False; return True; } @@ -227,7 +260,7 @@ static void async_simple(struct smbcli_request *c_req) /* save some typing for the simple functions */ -#define ASYNC_RECV_TAIL(io, async_fn) do { \ +#define ASYNC_RECV_TAIL_F(io, async_fn, file) do { \ if (!c_req) return NT_STATUS_UNSUCCESSFUL; \ { \ struct async_info *async; \ @@ -235,6 +268,7 @@ static void async_simple(struct smbcli_request *c_req) if (!async) return NT_STATUS_NO_MEMORY; \ async->parms = io; \ async->req = req; \ + async->f = file; \ async->cvfs = private; \ async->c_req = c_req; \ DLIST_ADD(private->pending, async); \ @@ -246,6 +280,8 @@ static void async_simple(struct smbcli_request *c_req) return NT_STATUS_OK; \ } while (0) +#define ASYNC_RECV_TAIL(io, async_fn) ASYNC_RECV_TAIL_F(io, async_fn, NULL) + #define SIMPLE_ASYNC_TAIL ASYNC_RECV_TAIL(NULL, async_simple) /* @@ -287,12 +323,12 @@ static void async_ioctl(struct smbcli_request *c_req) ioctl interface */ static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_ioctl *io) + struct ntvfs_request *req, union smb_ioctl *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; /* see if the front end will allow us to perform this function asynchronously. */ @@ -309,7 +345,7 @@ static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs, check if a directory exists */ static NTSTATUS cvfs_chkpath(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_chkpath *cp) + struct ntvfs_request *req, union smb_chkpath *cp) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -341,7 +377,7 @@ static void async_qpathinfo(struct smbcli_request *c_req) return info on a pathname */ static NTSTATUS cvfs_qpathinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_fileinfo *info) + struct ntvfs_request *req, union smb_fileinfo *info) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -373,20 +409,20 @@ static void async_qfileinfo(struct smbcli_request *c_req) query info on a open file */ static NTSTATUS cvfs_qfileinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_fileinfo *info) + struct ntvfs_request *req, union smb_fileinfo *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_fileinfo(private->tree, req, info); + return smb_raw_fileinfo(private->tree, req, io); } - c_req = smb_raw_fileinfo_send(private->tree, info); + c_req = smb_raw_fileinfo_send(private->tree, io); - ASYNC_RECV_TAIL(info, async_qfileinfo); + ASYNC_RECV_TAIL(io, async_qfileinfo); } @@ -394,7 +430,7 @@ static NTSTATUS cvfs_qfileinfo(struct ntvfs_module_context *ntvfs, set info on a pathname */ static NTSTATUS cvfs_setpathinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_setfileinfo *st) + struct ntvfs_request *req, union smb_setfileinfo *st) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -417,9 +453,21 @@ static NTSTATUS cvfs_setpathinfo(struct ntvfs_module_context *ntvfs, static void async_open(struct smbcli_request *c_req) { struct async_info *async = c_req->async.private; + struct cvfs_private *cvfs = async->cvfs; struct ntvfs_request *req = async->req; - req->async_states->status = smb_raw_open_recv(c_req, req, async->parms); + struct cvfs_file *f = async->f; + union smb_open *io = async->parms; + union smb_handle *file; talloc_free(async); + req->async_states->status = smb_raw_open_recv(c_req, req, io); + SMB_OPEN_OUT_FILE(io, file); + f->fnum = file->fnum; + file->ntvfs = NULL; + if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed; + req->async_states->status = ntvfs_handle_set_backend_data(f->h, cvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed; + file->ntvfs = f->h; +failed: req->async_states->send_fn(req); } @@ -427,10 +475,13 @@ static void async_open(struct smbcli_request *c_req) open a file */ static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_open *io) + struct ntvfs_request *req, union smb_open *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; + struct ntvfs_handle *h; + struct cvfs_file *f; + NTSTATUS status; SETUP_PID; @@ -439,20 +490,39 @@ static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs, return ntvfs_map_open(ntvfs, req, io); } + status = ntvfs_handle_new(ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc_zero(h, struct cvfs_file); + NT_STATUS_HAVE_NO_MEMORY(f); + f->h = h; + if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_open(private->tree, req, io); + union smb_handle *file; + + status = smb_raw_open(private->tree, req, io); + NT_STATUS_NOT_OK_RETURN(status); + + SMB_OPEN_OUT_FILE(io, file); + f->fnum = file->fnum; + file->ntvfs = NULL; + status = ntvfs_handle_set_backend_data(f->h, private->ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); + file->ntvfs = f->h; + + return NT_STATUS_OK; } c_req = smb_raw_open_send(private->tree, io); - ASYNC_RECV_TAIL(io, async_open); + ASYNC_RECV_TAIL_F(io, async_open, f); } /* create a directory */ static NTSTATUS cvfs_mkdir(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_mkdir *md) + struct ntvfs_request *req, union smb_mkdir *md) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -472,7 +542,7 @@ static NTSTATUS cvfs_mkdir(struct ntvfs_module_context *ntvfs, remove a directory */ static NTSTATUS cvfs_rmdir(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, struct smb_rmdir *rd) + struct ntvfs_request *req, struct smb_rmdir *rd) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -491,7 +561,7 @@ static NTSTATUS cvfs_rmdir(struct ntvfs_module_context *ntvfs, rename a set of files */ static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_rename *ren) + struct ntvfs_request *req, union smb_rename *ren) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -511,7 +581,7 @@ static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs, copy a set of files */ static NTSTATUS cvfs_copy(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, struct smb_copy *cp) + struct ntvfs_request *req, struct smb_copy *cp) { return NT_STATUS_NOT_SUPPORTED; } @@ -532,25 +602,27 @@ static void async_read(struct smbcli_request *c_req) read from a file */ static NTSTATUS cvfs_read(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_read *rd) + struct ntvfs_request *req, union smb_read *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; SETUP_PID; - if (rd->generic.level != RAW_READ_GENERIC && + if (io->generic.level != RAW_READ_GENERIC && private->map_generic) { - return ntvfs_map_read(ntvfs, req, rd); + return ntvfs_map_read(ntvfs, req, io); } + SETUP_FILE; + if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_read(private->tree, rd); + return smb_raw_read(private->tree, io); } - c_req = smb_raw_read_send(private->tree, rd); + c_req = smb_raw_read_send(private->tree, io); - ASYNC_RECV_TAIL(rd, async_read); + ASYNC_RECV_TAIL(io, async_read); } /* @@ -569,25 +641,26 @@ static void async_write(struct smbcli_request *c_req) write to a file */ static NTSTATUS cvfs_write(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_write *wr) + struct ntvfs_request *req, union smb_write *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; SETUP_PID; - if (wr->generic.level != RAW_WRITE_GENERIC && + if (io->generic.level != RAW_WRITE_GENERIC && private->map_generic) { - return ntvfs_map_write(ntvfs, req, wr); + return ntvfs_map_write(ntvfs, req, io); } + SETUP_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_write(private->tree, wr); + return smb_raw_write(private->tree, io); } - c_req = smb_raw_write_send(private->tree, wr); + c_req = smb_raw_write_send(private->tree, io); - ASYNC_RECV_TAIL(wr, async_write); + ASYNC_RECV_TAIL(io, async_write); } /* @@ -612,7 +685,7 @@ static NTSTATUS cvfs_seek(struct ntvfs_module_context *ntvfs, struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_seek(private->tree, io); @@ -634,6 +707,14 @@ static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs, struct smbcli_request *c_req; SETUP_PID; + switch (io->generic.level) { + case RAW_FLUSH_FLUSH: + SETUP_FILE; + break; + case RAW_FLUSH_ALL: + io->generic.in.file.fnum = 0xFFFF; + break; + } if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_flush(private->tree, io); @@ -648,7 +729,7 @@ static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs, close a file */ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_close *io) + struct ntvfs_request *req, union smb_close *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -659,6 +740,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, private->map_generic) { return ntvfs_map_close(ntvfs, req, io); } + SETUP_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return smb_raw_close(private->tree, io); @@ -673,7 +755,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, exit - closing files open by the pid */ static NTSTATUS cvfs_exit(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req) + struct ntvfs_request *req) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -693,7 +775,7 @@ static NTSTATUS cvfs_exit(struct ntvfs_module_context *ntvfs, logoff - closing files open by the user */ static NTSTATUS cvfs_logoff(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req) + struct ntvfs_request *req) { /* we can't do this right in the cifs backend .... */ return NT_STATUS_OK; @@ -736,23 +818,24 @@ static NTSTATUS cvfs_cancel(struct ntvfs_module_context *ntvfs, lock a byte range */ static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_lock *lck) + struct ntvfs_request *req, union smb_lock *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; SETUP_PID; - if (lck->generic.level != RAW_LOCK_GENERIC && + if (io->generic.level != RAW_LOCK_GENERIC && private->map_generic) { - return ntvfs_map_lock(ntvfs, req, lck); + return ntvfs_map_lock(ntvfs, req, io); } + SETUP_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_lock(private->tree, lck); + return smb_raw_lock(private->tree, io); } - c_req = smb_raw_lock_send(private->tree, lck); + c_req = smb_raw_lock_send(private->tree, io); SIMPLE_ASYNC_TAIL; } @@ -761,17 +844,17 @@ static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs, */ static NTSTATUS cvfs_setfileinfo(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, - union smb_setfileinfo *info) + union smb_setfileinfo *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; - SETUP_PID; + SETUP_PID_AND_FILE; if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return smb_raw_setfileinfo(private->tree, info); + return smb_raw_setfileinfo(private->tree, io); } - c_req = smb_raw_setfileinfo_send(private->tree, info); + c_req = smb_raw_setfileinfo_send(private->tree, io); SIMPLE_ASYNC_TAIL; } @@ -793,7 +876,7 @@ static void async_fsinfo(struct smbcli_request *c_req) return filesystem space info */ static NTSTATUS cvfs_fsinfo(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_fsinfo *fs) + struct ntvfs_request *req, union smb_fsinfo *fs) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; @@ -813,7 +896,7 @@ static NTSTATUS cvfs_fsinfo(struct ntvfs_module_context *ntvfs, return print queue info */ static NTSTATUS cvfs_lpq(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, union smb_lpq *lpq) + struct ntvfs_request *req, union smb_lpq *lpq) { return NT_STATUS_NOT_SUPPORTED; } @@ -916,14 +999,19 @@ static void async_changenotify(struct smbcli_request *c_req) /* change notify request - always async */ static NTSTATUS cvfs_notify(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, - struct smb_notify *info) + struct smb_notify *io) { struct cvfs_private *private = ntvfs->private_data; struct smbcli_request *c_req; int saved_timeout = private->transport->options.request_timeout; + struct cvfs_file *f; SETUP_PID; + f = ntvfs_handle_get_backend_data(io->in.file.ntvfs, ntvfs); + if (!f) return NT_STATUS_INVALID_HANDLE; + io->in.file.fnum = f->fnum; + /* this request doesn't make sense unless its async */ if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { return NT_STATUS_INVALID_PARAMETER; @@ -933,11 +1021,11 @@ static NTSTATUS cvfs_notify(struct ntvfs_module_context *ntvfs, forever */ private->transport->options.request_timeout = 0; - c_req = smb_raw_changenotify_send(private->tree, info); + c_req = smb_raw_changenotify_send(private->tree, io); private->transport->options.request_timeout = saved_timeout; - ASYNC_RECV_TAIL(info, async_changenotify); + ASYNC_RECV_TAIL(io, async_changenotify); } /* diff --git a/source4/ntvfs/cifs_posix_cli/vfs_simple.c b/source4/ntvfs/cifs_posix_cli/vfs_simple.c index bbe52d9db1..cf28a02806 100644 --- a/source4/ntvfs/cifs_posix_cli/vfs_simple.c +++ b/source4/ntvfs/cifs_posix_cli/vfs_simple.c @@ -19,6 +19,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* this module needs to be converted to use ntvfs_handle's! */ +#define fnum _XXX_use_ntvfs_handle_not_fnum_XXX_ + /* this implements a very simple NTVFS filesystem backend. diff --git a/source4/ntvfs/common/brlock.c b/source4/ntvfs/common/brlock.c index b5df434435..2816c563b8 100644 --- a/source4/ntvfs/common/brlock.c +++ b/source4/ntvfs/common/brlock.c @@ -57,7 +57,7 @@ struct lock_context { size of the record */ struct lock_struct { struct lock_context context; - uint16_t fnum; + struct ntvfs_handle *ntvfs; uint64_t start; uint64_t size; enum brl_type lock_type; @@ -67,7 +67,7 @@ struct lock_struct { /* this struct is attached to on oprn file handle */ struct brl_handle { DATA_BLOB key; - uint16_t fnum; + struct ntvfs_handle *ntvfs; struct lock_struct last_lock; }; @@ -109,7 +109,7 @@ struct brl_context *brl_init(TALLOC_CTX *mem_ctx, uint32_t server, return brl; } -struct brl_handle *brl_create_handle(TALLOC_CTX *mem_ctx, DATA_BLOB *file_key, uint16_t fnum) +struct brl_handle *brl_create_handle(TALLOC_CTX *mem_ctx, struct ntvfs_handle *ntvfs, DATA_BLOB *file_key) { struct brl_handle *brlh; @@ -119,7 +119,7 @@ struct brl_handle *brl_create_handle(TALLOC_CTX *mem_ctx, DATA_BLOB *file_key, u } brlh->key = *file_key; - brlh->fnum = fnum; + brlh->ntvfs = ntvfs; ZERO_STRUCT(brlh->last_lock); return brlh; @@ -173,7 +173,7 @@ static BOOL brl_conflict(struct lock_struct *lck1, } if (brl_same_context(&lck1->context, &lck2->context) && - lck2->lock_type == READ_LOCK && lck1->fnum == lck2->fnum) { + lck2->lock_type == READ_LOCK && lck1->ntvfs == lck2->ntvfs) { return False; } @@ -202,7 +202,7 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck * in smbtorture. */ if (brl_same_context(&lck1->context, &lck2->context) && - lck1->fnum == lck2->fnum && + lck1->ntvfs == lck2->ntvfs && (lck2->lock_type == READ_LOCK || lck1->lock_type == WRITE_LOCK)) { return False; } @@ -251,7 +251,7 @@ static NTSTATUS brl_lock_failed(struct brl_handle *brlh, struct lock_struct *loc */ if (lock->context.server == brlh->last_lock.context.server && lock->context.ctx == brlh->last_lock.context.ctx && - lock->fnum == brlh->last_lock.fnum && + lock->ntvfs == brlh->last_lock.ntvfs && lock->start == brlh->last_lock.start) { return NT_STATUS_FILE_LOCK_CONFLICT; } @@ -310,7 +310,7 @@ NTSTATUS brl_lock(struct brl_context *brl, lock.context.smbpid = smbpid; lock.context.server = brl->server; lock.context.ctx = brl; - lock.fnum = brlh->fnum; + lock.ntvfs = brlh->ntvfs; lock.context.ctx = brl; lock.start = start; lock.size = size; @@ -454,7 +454,7 @@ NTSTATUS brl_unlock(struct brl_context *brl, struct lock_struct *lock = &locks[i]; if (brl_same_context(&lock->context, &context) && - lock->fnum == brlh->fnum && + lock->ntvfs == brlh->ntvfs && lock->start == start && lock->size == size && lock->lock_type < PENDING_READ_LOCK) { @@ -595,7 +595,7 @@ NTSTATUS brl_locktest(struct brl_context *brl, lock.context.smbpid = smbpid; lock.context.server = brl->server; lock.context.ctx = brl; - lock.fnum = brlh->fnum; + lock.ntvfs = brlh->ntvfs; lock.start = start; lock.size = size; lock.lock_type = lock_type; @@ -649,7 +649,7 @@ NTSTATUS brl_close(struct brl_context *brl, if (lock->context.ctx == brl && lock->context.server == brl->server && - lock->fnum == brlh->fnum) { + lock->ntvfs == brlh->ntvfs) { /* found it - delete it */ if (count > 1 && i < count-1) { memmove(&locks[i], &locks[i+1], diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index 6ef380c4eb..fdad41145b 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -32,16 +32,12 @@ #include "ntvfs/ipc/proto.h" #include "rpc_server/dcerpc_server.h" -#define IPC_BASE_FNUM 0x400 - /* this is the private structure used to keep the state of an open ipc$ connection. It needs to keep information about all open pipes */ struct ipc_private { struct ntvfs_module_context *ntvfs; - struct idr_context *idtree_fnum; - struct dcesrv_context *dcesrv; /* a list of open pipes */ @@ -49,41 +45,43 @@ struct ipc_private { struct pipe_state *next, *prev; struct ipc_private *private; const char *pipe_name; - uint16_t fnum; + struct ntvfs_handle *handle; struct dcesrv_connection *dce_conn; uint16_t ipc_state; - /* we need to remember the session it was opened on, - as it is illegal to operate on someone elses fnum */ - struct auth_session_info *session_info; - - /* we need to remember the client pid that - opened the file so SMBexit works */ - uint16_t smbpid; } *pipe_list; }; /* - find a open pipe give a file descriptor + find a open pipe give a file handle */ -static struct pipe_state *pipe_state_find(struct ipc_private *private, uint16_t fnum, - struct auth_session_info *session_info) +static struct pipe_state *pipe_state_find(struct ipc_private *private, struct ntvfs_handle *handle) { struct pipe_state *s; void *p; - p = idr_find(private->idtree_fnum, fnum); + p = ntvfs_handle_get_backend_data(handle, private->ntvfs); if (!p) return NULL; s = talloc_get_type(p, struct pipe_state); - - if (s->session_info != session_info) { - return NULL; - } + if (!s) return NULL; return s; } +/* + find a open pipe give a wire fnum +*/ +static struct pipe_state *pipe_state_find_key(struct ipc_private *private, struct ntvfs_request *req, const DATA_BLOB *key) +{ + struct ntvfs_handle *h; + + h = ntvfs_handle_search_by_wire_key(private->ntvfs, req, key); + if (!h) return NULL; + + return pipe_state_find(private, h); +} + /* connect to a share - always works @@ -109,9 +107,6 @@ static NTSTATUS ipc_connect(struct ntvfs_module_context *ntvfs, private->ntvfs = ntvfs; private->pipe_list = NULL; - private->idtree_fnum = idr_init(private); - NT_STATUS_HAVE_NO_MEMORY(private->idtree_fnum); - /* setup the DCERPC server subsystem */ status = dcesrv_init_ipc_context(private, &private->dcesrv); NT_STATUS_NOT_OK_RETURN(status); @@ -182,7 +177,6 @@ static NTSTATUS ipc_setpathinfo(struct ntvfs_module_context *ntvfs, static int ipc_fd_destructor(void *ptr) { struct pipe_state *p = ptr; - idr_remove(p->private->idtree_fnum, p->fnum); DLIST_REMOVE(p->private->pipe_list, p); return 0; } @@ -212,9 +206,12 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, NTSTATUS status; struct dcerpc_binding *ep_description; struct ipc_private *private = ntvfs->private_data; - int fnum; + struct ntvfs_handle *h; + + status = ntvfs_handle_new(ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); - p = talloc(req, struct pipe_state); + p = talloc(h, struct pipe_state); NT_STATUS_HAVE_NO_MEMORY(p); ep_description = talloc(req, struct dcerpc_binding); @@ -225,12 +222,7 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, p->pipe_name = talloc_asprintf(p, "\\pipe\\%s", fname); NT_STATUS_HAVE_NO_MEMORY(p->pipe_name); - fnum = idr_get_new_above(private->idtree_fnum, p, IPC_BASE_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - p->fnum = fnum; + p->handle = h; p->ipc_state = 0x5ff; /* @@ -248,14 +240,11 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, status = dcesrv_endpoint_search_connect(private->dcesrv, p, ep_description, - req->session_info, + h->session_info, ntvfs->ctx->event_ctx, 0, &p->dce_conn); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(private->idtree_fnum, p->fnum); - return status; - } + NT_STATUS_NOT_OK_RETURN(status); p->dce_conn->transport.private_data = private; p->dce_conn->transport.report_output_data = NULL; @@ -264,16 +253,14 @@ static NTSTATUS ipc_open_generic(struct ntvfs_module_context *ntvfs, DLIST_ADD(private->pipe_list, p); - p->smbpid = req->smbpid; - p->session_info = req->session_info; p->private = private; - *ps = p; - - talloc_steal(private, p); - talloc_set_destructor(p, ipc_fd_destructor); + status = ntvfs_handle_set_backend_data(h, private->ntvfs, p); + NT_STATUS_NOT_OK_RETURN(status); + + *ps = p; return NT_STATUS_OK; } @@ -292,7 +279,7 @@ static NTSTATUS ipc_open_ntcreatex(struct ntvfs_module_context *ntvfs, } ZERO_STRUCT(oi->ntcreatex.out); - oi->ntcreatex.out.file.fnum = p->fnum; + oi->ntcreatex.out.file.ntvfs= p->handle; oi->ntcreatex.out.ipc_state = p->ipc_state; oi->ntcreatex.out.file_type = FILE_TYPE_MESSAGE_MODE_PIPE; @@ -315,7 +302,7 @@ static NTSTATUS ipc_open_openx(struct ntvfs_module_context *ntvfs, } ZERO_STRUCT(oi->openx.out); - oi->openx.out.file.fnum = p->fnum; + oi->openx.out.file.ntvfs= p->handle; oi->openx.out.ftype = 2; oi->openx.out.devstate = p->ipc_state; @@ -401,7 +388,6 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs, { struct ipc_private *private = ntvfs->private_data; DATA_BLOB data; - uint16_t fnum; struct pipe_state *p; NTSTATUS status = NT_STATUS_OK; @@ -409,9 +395,7 @@ static NTSTATUS ipc_read(struct ntvfs_module_context *ntvfs, return ntvfs_map_read(ntvfs, req, rd); } - fnum = rd->readx.in.file.fnum; - - p = pipe_state_find(private, fnum, req->session_info); + p = pipe_state_find(private, rd->readx.in.file.ntvfs); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -444,7 +428,6 @@ static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs, { struct ipc_private *private = ntvfs->private_data; DATA_BLOB data; - uint16_t fnum; struct pipe_state *p; NTSTATUS status; @@ -452,11 +435,10 @@ static NTSTATUS ipc_write(struct ntvfs_module_context *ntvfs, return ntvfs_map_write(ntvfs, req, wr); } - fnum = wr->writex.in.file.fnum; data.data = discard_const_p(void, wr->writex.in.data); data.length = wr->writex.in.count; - p = pipe_state_find(private, fnum, req->session_info); + p = pipe_state_find(private, wr->writex.in.file.ntvfs); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -505,7 +487,7 @@ static NTSTATUS ipc_close(struct ntvfs_module_context *ntvfs, return ntvfs_map_close(ntvfs, req, io); } - p = pipe_state_find(private, io->close.in.file.fnum, req->session_info); + p = pipe_state_find(private, io->close.in.file.ntvfs); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -526,8 +508,8 @@ static NTSTATUS ipc_exit(struct ntvfs_module_context *ntvfs, for (p=private->pipe_list; p; p=next) { next = p->next; - if (p->session_info == req->session_info && - p->smbpid == req->smbpid) { + if (p->handle->session_info == req->session_info && + p->handle->smbpid == req->smbpid) { talloc_free(p); } } @@ -546,7 +528,7 @@ static NTSTATUS ipc_logoff(struct ntvfs_module_context *ntvfs, for (p=private->pipe_list; p; p=next) { next = p->next; - if (p->session_info == req->session_info) { + if (p->handle->session_info == req->session_info) { talloc_free(p); } } @@ -674,9 +656,12 @@ static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs, struct pipe_state *p; struct ipc_private *private = ntvfs->private_data; NTSTATUS status; + DATA_BLOB fnum_key; /* the fnum is in setup[1] */ - p = pipe_state_find(private, trans->in.setup[1], req->session_info); + fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1])); + + p = pipe_state_find_key(private, req, &fnum_key); if (!p) { return NT_STATUS_INVALID_HANDLE; } @@ -715,13 +700,16 @@ static NTSTATUS ipc_dcerpc_cmd(struct ntvfs_module_context *ntvfs, /* SMBtrans - set named pipe state */ static NTSTATUS ipc_set_nm_pipe_state(struct ntvfs_module_context *ntvfs, - struct ntvfs_request *req, struct smb_trans2 *trans) + struct ntvfs_request *req, struct smb_trans2 *trans) { struct ipc_private *private = ntvfs->private_data; struct pipe_state *p; + DATA_BLOB fnum_key; /* the fnum is in setup[1] */ - p = pipe_state_find(private, trans->in.setup[1], req->session_info); + fnum_key = data_blob_const(&trans->in.setup[1], sizeof(trans->in.setup[1])); + + p = pipe_state_find_key(private, req, &fnum_key); if (!p) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/nbench/vfs_nbench.c b/source4/ntvfs/nbench/vfs_nbench.c index 963d422cf0..2df3b95494 100644 --- a/source4/ntvfs/nbench/vfs_nbench.c +++ b/source4/ntvfs/nbench/vfs_nbench.c @@ -54,6 +54,26 @@ static void nbench_log(struct ntvfs_request *req, free(s); } +static char *nbench_ntvfs_handle_string(struct ntvfs_request *req, struct ntvfs_handle *h) +{ + DATA_BLOB key; + uint16_t fnum = 0; + + key = ntvfs_handle_get_wire_key(h, req); + + switch (key.length) { + case 2: /* SMB fnum */ + fnum = SVAL(key.data, 0); + break; + default: + DEBUG(0,("%s: invalid wire handle size: %u\n", + __FUNCTION__, key.length)); + break; + } + + return talloc_asprintf(req, "%u", fnum); +} + /* this pass through macro operates on request contexts, and disables async calls. @@ -237,8 +257,8 @@ static void nbench_qfileinfo_send(struct ntvfs_request *req) { union smb_fileinfo *info = req->async_states->private_data; - nbench_log(req, "QUERY_FILE_INFORMATION %d %d %s\n", - info->generic.in.file.fnum, + nbench_log(req, "QUERY_FILE_INFORMATION %s %d %s\n", + nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs), info->generic.level, get_nt_error_c_code(req->async_states->status)); @@ -292,11 +312,11 @@ static void nbench_open_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(io->ntcreatex.out); } - nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %d %s\n", + nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %s %s\n", io->ntcreatex.in.fname, io->ntcreatex.in.create_options, io->ntcreatex.in.open_disposition, - io->ntcreatex.out.file.fnum, + nbench_ntvfs_handle_string(req, io->ntcreatex.out.file.ntvfs), get_nt_error_c_code(req->async_states->status)); break; @@ -430,8 +450,8 @@ static void nbench_read_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(rd->readx.out); } - nbench_log(req, "ReadX %d %d %d %d %s\n", - rd->readx.in.file.fnum, + nbench_log(req, "ReadX %s %d %d %d %s\n", + nbench_ntvfs_handle_string(req, rd->readx.in.file.ntvfs), (int)rd->readx.in.offset, rd->readx.in.maxcnt, rd->readx.out.nread, @@ -468,8 +488,8 @@ static void nbench_write_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(wr->writex.out); } - nbench_log(req, "WriteX %d %d %d %d %s\n", - wr->writex.in.file.fnum, + nbench_log(req, "WriteX %s %d %d %d %s\n", + nbench_ntvfs_handle_string(req, wr->writex.in.file.ntvfs), (int)wr->writex.in.offset, wr->writex.in.count, wr->writex.out.nwritten, @@ -480,8 +500,8 @@ static void nbench_write_send(struct ntvfs_request *req) if (!NT_STATUS_IS_OK(req->async_states->status)) { ZERO_STRUCT(wr->write.out); } - nbench_log(req, "Write %d %d %d %d %s\n", - wr->write.in.file.fnum, + nbench_log(req, "Write %s %d %d %d %s\n", + nbench_ntvfs_handle_string(req, wr->write.in.file.ntvfs), wr->write.in.offset, wr->write.in.count, wr->write.out.nwritten, @@ -534,20 +554,20 @@ static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs, static void nbench_flush_send(struct ntvfs_request *req) { union smb_flush *io = req->async_states->private_data; - uint16_t fnum; switch (io->generic.level) { case RAW_FLUSH_FLUSH: - fnum = io->flush.in.file.fnum; + nbench_log(req, "Flush %s %s\n", + nbench_ntvfs_handle_string(req, io->flush.in.file.ntvfs), + get_nt_error_c_code(req->async_states->status)); break; case RAW_FLUSH_ALL: - fnum = 0xFFFF; + nbench_log(req, "Flush %d %s\n", + 0xFFFF, + get_nt_error_c_code(req->async_states->status)); break; } - nbench_log(req, "Flush %d %s\n", - fnum, get_nt_error_c_code(req->async_states->status)); - PASS_THRU_REP_POST(req); } @@ -571,8 +591,8 @@ static void nbench_close_send(struct ntvfs_request *req) switch (io->generic.level) { case RAW_CLOSE_CLOSE: - nbench_log(req, "Close %d %s\n", - io->close.in.file.fnum, + nbench_log(req, "Close %s %s\n", + nbench_ntvfs_handle_string(req, io->close.in.file.ntvfs), get_nt_error_c_code(req->async_states->status)); break; @@ -686,15 +706,15 @@ static void nbench_lock_send(struct ntvfs_request *req) if (lck->generic.level == RAW_LOCK_LOCKX && lck->lockx.in.lock_cnt == 1 && lck->lockx.in.ulock_cnt == 0) { - nbench_log(req, "LockX %d %d %d %s\n", - lck->lockx.in.file.fnum, + nbench_log(req, "LockX %s %d %d %s\n", + nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs), (int)lck->lockx.in.locks[0].offset, (int)lck->lockx.in.locks[0].count, get_nt_error_c_code(req->async_states->status)); } else if (lck->generic.level == RAW_LOCK_LOCKX && lck->lockx.in.ulock_cnt == 1) { - nbench_log(req, "UnlockX %d %d %d %s\n", - lck->lockx.in.file.fnum, + nbench_log(req, "UnlockX %s %d %d %s\n", + nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs), (int)lck->lockx.in.locks[0].offset, (int)lck->lockx.in.locks[0].count, get_nt_error_c_code(req->async_states->status)); @@ -722,8 +742,8 @@ static void nbench_setfileinfo_send(struct ntvfs_request *req) { union smb_setfileinfo *info = req->async_states->private_data; - nbench_log(req, "SET_FILE_INFORMATION %d %d %s\n", - info->generic.in.file.fnum, + nbench_log(req, "SET_FILE_INFORMATION %s %d %s\n", + nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs), info->generic.level, get_nt_error_c_code(req->async_states->status)); diff --git a/source4/ntvfs/ntvfs.h b/source4/ntvfs/ntvfs.h index 9069e6c2ac..cf541de81e 100644 --- a/source4/ntvfs/ntvfs.h +++ b/source4/ntvfs/ntvfs.h @@ -191,7 +191,7 @@ struct ntvfs_context { struct { void *private_data; - NTSTATUS (*handler)(void *private_data, uint16_t fnum, uint8_t level); + NTSTATUS (*handler)(void *private_data, struct ntvfs_handle *handle, uint8_t level); } oplock; struct { @@ -199,8 +199,16 @@ struct ntvfs_context { struct socket_address *(*get_my_addr)(void *private_data, TALLOC_CTX *mem_ctx); struct socket_address *(*get_peer_addr)(void *private_data, TALLOC_CTX *mem_ctx); } client; -}; + struct { + void *private_data; + NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h); + NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h); + void (*destroy)(void *private_data, struct ntvfs_handle *h); + struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key); + DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx); + } handles; +}; /* a set of flags to control handling of request structures */ #define NTVFS_ASYNC_STATE_ASYNC (1<<1) /* the backend will answer this one later */ @@ -253,6 +261,28 @@ struct ntvfs_request { /* the system time when the request arrived */ struct timeval request_time; } statistics; + + struct { + void *private_data; + } frontend_data; +}; + +struct ntvfs_handle { + struct ntvfs_context *ctx; + + struct auth_session_info *session_info; + + uint16_t smbpid; + + struct ntvfs_handle_data { + struct ntvfs_handle_data *prev, *next; + struct ntvfs_module_context *owner; + void *private_data;/* this must be a valid talloc pointer */ + } *backend_data; + + struct { + void *private_data; + } frontend_data; }; /* this structure is used by backends to determine the size of some critical types */ @@ -264,6 +294,8 @@ struct ntvfs_critical_sizes { int sizeof_ntvfs_ops; int sizeof_ntvfs_async_state; int sizeof_ntvfs_request; + int sizeof_ntvfs_handle; + int sizeof_ntvfs_handle_data; }; #define NTVFS_CURRENT_CRITICAL_SIZES(c) \ @@ -275,6 +307,8 @@ struct ntvfs_critical_sizes { .sizeof_ntvfs_ops = sizeof(struct ntvfs_ops), \ .sizeof_ntvfs_async_state = sizeof(struct ntvfs_async_state), \ .sizeof_ntvfs_request = sizeof(struct ntvfs_request), \ + .sizeof_ntvfs_handle = sizeof(struct ntvfs_handle), \ + .sizeof_ntvfs_handle_data = sizeof(struct ntvfs_handle_data), \ } struct messaging_context; diff --git a/source4/ntvfs/ntvfs_generic.c b/source4/ntvfs/ntvfs_generic.c index b04a3af21e..5058225ceb 100644 --- a/source4/ntvfs/ntvfs_generic.c +++ b/source4/ntvfs/ntvfs_generic.c @@ -153,7 +153,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, switch (io->generic.level) { case RAW_OPEN_OPEN: - io->openold.out.file.fnum = io2->generic.out.file.fnum; + io->openold.out.file.ntvfs = io2->generic.out.file.ntvfs; io->openold.out.attrib = io2->generic.out.attrib; io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time); io->openold.out.size = io2->generic.out.size; @@ -161,7 +161,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, break; case RAW_OPEN_OPENX: - io->openx.out.file.fnum = io2->generic.out.file.fnum; + io->openx.out.file.ntvfs = io2->generic.out.file.ntvfs; io->openx.out.attrib = io2->generic.out.attrib; io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time); io->openx.out.size = io2->generic.out.size; @@ -181,7 +181,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, break; case RAW_OPEN_T2OPEN: - io->t2open.out.file.fnum = io2->generic.out.file.fnum; + io->t2open.out.file.ntvfs = io2->generic.out.file.ntvfs; io->t2open.out.attrib = io2->generic.out.attrib; io->t2open.out.write_time = nt_time_to_unix(io2->generic.out.write_time); io->t2open.out.size = io2->generic.out.size; @@ -194,12 +194,12 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, case RAW_OPEN_MKNEW: case RAW_OPEN_CREATE: - io->mknew.out.file.fnum = io2->generic.out.file.fnum; + io->mknew.out.file.ntvfs= io2->generic.out.file.ntvfs; write_time = io->mknew.in.write_time; break; case RAW_OPEN_CTEMP: - io->ctemp.out.file.fnum = io2->generic.out.file.fnum; + io->ctemp.out.file.ntvfs= io2->generic.out.file.ntvfs; io->ctemp.out.name = talloc_strdup(req, io2->generic.in.fname + strlen(io->ctemp.in.directory) + 1); NT_STATUS_HAVE_NO_MEMORY(io->ctemp.out.name); @@ -218,7 +218,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, sf = talloc(req, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(sf); sf->generic.level = RAW_SFILEINFO_STANDARD; - sf->generic.in.file.fnum = io2->generic.out.file.fnum; + sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs; sf->standard.in.create_time = 0; sf->standard.in.write_time = write_time; sf->standard.in.access_time = 0; @@ -229,7 +229,7 @@ static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs, sf = talloc(req, union smb_setfileinfo); NT_STATUS_HAVE_NO_MEMORY(sf); sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION; - sf->generic.in.file.fnum = io2->generic.out.file.fnum; + sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs; sf->end_of_file_info.in.size = set_size; status = ntvfs->ops->setfileinfo(ntvfs, req, sf); if (NT_STATUS_IS_OK(status)) { @@ -859,7 +859,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs, /* ask the backend for the generic info */ info2->generic.level = RAW_FILEINFO_GENERIC; - info2->generic.in.file.fnum = info->generic.in.file.fnum; + info2->generic.in.file.ntvfs= info->generic.in.file.ntvfs; /* only used by the simple backend, which doesn't do async */ req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC; @@ -941,7 +941,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs, } lck2->generic.level = RAW_LOCK_GENERIC; - lck2->generic.in.file.fnum = lck->lock.in.file.fnum; + lck2->generic.in.file.ntvfs= lck->lock.in.file.ntvfs; lck2->generic.in.mode = 0; lck2->generic.in.timeout = 0; lck2->generic.in.locks = locks; @@ -988,10 +988,10 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } - lck->unlock.level = RAW_LOCK_UNLOCK; - lck->unlock.in.file.fnum= wr->writeunlock.in.file.fnum; - lck->unlock.in.count = wr->writeunlock.in.count; - lck->unlock.in.offset = wr->writeunlock.in.offset; + lck->unlock.level = RAW_LOCK_UNLOCK; + lck->unlock.in.file.ntvfs = wr->writeunlock.in.file.ntvfs; + lck->unlock.in.count = wr->writeunlock.in.count; + lck->unlock.in.offset = wr->writeunlock.in.offset; if (lck->unlock.in.count != 0) { /* do the lock sync for now */ @@ -1011,7 +1011,7 @@ static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs, } cl->close.level = RAW_CLOSE_CLOSE; - cl->close.in.file.fnum = wr->writeclose.in.file.fnum; + cl->close.in.file.ntvfs = wr->writeclose.in.file.ntvfs; cl->close.in.write_time = wr->writeclose.in.mtime; if (wr2->generic.in.count != 0) { @@ -1062,7 +1062,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_WRITE: - wr2->writex.in.file.fnum = wr->write.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->write.in.file.ntvfs; wr2->writex.in.offset = wr->write.in.offset; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = wr->write.in.remaining; @@ -1072,7 +1072,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_WRITEUNLOCK: - wr2->writex.in.file.fnum = wr->writeunlock.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->writeunlock.in.file.ntvfs; wr2->writex.in.offset = wr->writeunlock.in.offset; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = wr->writeunlock.in.remaining; @@ -1082,7 +1082,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_WRITECLOSE: - wr2->writex.in.file.fnum = wr->writeclose.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->writeclose.in.file.ntvfs; wr2->writex.in.offset = wr->writeclose.in.offset; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = 0; @@ -1092,7 +1092,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs, break; case RAW_WRITE_SPLWRITE: - wr2->writex.in.file.fnum = wr->splwrite.in.file.fnum; + wr2->writex.in.file.ntvfs= wr->splwrite.in.file.ntvfs; wr2->writex.in.offset = 0; wr2->writex.in.wmode = 0; wr2->writex.in.remaining = 0; @@ -1164,7 +1164,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs, break; case RAW_READ_READ: - rd2->readx.in.file.fnum = rd->read.in.file.fnum; + rd2->readx.in.file.ntvfs= rd->read.in.file.ntvfs; rd2->readx.in.offset = rd->read.in.offset; rd2->readx.in.mincnt = rd->read.in.count; rd2->readx.in.maxcnt = rd->read.in.count; @@ -1174,7 +1174,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs, break; case RAW_READ_READBRAW: - rd2->readx.in.file.fnum = rd->readbraw.in.file.fnum; + rd2->readx.in.file.ntvfs= rd->readbraw.in.file.ntvfs; rd2->readx.in.offset = rd->readbraw.in.offset; rd2->readx.in.mincnt = rd->readbraw.in.mincnt; rd2->readx.in.maxcnt = rd->readbraw.in.maxcnt; @@ -1194,13 +1194,13 @@ _PUBLIC_ NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs, goto done; } lck->lock.level = RAW_LOCK_LOCK; - lck->lock.in.file.fnum = rd->lockread.in.file.fnum; + lck->lock.in.file.ntvfs = rd->lockread.in.file.ntvfs; lck->lock.in.count = rd->lockread.in.count; lck->lock.in.offset = rd->lockread.in.offset; status = ntvfs->ops->lock(ntvfs, req, lck); req->async_states->state = state; - rd2->readx.in.file.fnum = rd->lockread.in.file.fnum; + rd2->readx.in.file.ntvfs= rd->lockread.in.file.ntvfs; rd2->readx.in.offset = rd->lockread.in.offset; rd2->readx.in.mincnt = rd->lockread.in.count; rd2->readx.in.maxcnt = rd->lockread.in.count; @@ -1238,7 +1238,7 @@ _PUBLIC_ NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs, case RAW_CLOSE_SPLCLOSE: cl2->close.level = RAW_CLOSE_CLOSE; - cl2->close.in.file.fnum = cl->splclose.in.file.fnum; + cl2->close.in.file.ntvfs= cl->splclose.in.file.ntvfs; break; } diff --git a/source4/ntvfs/ntvfs_interface.c b/source4/ntvfs/ntvfs_interface.c index c26832d96e..67cbe8df22 100644 --- a/source4/ntvfs/ntvfs_interface.c +++ b/source4/ntvfs/ntvfs_interface.c @@ -668,7 +668,7 @@ _PUBLIC_ NTSTATUS ntvfs_next_exit(struct ntvfs_module_context *ntvfs, /* oplock helpers */ _PUBLIC_ NTSTATUS ntvfs_set_oplock_handler(struct ntvfs_context *ntvfs, - NTSTATUS (*handler)(void *private_data, uint16_t fnum, uint8_t level), + NTSTATUS (*handler)(void *private_data, struct ntvfs_handle *handle, uint8_t level), void *private_data) { ntvfs->oplock.handler = handler; @@ -677,13 +677,13 @@ _PUBLIC_ NTSTATUS ntvfs_set_oplock_handler(struct ntvfs_context *ntvfs, } _PUBLIC_ NTSTATUS ntvfs_send_oplock_break(struct ntvfs_module_context *ntvfs, - uint16_t fnum, uint8_t level) + struct ntvfs_handle *handle, uint8_t level) { if (!ntvfs->ctx->oplock.handler) { return NT_STATUS_OK; } - return ntvfs->ctx->oplock.handler(ntvfs->ctx->oplock.private_data, fnum, level); + return ntvfs->ctx->oplock.handler(ntvfs->ctx->oplock.private_data, handle, level); } /* client connection callback */ diff --git a/source4/ntvfs/ntvfs_util.c b/source4/ntvfs/ntvfs_util.c index 52f03430ce..de19a9c352 100644 --- a/source4/ntvfs/ntvfs_util.c +++ b/source4/ntvfs/ntvfs_util.c @@ -98,3 +98,100 @@ _PUBLIC_ void ntvfs_async_state_pop(struct ntvfs_request *req) talloc_free(async); } + +_PUBLIC_ NTSTATUS ntvfs_handle_new(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + struct ntvfs_handle **h) +{ + return ntvfs->ctx->handles.create_new(ntvfs->ctx->handles.private_data, req, h); +} + +_PUBLIC_ NTSTATUS ntvfs_handle_set_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs, + TALLOC_CTX *private_data) +{ + struct ntvfs_handle_data *d; + BOOL first_time = h->backend_data?False:True; + + for (d=h->backend_data; d; d = d->next) { + if (d->owner != ntvfs) continue; + d->private_data = talloc_steal(d, private_data); + return NT_STATUS_OK; + } + + d = talloc(h, struct ntvfs_handle_data); + NT_STATUS_HAVE_NO_MEMORY(d); + d->owner = ntvfs; + d->private_data = talloc_steal(d, private_data); + + DLIST_ADD(h->backend_data, d); + + if (first_time) { + NTSTATUS status; + status = h->ctx->handles.make_valid(h->ctx->handles.private_data, h); + NT_STATUS_NOT_OK_RETURN(status); + } + + return NT_STATUS_OK; +} + +_PUBLIC_ void *ntvfs_handle_get_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs) +{ + struct ntvfs_handle_data *d; + + for (d=h->backend_data; d; d = d->next) { + if (d->owner != ntvfs) continue; + return d->private_data; + } + + return NULL; +} + +_PUBLIC_ void ntvfs_handle_remove_backend_data(struct ntvfs_handle *h, + struct ntvfs_module_context *ntvfs) +{ + struct ntvfs_handle_data *d,*n; + + for (d=h->backend_data; d; d = n) { + n = d->next; + if (d->owner != ntvfs) continue; + DLIST_REMOVE(h->backend_data, d); + talloc_free(d); + d = NULL; + } + + if (h->backend_data) return; + + /* if there's no backend_data anymore, destroy the handle */ + h->ctx->handles.destroy(h->ctx->handles.private_data, h); +} + +_PUBLIC_ struct ntvfs_handle *ntvfs_handle_search_by_wire_key(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + const DATA_BLOB *key) +{ + return ntvfs->ctx->handles.search_by_wire_key(ntvfs->ctx->handles.private_data, req, key); +} + +_PUBLIC_ DATA_BLOB ntvfs_handle_get_wire_key(struct ntvfs_handle *h, TALLOC_CTX *mem_ctx) +{ + return h->ctx->handles.get_wire_key(h->ctx->handles.private_data, h, mem_ctx); +} + +_PUBLIC_ NTSTATUS ntvfs_set_handle_callbacks(struct ntvfs_context *ntvfs, + NTSTATUS (*create_new)(void *private_data, struct ntvfs_request *req, struct ntvfs_handle **h), + NTSTATUS (*make_valid)(void *private_data, struct ntvfs_handle *h), + void (*destroy)(void *private_data, struct ntvfs_handle *h), + struct ntvfs_handle *(*search_by_wire_key)(void *private_data, struct ntvfs_request *req, const DATA_BLOB *key), + DATA_BLOB (*get_wire_key)(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx), + void *private_data) +{ + ntvfs->handles.create_new = create_new; + ntvfs->handles.make_valid = make_valid; + ntvfs->handles.destroy = destroy; + ntvfs->handles.search_by_wire_key = search_by_wire_key; + ntvfs->handles.get_wire_key = get_wire_key; + ntvfs->handles.private_data = private_data; + return NT_STATUS_OK; +} diff --git a/source4/ntvfs/posix/pvfs_flush.c b/source4/ntvfs/posix/pvfs_flush.c index c1d8820c43..7bd973ed4e 100644 --- a/source4/ntvfs/posix/pvfs_flush.c +++ b/source4/ntvfs/posix/pvfs_flush.c @@ -48,7 +48,7 @@ NTSTATUS pvfs_flush(struct ntvfs_module_context *ntvfs, switch (io->generic.level) { case RAW_FLUSH_FLUSH: - f = pvfs_find_fd(pvfs, req, io->flush.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->flush.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_ioctl.c b/source4/ntvfs/posix/pvfs_ioctl.c index 829da47a12..417458edf0 100644 --- a/source4/ntvfs/posix/pvfs_ioctl.c +++ b/source4/ntvfs/posix/pvfs_ioctl.c @@ -42,7 +42,7 @@ static NTSTATUS pvfs_ntioctl(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; - f = pvfs_find_fd(pvfs, req, io->ntioctl.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->ntioctl.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index 99b694665d..8dcee5f983 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -244,7 +244,7 @@ static NTSTATUS pvfs_lock_cancel(struct pvfs_state *pvfs, struct ntvfs_request * /* check if the lock request matches exactly - you can only cancel with exact matches */ if (p->lck->lockx.in.ulock_cnt == lck->lockx.in.ulock_cnt && p->lck->lockx.in.lock_cnt == lck->lockx.in.lock_cnt && - p->lck->lockx.in.file.fnum == lck->lockx.in.file.fnum && + p->lck->lockx.in.file.ntvfs== lck->lockx.in.file.ntvfs && p->lck->lockx.in.mode == (lck->lockx.in.mode & ~LOCKING_ANDX_CANCEL_LOCK)) { int i; @@ -286,7 +286,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs, return ntvfs_map_lock(ntvfs, req, lck); } - f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.fnum); + f = pvfs_find_fd(pvfs, req, lck->lockx.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_notify.c b/source4/ntvfs/posix/pvfs_notify.c index ea4c0b2bc6..dfe1737060 100644 --- a/source4/ntvfs/posix/pvfs_notify.c +++ b/source4/ntvfs/posix/pvfs_notify.c @@ -203,7 +203,7 @@ NTSTATUS pvfs_notify(struct ntvfs_module_context *ntvfs, NTSTATUS status; struct notify_pending *pending; - f = pvfs_find_fd(pvfs, req, info->in.file.fnum); + f = pvfs_find_fd(pvfs, req, info->in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3bbf840154..fd382ba1d9 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -29,39 +29,28 @@ #include "librpc/gen_ndr/xattr.h" /* - create file handles with convenient numbers for sniffers -*/ -#define PVFS_MIN_FILE_FNUM 0x100 -#define PVFS_MIN_NEW_FNUM 0x200 -#define PVFS_MIN_DIR_FNUM 0x300 - -/* find open file handle given fnum */ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, - struct ntvfs_request *req, uint16_t fnum) + struct ntvfs_request *req, struct ntvfs_handle *h) { + void *p; struct pvfs_file *f; - f = idr_find(pvfs->files.idtree, fnum); - if (f == NULL) { - return NULL; - } + p = ntvfs_handle_get_backend_data(h, pvfs->ntvfs); + if (!p) return NULL; - if (f->fnum != fnum) { - smb_panic("pvfs_find_fd: idtree_fnum corruption\n"); - } + f = talloc_get_type(p, struct pvfs_file); + if (!f) return NULL; if (req->session_info != f->session_info) { - DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", - fnum)); + DEBUG(2,("pvfs_find_fd: attempt to use wrong session for handle %p\n",h)); return NULL; } return f; } - /* cleanup a open directory handle */ @@ -114,8 +103,10 @@ static int pvfs_dir_handle_destructor(void *p) static int pvfs_dir_fnum_destructor(void *p) { struct pvfs_file *f = p; + DLIST_REMOVE(f->pvfs->files.list, f); - idr_remove(f->pvfs->files.idtree, f->fnum); + ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); + return 0; } @@ -125,7 +116,7 @@ static int pvfs_dir_fnum_destructor(void *p) static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_filename *name, - int fd, int fnum, + int fd, struct pvfs_file *f, union smb_open *io) { NTSTATUS status; @@ -150,7 +141,7 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, * but the user doesn't have SeSecurityPrivilege * - w2k3 allows it */ - set.set_secdesc.in.file.fnum = fnum; + set.set_secdesc.in.file.ntvfs = f->ntvfs; set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; @@ -197,7 +188,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, union smb_open *io) { struct pvfs_file *f; - int fnum; + struct ntvfs_handle *h; NTSTATUS status; uint32_t create_action; uint32_t access_mask = io->generic.in.access_mask; @@ -242,7 +233,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INVALID_PARAMETER; } - f = talloc(req, struct pvfs_file); + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(h, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } @@ -252,11 +246,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - if (name->exists) { /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); @@ -264,11 +253,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, status = pvfs_access_check_create(pvfs, req, name, &access_mask); } if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); return status; } - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -297,12 +285,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, del_on_close = False; } - if (name->exists) { /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -313,7 +299,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -323,7 +308,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); talloc_free(lck); return status; } @@ -342,7 +326,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, mode_t mode = pvfs_fileperms(pvfs, attrib); if (mkdir(name->full_name, mode) == -1) { - idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs,errno); } @@ -353,7 +336,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } - status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, fnum, io); + status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -361,7 +344,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -371,7 +353,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -396,15 +377,17 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } if (!name->exists) { - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* the open succeeded, keep this handle permanently */ - talloc_steal(pvfs, f); + status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = h; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -420,7 +403,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->files.idtree, fnum); rmdir(name->full_name); return status; } @@ -510,11 +492,11 @@ static int pvfs_handle_destructor(void *p) */ static int pvfs_fnum_destructor(void *p) { - struct pvfs_file *f = p; + struct pvfs_file *f = talloc_get_type(p, struct pvfs_file); DLIST_REMOVE(f->pvfs->files.list, f); pvfs_lock_close(f->pvfs, f); - idr_remove(f->pvfs->files.idtree, f->fnum); + ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); return 0; } @@ -527,8 +509,8 @@ static int pvfs_fnum_destructor(void *p) locking space) */ static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx, - struct pvfs_filename *name, - uint16_t fnum, + struct pvfs_filename *name, + struct ntvfs_handle *ntvfs, struct brl_handle **_h) { DATA_BLOB odb_key, key; @@ -550,7 +532,7 @@ static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx, data_blob_free(&odb_key); } - h = brl_create_handle(mem_ctx, &key, fnum); + h = brl_create_handle(mem_ctx, ntvfs, &key); NT_STATUS_HAVE_NO_MEMORY(h); *_h = h; @@ -567,7 +549,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, { struct pvfs_file *f; NTSTATUS status; - int flags, fnum, fd; + struct ntvfs_handle *h; + int flags, fd; struct odb_lock *lck; uint32_t create_options = io->generic.in.create_options; uint32_t share_access = io->generic.in.share_access; @@ -606,20 +589,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, flags = O_RDONLY; } - f = talloc(req, struct pvfs_file); - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); - f->handle = talloc(f, struct pvfs_file_handle); - if (f->handle == NULL) { - return NT_STATUS_NO_MEMORY; - } + f = talloc(h, struct pvfs_file); + NT_STATUS_HAVE_NO_MEMORY(f); - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } + f->handle = talloc(f, struct pvfs_file_handle); + NT_STATUS_HAVE_NO_MEMORY(f->handle); attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; mode = pvfs_fileperms(pvfs, attrib); @@ -627,7 +604,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* create the file */ fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); if (fd == -1) { - idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs, errno); } @@ -637,7 +613,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, if (name->stream_name) { status = pvfs_stream_create(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -646,7 +621,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -658,7 +632,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } - status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, fnum, io); + status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -670,7 +644,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } - status = pvfs_brl_locking_handle(f, name, fnum, &f->brl_handle); + status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -708,7 +682,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* bad news, we must have hit a race - we don't delete the file here as the most likely scenario is that someone else created the file at the same time */ - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -717,7 +690,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, oplock_granted = OPLOCK_BATCH; } - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -746,7 +719,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_set_destructor(f->handle, pvfs_handle_destructor); io->generic.out.oplock_level = oplock_granted; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = f->ntvfs; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -760,7 +733,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, io->generic.out.is_directory = 0; /* success - keep the file handle */ - talloc_steal(pvfs, f); + status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, @@ -770,7 +746,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->files.idtree, fnum); close(fd); unlink(name->full_name); return status; @@ -873,6 +848,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f2; struct pvfs_filename *name; + NTSTATUS status; /* search for an existing open with the right parameters. Note the magic ntcreatex options flag, which is set in the @@ -919,7 +895,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = f->ntvfs; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -931,8 +907,9 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, io->generic.out.file_type = FILE_TYPE_DISK; io->generic.out.ipc_state = 0; io->generic.out.is_directory = 0; - - talloc_steal(f->pvfs, f); + + status = ntvfs_handle_set_backend_data(f->ntvfs, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); return NT_STATUS_OK; } @@ -1009,8 +986,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, int flags; struct pvfs_filename *name; struct pvfs_file *f; + struct ntvfs_handle *h; NTSTATUS status; - int fnum, fd; + int fd; struct odb_lock *lck; uint32_t create_options; uint32_t share_access; @@ -1128,7 +1106,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - f = talloc(req, struct pvfs_file); + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(h, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1138,13 +1119,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } - /* allocate a fnum */ - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_FILE_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -1169,13 +1144,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } - status = pvfs_brl_locking_handle(f, name, f->fnum, &f->brl_handle); + status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -1186,7 +1159,6 @@ 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->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -1288,8 +1260,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); + status = ntvfs_handle_set_backend_data(h, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); + io->generic.out.oplock_level = oplock_granted; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = h; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -1303,9 +1278,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.out.ipc_state = 0; io->generic.out.is_directory = 0; - /* success - keep the file handle */ - talloc_steal(f->pvfs, f); - return NT_STATUS_OK; } @@ -1328,7 +1300,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_qfileinfo.c b/source4/ntvfs/posix/pvfs_qfileinfo.c index e4e69a8289..2d43c5a582 100644 --- a/source4/ntvfs/posix/pvfs_qfileinfo.c +++ b/source4/ntvfs/posix/pvfs_qfileinfo.c @@ -336,7 +336,7 @@ NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs, NTSTATUS status; uint32_t access_needed; - f = pvfs_find_fd(pvfs, req, info->generic.in.file.fnum); + f = pvfs_find_fd(pvfs, req, info->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_read.c b/source4/ntvfs/posix/pvfs_read.c index 411fbd9c27..13e8264000 100644 --- a/source4/ntvfs/posix/pvfs_read.c +++ b/source4/ntvfs/posix/pvfs_read.c @@ -41,7 +41,7 @@ NTSTATUS pvfs_read(struct ntvfs_module_context *ntvfs, return ntvfs_map_read(ntvfs, req, rd); } - f = pvfs_find_fd(pvfs, req, rd->readx.in.file.fnum); + f = pvfs_find_fd(pvfs, req, rd->readx.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_seek.c b/source4/ntvfs/posix/pvfs_seek.c index dbfb4e1c3d..7365f33b15 100644 --- a/source4/ntvfs/posix/pvfs_seek.c +++ b/source4/ntvfs/posix/pvfs_seek.c @@ -35,7 +35,7 @@ NTSTATUS pvfs_seek(struct ntvfs_module_context *ntvfs, struct pvfs_file_handle *h; NTSTATUS status; - f = pvfs_find_fd(pvfs, req, io->lseek.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->lseek.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_setfileinfo.c b/source4/ntvfs/posix/pvfs_setfileinfo.c index e85f52fc2c..2665b9e5f5 100644 --- a/source4/ntvfs/posix/pvfs_setfileinfo.c +++ b/source4/ntvfs/posix/pvfs_setfileinfo.c @@ -262,7 +262,7 @@ NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs, uint32_t access_needed; uint32_t change_mask = 0; - f = pvfs_find_fd(pvfs, req, info->generic.in.file.fnum); + f = pvfs_find_fd(pvfs, req, info->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/pvfs_write.c b/source4/ntvfs/posix/pvfs_write.c index 1da1985550..9f58281919 100644 --- a/source4/ntvfs/posix/pvfs_write.c +++ b/source4/ntvfs/posix/pvfs_write.c @@ -40,7 +40,7 @@ NTSTATUS pvfs_write(struct ntvfs_module_context *ntvfs, return ntvfs_map_write(ntvfs, req, wr); } - f = pvfs_find_fd(pvfs, req, wr->writex.in.file.fnum); + f = pvfs_find_fd(pvfs, req, wr->writex.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c index eeee00313b..1682a94ac9 100644 --- a/source4/ntvfs/posix/vfs_posix.c +++ b/source4/ntvfs/posix/vfs_posix.c @@ -194,10 +194,6 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* allocate the fnum id -> ptr tree */ - pvfs->files.idtree = idr_init(pvfs); - NT_STATUS_HAVE_NO_MEMORY(pvfs->files.idtree); - /* allocate the search handle -> ptr tree */ pvfs->search.idtree = idr_init(pvfs); NT_STATUS_HAVE_NO_MEMORY(pvfs->search.idtree); diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index 39481c03b1..63ee3395f8 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -63,9 +63,6 @@ struct pvfs_state { uint32_t alloc_size_rounding; struct { - /* an id tree mapping open file handle -> struct pvfs_file */ - struct idr_context *idtree; - /* the open files as DLINKLIST */ struct pvfs_file *list; } files; @@ -156,7 +153,7 @@ struct pvfs_file_handle { struct pvfs_file { struct pvfs_file *next, *prev; struct pvfs_file_handle *handle; - uint16_t fnum; + struct ntvfs_handle *ntvfs; struct pvfs_state *pvfs; diff --git a/source4/ntvfs/simple/svfs.h b/source4/ntvfs/simple/svfs.h index 74e7b6c452..e5ad3b95d9 100644 --- a/source4/ntvfs/simple/svfs.h +++ b/source4/ntvfs/simple/svfs.h @@ -1,5 +1,7 @@ struct svfs_private { + struct ntvfs_module_context *ntvfs; + /* the base directory */ char *connectpath; @@ -24,6 +26,7 @@ struct svfs_dir { struct svfs_file { struct svfs_file *next, *prev; int fd; + struct ntvfs_handle *handle; char *name; }; diff --git a/source4/ntvfs/simple/vfs_simple.c b/source4/ntvfs/simple/vfs_simple.c index 1698f57aee..e0f0083630 100644 --- a/source4/ntvfs/simple/vfs_simple.c +++ b/source4/ntvfs/simple/vfs_simple.c @@ -55,7 +55,8 @@ static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs, int snum = ntvfs->ctx->config.snum; private = talloc(ntvfs, struct svfs_private); - + NT_STATUS_HAVE_NO_MEMORY(private); + private->ntvfs = ntvfs; private->next_search_handle = 0; private->connectpath = talloc_strdup(private, lp_pathname(snum)); private->open_files = NULL; @@ -91,15 +92,18 @@ static NTSTATUS svfs_disconnect(struct ntvfs_module_context *ntvfs) /* find open file handle given fd */ -static struct svfs_file *find_fd(struct svfs_private *private, int fd) +static struct svfs_file *find_fd(struct svfs_private *private, struct ntvfs_handle *handle) { struct svfs_file *f; - for (f=private->open_files;f;f=f->next) { - if (f->fd == fd) { - return f; - } - } - return NULL; + void *p; + + p = ntvfs_handle_get_backend_data(handle, private->ntvfs); + if (!p) return NULL; + + f = talloc_get_type(p, struct svfs_file); + if (!f) return NULL; + + return f; } /* @@ -282,12 +286,12 @@ static NTSTATUS svfs_qfileinfo(struct ntvfs_module_context *ntvfs, return ntvfs_map_qfileinfo(ntvfs, req, info); } - f = find_fd(private, info->generic.in.file.fnum); + f = find_fd(private, info->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } - if (fstat(info->generic.in.file.fnum, &st) == -1) { + if (fstat(f->fd, &st) == -1) { return map_nt_error_from_unix(errno); } @@ -308,6 +312,8 @@ static NTSTATUS svfs_open(struct ntvfs_module_context *ntvfs, struct svfs_file *f; int create_flags, rdwr_flags; BOOL readonly; + NTSTATUS status; + struct ntvfs_handle *handle; if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(ntvfs, req, io); @@ -379,7 +385,10 @@ do_open: return map_nt_error_from_unix(errno); } - f = talloc(ntvfs, struct svfs_file); + status = ntvfs_handle_new(ntvfs, req, &handle); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(handle, struct svfs_file); NT_STATUS_HAVE_NO_MEMORY(f); f->fd = fd; f->name = talloc_strdup(f, unix_path); @@ -387,13 +396,16 @@ do_open: DLIST_ADD(private->open_files, f); + status = ntvfs_handle_set_backend_data(handle, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); + ZERO_STRUCT(io->generic.out); unix_to_nt_time(&io->generic.out.create_time, st.st_ctime); unix_to_nt_time(&io->generic.out.access_time, st.st_atime); unix_to_nt_time(&io->generic.out.write_time, st.st_mtime); unix_to_nt_time(&io->generic.out.change_time, st.st_mtime); - io->generic.out.file.fnum = fd; + io->generic.out.file.ntvfs = handle; io->generic.out.alloc_size = st.st_size; io->generic.out.size = st.st_size; io->generic.out.attrib = svfs_unix_to_dos_attrib(st.st_mode); @@ -483,13 +495,20 @@ static NTSTATUS svfs_copy(struct ntvfs_module_context *ntvfs, static NTSTATUS svfs_read(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_read *rd) { + struct svfs_private *private = ntvfs->private_data; + struct svfs_file *f; ssize_t ret; if (rd->generic.level != RAW_READ_READX) { return NT_STATUS_NOT_SUPPORTED; } - ret = pread(rd->readx.in.file.fnum, + f = find_fd(private, rd->readx.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + ret = pread(f->fd, rd->readx.out.data, rd->readx.in.maxcnt, rd->readx.in.offset); @@ -510,6 +529,8 @@ static NTSTATUS svfs_read(struct ntvfs_module_context *ntvfs, static NTSTATUS svfs_write(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_write *wr) { + struct svfs_private *private = ntvfs->private_data; + struct svfs_file *f; ssize_t ret; if (wr->generic.level != RAW_WRITE_WRITEX) { @@ -518,7 +539,12 @@ static NTSTATUS svfs_write(struct ntvfs_module_context *ntvfs, CHECK_READ_ONLY(req); - ret = pwrite(wr->writex.in.file.fnum, + f = find_fd(private, wr->writex.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + ret = pwrite(f->fd, wr->writex.in.data, wr->writex.in.count, wr->writex.in.offset); @@ -554,7 +580,11 @@ static NTSTATUS svfs_flush(struct ntvfs_module_context *ntvfs, switch (io->generic.level) { case RAW_FLUSH_FLUSH: - fsync(io->flush.in.file.fnum); + f = find_fd(private, io->flush.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + fsync(f->fd); return NT_STATUS_OK; case RAW_FLUSH_ALL: @@ -582,12 +612,12 @@ static NTSTATUS svfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_LEVEL; } - f = find_fd(private, io->close.in.file.fnum); + f = find_fd(private, io->close.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } - if (close(io->close.in.file.fnum) == -1) { + if (close(f->fd) == -1) { return map_nt_error_from_unix(errno); } @@ -662,15 +692,21 @@ static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_setfileinfo *info) { + struct svfs_private *private = ntvfs->private_data; + struct svfs_file *f; struct utimbuf unix_times; - int fd; CHECK_READ_ONLY(req); - + + f = find_fd(private, info->generic.in.file.ntvfs); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + switch (info->generic.level) { case RAW_SFILEINFO_END_OF_FILE_INFO: case RAW_SFILEINFO_END_OF_FILE_INFORMATION: - if (ftruncate(info->end_of_file_info.in.file.fnum, + if (ftruncate(f->fd, info->end_of_file_info.in.size) == -1) { return map_nt_error_from_unix(errno); } @@ -678,8 +714,7 @@ static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs, case RAW_SFILEINFO_SETATTRE: unix_times.actime = info->setattre.in.access_time; unix_times.modtime = info->setattre.in.write_time; - fd = info->setattre.in.file.fnum; - + if (unix_times.actime == 0 && unix_times.modtime == 0) { break; } @@ -690,7 +725,7 @@ static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs, } /* Set the date on this file */ - if (svfs_file_utime(fd, &unix_times) != 0) { + if (svfs_file_utime(f->fd, &unix_times) != 0) { return NT_STATUS_ACCESS_DENIED; } break; |