ntvfs/cifs: fix the fnum on RAW_RENAME_NTTRANS
[jelmer/samba4-debian.git] / source / ntvfs / cifs / vfs_cifs.c
index cd4e36390663f605d663ea687ad7c5fb81267066..3c090b5f5c65a9991709a45c9ca3884c493aa978 100644 (file)
@@ -32,6 +32,7 @@
 #include "ntvfs/ntvfs.h"
 #include "lib/util/dlinklist.h"
 #include "param/param.h"
+#include "libcli/resolve/resolve.h"
 
 struct cvfs_file {
        struct cvfs_file *prev, *next;
@@ -63,12 +64,16 @@ struct async_info {
 
 #define SETUP_PID private->tree->session->pid = req->smbpid
 
-#define SETUP_FILE do { \
-       struct cvfs_file *f; \
+#define SETUP_FILE_HERE(f) do { \
        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) 
+} while (0)
+
+#define SETUP_FILE do { \
+       struct cvfs_file *f; \
+       SETUP_FILE_HERE(f); \
+} while (0)
 
 #define SETUP_PID_AND_FILE do { \
        SETUP_PID; \
@@ -166,7 +171,7 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
                        return NT_STATUS_NO_MEMORY;
                }
                cli_credentials_set_event_context(credentials, ntvfs->ctx->event_ctx);
-               cli_credentials_set_conf(credentials, global_loadparm);
+               cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
                cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
                if (domain) {
                        cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
@@ -176,11 +181,11 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
                DEBUG(5, ("CIFS backend: Using machine account\n"));
                credentials = cli_credentials_init(private);
                cli_credentials_set_event_context(credentials, ntvfs->ctx->event_ctx);
-               cli_credentials_set_conf(credentials, global_loadparm);
+               cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
                if (domain) {
                        cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
                }
-               status = cli_credentials_set_machine_account(credentials);
+               status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -194,15 +199,22 @@ static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs,
 
        /* connect to the server, using the smbd event context */
        io.in.dest_host = host;
-       io.in.port = 0;
+       io.in.dest_ports = lp_smb_ports(ntvfs->ctx->lp_ctx);
        io.in.called_name = host;
        io.in.credentials = credentials;
        io.in.fallback_to_anonymous = false;
-       io.in.workgroup = lp_workgroup(global_loadparm);
+       io.in.workgroup = lp_workgroup(ntvfs->ctx->lp_ctx);
        io.in.service = remote_share;
        io.in.service_type = "?????";
-       
-       creq = smb_composite_connect_send(&io, private, ntvfs->ctx->event_ctx);
+       lp_smbcli_options(ntvfs->ctx->lp_ctx, &io.in.options);
+
+       if (!(ntvfs->ctx->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS)) {
+               io.in.options.use_level2_oplocks = false;
+       }
+
+       creq = smb_composite_connect_send(&io, private, 
+                                         lp_resolve_context(ntvfs->ctx->lp_ctx),
+                                         ntvfs->ctx->event_ctx);
        status = smb_composite_connect_recv(creq, private);
        NT_STATUS_NOT_OK_RETURN(status);
 
@@ -480,6 +492,7 @@ static void async_open(struct smbcli_request *c_req)
        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;
+       DLIST_ADD(cvfs->files, f);
 failed:
        req->async_states->send_fn(req);
 }
@@ -522,6 +535,7 @@ static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs,
                status = ntvfs_handle_set_backend_data(f->h, private->ntvfs, f);
                NT_STATUS_NOT_OK_RETURN(status);
                file->ntvfs = f->h;
+               DLIST_ADD(private->files, f);
 
                return NT_STATUS_OK;
        }
@@ -581,6 +595,13 @@ static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
+       if (ren->nttrans.level == RAW_RENAME_NTTRANS) {
+               struct cvfs_file *f;
+               f = ntvfs_handle_get_backend_data(ren->nttrans.in.file.ntvfs, ntvfs);
+               if (!f) return NT_STATUS_INVALID_HANDLE;
+               ren->nttrans.in.file.fnum = f->fnum;
+       }
+
        if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_rename(private->tree, ren);
        }
@@ -748,6 +769,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs,
 {
        struct cvfs_private *private = ntvfs->private_data;
        struct smbcli_request *c_req;
+       struct cvfs_file *f;
 
        SETUP_PID;
 
@@ -755,7 +777,12 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs,
            private->map_generic) {
                return ntvfs_map_close(ntvfs, req, io);
        }
-       SETUP_FILE;
+       SETUP_FILE_HERE(f);
+       /* Note, we aren't free-ing f, or it's h here. Should we?
+          even if file-close fails, we'll remove it from the list,
+          what else would we do? Maybe we should not remove until
+          after the proxied call completes? */
+       DLIST_REMOVE(private->files, f);
 
        if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_close(private->tree, io);