LCOV - code coverage report
Current view: top level - source4/ntvfs/cifs - vfs_cifs.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 329 584 56.3 %
Date: 2024-04-21 15:09:00 Functions: 30 46 65.2 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    CIFS-on-CIFS NTVFS filesystem backend
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) James J Myers 2003 <myersjj@samba.org>
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : /*
      23             :   this implements a CIFS->CIFS NTVFS filesystem backend. 
      24             :   
      25             : */
      26             : 
      27             : #include "includes.h"
      28             : #include "libcli/raw/libcliraw.h"
      29             : #include "libcli/raw/raw_proto.h"
      30             : #include "libcli/smb_composite/smb_composite.h"
      31             : #include "auth/auth.h"
      32             : #include "auth/credentials/credentials.h"
      33             : #include "ntvfs/ntvfs.h"
      34             : #include "../lib/util/dlinklist.h"
      35             : #include "param/param.h"
      36             : #include "libcli/resolve/resolve.h"
      37             : #include "../libcli/smb/smbXcli_base.h"
      38             : 
      39             : struct cvfs_file {
      40             :         struct cvfs_file *prev, *next;
      41             :         uint16_t fnum;
      42             :         struct ntvfs_handle *h;
      43             : };
      44             : 
      45             : /* this is stored in ntvfs_private */
      46             : struct cvfs_private {
      47             :         struct smbcli_tree *tree;
      48             :         struct smbcli_transport *transport;
      49             :         struct ntvfs_module_context *ntvfs;
      50             :         struct async_info *pending;
      51             :         struct cvfs_file *files;
      52             :         bool map_generic;
      53             :         bool map_trans2;
      54             : };
      55             : 
      56             : 
      57             : /* a structure used to pass information to an async handler */
      58             : struct async_info {
      59             :         struct async_info *next, *prev;
      60             :         struct cvfs_private *cvfs;
      61             :         struct ntvfs_request *req;
      62             :         struct smbcli_request *c_req;
      63             :         struct cvfs_file *f;
      64             :         void *parms;
      65             : };
      66             : 
      67             : NTSTATUS ntvfs_cifs_init(TALLOC_CTX *);
      68             : 
      69             : #define CHECK_UPSTREAM_OPEN do { \
      70             :         if (!smbXcli_conn_is_connected(p->transport->conn)) { \
      71             :                 req->async_states->state|=NTVFS_ASYNC_STATE_CLOSE; \
      72             :                 return NT_STATUS_CONNECTION_DISCONNECTED; \
      73             :         } \
      74             : } while(0)
      75             : 
      76             : #define SETUP_PID do { \
      77             :         p->tree->session->pid = req->smbpid; \
      78             :         CHECK_UPSTREAM_OPEN; \
      79             : } while(0)
      80             : 
      81             : #define SETUP_FILE_HERE(f) do { \
      82             :         f = ntvfs_handle_get_backend_data(io->generic.in.file.ntvfs, ntvfs); \
      83             :         if (!f) return NT_STATUS_INVALID_HANDLE; \
      84             :         io->generic.in.file.fnum = f->fnum; \
      85             : } while (0)
      86             : 
      87             : #define SETUP_FILE do { \
      88             :         struct cvfs_file *f; \
      89             :         SETUP_FILE_HERE(f); \
      90             : } while (0)
      91             : 
      92             : #define SETUP_PID_AND_FILE do { \
      93             :         SETUP_PID; \
      94             :         SETUP_FILE; \
      95             : } while (0)
      96             : 
      97             : #define CIFS_SERVER             "cifs:server"
      98             : #define CIFS_USER               "cifs:user"
      99             : #define CIFS_PASSWORD           "cifs:password"
     100             : #define CIFS_DOMAIN             "cifs:domain"
     101             : #define CIFS_SHARE              "cifs:share"
     102             : #define CIFS_USE_MACHINE_ACCT   "cifs:use-machine-account"
     103             : #define CIFS_USE_S4U2PROXY      "cifs:use-s4u2proxy"
     104             : #define CIFS_MAP_GENERIC        "cifs:map-generic"
     105             : #define CIFS_MAP_TRANS2         "cifs:map-trans2"
     106             : 
     107             : #define CIFS_USE_MACHINE_ACCT_DEFAULT   false
     108             : #define CIFS_USE_S4U2PROXY_DEFAULT      false
     109             : #define CIFS_MAP_GENERIC_DEFAULT        false
     110             : #define CIFS_MAP_TRANS2_DEFAULT         true
     111             : 
     112             : /*
     113             :   a handler for oplock break events from the server - these need to be passed
     114             :   along to the client
     115             :  */
     116           0 : static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *p_private)
     117             : {
     118           0 :         struct cvfs_private *p = p_private;
     119           0 :         NTSTATUS status;
     120           0 :         struct ntvfs_handle *h = NULL;
     121           0 :         struct cvfs_file *f;
     122             : 
     123           0 :         for (f=p->files; f; f=f->next) {
     124           0 :                 if (f->fnum != fnum) continue;
     125           0 :                 h = f->h;
     126           0 :                 break;
     127             :         }
     128             : 
     129           0 :         if (!h) {
     130           0 :                 DEBUG(5,("vfs_cifs: ignoring oplock break level %d for fnum %d\n", level, fnum));
     131           0 :                 return true;
     132             :         }
     133             : 
     134           0 :         DEBUG(5,("vfs_cifs: sending oplock break level %d for fnum %d\n", level, fnum));
     135           0 :         status = ntvfs_send_oplock_break(p->ntvfs, h, level);
     136           0 :         if (!NT_STATUS_IS_OK(status)) return false;
     137           0 :         return true;
     138             : }
     139             : 
     140             : /*
     141             :   connect to a share - used when a tree_connect operation comes in.
     142             : */
     143         156 : static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, 
     144             :                              struct ntvfs_request *req,
     145             :                              union smb_tcon *tcon)
     146             : {
     147           0 :         NTSTATUS status;
     148           0 :         struct cvfs_private *p;
     149           0 :         const char *host, *user, *pass, *domain, *remote_share;
     150           0 :         struct smb_composite_connect io;
     151           0 :         struct composite_context *creq;
     152         156 :         struct share_config *scfg = ntvfs->ctx->config;
     153             : 
     154           0 :         struct cli_credentials *credentials;
     155           0 :         bool machine_account;
     156           0 :         bool s4u2proxy;
     157           0 :         const char* sharename;
     158           0 :         TALLOC_CTX *tmp_ctx;
     159             : 
     160         156 :         tmp_ctx = talloc_new(req);
     161         156 :         if (tmp_ctx == NULL) {
     162           0 :                 return NT_STATUS_NO_MEMORY;
     163             :         }
     164             : 
     165         156 :         switch (tcon->generic.level) {
     166           0 :         case RAW_TCON_TCON:
     167           0 :                 sharename = tcon->tcon.in.service;
     168           0 :                 break;
     169         156 :         case RAW_TCON_TCONX:
     170         156 :                 sharename = tcon->tconx.in.path;
     171         156 :                 break;
     172           0 :         case RAW_TCON_SMB2:
     173           0 :                 sharename = tcon->smb2.in.path;
     174           0 :                 break;
     175           0 :         default:
     176           0 :                 status = NT_STATUS_INVALID_LEVEL;
     177           0 :                 goto out;
     178             :         }
     179             : 
     180         156 :         if (strncmp(sharename, "\\\\", 2) == 0) {
     181         153 :                 char *str = strchr(sharename+2, '\\');
     182         153 :                 if (str) {
     183         153 :                         sharename = str + 1;
     184             :                 }
     185             :         }
     186             : 
     187             :         /* Here we need to determine which server to connect to.
     188             :          * For now we use parametric options, type cifs.
     189             :          */
     190         156 :         host = share_string_option(tmp_ctx, scfg, CIFS_SERVER, NULL);
     191         156 :         user = share_string_option(tmp_ctx, scfg, CIFS_USER, NULL);
     192         156 :         pass = share_string_option(tmp_ctx, scfg, CIFS_PASSWORD, NULL);
     193         156 :         domain = share_string_option(tmp_ctx, scfg, CIFS_DOMAIN, NULL);
     194         156 :         remote_share = share_string_option(tmp_ctx, scfg, CIFS_SHARE, NULL);
     195         156 :         if (!remote_share) {
     196           0 :                 remote_share = sharename;
     197             :         }
     198             : 
     199         156 :         machine_account = share_bool_option(scfg, CIFS_USE_MACHINE_ACCT, CIFS_USE_MACHINE_ACCT_DEFAULT);
     200         156 :         s4u2proxy = share_bool_option(scfg, CIFS_USE_S4U2PROXY, CIFS_USE_S4U2PROXY_DEFAULT);
     201             : 
     202         156 :         p = talloc_zero(ntvfs, struct cvfs_private);
     203         156 :         if (!p) {
     204           0 :                 status = NT_STATUS_NO_MEMORY;
     205           0 :                 goto out;
     206             :         }
     207             : 
     208         156 :         ntvfs->private_data = p;
     209             : 
     210         156 :         if (!host) {
     211           0 :                 DEBUG(1,("CIFS backend: You must supply server\n"));
     212           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     213           0 :                 goto out;
     214             :         } 
     215             :         
     216         156 :         if (user && pass) {
     217           0 :                 DEBUG(5, ("CIFS backend: Using specified password\n"));
     218           0 :                 credentials = cli_credentials_init(p);
     219           0 :                 if (!credentials) {
     220           0 :                         status = NT_STATUS_NO_MEMORY;
     221           0 :                         goto out;
     222             :                 }
     223           0 :                 cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
     224           0 :                 cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
     225           0 :                 if (domain) {
     226           0 :                         cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
     227             :                 }
     228           0 :                 cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
     229         156 :         } else if (machine_account) {
     230           0 :                 DEBUG(5, ("CIFS backend: Using machine account\n"));
     231           0 :                 credentials = cli_credentials_init_server(p,
     232           0 :                                                           ntvfs->ctx->lp_ctx);
     233           0 :                 if (credentials == NULL) {
     234           0 :                         status = NT_STATUS_NO_MEMORY;
     235           0 :                         goto out;
     236             :                 }
     237         156 :         } else if (req->session_info->credentials) {
     238         151 :                 DEBUG(5, ("CIFS backend: Using delegated credentials\n"));
     239         151 :                 credentials = req->session_info->credentials;
     240           5 :         } else if (s4u2proxy) {
     241           5 :                 struct ccache_container *ccc = NULL;
     242           5 :                 const char *err_str = NULL;
     243           0 :                 int ret;
     244           0 :                 char *impersonate_principal;
     245           0 :                 char *self_service;
     246           0 :                 char *target_service;
     247             : 
     248           5 :                 impersonate_principal = talloc_asprintf(req, "%s@%s",
     249           5 :                                                 req->session_info->info->account_name,
     250           5 :                                                 req->session_info->info->domain_name);
     251             : 
     252           5 :                 self_service = talloc_asprintf(req, "cifs/%s",
     253           5 :                                                lpcfg_netbios_name(ntvfs->ctx->lp_ctx));
     254             : 
     255           5 :                 target_service = talloc_asprintf(req, "cifs/%s", host);
     256             : 
     257           5 :                 DEBUG(5, ("CIFS backend: Using S4U2Proxy credentials\n"));
     258             : 
     259           5 :                 credentials = cli_credentials_init_server(p,
     260           5 :                                                           ntvfs->ctx->lp_ctx);
     261           5 :                 if (credentials == NULL) {
     262           0 :                         status = NT_STATUS_NO_MEMORY;
     263           0 :                         goto out;
     264             :                 }
     265           5 :                 cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
     266           5 :                 cli_credentials_set_impersonate_principal(credentials,
     267             :                                                           impersonate_principal,
     268             :                                                           self_service);
     269           5 :                 cli_credentials_set_target_service(credentials, target_service);
     270           5 :                 ret = cli_credentials_get_ccache(credentials,
     271           5 :                                                  ntvfs->ctx->event_ctx,
     272           5 :                                                  ntvfs->ctx->lp_ctx,
     273             :                                                  &ccc,
     274             :                                                  &err_str);
     275           5 :                 if (ret != 0) {
     276           0 :                         status = NT_STATUS_CROSSREALM_DELEGATION_FAILURE;
     277           0 :                         DEBUG(1,("S4U2Proxy: cli_credentials_get_ccache() gave: ret[%d] str[%s] - %s\n",
     278             :                                 ret, err_str, nt_errstr(status)));
     279           0 :                         goto out;
     280             :                 }
     281             : 
     282             :         } else {
     283           0 :                 DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n"));
     284           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     285           0 :                 goto out;
     286             :         }
     287             : 
     288             :         /* connect to the server, using the smbd event context */
     289         156 :         io.in.dest_host = host;
     290         156 :         io.in.dest_ports = lpcfg_smb_ports(ntvfs->ctx->lp_ctx);
     291         156 :         io.in.socket_options = lpcfg_socket_options(ntvfs->ctx->lp_ctx);
     292         156 :         io.in.called_name = host;
     293         156 :         io.in.existing_conn = NULL;
     294         156 :         io.in.credentials = credentials;
     295         156 :         io.in.fallback_to_anonymous = false;
     296         156 :         io.in.workgroup = lpcfg_workgroup(ntvfs->ctx->lp_ctx);
     297         156 :         io.in.service = remote_share;
     298         156 :         io.in.service_type = "?????";
     299         156 :         io.in.gensec_settings = lpcfg_gensec_settings(p, ntvfs->ctx->lp_ctx);
     300         156 :         lpcfg_smbcli_options(ntvfs->ctx->lp_ctx, &io.in.options);
     301         156 :         lpcfg_smbcli_session_options(ntvfs->ctx->lp_ctx, &io.in.session_options);
     302             : 
     303         156 :         if (!(ntvfs->ctx->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS)) {
     304           0 :                 io.in.options.use_level2_oplocks = false;
     305             :         }
     306             : 
     307         156 :         creq = smb_composite_connect_send(&io, p,
     308         156 :                                           lpcfg_resolve_context(ntvfs->ctx->lp_ctx),
     309         156 :                                           ntvfs->ctx->event_ctx);
     310         156 :         status = smb_composite_connect_recv(creq, p);
     311         156 :         if (!NT_STATUS_IS_OK(status)) {
     312           0 :                 goto out;
     313             :         }
     314             : 
     315         156 :         p->tree = io.out.tree;
     316             : 
     317         156 :         p->transport = p->tree->session->transport;
     318         156 :         SETUP_PID;
     319         156 :         p->ntvfs = ntvfs;
     320             : 
     321         156 :         ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
     322         156 :         if (ntvfs->ctx->fs_type == NULL) {
     323           0 :                 status = NT_STATUS_NO_MEMORY;
     324           0 :                 goto out;
     325             :         }
     326         156 :         ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
     327         156 :         if (ntvfs->ctx->dev_type == NULL) {
     328           0 :                 status = NT_STATUS_NO_MEMORY;
     329           0 :                 goto out;
     330             :         }
     331             : 
     332         156 :         if (tcon->generic.level == RAW_TCON_TCONX) {
     333         156 :                 tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
     334         156 :                 tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
     335             :         }
     336             : 
     337             :         /* we need to receive oplock break requests from the server */
     338         156 :         smbcli_oplock_handler(p->transport, oplock_handler, p);
     339             : 
     340         156 :         p->map_generic = share_bool_option(scfg, CIFS_MAP_GENERIC, CIFS_MAP_GENERIC_DEFAULT);
     341             : 
     342         156 :         p->map_trans2 = share_bool_option(scfg, CIFS_MAP_TRANS2, CIFS_MAP_TRANS2_DEFAULT);
     343             : 
     344         156 :         status = NT_STATUS_OK;
     345             : 
     346         156 : out:
     347         156 :         TALLOC_FREE(tmp_ctx);
     348         156 :         return status;
     349             : }
     350             : 
     351             : /*
     352             :   disconnect from a share
     353             : */
     354         156 : static NTSTATUS cvfs_disconnect(struct ntvfs_module_context *ntvfs)
     355             : {
     356         156 :         struct cvfs_private *p = ntvfs->private_data;
     357           0 :         struct async_info *a, *an;
     358             : 
     359             :         /* first cleanup pending requests */
     360         186 :         for (a=p->pending; a; a = an) {
     361          30 :                 an = a->next;
     362          30 :                 smbcli_request_destroy(a->c_req);
     363          30 :                 talloc_free(a);
     364             :         }
     365             : 
     366         156 :         talloc_free(p);
     367         156 :         ntvfs->private_data = NULL;
     368             : 
     369         156 :         return NT_STATUS_OK;
     370             : }
     371             : 
     372             : /*
     373             :   destroy an async info structure
     374             : */
     375       66981 : static int async_info_destructor(struct async_info *async)
     376             : {
     377       66981 :         DLIST_REMOVE(async->cvfs->pending, async);
     378       66981 :         return 0;
     379             : }
     380             : 
     381             : /*
     382             :   a handler for simple async replies
     383             :   this handler can only be used for functions that don't return any
     384             :   parameters (those that just return a status code)
     385             :  */
     386       21425 : static void async_simple(struct smbcli_request *c_req)
     387             : {
     388       21425 :         struct async_info *async = c_req->async.private_data;
     389       21425 :         struct ntvfs_request *req = async->req;
     390       21425 :         req->async_states->status = smbcli_request_simple_recv(c_req);
     391       21425 :         talloc_free(async);
     392       21425 :         req->async_states->send_fn(req);
     393       21425 : }
     394             : 
     395             : 
     396             : /* save some typing for the simple functions */
     397             : #define ASYNC_RECV_TAIL_F(io, async_fn, file) do { \
     398             :         if (!c_req) return NT_STATUS_UNSUCCESSFUL; \
     399             :         { \
     400             :                 struct async_info *async; \
     401             :                 async = talloc(req, struct async_info); \
     402             :                 if (!async) return NT_STATUS_NO_MEMORY; \
     403             :                 async->parms = io; \
     404             :                 async->req = req; \
     405             :                 async->f = file; \
     406             :                 async->cvfs = p; \
     407             :                 async->c_req = c_req; \
     408             :                 DLIST_ADD(p->pending, async); \
     409             :                 c_req->async.private_data = async; \
     410             :                 talloc_set_destructor(async, async_info_destructor); \
     411             :         } \
     412             :         c_req->async.fn = async_fn; \
     413             :         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; \
     414             :         return NT_STATUS_OK; \
     415             : } while (0)
     416             : 
     417             : #define ASYNC_RECV_TAIL(io, async_fn) ASYNC_RECV_TAIL_F(io, async_fn, NULL)
     418             : 
     419             : #define SIMPLE_ASYNC_TAIL ASYNC_RECV_TAIL(NULL, async_simple)
     420             : 
     421             : /*
     422             :   delete a file - the dirtype specifies the file types to include in the search. 
     423             :   The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
     424             : */
     425        6923 : static NTSTATUS cvfs_unlink(struct ntvfs_module_context *ntvfs, 
     426             :                             struct ntvfs_request *req, union smb_unlink *unl)
     427             : {
     428        6923 :         struct cvfs_private *p = ntvfs->private_data;
     429           0 :         struct smbcli_request *c_req;
     430             : 
     431        6923 :         SETUP_PID;
     432             : 
     433             :         /* see if the front end will allow us to perform this
     434             :            function asynchronously.  */
     435        6923 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     436           0 :                 return smb_raw_unlink(p->tree, unl);
     437             :         }
     438             : 
     439        6923 :         c_req = smb_raw_unlink_send(p->tree, unl);
     440             : 
     441        6923 :         SIMPLE_ASYNC_TAIL;
     442             : }
     443             : 
     444             : /*
     445             :   a handler for async ioctl replies
     446             :  */
     447           0 : static void async_ioctl(struct smbcli_request *c_req)
     448             : {
     449           0 :         struct async_info *async = c_req->async.private_data;
     450           0 :         struct ntvfs_request *req = async->req;
     451           0 :         req->async_states->status = smb_raw_ioctl_recv(c_req, req, async->parms);
     452           0 :         talloc_free(async);
     453           0 :         req->async_states->send_fn(req);
     454           0 : }
     455             : 
     456             : /*
     457             :   ioctl interface
     458             : */
     459           0 : static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs, 
     460             :                            struct ntvfs_request *req, union smb_ioctl *io)
     461             : {
     462           0 :         struct cvfs_private *p = ntvfs->private_data;
     463           0 :         struct smbcli_request *c_req;
     464             : 
     465           0 :         SETUP_PID_AND_FILE;
     466             : 
     467             :         /* see if the front end will allow us to perform this
     468             :            function asynchronously.  */
     469           0 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     470           0 :                 return smb_raw_ioctl(p->tree, req, io);
     471             :         }
     472             : 
     473           0 :         c_req = smb_raw_ioctl_send(p->tree, io);
     474             : 
     475           0 :         ASYNC_RECV_TAIL(io, async_ioctl);
     476             : }
     477             : 
     478             : /*
     479             :   check if a directory exists
     480             : */
     481          25 : static NTSTATUS cvfs_chkpath(struct ntvfs_module_context *ntvfs, 
     482             :                              struct ntvfs_request *req, union smb_chkpath *cp)
     483             : {
     484          25 :         struct cvfs_private *p = ntvfs->private_data;
     485           0 :         struct smbcli_request *c_req;
     486             : 
     487          25 :         SETUP_PID;
     488             : 
     489          25 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     490           0 :                 return smb_raw_chkpath(p->tree, cp);
     491             :         }
     492             : 
     493          25 :         c_req = smb_raw_chkpath_send(p->tree, cp);
     494             : 
     495          25 :         SIMPLE_ASYNC_TAIL;
     496             : }
     497             : 
     498             : /*
     499             :   a handler for async qpathinfo replies
     500             :  */
     501        2373 : static void async_qpathinfo(struct smbcli_request *c_req)
     502             : {
     503        2373 :         struct async_info *async = c_req->async.private_data;
     504        2373 :         struct ntvfs_request *req = async->req;
     505        2373 :         req->async_states->status = smb_raw_pathinfo_recv(c_req, req, async->parms);
     506        2373 :         talloc_free(async);
     507        2373 :         req->async_states->send_fn(req);
     508        2373 : }
     509             : 
     510             : /*
     511             :   return info on a pathname
     512             : */
     513        2373 : static NTSTATUS cvfs_qpathinfo(struct ntvfs_module_context *ntvfs, 
     514             :                                struct ntvfs_request *req, union smb_fileinfo *info)
     515             : {
     516        2373 :         struct cvfs_private *p = ntvfs->private_data;
     517           0 :         struct smbcli_request *c_req;
     518             : 
     519        2373 :         SETUP_PID;
     520             : 
     521        2373 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     522           0 :                 return smb_raw_pathinfo(p->tree, req, info);
     523             :         }
     524             : 
     525        2373 :         c_req = smb_raw_pathinfo_send(p->tree, info);
     526             : 
     527        2373 :         ASYNC_RECV_TAIL(info, async_qpathinfo);
     528             : }
     529             : 
     530             : /*
     531             :   a handler for async qfileinfo replies
     532             :  */
     533        2157 : static void async_qfileinfo(struct smbcli_request *c_req)
     534             : {
     535        2157 :         struct async_info *async = c_req->async.private_data;
     536        2157 :         struct ntvfs_request *req = async->req;
     537        2157 :         req->async_states->status = smb_raw_fileinfo_recv(c_req, req, async->parms);
     538        2157 :         talloc_free(async);
     539        2157 :         req->async_states->send_fn(req);
     540        2157 : }
     541             : 
     542             : /*
     543             :   query info on a open file
     544             : */
     545        2157 : static NTSTATUS cvfs_qfileinfo(struct ntvfs_module_context *ntvfs, 
     546             :                                struct ntvfs_request *req, union smb_fileinfo *io)
     547             : {
     548        2157 :         struct cvfs_private *p = ntvfs->private_data;
     549           0 :         struct smbcli_request *c_req;
     550             : 
     551        2157 :         SETUP_PID_AND_FILE;
     552             : 
     553        2157 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     554           0 :                 return smb_raw_fileinfo(p->tree, req, io);
     555             :         }
     556             : 
     557        2157 :         c_req = smb_raw_fileinfo_send(p->tree, io);
     558             : 
     559        2157 :         ASYNC_RECV_TAIL(io, async_qfileinfo);
     560             : }
     561             : 
     562             : 
     563             : /*
     564             :   set info on a pathname
     565             : */
     566         146 : static NTSTATUS cvfs_setpathinfo(struct ntvfs_module_context *ntvfs, 
     567             :                                  struct ntvfs_request *req, union smb_setfileinfo *st)
     568             : {
     569         146 :         struct cvfs_private *p = ntvfs->private_data;
     570           0 :         struct smbcli_request *c_req;
     571             : 
     572         146 :         SETUP_PID;
     573             : 
     574         146 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     575           0 :                 return smb_raw_setpathinfo(p->tree, st);
     576             :         }
     577             : 
     578         146 :         c_req = smb_raw_setpathinfo_send(p->tree, st);
     579             : 
     580         146 :         SIMPLE_ASYNC_TAIL;
     581             : }
     582             : 
     583             : 
     584             : /*
     585             :   a handler for async open replies
     586             :  */
     587       13380 : static void async_open(struct smbcli_request *c_req)
     588             : {
     589       13380 :         struct async_info *async = c_req->async.private_data;
     590       13380 :         struct cvfs_private *cvfs = async->cvfs;
     591       13380 :         struct ntvfs_request *req = async->req;
     592       13380 :         struct cvfs_file *f = async->f;
     593       13380 :         union smb_open *io = async->parms;
     594           0 :         union smb_handle *file;
     595       13380 :         if (f == NULL) {
     596           0 :                 goto failed;
     597             :         }
     598       13380 :         talloc_free(async);
     599       13380 :         req->async_states->status = smb_raw_open_recv(c_req, req, io);
     600       13380 :         SMB_OPEN_OUT_FILE(io, file);
     601       13380 :         if (file == NULL) {
     602           0 :                 goto failed;
     603             :         }
     604       13380 :         f->fnum = file->fnum;
     605       13380 :         file->ntvfs = NULL;
     606       13380 :         if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed;
     607       11789 :         req->async_states->status = ntvfs_handle_set_backend_data(f->h, cvfs->ntvfs, f);
     608       11789 :         if (!NT_STATUS_IS_OK(req->async_states->status)) goto failed;
     609       11789 :         file->ntvfs = f->h;
     610       11789 :         DLIST_ADD(cvfs->files, f);
     611       13380 : failed:
     612       13380 :         req->async_states->send_fn(req);
     613       13380 : }
     614             : 
     615             : /*
     616             :   open a file
     617             : */
     618       13400 : static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs, 
     619             :                           struct ntvfs_request *req, union smb_open *io)
     620             : {
     621       13400 :         struct cvfs_private *p = ntvfs->private_data;
     622           0 :         struct smbcli_request *c_req;
     623           0 :         struct ntvfs_handle *h;
     624           0 :         struct cvfs_file *f;
     625           0 :         NTSTATUS status;
     626             : 
     627       13400 :         SETUP_PID;
     628             : 
     629       13400 :         if (io->generic.level != RAW_OPEN_GENERIC &&
     630        2726 :             p->map_generic) {
     631           0 :                 return ntvfs_map_open(ntvfs, req, io);
     632             :         }
     633             : 
     634       13400 :         status = ntvfs_handle_new(ntvfs, req, &h);
     635       13400 :         NT_STATUS_NOT_OK_RETURN(status);
     636             : 
     637       13400 :         f = talloc_zero(h, struct cvfs_file);
     638       13400 :         NT_STATUS_HAVE_NO_MEMORY(f);
     639       13400 :         f->h = h;
     640             : 
     641       13400 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     642           0 :                 union smb_handle *file;
     643             : 
     644           0 :                 status = smb_raw_open(p->tree, req, io);
     645           0 :                 NT_STATUS_NOT_OK_RETURN(status);
     646             : 
     647           0 :                 SMB_OPEN_OUT_FILE(io, file);
     648           0 :                 if (file == NULL) {
     649           0 :                         return NT_STATUS_INVALID_PARAMETER;
     650             :                 }
     651           0 :                 f->fnum = file->fnum;
     652           0 :                 file->ntvfs = NULL;
     653           0 :                 status = ntvfs_handle_set_backend_data(f->h, p->ntvfs, f);
     654           0 :                 NT_STATUS_NOT_OK_RETURN(status);
     655           0 :                 file->ntvfs = f->h;
     656           0 :                 DLIST_ADD(p->files, f);
     657             : 
     658           0 :                 return NT_STATUS_OK;
     659             :         }
     660             : 
     661       13400 :         c_req = smb_raw_open_send(p->tree, io);
     662             : 
     663       13400 :         ASYNC_RECV_TAIL_F(io, async_open, f);
     664             : }
     665             : 
     666             : /*
     667             :   create a directory
     668             : */
     669        1125 : static NTSTATUS cvfs_mkdir(struct ntvfs_module_context *ntvfs, 
     670             :                            struct ntvfs_request *req, union smb_mkdir *md)
     671             : {
     672        1125 :         struct cvfs_private *p = ntvfs->private_data;
     673           0 :         struct smbcli_request *c_req;
     674             : 
     675        1125 :         SETUP_PID;
     676             : 
     677        1125 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     678           0 :                 return smb_raw_mkdir(p->tree, md);
     679             :         }
     680             : 
     681        1125 :         c_req = smb_raw_mkdir_send(p->tree, md);
     682             : 
     683        1125 :         SIMPLE_ASYNC_TAIL;
     684             : }
     685             : 
     686             : /*
     687             :   remove a directory
     688             : */
     689        1230 : static NTSTATUS cvfs_rmdir(struct ntvfs_module_context *ntvfs, 
     690             :                            struct ntvfs_request *req, struct smb_rmdir *rd)
     691             : {
     692        1230 :         struct cvfs_private *p = ntvfs->private_data;
     693           0 :         struct smbcli_request *c_req;
     694             : 
     695        1230 :         SETUP_PID;
     696             : 
     697        1230 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     698           0 :                 return smb_raw_rmdir(p->tree, rd);
     699             :         }
     700        1230 :         c_req = smb_raw_rmdir_send(p->tree, rd);
     701             : 
     702        1230 :         SIMPLE_ASYNC_TAIL;
     703             : }
     704             : 
     705             : /*
     706             :   rename a set of files
     707             : */
     708           4 : static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs, 
     709             :                             struct ntvfs_request *req, union smb_rename *ren)
     710             : {
     711           4 :         struct cvfs_private *p = ntvfs->private_data;
     712           0 :         struct smbcli_request *c_req;
     713             : 
     714           4 :         SETUP_PID;
     715             : 
     716           4 :         if (ren->nttrans.level == RAW_RENAME_NTTRANS) {
     717           0 :                 struct cvfs_file *f;
     718           0 :                 f = ntvfs_handle_get_backend_data(ren->nttrans.in.file.ntvfs, ntvfs);
     719           0 :                 if (!f) return NT_STATUS_INVALID_HANDLE;
     720           0 :                 ren->nttrans.in.file.fnum = f->fnum;
     721             :         }
     722             : 
     723           4 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     724           0 :                 return smb_raw_rename(p->tree, ren);
     725             :         }
     726             : 
     727           4 :         c_req = smb_raw_rename_send(p->tree, ren);
     728             : 
     729           4 :         SIMPLE_ASYNC_TAIL;
     730             : }
     731             : 
     732             : /*
     733             :   copy a set of files
     734             : */
     735           0 : static NTSTATUS cvfs_copy(struct ntvfs_module_context *ntvfs, 
     736             :                           struct ntvfs_request *req, struct smb_copy *cp)
     737             : {
     738           0 :         return NT_STATUS_NOT_SUPPORTED;
     739             : }
     740             : 
     741             : /*
     742             :   a handler for async read replies
     743             :  */
     744       16958 : static void async_read(struct smbcli_request *c_req)
     745             : {
     746       16958 :         struct async_info *async = c_req->async.private_data;
     747       16958 :         struct ntvfs_request *req = async->req;
     748       16958 :         req->async_states->status = smb_raw_read_recv(c_req, async->parms);
     749       16958 :         talloc_free(async);
     750       16958 :         req->async_states->send_fn(req);
     751       16958 : }
     752             : 
     753             : /*
     754             :   read from a file
     755             : */
     756       16958 : static NTSTATUS cvfs_read(struct ntvfs_module_context *ntvfs, 
     757             :                           struct ntvfs_request *req, union smb_read *io)
     758             : {
     759       16958 :         struct cvfs_private *p = ntvfs->private_data;
     760           0 :         struct smbcli_request *c_req;
     761             : 
     762       16958 :         SETUP_PID;
     763             : 
     764       16958 :         if (io->generic.level != RAW_READ_GENERIC &&
     765           0 :             p->map_generic) {
     766           0 :                 return ntvfs_map_read(ntvfs, req, io);
     767             :         }
     768             : 
     769       16958 :         SETUP_FILE;
     770             : 
     771       16958 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     772           0 :                 return smb_raw_read(p->tree, io);
     773             :         }
     774             : 
     775       16958 :         c_req = smb_raw_read_send(p->tree, io);
     776             : 
     777       16958 :         ASYNC_RECV_TAIL(io, async_read);
     778             : }
     779             : 
     780             : /*
     781             :   a handler for async write replies
     782             :  */
     783        8657 : static void async_write(struct smbcli_request *c_req)
     784             : {
     785        8657 :         struct async_info *async = c_req->async.private_data;
     786        8657 :         struct ntvfs_request *req = async->req;
     787        8657 :         req->async_states->status = smb_raw_write_recv(c_req, async->parms);
     788        8657 :         talloc_free(async);
     789        8657 :         req->async_states->send_fn(req);
     790        8657 : }
     791             : 
     792             : /*
     793             :   write to a file
     794             : */
     795        8657 : static NTSTATUS cvfs_write(struct ntvfs_module_context *ntvfs, 
     796             :                            struct ntvfs_request *req, union smb_write *io)
     797             : {
     798        8657 :         struct cvfs_private *p = ntvfs->private_data;
     799           0 :         struct smbcli_request *c_req;
     800             : 
     801        8657 :         SETUP_PID;
     802             : 
     803        8657 :         if (io->generic.level != RAW_WRITE_GENERIC &&
     804           0 :             p->map_generic) {
     805           0 :                 return ntvfs_map_write(ntvfs, req, io);
     806             :         }
     807        8657 :         SETUP_FILE;
     808             : 
     809        8657 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     810           0 :                 return smb_raw_write(p->tree, io);
     811             :         }
     812             : 
     813        8657 :         c_req = smb_raw_write_send(p->tree, io);
     814             : 
     815        8657 :         ASYNC_RECV_TAIL(io, async_write);
     816             : }
     817             : 
     818             : /*
     819             :   a handler for async seek replies
     820             :  */
     821           0 : static void async_seek(struct smbcli_request *c_req)
     822             : {
     823           0 :         struct async_info *async = c_req->async.private_data;
     824           0 :         struct ntvfs_request *req = async->req;
     825           0 :         req->async_states->status = smb_raw_seek_recv(c_req, async->parms);
     826           0 :         talloc_free(async);
     827           0 :         req->async_states->send_fn(req);
     828           0 : }
     829             : 
     830             : /*
     831             :   seek in a file
     832             : */
     833           0 : static NTSTATUS cvfs_seek(struct ntvfs_module_context *ntvfs, 
     834             :                           struct ntvfs_request *req,
     835             :                           union smb_seek *io)
     836             : {
     837           0 :         struct cvfs_private *p = ntvfs->private_data;
     838           0 :         struct smbcli_request *c_req;
     839             : 
     840           0 :         SETUP_PID_AND_FILE;
     841             : 
     842           0 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     843           0 :                 return smb_raw_seek(p->tree, io);
     844             :         }
     845             : 
     846           0 :         c_req = smb_raw_seek_send(p->tree, io);
     847             : 
     848           0 :         ASYNC_RECV_TAIL(io, async_seek);
     849             : }
     850             : 
     851             : /*
     852             :   flush a file
     853             : */
     854           0 : static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs, 
     855             :                            struct ntvfs_request *req,
     856             :                            union smb_flush *io)
     857             : {
     858           0 :         struct cvfs_private *p = ntvfs->private_data;
     859           0 :         struct smbcli_request *c_req;
     860             : 
     861           0 :         SETUP_PID;
     862           0 :         switch (io->generic.level) {
     863           0 :         case RAW_FLUSH_FLUSH:
     864           0 :                 SETUP_FILE;
     865           0 :                 break;
     866           0 :         case RAW_FLUSH_ALL:
     867           0 :                 io->generic.in.file.fnum = 0xFFFF;
     868           0 :                 break;
     869           0 :         case RAW_FLUSH_SMB2:
     870           0 :                 return NT_STATUS_INVALID_LEVEL;
     871             :         }
     872             : 
     873           0 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     874           0 :                 return smb_raw_flush(p->tree, io);
     875             :         }
     876             : 
     877           0 :         c_req = smb_raw_flush_send(p->tree, io);
     878             : 
     879           0 :         SIMPLE_ASYNC_TAIL;
     880             : }
     881             : 
     882             : /*
     883             :   close a file
     884             : */
     885       11754 : static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs, 
     886             :                            struct ntvfs_request *req, union smb_close *io)
     887             : {
     888       11754 :         struct cvfs_private *p = ntvfs->private_data;
     889           0 :         struct smbcli_request *c_req;
     890           0 :         struct cvfs_file *f;
     891           0 :         union smb_close io2;
     892             : 
     893       11754 :         SETUP_PID;
     894             : 
     895       11754 :         if (io->generic.level != RAW_CLOSE_GENERIC &&
     896       11754 :             p->map_generic) {
     897           0 :                 return ntvfs_map_close(ntvfs, req, io);
     898             :         }
     899             : 
     900       11754 :         if (io->generic.level == RAW_CLOSE_GENERIC) {
     901           0 :                 ZERO_STRUCT(io2);
     902           0 :                 io2.close.level = RAW_CLOSE_CLOSE;
     903           0 :                 io2.close.in.file = io->generic.in.file;
     904           0 :                 io2.close.in.write_time = io->generic.in.write_time;
     905           0 :                 io = &io2;
     906             :         }
     907             : 
     908       11754 :         SETUP_FILE_HERE(f);
     909             :         /* Note, we aren't free-ing f, or it's h here. Should we?
     910             :            even if file-close fails, we'll remove it from the list,
     911             :            what else would we do? Maybe we should not remove until
     912             :            after the proxied call completes? */
     913       11754 :         DLIST_REMOVE(p->files, f);
     914             : 
     915       11754 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     916           0 :                 return smb_raw_close(p->tree, io);
     917             :         }
     918             : 
     919       11754 :         c_req = smb_raw_close_send(p->tree, io);
     920             : 
     921       11754 :         SIMPLE_ASYNC_TAIL;
     922             : }
     923             : 
     924             : /*
     925             :   exit - closing files open by the pid
     926             : */
     927          91 : static NTSTATUS cvfs_exit(struct ntvfs_module_context *ntvfs, 
     928             :                           struct ntvfs_request *req)
     929             : {
     930          91 :         struct cvfs_private *p = ntvfs->private_data;
     931           0 :         struct smbcli_request *c_req;
     932             : 
     933          91 :         SETUP_PID;
     934             : 
     935          91 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
     936          91 :                 return smb_raw_exit(p->tree->session);
     937             :         }
     938             : 
     939           0 :         c_req = smb_raw_exit_send(p->tree->session);
     940             : 
     941           0 :         SIMPLE_ASYNC_TAIL;
     942             : }
     943             : 
     944             : /*
     945             :   logoff - closing files open by the user
     946             : */
     947           0 : static NTSTATUS cvfs_logoff(struct ntvfs_module_context *ntvfs, 
     948             :                             struct ntvfs_request *req)
     949             : {
     950             :         /* we can't do this right in the cifs backend .... */
     951           0 :         return NT_STATUS_OK;
     952             : }
     953             : 
     954             : /*
     955             :   setup for an async call - nothing to do yet
     956             : */
     957           0 : static NTSTATUS cvfs_async_setup(struct ntvfs_module_context *ntvfs, 
     958             :                                  struct ntvfs_request *req, 
     959             :                                  void *private_data)
     960             : {
     961           0 :         return NT_STATUS_OK;
     962             : }
     963             : 
     964             : /*
     965             :   cancel an async call
     966             : */
     967           0 : static NTSTATUS cvfs_cancel(struct ntvfs_module_context *ntvfs, 
     968             :                             struct ntvfs_request *req)
     969             : {
     970           0 :         struct cvfs_private *p = ntvfs->private_data;
     971           0 :         struct async_info *a;
     972             : 
     973             :         /* find the matching request */
     974           0 :         for (a=p->pending;a;a=a->next) {
     975           0 :                 if (a->req == req) {
     976           0 :                         break;
     977             :                 }
     978             :         }
     979             : 
     980           0 :         if (a == NULL) {
     981           0 :                 return NT_STATUS_INVALID_PARAMETER;
     982             :         }
     983             : 
     984           0 :         return smb_raw_ntcancel(a->c_req);
     985             : }
     986             : 
     987             : /*
     988             :   lock a byte range
     989             : */
     990         190 : static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs, 
     991             :                           struct ntvfs_request *req, union smb_lock *io)
     992             : {
     993         190 :         struct cvfs_private *p = ntvfs->private_data;
     994           0 :         struct smbcli_request *c_req;
     995             : 
     996         190 :         SETUP_PID;
     997             : 
     998         190 :         if (io->generic.level != RAW_LOCK_GENERIC &&
     999           0 :             p->map_generic) {
    1000           0 :                 return ntvfs_map_lock(ntvfs, req, io);
    1001             :         }
    1002         190 :         SETUP_FILE;
    1003             : 
    1004         190 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
    1005           0 :                 return smb_raw_lock(p->tree, io);
    1006             :         }
    1007             : 
    1008         190 :         c_req = smb_raw_lock_send(p->tree, io);
    1009         190 :         SIMPLE_ASYNC_TAIL;
    1010             : }
    1011             : 
    1012             : /*
    1013             :   set info on a open file
    1014             : */
    1015          38 : static NTSTATUS cvfs_setfileinfo(struct ntvfs_module_context *ntvfs, 
    1016             :                                  struct ntvfs_request *req, 
    1017             :                                  union smb_setfileinfo *io)
    1018             : {
    1019          38 :         struct cvfs_private *p = ntvfs->private_data;
    1020           0 :         struct smbcli_request *c_req;
    1021             : 
    1022          38 :         SETUP_PID_AND_FILE;
    1023             : 
    1024          38 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
    1025           0 :                 return smb_raw_setfileinfo(p->tree, io);
    1026             :         }
    1027          38 :         c_req = smb_raw_setfileinfo_send(p->tree, io);
    1028             : 
    1029          38 :         SIMPLE_ASYNC_TAIL;
    1030             : }
    1031             : 
    1032             : 
    1033             : /*
    1034             :   a handler for async fsinfo replies
    1035             :  */
    1036        2001 : static void async_fsinfo(struct smbcli_request *c_req)
    1037             : {
    1038        2001 :         struct async_info *async = c_req->async.private_data;
    1039        2001 :         struct ntvfs_request *req = async->req;
    1040        2001 :         req->async_states->status = smb_raw_fsinfo_recv(c_req, req, async->parms);
    1041        2001 :         talloc_free(async);
    1042        2001 :         req->async_states->send_fn(req);
    1043        2001 : }
    1044             : 
    1045             : /*
    1046             :   return filesystem space info
    1047             : */
    1048        2001 : static NTSTATUS cvfs_fsinfo(struct ntvfs_module_context *ntvfs, 
    1049             :                             struct ntvfs_request *req, union smb_fsinfo *fs)
    1050             : {
    1051        2001 :         struct cvfs_private *p = ntvfs->private_data;
    1052           0 :         struct smbcli_request *c_req;
    1053             : 
    1054        2001 :         SETUP_PID;
    1055             : 
    1056        2001 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
    1057           0 :                 return smb_raw_fsinfo(p->tree, req, fs);
    1058             :         }
    1059             : 
    1060        2001 :         c_req = smb_raw_fsinfo_send(p->tree, req, fs);
    1061             : 
    1062        2001 :         ASYNC_RECV_TAIL(fs, async_fsinfo);
    1063             : }
    1064             : 
    1065             : /*
    1066             :   return print queue info
    1067             : */
    1068           0 : static NTSTATUS cvfs_lpq(struct ntvfs_module_context *ntvfs, 
    1069             :                          struct ntvfs_request *req, union smb_lpq *lpq)
    1070             : {
    1071           0 :         return NT_STATUS_NOT_SUPPORTED;
    1072             : }
    1073             : 
    1074             : /* 
    1075             :    list files in a directory matching a wildcard pattern
    1076             : */
    1077        3127 : static NTSTATUS cvfs_search_first(struct ntvfs_module_context *ntvfs, 
    1078             :                                   struct ntvfs_request *req, union smb_search_first *io, 
    1079             :                                   void *search_private, 
    1080             :                                   bool (*callback)(void *, const union smb_search_data *))
    1081             : {
    1082        3127 :         struct cvfs_private *p = ntvfs->private_data;
    1083             : 
    1084        3127 :         SETUP_PID;
    1085             : 
    1086        3127 :         return smb_raw_search_first(p->tree, req, io, search_private, callback);
    1087             : }
    1088             : 
    1089             : /* continue a search */
    1090          12 : static NTSTATUS cvfs_search_next(struct ntvfs_module_context *ntvfs, 
    1091             :                                  struct ntvfs_request *req, union smb_search_next *io, 
    1092             :                                  void *search_private, 
    1093             :                                  bool (*callback)(void *, const union smb_search_data *))
    1094             : {
    1095          12 :         struct cvfs_private *p = ntvfs->private_data;
    1096             : 
    1097          12 :         SETUP_PID;
    1098             : 
    1099          12 :         return smb_raw_search_next(p->tree, req, io, search_private, callback);
    1100             : }
    1101             : 
    1102             : /* close a search */
    1103           0 : static NTSTATUS cvfs_search_close(struct ntvfs_module_context *ntvfs, 
    1104             :                                   struct ntvfs_request *req, union smb_search_close *io)
    1105             : {
    1106           0 :         struct cvfs_private *p = ntvfs->private_data;
    1107             : 
    1108           0 :         SETUP_PID;
    1109             : 
    1110           0 :         return smb_raw_search_close(p->tree, io);
    1111             : }
    1112             : 
    1113             : /*
    1114             :   a handler for async trans2 replies
    1115             :  */
    1116           0 : static void async_trans2(struct smbcli_request *c_req)
    1117             : {
    1118           0 :         struct async_info *async = c_req->async.private_data;
    1119           0 :         struct ntvfs_request *req = async->req;
    1120           0 :         req->async_states->status = smb_raw_trans2_recv(c_req, req, async->parms);
    1121           0 :         talloc_free(async);
    1122           0 :         req->async_states->send_fn(req);
    1123           0 : }
    1124             : 
    1125             : /* raw trans2 */
    1126       11624 : static NTSTATUS cvfs_trans2(struct ntvfs_module_context *ntvfs, 
    1127             :                             struct ntvfs_request *req,
    1128             :                             struct smb_trans2 *trans2)
    1129             : {
    1130       11624 :         struct cvfs_private *p = ntvfs->private_data;
    1131           0 :         struct smbcli_request *c_req;
    1132             : 
    1133       11624 :         if (p->map_trans2) {
    1134       11624 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1135             :         }
    1136             : 
    1137           0 :         SETUP_PID;
    1138             : 
    1139           0 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
    1140           0 :                 return smb_raw_trans2(p->tree, req, trans2);
    1141             :         }
    1142             : 
    1143           0 :         c_req = smb_raw_trans2_send(p->tree, trans2);
    1144             : 
    1145           0 :         ASYNC_RECV_TAIL(trans2, async_trans2);
    1146             : }
    1147             : 
    1148             : 
    1149             : /* SMBtrans - not used on file shares */
    1150           0 : static NTSTATUS cvfs_trans(struct ntvfs_module_context *ntvfs, 
    1151             :                            struct ntvfs_request *req,
    1152             :                            struct smb_trans2 *trans2)
    1153             : {
    1154           0 :         return NT_STATUS_ACCESS_DENIED;
    1155             : }
    1156             : 
    1157             : /*
    1158             :   a handler for async change notify replies
    1159             :  */
    1160           0 : static void async_changenotify(struct smbcli_request *c_req)
    1161             : {
    1162           0 :         struct async_info *async = c_req->async.private_data;
    1163           0 :         struct ntvfs_request *req = async->req;
    1164           0 :         req->async_states->status = smb_raw_changenotify_recv(c_req, req, async->parms);
    1165           0 :         talloc_free(async);
    1166           0 :         req->async_states->send_fn(req);
    1167           0 : }
    1168             : 
    1169             : /* change notify request - always async */
    1170           0 : static NTSTATUS cvfs_notify(struct ntvfs_module_context *ntvfs, 
    1171             :                             struct ntvfs_request *req,
    1172             :                             union smb_notify *io)
    1173             : {
    1174           0 :         struct cvfs_private *p = ntvfs->private_data;
    1175           0 :         struct smbcli_request *c_req;
    1176           0 :         int saved_timeout = p->transport->options.request_timeout;
    1177           0 :         struct cvfs_file *f;
    1178             : 
    1179           0 :         if (io->nttrans.level != RAW_NOTIFY_NTTRANS) {
    1180           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1181             :         }
    1182             : 
    1183           0 :         SETUP_PID;
    1184             : 
    1185           0 :         f = ntvfs_handle_get_backend_data(io->nttrans.in.file.ntvfs, ntvfs);
    1186           0 :         if (!f) return NT_STATUS_INVALID_HANDLE;
    1187           0 :         io->nttrans.in.file.fnum = f->fnum;
    1188             : 
    1189             :         /* this request doesn't make sense unless its async */
    1190           0 :         if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
    1191           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1192             :         }
    1193             : 
    1194             :         /* we must not timeout on notify requests - they wait
    1195             :            forever */
    1196           0 :         p->transport->options.request_timeout = 0;
    1197             : 
    1198           0 :         c_req = smb_raw_changenotify_send(p->tree, io);
    1199             : 
    1200           0 :         p->transport->options.request_timeout = saved_timeout;
    1201             : 
    1202           0 :         ASYNC_RECV_TAIL(io, async_changenotify);
    1203             : }
    1204             : 
    1205             : /*
    1206             :   initialise the CIFS->CIFS backend, registering ourselves with the ntvfs subsystem
    1207             :  */
    1208          68 : NTSTATUS ntvfs_cifs_init(TALLOC_CTX *ctx)
    1209             : {
    1210           3 :         NTSTATUS ret;
    1211           3 :         struct ntvfs_ops ops;
    1212          68 :         NTVFS_CURRENT_CRITICAL_SIZES(vers);
    1213             : 
    1214          68 :         ZERO_STRUCT(ops);
    1215             : 
    1216             :         /* fill in the name and type */
    1217          68 :         ops.name = "cifs";
    1218          68 :         ops.type = NTVFS_DISK;
    1219             :         
    1220             :         /* fill in all the operations */
    1221          68 :         ops.connect_fn = cvfs_connect;
    1222          68 :         ops.disconnect_fn = cvfs_disconnect;
    1223          68 :         ops.unlink_fn = cvfs_unlink;
    1224          68 :         ops.chkpath_fn = cvfs_chkpath;
    1225          68 :         ops.qpathinfo_fn = cvfs_qpathinfo;
    1226          68 :         ops.setpathinfo_fn = cvfs_setpathinfo;
    1227          68 :         ops.open_fn = cvfs_open;
    1228          68 :         ops.mkdir_fn = cvfs_mkdir;
    1229          68 :         ops.rmdir_fn = cvfs_rmdir;
    1230          68 :         ops.rename_fn = cvfs_rename;
    1231          68 :         ops.copy_fn = cvfs_copy;
    1232          68 :         ops.ioctl_fn = cvfs_ioctl;
    1233          68 :         ops.read_fn = cvfs_read;
    1234          68 :         ops.write_fn = cvfs_write;
    1235          68 :         ops.seek_fn = cvfs_seek;
    1236          68 :         ops.flush_fn = cvfs_flush;
    1237          68 :         ops.close_fn = cvfs_close;
    1238          68 :         ops.exit_fn = cvfs_exit;
    1239          68 :         ops.lock_fn = cvfs_lock;
    1240          68 :         ops.setfileinfo_fn = cvfs_setfileinfo;
    1241          68 :         ops.qfileinfo_fn = cvfs_qfileinfo;
    1242          68 :         ops.fsinfo_fn = cvfs_fsinfo;
    1243          68 :         ops.lpq_fn = cvfs_lpq;
    1244          68 :         ops.search_first_fn = cvfs_search_first;
    1245          68 :         ops.search_next_fn = cvfs_search_next;
    1246          68 :         ops.search_close_fn = cvfs_search_close;
    1247          68 :         ops.trans_fn = cvfs_trans;
    1248          68 :         ops.logoff_fn = cvfs_logoff;
    1249          68 :         ops.async_setup_fn = cvfs_async_setup;
    1250          68 :         ops.cancel_fn = cvfs_cancel;
    1251          68 :         ops.notify_fn = cvfs_notify;
    1252          68 :         ops.trans2_fn = cvfs_trans2;
    1253             : 
    1254             :         /* register ourselves with the NTVFS subsystem. We register
    1255             :            under the name 'cifs'. */
    1256          68 :         ret = ntvfs_register(&ops, &vers);
    1257             : 
    1258          68 :         if (!NT_STATUS_IS_OK(ret)) {
    1259           0 :                 DEBUG(0,("Failed to register CIFS backend!\n"));
    1260             :         }
    1261             :         
    1262          68 :         return ret;
    1263             : }

Generated by: LCOV version 1.14