diff options
Diffstat (limited to 'source4/ntvfs/cifs/vfs_cifs.c')
-rw-r--r-- | source4/ntvfs/cifs/vfs_cifs.c | 188 |
1 files changed, 138 insertions, 50 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); } /* |