struct smbcli_tree *tree;
struct smbcli_transport *transport;
struct smbsrv_tcon *tcon;
- const char *map_calls;
+ const struct ntvfs_ops *ops;
};
/*
connect to a share - used when a tree_connect operation comes in.
*/
-static NTSTATUS cvfs_connect(struct smbsrv_request *req, const char *sharename)
+static NTSTATUS cvfs_connect(struct smbsrv_request *req, const char *sharename, int depth)
{
struct smbsrv_tcon *tcon = req->tcon;
NTSTATUS status;
struct cvfs_private *private;
- const char *map_calls;
const char *host, *user, *pass, *domain, *remote_share;
/* Here we need to determine which server to connect to.
}
ZERO_STRUCTP(private);
- req->tcon->ntvfs_private = (void *)private;
+ ntvfs_set_private(req->tcon, depth, private);
status = smbcli_tree_full_connection(&private->tree,
"vfs_cifs",
private->transport = private->tree->session->transport;
private->tree->session->pid = SVAL(req->in.hdr, HDR_PID);
private->tcon = req->tcon;
+ private->ops = ntvfs_backend_byname("cifs", NTVFS_DISK);
tcon->fs_type = talloc_strdup(tcon, "NTFS");
tcon->dev_type = talloc_strdup(tcon, "A:");
- map_calls = lp_parm_string(req->tcon->service, "cifs", "map calls");
- if (map_calls) {
- private->map_calls = talloc_strdup(tcon, map_calls);
- }
-
- /* if we are mapping trans2, then we need to give a trans2
- pointer in the operations structure */
- if (private->map_calls && in_list("trans2", private->map_calls, True)) {
- struct ntvfs_ops *ops = talloc_memdup(tcon, tcon->ntvfs_ops,sizeof(*ops));
- static NTSTATUS cvfs_trans2(struct smbsrv_request *,struct smb_trans2 *);
- if (!ops) {
- return NT_STATUS_NO_MEMORY;
- }
- ops->trans2 = cvfs_trans2;
- tcon->ntvfs_ops = ops;
- }
-
/* we need to receive oplock break requests from the server */
smbcli_oplock_handler(private->transport, oplock_handler, private);
smbcli_transport_idle_handler(private->transport, idle_func, 1, private);
/*
disconnect from a share
*/
-static NTSTATUS cvfs_disconnect(struct smbsrv_tcon *tcon)
+static NTSTATUS cvfs_disconnect(struct smbsrv_tcon *tcon, int depth)
{
- struct cvfs_private *private = tcon->ntvfs_private;
+ struct cvfs_private *private = tcon->ntvfs_private_list[depth];
smb_tree_disconnect(private->tree);
smbcli_tree_close(private->tree);
*/
static NTSTATUS cvfs_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
/* see if the front end will allow us to perform this
*/
static NTSTATUS cvfs_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
/* see if the front end will allow us to perform this
*/
static NTSTATUS cvfs_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_setpathinfo(struct smbsrv_request *req, union smb_setfileinfo *st)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_open(struct smbsrv_request *req, union smb_open *io)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
- if (private->map_calls && in_list("open", private->map_calls, True) &&
- io->generic.level != RAW_OPEN_GENERIC) {
- return ntvfs_map_open(req, io);
- }
-
if (!req->async.send_fn) {
return smb_raw_open(private->tree, req, io);
}
*/
static NTSTATUS cvfs_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_rename(struct smbsrv_request *req, union smb_rename *ren)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_read(struct smbsrv_request *req, union smb_read *rd)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_write(struct smbsrv_request *req, union smb_write *wr)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_close(struct smbsrv_request *req, union smb_close *io)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_lock(struct smbsrv_request *req, union smb_lock *lck)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
static NTSTATUS cvfs_setfileinfo(struct smbsrv_request *req,
union smb_setfileinfo *info)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
*/
static NTSTATUS cvfs_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
return smb_raw_search_first(private->tree, req, io, search_private, callback);
}
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
return smb_raw_search_next(private->tree, req, io, search_private, callback);
}
/* close a search */
static NTSTATUS cvfs_search_close(struct smbsrv_request *req, union smb_search_close *io)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
return smb_raw_search_close(private->tree, io);
}
/* raw trans2 */
static NTSTATUS cvfs_trans2(struct smbsrv_request *req, struct smb_trans2 *trans2)
{
- struct cvfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(cvfs_private, private, req);
struct smbcli_request *c_req;
if (!req->async.send_fn) {
ops.search_close = cvfs_search_close;
ops.trans = cvfs_trans;
- /* only define this one for trans2 testing */
- ops.trans2 = NULL;
+ if (lp_parm_bool(-1, "cifs", "maptrans2", False)) {
+ ops.trans2 = cvfs_trans2;
+ }
/* register ourselves with the NTVFS subsystem. We register
under the name 'cifs'. */
/*
connect to a share - always works
*/
-static NTSTATUS ipc_connect(struct smbsrv_request *req, const char *sharename)
+static NTSTATUS ipc_connect(struct smbsrv_request *req, const char *sharename, int depth)
{
struct smbsrv_tcon *tcon = req->tcon;
struct ipc_private *private;
if (!private) {
return NT_STATUS_NO_MEMORY;
}
- tcon->ntvfs_private = (void *)private;
+ ntvfs_set_private(tcon, depth, private);
private->pipe_list = NULL;
private->next_fnum = 1;
/*
disconnect from a share
*/
-static NTSTATUS ipc_disconnect(struct smbsrv_tcon *tcon)
+static NTSTATUS ipc_disconnect(struct smbsrv_tcon *tcon, int depth)
{
- struct ipc_private *private = tcon->ntvfs_private;
+ struct ipc_private *private = tcon->ntvfs_private_list[depth];
/* close any pipes that are open. Discard any unread data */
while (private->pipe_list) {
NTSTATUS status;
struct dcesrv_ep_description ep_description;
struct auth_session_info *session_info = NULL;
- struct ipc_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(ipc_private, private, req);
mem_ctx = talloc_init("ipc_open '%s'", fname);
if (!mem_ctx) {
*/
static NTSTATUS ipc_read(struct smbsrv_request *req, union smb_read *rd)
{
- struct ipc_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(ipc_private, private, req);
DATA_BLOB data;
uint16_t fnum;
struct pipe_state *p;
*/
static NTSTATUS ipc_write(struct smbsrv_request *req, union smb_write *wr)
{
- struct ipc_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(ipc_private, private, req);
DATA_BLOB data;
uint16_t fnum;
struct pipe_state *p;
*/
static NTSTATUS ipc_close(struct smbsrv_request *req, union smb_close *io)
{
- struct ipc_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(ipc_private, private, req);
struct pipe_state *p;
if (io->generic.level != RAW_CLOSE_CLOSE) {
static NTSTATUS ipc_dcerpc_cmd(struct smbsrv_request *req, struct smb_trans2 *trans)
{
struct pipe_state *p;
- struct ipc_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(ipc_private, private, req);
NTSTATUS status;
/* the fnum is in setup[1] */
/* SMBtrans - set named pipe state */
static NTSTATUS ipc_set_nm_pipe_state(struct smbsrv_request *req, struct smb_trans2 *trans)
{
+ NTVFS_GET_PRIVATE(ipc_private, private, req);
struct pipe_state *p;
- struct ipc_private *private = req->tcon->ntvfs_private;
/* the fnum is in setup[1] */
p = pipe_state_find(private, trans->in.setup[1]);
/* this is stored in ntvfs_private */
struct nbench_private {
const struct ntvfs_ops *passthru_ops;
- void *passthru_private;
- const struct ntvfs_ops *nbench_ops;
int log_fd;
};
/*
- when we call the next stacked level of NTVFS module we need
- to give it its own private pointer, plus its own NTVFS operations structure.
- Then we need to restore both of these after the call, as the next level could
- modify either of these
+ this is used to call the next module in the ntvfs chain
*/
-#define PASS_THRU(tcon, op, args) do { \
- tcon->ntvfs_private = private->passthru_private; \
- tcon->ntvfs_ops = private->passthru_ops; \
-\
- status = private->passthru_ops->op args; \
-\
- private->passthru_private = tcon->ntvfs_private; \
- private->passthru_ops = tcon->ntvfs_ops; \
-\
- tcon->ntvfs_private = private; \
- tcon->ntvfs_ops = private->nbench_ops; \
-} while (0)
+#define PASS_THRU(tcon, op, args) private->passthru_ops->op args;
/*
this pass through macro operates on request contexts, and disables
#define PASS_THRU_REQ(req, op, args) do { \
void *send_fn_saved = req->async.send_fn; \
req->async.send_fn = NULL; \
- PASS_THRU(req->tcon, op, args); \
+ req->ntvfs_depth++; \
+ status = PASS_THRU(req->tcon, op, args); \
+ req->ntvfs_depth--; \
req->async.send_fn = send_fn_saved; \
} while (0)
/*
connect to a share - used when a tree_connect operation comes in.
*/
-static NTSTATUS nbench_connect(struct smbsrv_request *req, const char *sharename)
+static NTSTATUS nbench_connect(struct smbsrv_request *req, const char *sharename, int depth)
{
struct nbench_private *private;
const char *passthru;
NTSTATUS status;
char *logname = NULL;
+ const char **handlers = lp_ntvfs_handler(req->tcon->service);
private = talloc_p(req->tcon, struct nbench_private);
if (!private) {
return NT_STATUS_NO_MEMORY;
}
- asprintf(&logname, "/tmp/nbenchlog.%u", getpid());
+ asprintf(&logname, "/tmp/nbenchlog%d.%u", depth, getpid());
private->log_fd = open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
free(logname);
return NT_STATUS_UNSUCCESSFUL;
}
- passthru = lp_parm_string(req->tcon->service, "nbench", "passthru");
-
- private->passthru_private = NULL;
- private->nbench_ops = req->tcon->ntvfs_ops;
- private->passthru_ops = ntvfs_backend_byname(passthru, NTVFS_DISK);
+ private->passthru_ops = ntvfs_backend_byname(handlers[depth+1], NTVFS_DISK);
if (!private->passthru_ops) {
DEBUG(0,("Unable to connect to '%s' pass through backend\n", passthru));
return NT_STATUS_UNSUCCESSFUL;
}
+
+ ntvfs_set_private(req->tcon, depth, private);
- PASS_THRU(req->tcon, connect, (req, sharename));
+ PASS_THRU(req->tcon, connect, (req, sharename, depth+1));
return status;
}
/*
disconnect from a share
*/
-static NTSTATUS nbench_disconnect(struct smbsrv_tcon *tcon)
+static NTSTATUS nbench_disconnect(struct smbsrv_tcon *tcon, int depth)
{
- struct nbench_private *private = tcon->ntvfs_private;
+ struct nbench_private *private = tcon->ntvfs_private_list[depth];
NTSTATUS status;
- PASS_THRU(tcon, disconnect, (tcon));
-
close(private->log_fd);
+ PASS_THRU(tcon, disconnect, (tcon, depth+1));
+
return status;
}
*/
static NTSTATUS nbench_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, unlink, (req, unl));
*/
static NTSTATUS nbench_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, ioctl, (req, io));
*/
static NTSTATUS nbench_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, chkpath, (req, cp));
*/
static NTSTATUS nbench_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, qpathinfo, (req, info));
*/
static NTSTATUS nbench_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, qfileinfo, (req, info));
*/
static NTSTATUS nbench_setpathinfo(struct smbsrv_request *req, union smb_setfileinfo *st)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, setpathinfo, (req, st));
*/
static NTSTATUS nbench_open(struct smbsrv_request *req, union smb_open *io)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, open, (req, io));
*/
static NTSTATUS nbench_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, mkdir, (req, md));
*/
static NTSTATUS nbench_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, rmdir, (req, rd));
*/
static NTSTATUS nbench_rename(struct smbsrv_request *req, union smb_rename *ren)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, rename, (req, ren));
*/
static NTSTATUS nbench_copy(struct smbsrv_request *req, struct smb_copy *cp)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, copy, (req, cp));
*/
static NTSTATUS nbench_read(struct smbsrv_request *req, union smb_read *rd)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, read, (req, rd));
*/
static NTSTATUS nbench_write(struct smbsrv_request *req, union smb_write *wr)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, write, (req, wr));
*/
static NTSTATUS nbench_seek(struct smbsrv_request *req, struct smb_seek *io)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, seek, (req, io));
*/
static NTSTATUS nbench_flush(struct smbsrv_request *req, struct smb_flush *io)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, flush, (req, io));
*/
static NTSTATUS nbench_close(struct smbsrv_request *req, union smb_close *io)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, close, (req, io));
*/
static NTSTATUS nbench_exit(struct smbsrv_request *req)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, exit, (req));
*/
static NTSTATUS nbench_lock(struct smbsrv_request *req, union smb_lock *lck)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, lock, (req, lck));
static NTSTATUS nbench_setfileinfo(struct smbsrv_request *req,
union smb_setfileinfo *info)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, setfileinfo, (req, info));
*/
static NTSTATUS nbench_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, fsinfo, (req, fs));
*/
static NTSTATUS nbench_lpq(struct smbsrv_request *req, union smb_lpq *lpq)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, lpq, (req, lpq));
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, search_first, (req, io, search_private, callback));
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, search_next, (req, io, search_private, callback));
/* close a search */
static NTSTATUS nbench_search_close(struct smbsrv_request *req, union smb_search_close *io)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, search_close, (req, io));
/* SMBtrans - not used on file shares */
static NTSTATUS nbench_trans(struct smbsrv_request *req, struct smb_trans2 *trans2)
{
- struct nbench_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(nbench_private, private, req);
NTSTATUS status;
PASS_THRU_REQ(req, trans, (req,trans2));
enum ntvfs_type type;
/* initial setup */
- NTSTATUS (*connect)(struct smbsrv_request *req, const char *sharename);
- NTSTATUS (*disconnect)(struct smbsrv_tcon *tcon);
+ NTSTATUS (*connect)(struct smbsrv_request *req, const char *sharename, int depth);
+ NTSTATUS (*disconnect)(struct smbsrv_tcon *tcon, int depth);
/* path operations */
NTSTATUS (*unlink)(struct smbsrv_request *req, struct smb_unlink *unl);
int sizeof_smbsrv_tcon;
int sizeof_smbsrv_request;
};
+
+/* useful macro for backends */
+#define NTVFS_GET_PRIVATE(struct_name, name, req) \
+ struct struct_name *name = req->tcon->ntvfs_private_list[req->ntvfs_depth]
*/
NTSTATUS ntvfs_init_connection(struct smbsrv_request *req)
{
- const char *handler = lp_ntvfs_handler(req->tcon->service);
+ const char **handlers = lp_ntvfs_handler(req->tcon->service);
- req->tcon->ntvfs_ops = ntvfs_backend_byname(handler, req->tcon->type);
+ req->tcon->ntvfs_ops = ntvfs_backend_byname(handlers[0], req->tcon->type);
if (!req->tcon->ntvfs_ops) {
- DEBUG(1,("ntvfs_init_connection: failed to find backend=%s, type=%d\n", handler, req->tcon->type));
+ DEBUG(1,("ntvfs_init_connection: failed to find backend=%s, type=%d\n", handlers[0], req->tcon->type));
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_OK;
}
+
+
+/*
+ set the private pointer for a backend
+*/
+void ntvfs_set_private(struct smbsrv_tcon *tcon, int depth, void *value)
+{
+ if (!tcon->ntvfs_private_list) {
+ tcon->ntvfs_private_list = talloc_array_p(tcon, void *, depth+1);
+ } else {
+ tcon->ntvfs_private_list = talloc_realloc_p(tcon->ntvfs_private_list,
+ void *, depth+1);
+ }
+ tcon->ntvfs_private_list[depth] = value;
+}
/*
NTVFS open generic to any mapper
*/
-NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io)
+NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
+ const struct ntvfs_ops *ops)
{
NTSTATUS status;
union smb_open io2;
io2.generic.in.file_attr = io->openx.in.file_attrs;
io2.generic.in.fname = io->openx.in.fname;
- status = req->tcon->ntvfs_ops->open(req, &io2);
+ status = ops->open(req, &io2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
DEBUG(9,("ntvfs_map_open(OPEN): mapped flags=0x%x to access_mask=0x%x and share_access=0x%x\n",
io->open.in.flags, io2.generic.in.access_mask, io2.generic.in.share_access));
- status = req->tcon->ntvfs_ops->open(req, &io2);
+ status = ops->open(req, &io2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/*
NTVFS fsinfo generic to any mapper
*/
-NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
+NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs,
+ const struct ntvfs_ops *ops)
{
NTSTATUS status;
union smb_fsinfo fs2;
/* ask the backend for the generic info */
fs2.generic.level = RAW_QFS_GENERIC;
- status = req->tcon->ntvfs_ops->fsinfo(req, &fs2);
+ status = ops->fsinfo(req, &fs2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/*
NTVFS fileinfo generic to any mapper
*/
-NTSTATUS ntvfs_map_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
+NTSTATUS ntvfs_map_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info,
+ const struct ntvfs_ops *ops)
{
NTSTATUS status;
union smb_fileinfo info2;
info2.generic.level = RAW_FILEINFO_GENERIC;
info2.generic.in.fnum = info->generic.in.fnum;
- status = req->tcon->ntvfs_ops->qfileinfo(req, &info2);
+ status = ops->qfileinfo(req, &info2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/*
NTVFS pathinfo generic to any mapper
*/
-NTSTATUS ntvfs_map_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
+NTSTATUS ntvfs_map_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info,
+ const struct ntvfs_ops *ops)
{
NTSTATUS status;
union smb_fileinfo info2;
info2.generic.level = RAW_FILEINFO_GENERIC;
info2.generic.in.fname = info->generic.in.fname;
- status = req->tcon->ntvfs_ops->qpathinfo(req, &info2);
+ status = ops->qpathinfo(req, &info2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
*/
NTSTATUS pvfs_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct stat st;
if (fs->generic.level != RAW_QFS_GENERIC) {
- return ntvfs_map_fsinfo(req, fs);
+ return ntvfs_map_fsinfo(req, fs, pvfs->ops);
}
if (sys_fsusage(pvfs->base_directory,
*/
NTSTATUS pvfs_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
NTSTATUS status;
struct pvfs_filename *name;
*/
NTSTATUS pvfs_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
NTSTATUS status;
struct pvfs_filename *name;
*/
NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
int fd, flags;
struct pvfs_filename *name;
struct pvfs_file *f;
NTSTATUS status;
if (io->generic.level != RAW_OPEN_GENERIC) {
- return ntvfs_map_open(req, io);
+ return ntvfs_map_open(req, io, pvfs->ops);
}
/* resolve the cifs name to a posix name */
*/
NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_file *f;
if (io->generic.level != RAW_CLOSE_CLOSE) {
*/
NTSTATUS pvfs_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_filename *name;
NTSTATUS status;
if (info->generic.level != RAW_FILEINFO_GENERIC) {
- return ntvfs_map_qpathinfo(req, info);
+ return ntvfs_map_qpathinfo(req, info, pvfs->ops);
}
/* resolve the cifs name to a posix name */
*/
NTSTATUS pvfs_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_file *f;
NTSTATUS status;
if (info->generic.level != RAW_FILEINFO_GENERIC) {
- return ntvfs_map_qfileinfo(req, info);
+ return ntvfs_map_qfileinfo(req, info, pvfs->ops);
}
f = pvfs_find_fd(pvfs, info->generic.in.fnum);
*/
NTSTATUS pvfs_read(struct smbsrv_request *req, union smb_read *rd)
{
- struct pvfs_private *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
ssize_t ret;
struct pvfs_file *f;
*/
NTSTATUS pvfs_rename(struct smbsrv_request *req, union smb_rename *ren)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
NTSTATUS status;
struct pvfs_filename *name1, *name2;
name->stream_name = NULL;
name->has_wildcard = False;
- if (*cifs_name == '\\') {
+ while (*cifs_name == '\\') {
cifs_name++;
}
+ if (*cifs_name == 0) {
+ name->full_name = talloc_asprintf(name, "%s/.", pvfs->base_directory);
+ if (name->full_name == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ return NT_STATUS_OK;
+ }
+
ret = talloc_asprintf(name, "%s/%s", pvfs->base_directory, cifs_name);
if (ret == NULL) {
return NT_STATUS_NO_MEMORY;
p = ret + strlen(pvfs->base_directory) + 1;
+ if (p[strlen(cifs_name)-1] == '\\') {
+ p[strlen(cifs_name)-1] = 0;
+ }
+
/* now do an in-place conversion of '\' to '/', checking
for legal characters */
for (;*p;p++) {
BOOL (*callback)(void *, union smb_search_data *))
{
struct pvfs_dir *dir;
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_search_state *search;
uint_t reply_count;
uint16_t search_attrib;
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_search_state *search;
struct pvfs_dir *dir;
uint_t reply_count, max_count;
BOOL (*callback)(void *, union smb_search_data *))
{
struct pvfs_dir *dir;
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_search_state *search;
uint_t reply_count;
uint16_t search_attrib, max_count;
void *search_private,
BOOL (*callback)(void *, union smb_search_data *))
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_search_state *search;
struct pvfs_dir *dir;
uint_t reply_count;
/* close a search */
NTSTATUS pvfs_search_close(struct smbsrv_request *req, union smb_search_close *io)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_search_state *search;
uint16_t handle;
NTSTATUS pvfs_setfileinfo(struct smbsrv_request *req,
union smb_setfileinfo *info)
{
- struct pvfs_private *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_private, pvfs, req);
struct utimbuf unix_times;
struct pvfs_file *f;
*/
NTSTATUS pvfs_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_dir *dir;
NTSTATUS status;
uint32_t i, total_deleted=0;
*/
NTSTATUS pvfs_write(struct smbsrv_request *req, union smb_write *wr)
{
- struct pvfs_private *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
ssize_t ret;
struct pvfs_file *f;
directory exists (tho it doesn't need to be accessible by the user,
that comes later)
*/
-static NTSTATUS pvfs_connect(struct smbsrv_request *req, const char *sharename)
+static NTSTATUS pvfs_connect(struct smbsrv_request *req, const char *sharename, int depth)
{
struct smbsrv_tcon *tcon = req->tcon;
struct pvfs_state *pvfs;
pvfs->tcon = tcon;
pvfs->base_directory = base_directory;
+ pvfs->ops = ntvfs_backend_byname("posix", NTVFS_DISK);
/* the directory must exist. Note that we deliberately don't
check that it is readable */
tcon->fs_type = talloc_strdup(tcon, "NTFS");
tcon->dev_type = talloc_strdup(tcon, "A:");
- tcon->ntvfs_private = pvfs;
+
+ ntvfs_set_private(tcon, depth, pvfs);
pvfs_setup_options(pvfs);
/*
disconnect from a share
*/
-static NTSTATUS pvfs_disconnect(struct smbsrv_tcon *tcon)
+static NTSTATUS pvfs_disconnect(struct smbsrv_tcon *tcon, int depth)
{
return NT_STATUS_OK;
}
*/
static NTSTATUS pvfs_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
{
- struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
struct pvfs_filename *name;
NTSTATUS status;
} search;
struct pvfs_file *open_files;
+
+ const struct ntvfs_ops *ops;
};
uint16_t next_search_handle;
struct svfs_file *open_files;
+
+ const struct ntvfs_ops *ops;
};
struct svfs_dir {
*/
char *svfs_unix_path(struct smbsrv_request *req, const char *name)
{
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
char *ret;
if (*name != '\\') {
directory exists (tho it doesn't need to be accessible by the user,
that comes later)
*/
-static NTSTATUS svfs_connect(struct smbsrv_request *req, const char *sharename)
+static NTSTATUS svfs_connect(struct smbsrv_request *req, const char *sharename, int depth)
{
struct stat st;
struct smbsrv_tcon *tcon = req->tcon;
struct svfs_private *private;
- tcon->ntvfs_private = talloc_p(tcon, struct svfs_private);
-
- private = tcon->ntvfs_private;
+ private = talloc_p(tcon, struct svfs_private);
private->next_search_handle = 0;
private->connectpath = talloc_strdup(tcon, lp_pathname(tcon->service));
tcon->fs_type = talloc_strdup(tcon, "NTFS");
tcon->dev_type = talloc_strdup(tcon, "A:");
+ ntvfs_set_private(tcon, depth, private);
+
DEBUG(0,("WARNING: ntvfs simple: connect to share [%s] with ROOT privileges!!!\n",sharename));
return NT_STATUS_OK;
/*
disconnect from a share
*/
-static NTSTATUS svfs_disconnect(struct smbsrv_tcon *tcon)
+static NTSTATUS svfs_disconnect(struct smbsrv_tcon *tcon, int depth)
{
return NT_STATUS_OK;
}
*/
static NTSTATUS svfs_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
char *unix_path;
struct stat st;
DEBUG(19,("svfs_qpathinfo: file %s level 0x%x\n", info->generic.in.fname, info->generic.level));
if (info->generic.level != RAW_FILEINFO_GENERIC) {
- return ntvfs_map_qpathinfo(req, info);
+ return ntvfs_map_qpathinfo(req, info, private->ops);
}
unix_path = svfs_unix_path(req, info->generic.in.fname);
*/
static NTSTATUS svfs_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
{
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
struct svfs_file *f;
struct stat st;
if (info->generic.level != RAW_FILEINFO_GENERIC) {
- return ntvfs_map_qfileinfo(req, info);
+ return ntvfs_map_qfileinfo(req, info, private->ops);
}
f = find_fd(private, info->generic.in.fnum);
*/
static NTSTATUS svfs_open(struct smbsrv_request *req, union smb_open *io)
{
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
char *unix_path;
struct stat st;
int fd, flags;
int create_flags, rdwr_flags;
if (io->generic.level != RAW_OPEN_GENERIC) {
- return ntvfs_map_open(req, io);
+ return ntvfs_map_open(req, io, private->ops);
}
if (lp_readonly(req->tcon->service)) {
*/
static NTSTATUS svfs_close(struct smbsrv_request *req, union smb_close *io)
{
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
struct svfs_file *f;
if (io->generic.level != RAW_CLOSE_CLOSE) {
*/
static NTSTATUS svfs_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
{
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
struct stat st;
if (fs->generic.level != RAW_QFS_GENERIC) {
- return ntvfs_map_fsinfo(req, fs);
+ return ntvfs_map_fsinfo(req, fs, private->ops);
}
if (sys_fsusage(private->connectpath,
static NTSTATUS svfs_fsattr(struct smbsrv_request *req, union smb_fsattr *fs)
{
struct stat st;
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
if (fs->generic.level != RAW_FSATTR_GENERIC) {
return ntvfs_map_fsattr(req, fs);
{
struct svfs_dir *dir;
int i;
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
struct search_state *search;
union smb_search_data file;
uint_t max_count;
{
struct svfs_dir *dir;
int i;
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
struct search_state *search;
union smb_search_data file;
uint_t max_count;
/* close a search */
static NTSTATUS svfs_search_close(struct smbsrv_request *req, union smb_search_close *io)
{
- struct svfs_private *private = req->tcon->ntvfs_private;
+ NTVFS_GET_PRIVATE(svfs_private, private, req);
struct search_state *search;
for (search=private->search; search; search = search->next) {
ZERO_STRUCT(ops);
- /* fill in the name and type */
- ops.type = NTVFS_DISK;
-
/* fill in all the operations */
ops.connect = svfs_connect;
ops.disconnect = svfs_disconnect;
/* register ourselves with the NTVFS subsystem. We register
under names 'simple'
*/
+
+ ops.type = NTVFS_DISK;
ops.name = "simple";
ret = register_backend("ntvfs", &ops);
char *volume;
char *fstype;
char *szMSDfsProxy;
- char *ntvfs_handler;
+ char **ntvfs_handler;
int iMinPrintSpace;
int iMaxPrintJobs;
int iMaxConnections;
{"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
{"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
{"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
- {"ntvfs handler", P_STRING, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
+ {"ntvfs handler", P_LIST, P_LOCAL, &sDefault.ntvfs_handler, NULL, NULL, FLAG_ADVANCED},
{"dcerpc endpoint servers", P_LIST, P_GLOBAL, &Globals.dcerpc_ep_servers, NULL, NULL, FLAG_ADVANCED},
{"server services", P_LIST, P_GLOBAL, &Globals.server_services, NULL, NULL, FLAG_ADVANCED},
FN_LOCAL_STRING(lp_fstype, fstype)
FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
static FN_LOCAL_STRING(lp_volume, volume)
-FN_LOCAL_STRING(lp_ntvfs_handler, ntvfs_handler)
+FN_LOCAL_LIST(lp_ntvfs_handler, ntvfs_handler)
FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
FN_LOCAL_BOOL(lp_browseable, bBrowseable)
/* Invoke NTVFS connection hook */
if (tcon->ntvfs_ops->connect) {
- status = tcon->ntvfs_ops->connect(req, lp_servicename(snum));
+ status = tcon->ntvfs_ops->connect(req, lp_servicename(snum), 0);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("make_connection: NTVFS make connection failed!\n"));
conn_free(req->smb_conn, tcon);
lp_servicename(SNUM(tcon))));
/* tell the ntvfs backend that we are disconnecting */
- tcon->ntvfs_ops->disconnect(tcon);
+ tcon->ntvfs_ops->disconnect(tcon, 0);
conn_free(tcon->smb_conn, tcon);
}
/* the server context that this was created on */
struct smbsrv_connection *smb_conn;
- /* a private structure used by the active NTVFS backend */
- void *ntvfs_private;
+ /* an array of private structures used by the active NTVFS backends */
+ void **ntvfs_private_list;
uint16_t cnum; /* an index passed over the wire (the TID) */
int service;
/* the session context is derived from the vuid */
struct smbsrv_session *session;
+ /* the ntvfs chaining depth */
+ int ntvfs_depth;
+
/* a set of flags to control usage of the request. See REQ_CONTROL_* */
unsigned control_flags;