summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/ntvfs/cifs/vfs_cifs.c188
-rw-r--r--source4/ntvfs/cifs_posix_cli/vfs_simple.c4
-rw-r--r--source4/ntvfs/common/brlock.c22
-rw-r--r--source4/ntvfs/ipc/vfs_ipc.c106
-rw-r--r--source4/ntvfs/nbench/vfs_nbench.c68
-rw-r--r--source4/ntvfs/ntvfs.h38
-rw-r--r--source4/ntvfs/ntvfs_generic.c46
-rw-r--r--source4/ntvfs/ntvfs_interface.c6
-rw-r--r--source4/ntvfs/ntvfs_util.c97
-rw-r--r--source4/ntvfs/posix/pvfs_flush.c2
-rw-r--r--source4/ntvfs/posix/pvfs_ioctl.c2
-rw-r--r--source4/ntvfs/posix/pvfs_lock.c4
-rw-r--r--source4/ntvfs/posix/pvfs_notify.c2
-rw-r--r--source4/ntvfs/posix/pvfs_open.c154
-rw-r--r--source4/ntvfs/posix/pvfs_qfileinfo.c2
-rw-r--r--source4/ntvfs/posix/pvfs_read.c2
-rw-r--r--source4/ntvfs/posix/pvfs_seek.c2
-rw-r--r--source4/ntvfs/posix/pvfs_setfileinfo.c2
-rw-r--r--source4/ntvfs/posix/pvfs_write.c2
-rw-r--r--source4/ntvfs/posix/vfs_posix.c4
-rw-r--r--source4/ntvfs/posix/vfs_posix.h5
-rw-r--r--source4/ntvfs/simple/svfs.h3
-rw-r--r--source4/ntvfs/simple/vfs_simple.c81
-rw-r--r--source4/smb_server/config.mk1
-rw-r--r--source4/smb_server/handle.c137
-rw-r--r--source4/smb_server/smb/nttrans.c15
-rw-r--r--source4/smb_server/smb/receive.c4
-rw-r--r--source4/smb_server/smb/reply.c229
-rw-r--r--source4/smb_server/smb/request.c92
-rw-r--r--source4/smb_server/smb/service.c14
-rw-r--r--source4/smb_server/smb/trans2.c18
-rw-r--r--source4/smb_server/smb_server.h104
-rw-r--r--source4/smb_server/tcon.c13
33 files changed, 1060 insertions, 409 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;
diff --git a/source4/smb_server/config.mk b/source4/smb_server/config.mk
index 6130d7ce9f..abcade4999 100644
--- a/source4/smb_server/config.mk
+++ b/source4/smb_server/config.mk
@@ -11,6 +11,7 @@ PRIVATE_DEPENDENCIES = SMB_SERVER
# Start SUBSYSTEM SMB
[SUBSYSTEM::SMB_SERVER]
OBJ_FILES = \
+ handle.o \
tcon.o \
session.o \
management.o
diff --git a/source4/smb_server/handle.c b/source4/smb_server/handle.c
new file mode 100644
index 0000000000..c2fea9e91c
--- /dev/null
+++ b/source4/smb_server/handle.c
@@ -0,0 +1,137 @@
+/*
+ Unix SMB/CIFS implementation.
+ Manage smbsrv_handle structures
+ Copyright (C) Stefan Metzmacher 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "dlinklist.h"
+#include "smb_server/smb_server.h"
+#include "ntvfs/ntvfs.h"
+
+
+/****************************************************************************
+init the handle structures
+****************************************************************************/
+NTSTATUS smbsrv_init_handles(struct smbsrv_tcon *tcon, uint64_t limit)
+{
+ /*
+ * the idr_* functions take 'int' as limit,
+ * and only work with a max limit 0x00FFFFFF
+ */
+ limit &= 0x00FFFFFF;
+
+ tcon->handles.idtree_hid = idr_init(tcon);
+ NT_STATUS_HAVE_NO_MEMORY(tcon->handles.idtree_hid);
+ tcon->handles.idtree_limit = limit;
+ tcon->handles.list = NULL;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+find a handle given a handle id
+****************************************************************************/
+static struct smbsrv_handle *smbsrv_handle_find(struct smbsrv_handles_context *handles_ctx,
+ uint64_t hid, struct timeval request_time)
+{
+ void *p;
+ struct smbsrv_handle *handle;
+
+ if (hid == 0) return NULL;
+
+ if (hid > handles_ctx->idtree_limit) return NULL;
+
+ p = idr_find(handles_ctx->idtree_hid, hid);
+ if (!p) return NULL;
+
+ handle = talloc_get_type(p, struct smbsrv_handle);
+ if (!handle) return NULL;
+
+ /* only give it away when the ntvfs subsystem has made the handle valid */
+ if (!handle->ntvfs) return NULL;
+
+ handle->statistics.last_use_time = request_time;
+
+ return handle;
+}
+
+struct smbsrv_handle *smbsrv_smb_handle_find(struct smbsrv_tcon *smb_tcon,
+ uint16_t fnum, struct timeval request_time)
+{
+ return smbsrv_handle_find(&smb_tcon->handles, fnum, request_time);
+}
+
+/*
+ destroy a connection structure
+*/
+static int smbsrv_handle_destructor(void *ptr)
+{
+ struct smbsrv_handle *handle = talloc_get_type(ptr, struct smbsrv_handle);
+ struct smbsrv_handles_context *handles_ctx;
+
+ handles_ctx = &handle->tcon->handles;
+
+ idr_remove(handles_ctx->idtree_hid, handle->hid);
+ DLIST_REMOVE(handles_ctx->list, handle);
+ DLIST_REMOVE(handle->session->handles, &handle->session_item);
+
+ /* tell the ntvfs backend that we are disconnecting */
+ if (handle->ntvfs) {
+ talloc_free(handle->ntvfs);
+ handle->ntvfs = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ find first available handle slot
+*/
+struct smbsrv_handle *smbsrv_handle_new(struct smbsrv_request *req)
+{
+ struct smbsrv_handles_context *handles_ctx = &req->tcon->handles;
+ struct smbsrv_handle *handle;
+ int i;
+
+ handle = talloc_zero(req, struct smbsrv_handle);
+ if (!handle) return NULL;
+ handle->tcon = req->tcon;
+ handle->session = req->session;
+
+ i = idr_get_new_above(handles_ctx->idtree_hid, handle, 1, handles_ctx->idtree_limit);
+ if (i == -1) {
+ DEBUG(1,("ERROR! Out of handle structures\n"));
+ goto failed;
+ }
+ handle->hid = i;
+ handle->session_item.handle = handle;
+
+ DLIST_ADD(handles_ctx->list, handle);
+ DLIST_ADD(handle->session->handles, &handle->session_item);
+ talloc_set_destructor(handle, smbsrv_handle_destructor);
+
+ /* now fill in some statistics */
+ handle->statistics.open_time = req->request_time;
+ handle->statistics.last_use_time = req->request_time;
+
+ return handle;
+
+failed:
+ talloc_free(handle);
+ return NULL;
+}
diff --git a/source4/smb_server/smb/nttrans.c b/source4/smb_server/smb/nttrans.c
index c5b950ec5b..3bc0ab69b2 100644
--- a/source4/smb_server/smb/nttrans.c
+++ b/source4/smb_server/smb/nttrans.c
@@ -75,7 +75,7 @@ static NTSTATUS nttrans_create_send(struct nttrans_op *op)
params = op->trans->out.params.data;
SSVAL(params, 0, io->ntcreatex.out.oplock_level);
- SSVAL(params, 2, io->ntcreatex.out.file.fnum);
+ smbsrv_push_fnum(params, 2, io->ntcreatex.out.file.ntvfs);
SIVAL(params, 4, io->ntcreatex.out.create_action);
SIVAL(params, 8, 0); /* ea error offset */
push_nttime(params, 12, io->ntcreatex.out.create_time);
@@ -230,12 +230,13 @@ static NTSTATUS nttrans_query_sec_desc(struct smbsrv_request *req,
NT_STATUS_HAVE_NO_MEMORY(io);
io->query_secdesc.level = RAW_FILEINFO_SEC_DESC;
- io->query_secdesc.in.file.fnum = SVAL(trans->in.params.data, 0);
+ io->query_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0);
io->query_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4);
op->op_info = io;
op->send_fn = nttrans_query_sec_desc_send;
+ SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->query_secdesc.in.file.ntvfs);
return ntvfs_qfileinfo(req->ntvfs, io);
}
@@ -259,7 +260,7 @@ static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req,
NT_STATUS_HAVE_NO_MEMORY(io);
io->set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
- io->set_secdesc.in.file.fnum = SVAL(trans->in.params.data, 0);
+ io->set_secdesc.in.file.ntvfs = smbsrv_pull_fnum(req, trans->in.params.data, 0);
io->set_secdesc.in.secinfo_flags = IVAL(trans->in.params.data, 4);
io->set_secdesc.in.sd = talloc(io, struct security_descriptor);
@@ -270,6 +271,7 @@ static NTSTATUS nttrans_set_sec_desc(struct smbsrv_request *req,
(ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
NT_STATUS_NOT_OK_RETURN(status);
+ SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(io->set_secdesc.in.file.ntvfs);
return ntvfs_setfileinfo(req->ntvfs, io);
}
@@ -304,6 +306,7 @@ static NTSTATUS nttrans_ioctl_send(struct nttrans_op *op)
return NT_STATUS_OK;
}
+
/*
parse NTTRANS_IOCTL request
*/
@@ -323,7 +326,7 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req,
nt->ntioctl.level = RAW_IOCTL_NTIOCTL;
nt->ntioctl.in.function = IVAL(trans->in.setup, 0);
- nt->ntioctl.in.file.fnum = SVAL(trans->in.setup, 4);
+ nt->ntioctl.in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4);
nt->ntioctl.in.fsctl = CVAL(trans->in.setup, 6);
nt->ntioctl.in.filter = CVAL(trans->in.setup, 7);
nt->ntioctl.in.max_data = trans->in.max_data;
@@ -332,6 +335,7 @@ static NTSTATUS nttrans_ioctl(struct smbsrv_request *req,
op->op_info = nt;
op->send_fn = nttrans_ioctl_send;
+ SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(nt->ntioctl.in.file.ntvfs);
return ntvfs_ioctl(req->ntvfs, nt);
}
@@ -408,13 +412,14 @@ static NTSTATUS nttrans_notify_change(struct smbsrv_request *req,
NT_STATUS_HAVE_NO_MEMORY(info);
info->in.completion_filter = IVAL(trans->in.setup, 0);
- info->in.file.fnum = SVAL(trans->in.setup, 4);
+ info->in.file.ntvfs = smbsrv_pull_fnum(req, (uint8_t *)trans->in.setup, 4);
info->in.recursive = SVAL(trans->in.setup, 6);
info->in.buffer_size = trans->in.max_param;
op->op_info = info;
op->send_fn = nttrans_notify_change_send;
+ SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(info->in.file.ntvfs);
return ntvfs_notify(req->ntvfs, info);
}
diff --git a/source4/smb_server/smb/receive.c b/source4/smb_server/smb/receive.c
index ee728e0ec5..a47d0a5442 100644
--- a/source4/smb_server/smb/receive.c
+++ b/source4/smb_server/smb/receive.c
@@ -31,7 +31,7 @@
/*
send an oplock break request to a client
*/
-NTSTATUS smbsrv_send_oplock_break(void *p, uint16_t fnum, uint8_t level)
+NTSTATUS smbsrv_send_oplock_break(void *p, struct ntvfs_handle *ntvfs, uint8_t level)
{
struct smbsrv_tcon *tcon = talloc_get_type(p, struct smbsrv_tcon);
struct smbsrv_request *req;
@@ -51,7 +51,7 @@ NTSTATUS smbsrv_send_oplock_break(void *p, uint16_t fnum, uint8_t level)
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), fnum);
+ smbsrv_push_fnum(req->out.vwv, VWV(2), ntvfs);
SCVAL(req->out.vwv, VWV(3), LOCKING_ANDX_OPLOCK_RELEASE);
SCVAL(req->out.vwv, VWV(3)+1, level);
SIVAL(req->out.vwv, VWV(4), 0);
diff --git a/source4/smb_server/smb/reply.c b/source4/smb_server/smb/reply.c
index 768fba1319..9abb35ad86 100644
--- a/source4/smb_server/smb/reply.c
+++ b/source4/smb_server/smb/reply.c
@@ -3,6 +3,7 @@
Main SMB reply routines
Copyright (C) Andrew Tridgell 1992-2003
Copyright (C) James J Myers 2003 <myersjj@samba.org>
+ Copyright (C) Stefan Metzmacher 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,7 +21,7 @@
*/
/*
This file handles most of the reply_ calls that the server
- makes to handle specific protocols
+ makes to handle specific SMB commands
*/
#include "includes.h"
@@ -204,10 +205,11 @@ void smbsrv_reply_ioctl(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->ioctl.level = RAW_IOCTL_IOCTL;
- io->ioctl.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->ioctl.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
- /* call backend */
+ SMBSRV_CHECK_FILE_HANDLE_ERROR(io->ioctl.in.file.ntvfs,
+ NT_STATUS_DOS(ERRSRV, ERRerror));
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));
}
@@ -353,7 +355,7 @@ static void reply_open_send(struct ntvfs_request *ntvfs)
/* construct reply */
smbsrv_setup_reply(req, 7, 0);
- SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
+ smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs);
SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
@@ -408,7 +410,7 @@ static void reply_open_and_X_send(struct ntvfs_request *ntvfs)
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), oi->openx.out.file.fnum);
+ smbsrv_push_fnum(req->out.vwv, VWV(2), oi->openx.out.file.ntvfs);
SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
@@ -423,7 +425,7 @@ static void reply_open_and_X_send(struct ntvfs_request *ntvfs)
SMBSRV_VWV_RESERVED(17, 2);
}
- req->chained_fnum = oi->openx.out.file.fnum;
+ req->chained_fnum = SVAL(req->out.vwv, VWV(2));
smbsrv_chain_reply(req);
}
@@ -475,7 +477,7 @@ static void reply_mknew_send(struct ntvfs_request *ntvfs)
/* build the reply */
smbsrv_setup_reply(req, 1, 0);
- SSVAL(req->out.vwv, VWV(0), oi->mknew.out.file.fnum);
+ smbsrv_push_fnum(req->out.vwv, VWV(0), oi->mknew.out.file.ntvfs);
smbsrv_send_reply(req);
}
@@ -524,7 +526,7 @@ static void reply_ctemp_send(struct ntvfs_request *ntvfs)
/* build the reply */
smbsrv_setup_reply(req, 1, 0);
- SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.file.fnum);
+ smbsrv_push_fnum(req->out.vwv, VWV(0), oi->ctemp.out.file.ntvfs);
/* the returned filename is relative to the directory */
req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
@@ -599,12 +601,16 @@ void smbsrv_reply_readbraw(struct smbsrv_request *req)
goto failed;
}
- io.readbraw.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io.readbraw.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
+ if (!io.readbraw.in.file.ntvfs) {
+ goto failed;
+ }
+
/* the 64 bit variant */
if (req->in.wct == 10) {
uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
@@ -695,17 +701,18 @@ void smbsrv_reply_lockread(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->lockread.level = RAW_READ_LOCKREAD;
- io->lockread.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->lockread.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
-
+
/* setup the reply packet assuming the maximum possible read */
smbsrv_setup_reply(req, 5, 3 + io->lockread.in.count);
/* tell the backend where to put the data */
io->lockread.out.data = req->out.data + 3;
+ SMBSRV_CHECK_FILE_HANDLE(io->lockread.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
}
@@ -749,17 +756,18 @@ void smbsrv_reply_read(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->read.level = RAW_READ_READ;
- io->read.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->read.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io->read.in.count = SVAL(req->in.vwv, VWV(1));
io->read.in.offset = IVAL(req->in.vwv, VWV(2));
io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
-
+
/* setup the reply packet assuming the maximum possible read */
smbsrv_setup_reply(req, 5, 3 + io->read.in.count);
/* tell the backend where to put the data */
io->read.out.data = req->out.data + 3;
+ SMBSRV_CHECK_FILE_HANDLE(io->read.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
}
@@ -812,7 +820,7 @@ void smbsrv_reply_read_and_X(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->readx.level = RAW_READ_READX;
- io->readx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
+ io->readx.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(2));
io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
@@ -847,6 +855,7 @@ void smbsrv_reply_read_and_X(struct smbsrv_request *req)
io->readx.out.data = req->out.data;
}
+ SMBSRV_CHECK_FILE_HANDLE(io->readx.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
}
@@ -890,7 +899,7 @@ void smbsrv_reply_writeunlock(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
- io->writeunlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->writeunlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
@@ -908,6 +917,7 @@ void smbsrv_reply_writeunlock(struct smbsrv_request *req)
return;
}
+ SMBSRV_CHECK_FILE_HANDLE(io->writeunlock.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
}
@@ -943,7 +953,7 @@ void smbsrv_reply_write(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->write.level = RAW_WRITE_WRITE;
- io->write.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->write.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io->write.in.count = SVAL(req->in.vwv, VWV(1));
io->write.in.offset = IVAL(req->in.vwv, VWV(2));
io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
@@ -961,6 +971,7 @@ void smbsrv_reply_write(struct smbsrv_request *req)
return;
}
+ SMBSRV_CHECK_FILE_HANDLE(io->write.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
}
@@ -1003,7 +1014,7 @@ void smbsrv_reply_write_and_X(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->writex.level = RAW_WRITE_WRITEX;
- io->writex.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
+ io->writex.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2));
io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
@@ -1021,8 +1032,9 @@ void smbsrv_reply_write_and_X(struct smbsrv_request *req)
if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
smbsrv_send_error(req, NT_STATUS_FOOBAR);
return;
- }
+ }
+ SMBSRV_CHECK_FILE_HANDLE(io->writex.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
}
@@ -1056,10 +1068,11 @@ void smbsrv_reply_lseek(struct smbsrv_request *req)
SMBSRV_TALLOC_IO_PTR(io, union smb_seek);
SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- io->lseek.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->lseek.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io->lseek.in.mode = SVAL(req->in.vwv, VWV(1));
io->lseek.in.offset = IVALS(req->in.vwv, VWV(2));
+ SMBSRV_CHECK_FILE_HANDLE(io->lseek.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req->ntvfs, io));
}
@@ -1076,46 +1089,18 @@ void smbsrv_reply_flush(struct smbsrv_request *req)
SMBSRV_TALLOC_IO_PTR(io, union smb_flush);
SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- fnum = req_fnum(req, req->in.vwv, VWV(0));
-
+ fnum = SVAL(req->in.vwv, VWV(0));
if (fnum == 0xFFFF) {
io->flush_all.level = RAW_FLUSH_ALL;
} else {
io->flush.level = RAW_FLUSH_FLUSH;
- io->flush.in.file.fnum = fnum;
+ io->flush.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
+ SMBSRV_CHECK_FILE_HANDLE(io->flush.in.file.ntvfs);
}
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req->ntvfs, io));
}
-
-/****************************************************************************
- Reply to a exit. This closes all files open by a smbpid
-****************************************************************************/
-void smbsrv_reply_exit(struct smbsrv_request *req)
-{
- NTSTATUS status;
- struct smbsrv_tcon *tcon;
- SMBSRV_CHECK_WCT(req, 0);
-
- for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
- req->tcon = tcon;
- SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
- status = ntvfs_exit(req->ntvfs);
- talloc_free(req->ntvfs);
- req->ntvfs = NULL;
- req->tcon = NULL;
- if (!NT_STATUS_IS_OK(status)) {
- smbsrv_send_error(req, status);
- return;
- }
- }
-
- smbsrv_setup_reply(req, 0, 0);
- smbsrv_send_reply(req);
-}
-
-
/****************************************************************************
Reply to a close
@@ -1131,9 +1116,10 @@ void smbsrv_reply_close(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
io->close.level = RAW_CLOSE_CLOSE;
- io->close.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->close.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
+ SMBSRV_CHECK_FILE_HANDLE(io->close.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
}
@@ -1171,12 +1157,12 @@ void smbsrv_reply_writeclose(struct smbsrv_request *req)
SMBSRV_TALLOC_IO_PTR(io, union smb_write);
SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- io->writeclose.level = RAW_WRITE_WRITECLOSE;
- io->writeclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
- io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
- io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
- io->writeclose.in.data = req->in.data + 1;
+ io->writeclose.level = RAW_WRITE_WRITECLOSE;
+ io->writeclose.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
+ io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
+ io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
+ io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
+ io->writeclose.in.data = req->in.data + 1;
/* make sure they gave us the data they promised */
if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
@@ -1184,6 +1170,7 @@ void smbsrv_reply_writeclose(struct smbsrv_request *req)
return;
}
+ SMBSRV_CHECK_FILE_HANDLE(io->writeclose.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
}
@@ -1200,10 +1187,11 @@ void smbsrv_reply_lock(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
lck->lock.level = RAW_LOCK_LOCK;
- lck->lock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ lck->lock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
+ SMBSRV_CHECK_FILE_HANDLE(lck->lock.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
}
@@ -1221,10 +1209,11 @@ void smbsrv_reply_unlock(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
lck->unlock.level = RAW_LOCK_UNLOCK;
- lck->unlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ lck->unlock.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
+ SMBSRV_CHECK_FILE_HANDLE(lck->unlock.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
}
@@ -1234,14 +1223,27 @@ void smbsrv_reply_unlock(struct smbsrv_request *req)
****************************************************************************/
void smbsrv_reply_tdis(struct smbsrv_request *req)
{
+ struct smbsrv_handle *h, *nh;
+
SMBSRV_CHECK_WCT(req, 0);
+ /*
+ * TODO: cancel all pending requests on this tcon
+ */
+
+ /*
+ * close all handles on this tcon
+ */
+ for (h=req->tcon->handles.list; h; h=nh) {
+ nh = h->next;
+ talloc_free(h);
+ }
+
+ /* finaly destroy the tcon */
talloc_free(req->tcon);
req->tcon = NULL;
- /* construct reply */
smbsrv_setup_reply(req, 0, 0);
-
smbsrv_send_reply(req);
}
@@ -1292,7 +1294,7 @@ static void reply_printopen_send(struct ntvfs_request *ntvfs)
/* construct reply */
smbsrv_setup_reply(req, 1, 0);
- SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
+ smbsrv_push_fnum(req->out.vwv, VWV(0), oi->openold.out.file.ntvfs);
smbsrv_send_reply(req);
}
@@ -1330,9 +1332,10 @@ void smbsrv_reply_printclose(struct smbsrv_request *req)
SMBSRV_TALLOC_IO_PTR(io, union smb_close);
SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- io->splclose.level = RAW_CLOSE_SPLCLOSE;
- io->splclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ io->splclose.level = RAW_CLOSE_SPLCLOSE;
+ io->splclose.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
+ SMBSRV_CHECK_FILE_HANDLE(io->splclose.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
}
@@ -1414,16 +1417,15 @@ void smbsrv_reply_printwrite(struct smbsrv_request *req)
SMBSRV_TALLOC_IO_PTR(io, union smb_write);
SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- io->splwrite.level = RAW_WRITE_SPLWRITE;
-
if (req->in.data_size < 3) {
smbsrv_send_error(req, NT_STATUS_FOOBAR);
return;
}
- io->splwrite.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->splwrite.in.count = SVAL(req->in.data, 1);
- io->splwrite.in.data = req->in.data + 3;
+ io->splwrite.level = RAW_WRITE_SPLWRITE;
+ io->splwrite.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
+ io->splwrite.in.count = SVAL(req->in.data, 1);
+ io->splwrite.in.data = req->in.data + 3;
/* make sure they gave us the data they promised */
if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
@@ -1431,6 +1433,7 @@ void smbsrv_reply_printwrite(struct smbsrv_request *req)
return;
}
+ SMBSRV_CHECK_FILE_HANDLE(io->splwrite.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
}
@@ -1621,7 +1624,7 @@ void smbsrv_reply_lockingX(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
lck->lockx.level = RAW_LOCK_LOCKX;
- lck->lockx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
+ lck->lockx.in.file.ntvfs= smbsrv_pull_fnum(req, req->in.vwv, VWV(2));
lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
@@ -1676,6 +1679,7 @@ void smbsrv_reply_lockingX(struct smbsrv_request *req)
p += lck_size;
}
+ SMBSRV_CHECK_FILE_HANDLE(lck->lockx.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
}
@@ -1702,11 +1706,12 @@ void smbsrv_reply_setattrE(struct smbsrv_request *req)
SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
info->setattre.level = RAW_SFILEINFO_SETATTRE;
- info->setattre.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ info->setattre.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
+ SMBSRV_CHECK_FILE_HANDLE(info->setattre.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req->ntvfs, info));
}
@@ -1765,9 +1770,10 @@ void smbsrv_reply_getattrE(struct smbsrv_request *req)
SMBSRV_TALLOC_IO_PTR(info, union smb_fileinfo);
SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
- info->getattr.level = RAW_FILEINFO_GETATTRE;
- info->getattr.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
+ info->getattr.level = RAW_FILEINFO_GETATTRE;
+ info->getattr.in.file.ntvfs = smbsrv_pull_fnum(req, req->in.vwv, VWV(0));
+ SMBSRV_CHECK_FILE_HANDLE(info->getattr.in.file.ntvfs);
SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req->ntvfs, info));
}
@@ -1988,26 +1994,81 @@ void smbsrv_reply_sesssetup(struct smbsrv_request *req)
}
/****************************************************************************
+ Reply to a exit. This closes all files open by a smbpid
+****************************************************************************/
+void smbsrv_reply_exit(struct smbsrv_request *req)
+{
+ struct smbsrv_handle_session_item *i, *ni;
+ struct smbsrv_handle *h;
+ struct smbsrv_tcon *tcon;
+ uint16_t smbpid;
+
+ SMBSRV_CHECK_WCT(req, 0);
+
+ smbpid = SVAL(req->in.hdr,HDR_PID);
+
+ /* first destroy all handles, which have the same PID as the request */
+ for (i=req->session->handles; i; i=ni) {
+ ni = i->next;
+ h = i->handle;
+ if (h->smbpid != smbpid) continue;
+
+ talloc_free(h);
+ }
+
+ /*
+ * then let the ntvfs backends proxy the call if they want to,
+ * but we didn't check the return value of the backends,
+ * as for the SMB client the call succeed
+ */
+ for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
+ req->tcon = tcon;
+ SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
+ ntvfs_exit(req->ntvfs);
+ talloc_free(req->ntvfs);
+ req->ntvfs = NULL;
+ req->tcon = NULL;
+ }
+
+ smbsrv_setup_reply(req, 0, 0);
+ smbsrv_send_reply(req);
+}
+
+/****************************************************************************
Reply to a SMBulogoffX.
****************************************************************************/
void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
{
+ struct smbsrv_handle_session_item *i, *ni;
+ struct smbsrv_handle *h;
struct smbsrv_tcon *tcon;
- NTSTATUS status;
- /* in user level security we are supposed to close any files
- open by this user on all open tree connects */
+ SMBSRV_CHECK_WCT(req, 2);
+
+ /*
+ * TODO: cancel all pending requests
+ */
+
+
+ /* destroy all handles */
+ for (i=req->session->handles; i; i=ni) {
+ ni = i->next;
+ h = i->handle;
+ talloc_free(h);
+ }
+
+ /*
+ * then let the ntvfs backends proxy the call if they want to,
+ * but we didn't check the return value of the backends,
+ * as for the SMB client the call succeed
+ */
for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
req->tcon = tcon;
SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
- status = ntvfs_logoff(req->ntvfs);
+ ntvfs_logoff(req->ntvfs);
talloc_free(req->ntvfs);
req->ntvfs = NULL;
req->tcon = NULL;
- if (!NT_STATUS_IS_OK(status)) {
- smbsrv_send_error(req, status);
- return;
- }
}
talloc_free(req->session);
@@ -2018,7 +2079,7 @@ void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
SSVAL(req->out.vwv, VWV(1), 0);
-
+
smbsrv_chain_reply(req);
}
@@ -2067,7 +2128,7 @@ static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs)
SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
/* the rest of the parameters are not aligned! */
- SSVAL(req->out.vwv, 5, io->ntcreatex.out.file.fnum);
+ smbsrv_push_fnum(req->out.vwv, 5, io->ntcreatex.out.file.ntvfs);
SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
@@ -2080,7 +2141,7 @@ static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs)
SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
- req->chained_fnum = io->ntcreatex.out.file.fnum;
+ req->chained_fnum = SVAL(req->out.vwv, 5);
smbsrv_chain_reply(req);
}
diff --git a/source4/smb_server/smb/request.c b/source4/smb_server/smb/request.c
index 21f89f40f9..2896a44d29 100644
--- a/source4/smb_server/smb/request.c
+++ b/source4/smb_server/smb/request.c
@@ -636,10 +636,100 @@ BOOL req_data_oob(struct smbsrv_request *req, const uint8_t *ptr, uint32_t count
/*
pull an open file handle from a packet, taking account of the chained_fnum
*/
-uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
+static uint16_t req_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
{
if (req->chained_fnum != -1) {
return req->chained_fnum;
}
return SVAL(base, offset);
}
+
+struct ntvfs_handle *smbsrv_pull_fnum(struct smbsrv_request *req, const uint8_t *base, uint_t offset)
+{
+ struct smbsrv_handle *handle;
+ uint16_t fnum = req_fnum(req, base, offset);
+
+ handle = smbsrv_smb_handle_find(req->tcon, fnum, req->request_time);
+ if (!handle) {
+ return NULL;
+ }
+
+ return handle->ntvfs;
+}
+
+void smbsrv_push_fnum(uint8_t *base, uint_t offset, struct ntvfs_handle *ntvfs)
+{
+ struct smbsrv_handle *handle = talloc_get_type(ntvfs->frontend_data.private_data,
+ struct smbsrv_handle);
+ SSVAL(base, offset, handle->hid);
+}
+
+NTSTATUS smbsrv_handle_create_new(void *private_data, struct ntvfs_request *ntvfs, struct ntvfs_handle **_h)
+{
+ struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data,
+ struct smbsrv_request);
+ struct smbsrv_handle *handle;
+ struct ntvfs_handle *h;
+
+ handle = smbsrv_handle_new(req);
+ if (!handle) return NT_STATUS_INSUFFICIENT_RESOURCES;
+
+ h = talloc_zero(handle, struct ntvfs_handle);
+ if (!h) goto nomem;
+
+ /*
+ * note: we don't set handle->ntvfs yet,
+ * this will be done by smbsrv_handle_make_valid()
+ * this makes sure the handle is invalid for clients
+ * until the ntvfs subsystem has made it valid
+ */
+ h->ctx = ntvfs->ctx;
+ h->session_info = ntvfs->session_info;
+ h->smbpid = ntvfs->smbpid;
+
+ h->frontend_data.private_data = handle;
+
+ *_h = h;
+ return NT_STATUS_OK;
+nomem:
+ talloc_free(handle);
+ return NT_STATUS_NO_MEMORY;
+}
+
+NTSTATUS smbsrv_handle_make_valid(void *private_data, struct ntvfs_handle *h)
+{
+ struct smbsrv_tcon *tcon = talloc_get_type(private_data, struct smbsrv_tcon);
+ struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data,
+ struct smbsrv_handle);
+ /* this tells the frontend that the handle is valid */
+ handle->ntvfs = h;
+ /* this moves the smbsrv_request to the smbsrv_tcon memory context */
+ talloc_steal(tcon, handle);
+ return NT_STATUS_OK;
+}
+
+void smbsrv_handle_destroy(void *private_data, struct ntvfs_handle *h)
+{
+ struct smbsrv_handle *handle = talloc_get_type(h->frontend_data.private_data,
+ struct smbsrv_handle);
+ talloc_free(handle);
+}
+
+struct ntvfs_handle *smbsrv_handle_search_by_wire_key(void *private_data, struct ntvfs_request *ntvfs, const DATA_BLOB *key)
+{
+ struct smbsrv_request *req = talloc_get_type(ntvfs->frontend_data.private_data,
+ struct smbsrv_request);
+
+ if (key->length != 2) return NULL;
+
+ return smbsrv_pull_fnum(req, key->data, 0);
+}
+
+DATA_BLOB smbsrv_handle_get_wire_key(void *private_data, struct ntvfs_handle *handle, TALLOC_CTX *mem_ctx)
+{
+ uint8_t key[2];
+
+ smbsrv_push_fnum(key, 0, handle);
+
+ return data_blob_talloc(mem_ctx, key, sizeof(key));
+}
diff --git a/source4/smb_server/smb/service.c b/source4/smb_server/smb/service.c
index 13ef268a98..7c703c8920 100644
--- a/source4/smb_server/smb/service.c
+++ b/source4/smb_server/smb/service.c
@@ -110,7 +110,19 @@ static NTSTATUS make_connection_snum(struct smbsrv_request *req,
status = ntvfs_set_addr_callbacks(tcon->ntvfs, smbsrv_get_my_addr, smbsrv_get_peer_addr, req->smb_conn);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("make_connection: NTVFS failed to set the oplock handler!\n"));
+ DEBUG(0,("make_connection: NTVFS failed to set the addr callbacks!\n"));
+ goto failed;
+ }
+
+ status = ntvfs_set_handle_callbacks(tcon->ntvfs,
+ smbsrv_handle_create_new,
+ smbsrv_handle_make_valid,
+ smbsrv_handle_destroy,
+ smbsrv_handle_search_by_wire_key,
+ smbsrv_handle_get_wire_key,
+ tcon);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("make_connection: NTVFS failed to set the handle callbacks!\n"));
goto failed;
}
diff --git a/source4/smb_server/smb/trans2.c b/source4/smb_server/smb/trans2.c
index 1145a08426..69fa65010c 100644
--- a/source4/smb_server/smb/trans2.c
+++ b/source4/smb_server/smb/trans2.c
@@ -447,7 +447,7 @@ static NTSTATUS trans2_open_send(struct trans_op *op)
trans2_setup_reply(trans, 30, 0, 0);
- SSVAL(trans->out.params.data, VWV(0), io->t2open.out.file.fnum);
+ smbsrv_push_fnum(trans->out.params.data, VWV(0), io->t2open.out.file.ntvfs);
SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);
srv_push_dos_date3(req->smb_conn, trans->out.params.data,
VWV(2), io->t2open.out.write_time);
@@ -847,7 +847,8 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op
struct smb_trans2 *trans = op->trans;
union smb_fileinfo *st;
NTSTATUS status;
- uint16_t level, fnum;
+ uint16_t level;
+ struct ntvfs_handle *h;
/* make sure we got enough parameters */
if (trans->in.params.length < 4) {
@@ -857,10 +858,10 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op
st = talloc(op, union smb_fileinfo);
NT_STATUS_HAVE_NO_MEMORY(st);
- fnum = SVAL(trans->in.params.data, 0);
+ h = smbsrv_pull_fnum(req, trans->in.params.data, 0);
level = SVAL(trans->in.params.data, 2);
- st->generic.in.file.fnum = fnum;
+ st->generic.in.file.ntvfs = h;
/* work out the backend level - we make it 1-1 in the header */
st->generic.level = (enum smb_fileinfo_level)level;
if (st->generic.level >= RAW_FILEINFO_GENERIC) {
@@ -877,6 +878,7 @@ static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op
op->op_info = st;
op->send_fn = trans2_fileinfo_send;
+ SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs);
return ntvfs_qfileinfo(req->ntvfs, st);
}
@@ -985,7 +987,8 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *
struct smb_trans2 *trans = op->trans;
union smb_setfileinfo *st;
NTSTATUS status;
- uint16_t level, fnum;
+ uint16_t level;
+ struct ntvfs_handle *h;
/* make sure we got enough parameters */
if (trans->in.params.length < 4) {
@@ -995,10 +998,10 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *
st = talloc(op, union smb_setfileinfo);
NT_STATUS_HAVE_NO_MEMORY(st);
- fnum = SVAL(trans->in.params.data, 0);
+ h = smbsrv_pull_fnum(req, trans->in.params.data, 0);
level = SVAL(trans->in.params.data, 2);
- st->generic.in.file.fnum = fnum;
+ st->generic.in.file.ntvfs = h;
/* work out the backend level - we make it 1-1 in the header */
st->generic.level = (enum smb_setfileinfo_level)level;
if (st->generic.level >= RAW_SFILEINFO_GENERIC) {
@@ -1011,6 +1014,7 @@ static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *
op->op_info = st;
op->send_fn = trans2_simple_send;
+ SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st->generic.in.file.ntvfs);
return ntvfs_setfileinfo(req->ntvfs, st);
}
diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h
index 12b12692f3..7c9ba6dc63 100644
--- a/source4/smb_server/smb_server.h
+++ b/source4/smb_server/smb_server.h
@@ -57,7 +57,19 @@ struct smbsrv_sessions_context {
/* also kept as a link list so it can be enumerated by
the management code */
struct smbsrv_session *list;
-} sessions;
+};
+
+struct smbsrv_handles_context {
+ /* an id tree used to allocate file handles */
+ struct idr_context *idtree_hid;
+
+ /* this is the limit of handle values for this context */
+ uint64_t idtree_limit;
+
+ /* also kept as a link list so it can be enumerated by
+ the management code */
+ struct smbsrv_handle *list;
+};
/* the current user context for a request */
struct smbsrv_session {
@@ -65,8 +77,18 @@ struct smbsrv_session {
struct smbsrv_connection *smb_conn;
+ /*
+ * in SMB2 tcons belong to just one session
+ * and not to the whole connection
+ */
struct smbsrv_tcons_context smb2_tcons;
+ /*
+ * the open file handles for this session,
+ * used for SMBexit, SMBulogoff and SMB2 SessionLogoff
+ */
+ struct smbsrv_handle_session_item *handles;
+
/*
* an index passed over the wire:
* - 16 bit for smb
@@ -78,7 +100,7 @@ struct smbsrv_session {
struct auth_session_info *session_info;
- /* some statictics for the management tools */
+ /* some statistics for the management tools */
struct {
/* the time when the session setup started */
struct timeval connect_time;
@@ -99,6 +121,9 @@ struct smbsrv_tcon {
/* the server context that this was created on */
struct smbsrv_connection *smb_conn;
+ /* the open file handles on this tcon */
+ struct smbsrv_handles_context handles;
+
/*
* an index passed over the wire:
* - 16 bit for smb
@@ -124,7 +149,7 @@ struct smbsrv_tcon {
struct smbsrv_session *session;
} smb2;
- /* some statictics for the management tools */
+ /* some statistics for the management tools */
struct {
/* the time when the tree connect started */
struct timeval connect_time;
@@ -133,6 +158,54 @@ struct smbsrv_tcon {
} statistics;
};
+struct smbsrv_handle {
+ struct smbsrv_handle *next, *prev;
+
+ /* the tcon the handle belongs to */
+ struct smbsrv_tcon *tcon;
+
+ /* the session the handle was opened on */
+ struct smbsrv_session *session;
+
+ /* the smbpid used on the open, used for SMBexit */
+ uint16_t smbpid;
+
+ /*
+ * this is for adding the handle into a linked list
+ * on the smbsrv_session, we can't use *next,*prev
+ * for this because they're used for the linked list on the
+ * smbsrv_tcon
+ */
+ struct smbsrv_handle_session_item {
+ struct smbsrv_handle_session_item *prev, *next;
+ struct smbsrv_handle *handle;
+ } session_item;
+
+ /*
+ * the value passed over the wire
+ * - 16 bit for smb
+ * - 64 bit for smb2
+ * Note: for SMB2 handles are 128 bit
+ * we'll fill the 2nd 64 bit with:
+ * - 32 bit TID
+ * - 32 bit 0xFFFFFFFF
+ */
+ uint64_t hid;
+
+ /*
+ * the ntvfs handle passed to the ntvfs backend
+ */
+ struct ntvfs_handle *ntvfs;
+
+ /* some statistics for the management tools */
+ struct {
+ /* the time when the tree connect started */
+ struct timeval open_time;
+ /* the time when the last request comes in */
+ struct timeval last_use_time;
+ } statistics;
+};
+
/* a set of flags to control handling of request structures */
#define SMBSRV_REQ_CONTROL_LARGE (1<<1) /* allow replies larger than max_xmit */
@@ -266,7 +339,7 @@ struct smbsrv_connection {
struct nbt_name *calling_name;
} negotiate;
- /* the context associated with open tree connects on a smb socket */
+ /* the context associated with open tree connects on a smb socket, not for SMB2 */
struct smbsrv_tcons_context smb_tcons;
/* context associated with currently valid session setups */
@@ -283,7 +356,7 @@ struct smbsrv_connection {
} *requests;
struct smb_signing_context signing;
-
+
struct stream_connection *connection;
/* this holds a partially received request */
@@ -350,6 +423,27 @@ struct smbsrv_connection {
smbsrv_send_error(req, NT_STATUS_NO_MEMORY); \
return; \
} \
+ req->ntvfs->frontend_data.private_data = req; \
+} while (0)
+
+#define SMBSRV_CHECK_FILE_HANDLE(handle) do { \
+ if (!handle) { \
+ smbsrv_send_error(req, NT_STATUS_INVALID_HANDLE); \
+ return; \
+ } \
+} while (0)
+
+#define SMBSRV_CHECK_FILE_HANDLE_ERROR(handle, _status) do { \
+ if (!handle) { \
+ smbsrv_send_error(req, _status); \
+ return; \
+ } \
+} while (0)
+
+#define SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(handle) do { \
+ if (!handle) { \
+ return NT_STATUS_INVALID_HANDLE; \
+ } \
} while (0)
/*
diff --git a/source4/smb_server/tcon.c b/source4/smb_server/tcon.c
index 8b100d11ce..dbd0677df1 100644
--- a/source4/smb_server/tcon.c
+++ b/source4/smb_server/tcon.c
@@ -3,6 +3,7 @@
Manage smbsrv_tcon structures
Copyright (C) Andrew Tridgell 1998
Copyright (C) Alexander Bokovoy 2002
+ Copyright (C) Stefan Metzmacher 2005-2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -109,6 +110,7 @@ static int smbsrv_tcon_destructor(void *ptr)
/* tell the ntvfs backend that we are disconnecting */
if (tcon->ntvfs) {
ntvfs_disconnect(tcon->ntvfs);
+ tcon->ntvfs = NULL;
}
if (tcon->smb2.session) {
@@ -132,6 +134,7 @@ static struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn,
TALLOC_CTX *mem_ctx;
struct smbsrv_tcons_context *tcons_ctx;
struct smbsrv_tcon *tcon;
+ NTSTATUS status;
int i;
if (smb_sess) {
@@ -149,6 +152,16 @@ static struct smbsrv_tcon *smbsrv_tcon_new(struct smbsrv_connection *smb_conn,
tcon->share_name = talloc_strdup(tcon, share_name);
if (!tcon->share_name) goto failed;
+ /*
+ * the use -1 here, because we don't want to give away the wildcard
+ * fnum used in SMBflush
+ */
+ status = smbsrv_init_handles(tcon, UINT16_MAX - 1);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1,("ERROR! failed to init handles: %s\n", nt_errstr(status)));
+ goto failed;
+ }
+
i = idr_get_new_random(tcons_ctx->idtree_tid, tcon, tcons_ctx->idtree_limit);
if (i == -1) {
DEBUG(1,("ERROR! Out of connection structures\n"));