LCOV - code coverage report
Current view: top level - source4/ntvfs - ntvfs_generic.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 694 986 70.4 %
Date: 2024-04-21 15:09:00 Functions: 19 23 82.6 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    NTVFS generic level mapping code
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003-2004
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : /*
      22             :   this implements mappings between info levels for NTVFS backend calls
      23             : 
      24             :   the idea is that each of these functions implements one of the NTVFS
      25             :   backend calls in terms of the 'generic' call. All backends that use
      26             :   these functions must supply the generic call, but can if it wants to
      27             :   also implement other levels if the need arises
      28             : 
      29             :   this allows backend writers to only implement one variant of each
      30             :   call unless they need fine grained control of the calls.
      31             : */
      32             : 
      33             : #include "includes.h"
      34             : #include "ntvfs/ntvfs.h"
      35             : #include "libcli/smb2/smb2.h"
      36             : #include "libcli/smb2/smb2_calls.h"
      37             : 
      38             : #undef strcasecmp
      39             : 
      40             : /* a second stage function converts from the out parameters of the generic
      41             :    call onto the out parameters of the specific call made */
      42             : typedef NTSTATUS (*second_stage_t)(struct ntvfs_module_context *,
      43             :                                    struct ntvfs_request *,
      44             :                                    void *, void *, NTSTATUS);
      45             : 
      46             : /* 
      47             :    this structure holds the async state for pending mapped async calls
      48             : */
      49             : struct ntvfs_map_async {
      50             :         struct ntvfs_module_context *ntvfs;
      51             :         void *io, *io2;
      52             :         second_stage_t fn;
      53             : };
      54             : 
      55             : /*
      56             :   this is a async wrapper, called from the backend when it has completed
      57             :   a function that it has decided to reply to in an async fashion
      58             : */
      59        5396 : static void ntvfs_map_async_send(struct ntvfs_request *req)
      60             : {
      61        5396 :         struct ntvfs_map_async *m = talloc_get_type(req->async_states->private_data,
      62             :                                     struct ntvfs_map_async);
      63             : 
      64        5396 :         ntvfs_async_state_pop(req);
      65             : 
      66             :         /* call the _finish function setup in ntvfs_map_async_setup() */
      67        5396 :         req->async_states->status = m->fn(m->ntvfs, req, m->io, m->io2, req->async_states->status);
      68             : 
      69             :         /* call the send function from the next module up */
      70        5396 :         req->async_states->send_fn(req);
      71        5396 : }
      72             : 
      73             : /*
      74             :   prepare for calling a ntvfs backend with async support
      75             :   io is the original call structure
      76             :   io2 is the new call structure for the mapped call
      77             :   fn is a second stage function for processing the out arguments
      78             : */
      79      424940 : static NTSTATUS ntvfs_map_async_setup(struct ntvfs_module_context *ntvfs,
      80             :                                       struct ntvfs_request *req,
      81             :                                       void *io, void *io2,
      82             :                                       second_stage_t fn)
      83             : {
      84           0 :         struct ntvfs_map_async *m;
      85      424940 :         m = talloc(req, struct ntvfs_map_async);
      86      424940 :         if (m == NULL) {
      87           0 :                 return NT_STATUS_NO_MEMORY;
      88             :         }
      89      424940 :         m->ntvfs = ntvfs;
      90      424940 :         m->io = io;
      91      424940 :         m->io2 = io2;
      92      424940 :         m->fn = fn;
      93      424940 :         return ntvfs_async_state_push(ntvfs, req, m, ntvfs_map_async_send);
      94             : }
      95             : 
      96             : /*
      97             :   called when first stage processing is complete. 
      98             : */      
      99      424940 : static NTSTATUS ntvfs_map_async_finish(struct ntvfs_request *req, NTSTATUS status)
     100             : {
     101           0 :         struct ntvfs_map_async *m;
     102             : 
     103             :         /* if the backend has decided to reply in an async fashion then
     104             :            we don't need to do any work here */
     105      424940 :         if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
     106        5396 :                 return status;
     107             :         }
     108             : 
     109             :         /* the backend is replying immediately. call the 2nd stage function after popping our local
     110             :            async state */
     111      419544 :         m = talloc_get_type(req->async_states->private_data,
     112             :                             struct ntvfs_map_async);
     113             : 
     114      419544 :         ntvfs_async_state_pop(req);
     115             : 
     116      419544 :         return m->fn(m->ntvfs, req, m->io, m->io2, status);
     117             : }
     118             : 
     119             : /*
     120             :   see if a filename ends in EXE COM DLL or SYM. This is needed for the
     121             :   DENY_DOS mapping for OpenX
     122             : */
     123        1388 : bool is_exe_filename(const char *fname)
     124             : {
     125           0 :         char *p;
     126        1388 :         p = strrchr(fname, '.');
     127        1388 :         if (!p) {
     128         273 :                 return false;
     129             :         }
     130        1115 :         p++;
     131        1115 :         if (strcasecmp(p, "EXE") == 0 ||
     132         635 :             strcasecmp(p, "COM") == 0 ||
     133         635 :             strcasecmp(p, "DLL") == 0 ||
     134         635 :             strcasecmp(p, "SYM") == 0) {
     135         480 :                 return true;
     136             :         }
     137         635 :         return false;
     138             : }
     139             : 
     140             : 
     141             : /* 
     142             :    NTVFS openx to ntcreatex mapper
     143             : */
     144      217211 : static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
     145             :                                       struct ntvfs_request *req, 
     146             :                                       union smb_open *io, 
     147             :                                       union smb_open *io2, 
     148             :                                       NTSTATUS status)
     149             : {
     150      217211 :         time_t write_time = 0;
     151      217211 :         uint32_t set_size = 0;
     152           0 :         union smb_setfileinfo *sf;
     153           0 :         unsigned int state;
     154             : 
     155      217211 :         if (!NT_STATUS_IS_OK(status)) {
     156       69171 :                 return status;
     157             :         }
     158             : 
     159      148040 :         switch (io->generic.level) {
     160           8 :         case RAW_OPEN_OPEN:
     161           8 :                 io->openold.out.file.ntvfs = io2->generic.out.file.ntvfs;
     162           8 :                 io->openold.out.attrib     = io2->generic.out.attrib;
     163           8 :                 io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
     164           8 :                 io->openold.out.size       = io2->generic.out.size;
     165           8 :                 io->openold.out.rmode      = io->openold.in.open_mode;
     166           8 :                 break;
     167             : 
     168        6409 :         case RAW_OPEN_OPENX:
     169        6409 :                 io->openx.out.file.ntvfs  = io2->generic.out.file.ntvfs;
     170        6409 :                 io->openx.out.attrib      = io2->generic.out.attrib;
     171        6409 :                 io->openx.out.write_time  = nt_time_to_unix(io2->generic.out.write_time);
     172        6409 :                 io->openx.out.size        = io2->generic.out.size;
     173        6409 :                 io->openx.out.access      = (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK);
     174        6409 :                 io->openx.out.ftype       = 0;
     175        6409 :                 io->openx.out.devstate    = 0;
     176        6409 :                 io->openx.out.action      = io2->generic.out.create_action;
     177        6409 :                 io->openx.out.unique_fid  = 0;
     178        6409 :                 io->openx.out.access_mask = SEC_STD_ALL;
     179        6409 :                 io->openx.out.unknown     = 0;
     180             :                 
     181             :                 /* we need to extend the file to the requested size if
     182             :                    it was newly created */
     183        6409 :                 if (io2->generic.out.create_action == NTCREATEX_ACTION_CREATED) {
     184        3108 :                         set_size = io->openx.in.size;
     185             :                 }
     186        6409 :                 break;
     187             : 
     188          11 :         case RAW_OPEN_T2OPEN:
     189          11 :                 io->t2open.out.file.ntvfs  = io2->generic.out.file.ntvfs;
     190          11 :                 io->t2open.out.attrib      = io2->generic.out.attrib;
     191          11 :                 io->t2open.out.write_time  = nt_time_to_unix(io2->generic.out.write_time);
     192          11 :                 io->t2open.out.size        = io2->generic.out.size;
     193          11 :                 io->t2open.out.access      = io->t2open.in.open_mode;
     194          11 :                 io->t2open.out.ftype       = 0;
     195          11 :                 io->t2open.out.devstate    = 0;
     196          11 :                 io->t2open.out.action      = io2->generic.out.create_action;
     197          11 :                 io->t2open.out.file_id      = 0;
     198          11 :                 break;
     199             : 
     200           7 :         case RAW_OPEN_MKNEW:
     201             :         case RAW_OPEN_CREATE:
     202           7 :                 io->mknew.out.file.ntvfs= io2->generic.out.file.ntvfs;
     203           7 :                 write_time              = io->mknew.in.write_time;
     204           7 :                 break;
     205             : 
     206           4 :         case RAW_OPEN_CTEMP:
     207           4 :                 io->ctemp.out.file.ntvfs= io2->generic.out.file.ntvfs;
     208           8 :                 io->ctemp.out.name   = talloc_strdup(req, io2->generic.in.fname + 
     209           4 :                                                         strlen(io->ctemp.in.directory) + 1);
     210           4 :                 NT_STATUS_HAVE_NO_MEMORY(io->ctemp.out.name);
     211           4 :                 break;
     212             : 
     213      141601 :         case RAW_OPEN_SMB2:
     214      141601 :                 ZERO_STRUCT(io->smb2.out);
     215      141601 :                 io->smb2.out.file.ntvfs              = io2->generic.out.file.ntvfs;
     216      141601 :                 switch (io2->generic.out.oplock_level) {
     217          48 :                 case BATCH_OPLOCK_RETURN:
     218          48 :                         io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
     219          48 :                         break;
     220          14 :                 case EXCLUSIVE_OPLOCK_RETURN:
     221          14 :                         io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
     222          14 :                         break;
     223          27 :                 case LEVEL_II_OPLOCK_RETURN:
     224          27 :                         io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_II;
     225          27 :                         break;
     226      141512 :                 default:
     227      141512 :                         io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
     228      141512 :                         break;
     229             :                 }
     230      141601 :                 io->smb2.out.reserved                = 0;
     231      141601 :                 io->smb2.out.create_action   = io2->generic.out.create_action;
     232      141601 :                 io->smb2.out.create_time     = io2->generic.out.create_time;
     233      141601 :                 io->smb2.out.access_time     = io2->generic.out.access_time;
     234      141601 :                 io->smb2.out.write_time              = io2->generic.out.write_time;
     235      141601 :                 io->smb2.out.change_time     = io2->generic.out.change_time;
     236      141601 :                 io->smb2.out.alloc_size              = io2->generic.out.alloc_size;
     237      141601 :                 io->smb2.out.size            = io2->generic.out.size;
     238      141601 :                 io->smb2.out.file_attr               = io2->generic.out.attrib;
     239      141601 :                 io->smb2.out.reserved2               = 0;
     240      141601 :                 io->smb2.out.maximal_access     = io2->generic.out.maximal_access;
     241      141601 :                 memcpy(io->smb2.out.on_disk_id, io2->generic.out.on_disk_id,
     242             :                        sizeof(io2->generic.out.on_disk_id));
     243      141601 :                 break;
     244             : 
     245           0 :         default:
     246           0 :                 return NT_STATUS_INVALID_LEVEL;
     247             :         }
     248             : 
     249             :         /* doing a secondary request async is more trouble than its
     250             :            worth */
     251      148040 :         state = req->async_states->state;
     252      148040 :         req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
     253             : 
     254      148040 :         if (write_time != 0) {
     255           4 :                 sf = talloc(req, union smb_setfileinfo);
     256           4 :                 NT_STATUS_HAVE_NO_MEMORY(sf);
     257           4 :                 sf->generic.level           = RAW_SFILEINFO_STANDARD;
     258           4 :                 sf->generic.in.file.ntvfs   = io2->generic.out.file.ntvfs;
     259           4 :                 sf->standard.in.create_time = 0;
     260           4 :                 sf->standard.in.write_time  = write_time;
     261           4 :                 sf->standard.in.access_time = 0;
     262           4 :                 status = ntvfs->ops->setfileinfo_fn(ntvfs, req, sf);
     263             :         }
     264             : 
     265      148040 :         if (set_size != 0) {
     266           6 :                 sf = talloc(req, union smb_setfileinfo);                        
     267           6 :                 NT_STATUS_HAVE_NO_MEMORY(sf);
     268           6 :                 sf->generic.level            = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
     269           6 :                 sf->generic.in.file.ntvfs    = io2->generic.out.file.ntvfs;
     270           6 :                 sf->end_of_file_info.in.size = set_size;
     271           6 :                 status = ntvfs->ops->setfileinfo_fn(ntvfs, req, sf);
     272           6 :                 if (NT_STATUS_IS_OK(status)) {
     273           6 :                         io->openx.out.size = io->openx.in.size;
     274             :                 }
     275             :         }
     276             : 
     277      148040 :         req->async_states->state = state;
     278             : 
     279      148040 :         return NT_STATUS_OK;
     280             : }
     281             : 
     282             : /*
     283             :   the core of the mapping between openx style parameters and ntcreatex 
     284             :   parameters
     285             : */
     286        8622 : static NTSTATUS map_openx_open(uint16_t flags, uint16_t open_mode, 
     287             :                                uint16_t open_func, const char *fname,
     288             :                                union smb_open *io2)
     289             : {
     290        8622 :         io2->generic.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
     291        8622 :         io2->generic.in.private_flags = 0;
     292             : 
     293        8622 :         if (flags & OPENX_FLAGS_REQUEST_OPLOCK) {
     294           3 :                 io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
     295             :         }
     296        8622 :         if (flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) {
     297           3 :                 io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
     298             :         }
     299             : 
     300        8622 :         switch (open_mode & OPENX_MODE_ACCESS_MASK) {
     301        1672 :         case OPENX_MODE_ACCESS_READ:
     302             :         case OPENX_MODE_ACCESS_EXEC:
     303        1672 :                 io2->generic.in.access_mask = SEC_RIGHTS_FILE_READ;
     304        1672 :                 break;
     305        1451 :         case OPENX_MODE_ACCESS_WRITE:
     306        1451 :                 io2->generic.in.access_mask = SEC_RIGHTS_FILE_WRITE;
     307        1451 :                 break;
     308        5493 :         case OPENX_MODE_ACCESS_RDWR:
     309             :         case OPENX_MODE_ACCESS_FCB:
     310        5493 :                 io2->generic.in.access_mask = 
     311             :                         SEC_RIGHTS_FILE_READ | 
     312             :                         SEC_RIGHTS_FILE_WRITE;
     313        5493 :                 break;
     314           6 :         default:
     315           6 :                 return NT_STATUS_DOS(ERRDOS, ERRbadaccess);
     316             :         }
     317             : 
     318        8616 :         switch (open_mode & OPENX_MODE_DENY_MASK) {
     319         864 :         case OPENX_MODE_DENY_READ:
     320         864 :                 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
     321         864 :                 break;
     322         871 :         case OPENX_MODE_DENY_WRITE:
     323         871 :                 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
     324         871 :                 break;
     325         974 :         case OPENX_MODE_DENY_ALL:
     326         974 :                 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     327         974 :                 break;
     328        3765 :         case OPENX_MODE_DENY_NONE:
     329        3765 :                 io2->generic.in.share_access = 
     330             :                         NTCREATEX_SHARE_ACCESS_READ | 
     331             :                         NTCREATEX_SHARE_ACCESS_WRITE;
     332        3765 :                 break;
     333        1273 :         case OPENX_MODE_DENY_DOS:
     334             :                 /* DENY_DOS is quite strange - it depends on the filename! */
     335        1273 :                 io2->generic.in.private_flags |=
     336             :                         NTCREATEX_FLAG_DENY_DOS;
     337        1273 :                 if (is_exe_filename(fname)) {
     338         432 :                         io2->generic.in.share_access = 
     339             :                                 NTCREATEX_SHARE_ACCESS_READ | 
     340             :                                 NTCREATEX_SHARE_ACCESS_WRITE;
     341             :                 } else {
     342         841 :                         if ((open_mode & OPENX_MODE_ACCESS_MASK) == OPENX_MODE_ACCESS_READ) {
     343         312 :                                 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
     344             :                         } else {
     345         529 :                                 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     346             :                         }
     347             :                 }
     348        1273 :                 break;
     349         867 :         case OPENX_MODE_DENY_FCB:
     350         867 :                 io2->generic.in.private_flags |= NTCREATEX_FLAG_DENY_FCB;
     351         867 :                 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
     352         867 :                 break;
     353           2 :         default:
     354           2 :                 return NT_STATUS_DOS(ERRDOS, ERRbadaccess);
     355             :         }
     356             : 
     357        8614 :         switch (open_func) {
     358        5345 :         case (OPENX_OPEN_FUNC_OPEN):
     359        5345 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
     360        5345 :                 break;
     361          11 :         case (OPENX_OPEN_FUNC_TRUNC):
     362          11 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
     363          11 :                 break;
     364         107 :         case (OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE):
     365         107 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
     366         107 :                 break;
     367        2793 :         case (OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE):
     368        2793 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
     369        2793 :                 break;
     370         351 :         case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE):
     371         351 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
     372         351 :                 break;                  
     373           7 :         default:
     374             :                 /* this one is very strange */
     375           7 :                 if ((open_mode & OPENX_MODE_ACCESS_MASK) == OPENX_MODE_ACCESS_EXEC) {
     376           3 :                         io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
     377           3 :                         break;
     378             :                 }
     379           4 :                 return NT_STATUS_DOS(ERRDOS, ERRbadaccess);
     380             :         }
     381             : 
     382        8610 :         return NT_STATUS_OK;
     383             : }
     384             : 
     385             : /* 
     386             :    NTVFS open generic to any mapper
     387             : */
     388      217211 : NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
     389             :                                  struct ntvfs_request *req,
     390             :                                  union smb_open *io)
     391             : {
     392           0 :         NTSTATUS status;
     393           0 :         union smb_open *io2;
     394             : 
     395      217211 :         io2 = talloc_zero(req, union smb_open);
     396      217211 :         if (io2 == NULL) {
     397           0 :                 return NT_STATUS_NO_MEMORY;
     398             :         }
     399             : 
     400      217211 :         status = ntvfs_map_async_setup(ntvfs, req,
     401             :                                        io, io2, 
     402             :                                        (second_stage_t)ntvfs_map_open_finish);
     403      217211 :         if (!NT_STATUS_IS_OK(status)) {
     404           0 :                 return status;
     405             :         }
     406             : 
     407      217211 :         io2->generic.level = RAW_OPEN_GENERIC;
     408             :                 
     409      217211 :         switch (io->generic.level) {
     410        8589 :         case RAW_OPEN_OPENX:
     411        8589 :                 status = map_openx_open(io->openx.in.flags,
     412        8589 :                                         io->openx.in.open_mode, 
     413        8589 :                                         io->openx.in.open_func, 
     414             :                                         io->openx.in.fname,
     415             :                                         io2);
     416        8589 :                 if (!NT_STATUS_IS_OK(status)) {
     417          14 :                         goto done;
     418             :                 }
     419             :                 
     420        8583 :                 io2->generic.in.file_attr = io->openx.in.file_attrs;
     421        8583 :                 io2->generic.in.fname = io->openx.in.fname;
     422             :                 
     423        8583 :                 status = ntvfs->ops->open_fn(ntvfs, req, io2);
     424      217197 :                 break;
     425             :                 
     426             :                 
     427          18 :         case RAW_OPEN_OPEN:
     428          18 :                 status = map_openx_open(0,
     429          18 :                                         io->openold.in.open_mode, 
     430             :                                         OPENX_OPEN_FUNC_OPEN, 
     431             :                                         io->openold.in.fname,
     432             :                                         io2);
     433          18 :                 if (!NT_STATUS_IS_OK(status)) {
     434           6 :                         goto done;
     435             :                 }
     436             : 
     437          12 :                 io2->generic.in.file_attr = io->openold.in.search_attrs;
     438          12 :                 io2->generic.in.fname = io->openold.in.fname;
     439             : 
     440          12 :                 status = ntvfs->ops->open_fn(ntvfs, req, io2);
     441          12 :                 break;
     442             : 
     443          17 :         case RAW_OPEN_T2OPEN:
     444          17 :                 io2->generic.level         = RAW_OPEN_NTTRANS_CREATE;
     445             : 
     446          17 :                 if (io->t2open.in.open_func == 0) {
     447           2 :                         status = NT_STATUS_OBJECT_NAME_COLLISION;
     448           2 :                         goto done;
     449             :                 }
     450             : 
     451          15 :                 status = map_openx_open(io->t2open.in.flags,
     452          15 :                                         io->t2open.in.open_mode, 
     453          15 :                                         io->t2open.in.open_func, 
     454             :                                         io->t2open.in.fname,
     455             :                                         io2);
     456          15 :                 if (!NT_STATUS_IS_OK(status)) {
     457           0 :                         goto done;
     458             :                 }
     459             : 
     460          15 :                 io2->generic.in.file_attr        = io->t2open.in.file_attrs;
     461          15 :                 io2->generic.in.fname            = io->t2open.in.fname;
     462          15 :                 io2->generic.in.ea_list          = talloc(io2, struct smb_ea_list);
     463          15 :                 io2->generic.in.ea_list->num_eas = io->t2open.in.num_eas;
     464          15 :                 io2->generic.in.ea_list->eas     = io->t2open.in.eas;
     465             : 
     466          15 :                 status = ntvfs->ops->open_fn(ntvfs, req, io2);
     467          15 :                 break;
     468             : 
     469           4 :         case RAW_OPEN_MKNEW:
     470           4 :                 io2->generic.in.file_attr = io->mknew.in.attrib;
     471           4 :                 io2->generic.in.fname = io->mknew.in.fname;
     472           4 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
     473           4 :                 io2->generic.in.access_mask = 
     474             :                         SEC_RIGHTS_FILE_READ |
     475             :                         SEC_RIGHTS_FILE_WRITE;
     476           4 :                 io2->generic.in.share_access = 
     477             :                         NTCREATEX_SHARE_ACCESS_READ | 
     478             :                         NTCREATEX_SHARE_ACCESS_WRITE;
     479           4 :                 status = ntvfs->ops->open_fn(ntvfs, req, io2);
     480           4 :                 break;
     481             : 
     482           4 :         case RAW_OPEN_CREATE:
     483           4 :                 io2->generic.in.file_attr = io->mknew.in.attrib;
     484           4 :                 io2->generic.in.fname = io->mknew.in.fname;
     485           4 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
     486           4 :                 io2->generic.in.access_mask = 
     487             :                         SEC_RIGHTS_FILE_READ |
     488             :                         SEC_RIGHTS_FILE_WRITE;
     489           4 :                 io2->generic.in.share_access = 
     490             :                         NTCREATEX_SHARE_ACCESS_READ | 
     491             :                         NTCREATEX_SHARE_ACCESS_WRITE;
     492           4 :                 status = ntvfs->ops->open_fn(ntvfs, req, io2);
     493           4 :                 break;
     494             : 
     495           4 :         case RAW_OPEN_CTEMP:
     496           4 :                 io2->generic.in.file_attr = io->ctemp.in.attrib;
     497           4 :                 io2->generic.in.fname = 
     498           4 :                         talloc_asprintf(io2, "%s\\SRV%s", 
     499             :                                         io->ctemp.in.directory,
     500             :                                         generate_random_str_list(io2, 5, "0123456789"));
     501           4 :                 io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
     502           4 :                 io2->generic.in.access_mask = 
     503             :                         SEC_RIGHTS_FILE_READ |
     504             :                         SEC_RIGHTS_FILE_WRITE;
     505           4 :                 io2->generic.in.share_access = 
     506             :                         NTCREATEX_SHARE_ACCESS_READ | 
     507             :                         NTCREATEX_SHARE_ACCESS_WRITE;
     508           4 :                 status = ntvfs->ops->open_fn(ntvfs, req, io2);
     509           4 :                 break;
     510      208575 :         case RAW_OPEN_SMB2:
     511      208575 :                 switch (io->smb2.in.oplock_level) {
     512          70 :                 case SMB2_OPLOCK_LEVEL_BATCH:
     513          70 :                         io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK |
     514             :                                                 NTCREATEX_FLAGS_REQUEST_OPLOCK;
     515          70 :                         break;
     516          26 :                 case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
     517          26 :                         io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_OPLOCK;
     518          26 :                         break;
     519      208479 :                 default:
     520      208479 :                         io2->generic.in.flags = 0;
     521      208479 :                         break;
     522             :                 }
     523      208575 :                 io2->generic.in.root_fid.fnum        = 0;
     524      208575 :                 io2->generic.in.access_mask  = io->smb2.in.desired_access;
     525      208575 :                 io2->generic.in.alloc_size   = io->smb2.in.alloc_size;
     526      208575 :                 io2->generic.in.file_attr    = io->smb2.in.file_attributes;
     527      208575 :                 io2->generic.in.share_access = io->smb2.in.share_access;
     528      208575 :                 io2->generic.in.open_disposition= io->smb2.in.create_disposition;
     529      208575 :                 io2->generic.in.create_options       = io->smb2.in.create_options;
     530      208575 :                 io2->generic.in.impersonation        = io->smb2.in.impersonation_level;
     531      208575 :                 io2->generic.in.security_flags       = 0;
     532      208575 :                 io2->generic.in.fname                = io->smb2.in.fname;
     533      208575 :                 io2->generic.in.sec_desc     = io->smb2.in.sec_desc;
     534      208575 :                 io2->generic.in.ea_list              = &io->smb2.in.eas;
     535      208575 :                 io2->generic.in.query_maximal_access = io->smb2.in.query_maximal_access; 
     536      208575 :                 io2->generic.in.query_on_disk_id = io->smb2.in.query_on_disk_id;
     537      208575 :                 io2->generic.in.private_flags        = 0;
     538             : 
     539             :                 /* we don't support timewarp yet */
     540      208575 :                 if (io->smb2.in.timewarp != 0) {
     541           1 :                         status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
     542           1 :                         break;
     543             :                 }
     544             : 
     545             :                 /* we need to check these bits before we check the private mask */
     546      208574 :                 if (io2->generic.in.create_options & SMB2_CREATE_OPTIONS_NOT_SUPPORTED_MASK) {
     547           2 :                         DEBUG(2,(__location__ " create_options 0x%x not supported\n",
     548             :                                  io2->generic.in.create_options));
     549           2 :                         status = NT_STATUS_NOT_SUPPORTED;
     550           2 :                         break;
     551             :                 }
     552             : 
     553             :                 /* TODO: find out why only SMB2 ignores these */
     554      208572 :                 io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_SYNC_ALERT;
     555      208572 :                 io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_ASYNC_ALERT;
     556             : 
     557      208572 :                 status = ntvfs->ops->open_fn(ntvfs, req, io2);
     558      208572 :                 break;
     559             : 
     560           0 :         default:
     561           0 :                 status = NT_STATUS_INVALID_LEVEL;
     562           0 :                 break;
     563             :         }
     564      217211 : done:
     565      217211 :         return ntvfs_map_async_finish(req, status);
     566             : }
     567             : 
     568             : 
     569             : /* 
     570             :    NTVFS any to fsinfo mapper
     571             : */
     572           0 : static NTSTATUS ntvfs_map_fsinfo_finish(struct ntvfs_module_context *ntvfs,
     573             :                                       struct ntvfs_request *req,
     574             :                                       union smb_fsinfo *fs,
     575             :                                       union smb_fsinfo *fs2,
     576             :                                       NTSTATUS status)
     577             : {
     578           0 :         if (!NT_STATUS_IS_OK(status)) {
     579           0 :                 return status;
     580             :         }
     581             : 
     582             :         /* and convert it to the required level */
     583           0 :         switch (fs->generic.level) {
     584           0 :         case RAW_QFS_DSKATTR: {
     585             :                 /* map from generic to DSKATTR */
     586           0 :                 unsigned int bpunit = 64;
     587             : 
     588             :                 /* we need to scale the sizes to fit */
     589           0 :                 for (bpunit=64; bpunit<0x10000; bpunit *= 2) {
     590           0 :                         if (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size < bpunit * 512 * 65535.0) {
     591           0 :                                 break;
     592             :                         }
     593             :                 }
     594             : 
     595           0 :                 fs->dskattr.out.blocks_per_unit = bpunit;
     596           0 :                 fs->dskattr.out.block_size = 512;
     597           0 :                 fs->dskattr.out.units_total = 
     598           0 :                         (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size) / (bpunit * 512);
     599           0 :                 fs->dskattr.out.units_free  = 
     600           0 :                         (fs2->generic.out.blocks_free  * (double)fs2->generic.out.block_size) / (bpunit * 512);
     601             : 
     602             :                 /* we must return a maximum of 2G to old DOS systems, or they get very confused */
     603           0 :                 if (bpunit > 64 && req->ctx->protocol <= PROTOCOL_LANMAN2) {
     604           0 :                         fs->dskattr.out.blocks_per_unit = 64;
     605           0 :                         fs->dskattr.out.units_total = 0xFFFF;
     606           0 :                         fs->dskattr.out.units_free = 0xFFFF;
     607             :                 }
     608           0 :                 return NT_STATUS_OK;
     609             :         }
     610             : 
     611           0 :         case RAW_QFS_ALLOCATION:
     612           0 :                 fs->allocation.out.fs_id = fs2->generic.out.fs_id;
     613           0 :                 fs->allocation.out.total_alloc_units = fs2->generic.out.blocks_total;
     614           0 :                 fs->allocation.out.avail_alloc_units = fs2->generic.out.blocks_free;
     615           0 :                 fs->allocation.out.sectors_per_unit = 1;
     616           0 :                 fs->allocation.out.bytes_per_sector = fs2->generic.out.block_size;
     617           0 :                 return NT_STATUS_OK;
     618             : 
     619           0 :         case RAW_QFS_VOLUME:
     620           0 :                 fs->volume.out.serial_number = fs2->generic.out.serial_number;
     621           0 :                 fs->volume.out.volume_name.s = fs2->generic.out.volume_name;
     622           0 :                 return NT_STATUS_OK;
     623             : 
     624           0 :         case RAW_QFS_VOLUME_INFO:
     625             :         case RAW_QFS_VOLUME_INFORMATION:
     626           0 :                 fs->volume_info.out.create_time = fs2->generic.out.create_time;
     627           0 :                 fs->volume_info.out.serial_number = fs2->generic.out.serial_number;
     628           0 :                 fs->volume_info.out.volume_name.s = fs2->generic.out.volume_name;
     629           0 :                 return NT_STATUS_OK;
     630             : 
     631           0 :         case RAW_QFS_SIZE_INFO:
     632             :         case RAW_QFS_SIZE_INFORMATION:
     633           0 :                 fs->size_info.out.total_alloc_units = fs2->generic.out.blocks_total;
     634           0 :                 fs->size_info.out.avail_alloc_units = fs2->generic.out.blocks_free;
     635           0 :                 fs->size_info.out.sectors_per_unit = 1;
     636           0 :                 fs->size_info.out.bytes_per_sector = fs2->generic.out.block_size;
     637           0 :                 return NT_STATUS_OK;
     638             : 
     639           0 :         case RAW_QFS_DEVICE_INFO:
     640             :         case RAW_QFS_DEVICE_INFORMATION:
     641           0 :                 fs->device_info.out.device_type = fs2->generic.out.device_type;
     642           0 :                 fs->device_info.out.characteristics = fs2->generic.out.device_characteristics;
     643           0 :                 return NT_STATUS_OK;
     644             : 
     645           0 :         case RAW_QFS_ATTRIBUTE_INFO:
     646             :         case RAW_QFS_ATTRIBUTE_INFORMATION:
     647           0 :                 fs->attribute_info.out.fs_attr = fs2->generic.out.fs_attr;
     648           0 :                 fs->attribute_info.out.max_file_component_length = fs2->generic.out.max_file_component_length;
     649           0 :                 fs->attribute_info.out.fs_type.s = fs2->generic.out.fs_type;
     650           0 :                 return NT_STATUS_OK;
     651             : 
     652           0 :         case RAW_QFS_QUOTA_INFORMATION:
     653           0 :                 ZERO_STRUCT(fs->quota_information.out.unknown);
     654           0 :                 fs->quota_information.out.quota_soft = fs2->generic.out.quota_soft;
     655           0 :                 fs->quota_information.out.quota_hard = fs2->generic.out.quota_hard;
     656           0 :                 fs->quota_information.out.quota_flags = fs2->generic.out.quota_flags;
     657           0 :                 return NT_STATUS_OK;
     658             : 
     659           0 :         case RAW_QFS_FULL_SIZE_INFORMATION:
     660           0 :                 fs->full_size_information.out.total_alloc_units = fs2->generic.out.blocks_total;
     661           0 :                 fs->full_size_information.out.call_avail_alloc_units = fs2->generic.out.blocks_free;
     662           0 :                 fs->full_size_information.out.actual_avail_alloc_units = fs2->generic.out.blocks_free;
     663           0 :                 fs->full_size_information.out.sectors_per_unit = 1;
     664           0 :                 fs->full_size_information.out.bytes_per_sector = fs2->generic.out.block_size;
     665           0 :                 return NT_STATUS_OK;
     666             : 
     667           0 :         case RAW_QFS_OBJECTID_INFORMATION:
     668           0 :                 fs->objectid_information.out.guid = fs2->generic.out.guid;
     669           0 :                 ZERO_STRUCT(fs->objectid_information.out.unknown);
     670           0 :                 return NT_STATUS_OK;
     671             : 
     672           0 :         case RAW_QFS_SECTOR_SIZE_INFORMATION:
     673           0 :                 fs->sector_size_info.out.logical_bytes_per_sector
     674           0 :                                                 = fs2->generic.out.block_size;
     675           0 :                 fs->sector_size_info.out.phys_bytes_per_sector_atomic
     676           0 :                                                 = fs2->generic.out.block_size;
     677           0 :                 fs->sector_size_info.out.phys_bytes_per_sector_perf
     678           0 :                                                 = fs2->generic.out.block_size;
     679           0 :                 fs->sector_size_info.out.fs_effective_phys_bytes_per_sector_atomic
     680           0 :                                                 = fs2->generic.out.block_size;
     681           0 :                 fs->sector_size_info.out.flags
     682           0 :                                         = QFS_SSINFO_FLAGS_ALIGNED_DEVICE
     683             :                                 | QFS_SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE;
     684           0 :                 fs->sector_size_info.out.byte_off_sector_align = 0;
     685           0 :                 fs->sector_size_info.out.byte_off_partition_align = 0;
     686           0 :                 return NT_STATUS_OK;
     687             : 
     688           0 :         case RAW_QFS_GENERIC:
     689             :         case RAW_QFS_UNIX_INFO:
     690           0 :                 return NT_STATUS_INVALID_LEVEL;
     691             :         }
     692             : 
     693           0 :         return NT_STATUS_INVALID_LEVEL;
     694             : }
     695             : 
     696             : /*
     697             :    NTVFS fsinfo any to generic mapper
     698             : */
     699           0 : NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
     700             :                           struct ntvfs_request *req,
     701             :                           union smb_fsinfo *fs)
     702             : {
     703           0 :         NTSTATUS status;
     704           0 :         union smb_fsinfo *fs2;
     705             : 
     706           0 :         fs2 = talloc(req, union smb_fsinfo);
     707           0 :         if (fs2 == NULL) {
     708           0 :                 return NT_STATUS_NO_MEMORY;
     709             :         }
     710             : 
     711           0 :         if (fs->generic.level == RAW_QFS_GENERIC) {
     712           0 :                 return NT_STATUS_INVALID_LEVEL;
     713             :         }
     714             : 
     715           0 :         status = ntvfs_map_async_setup(ntvfs, req, fs, fs2,
     716             :                                        (second_stage_t)ntvfs_map_fsinfo_finish);
     717           0 :         if (!NT_STATUS_IS_OK(status)) {
     718           0 :                 return status;
     719             :         }
     720             : 
     721             :         /* ask the backend for the generic info */
     722           0 :         fs2->generic.level = RAW_QFS_GENERIC;
     723             : 
     724           0 :         status = ntvfs->ops->fsinfo_fn(ntvfs, req, fs2);
     725           0 :         return ntvfs_map_async_finish(req, status);
     726             : }
     727             : 
     728             : 
     729             : /* 
     730             :    NTVFS fileinfo generic to any mapper
     731             : */
     732          20 : NTSTATUS ntvfs_map_fileinfo(TALLOC_CTX *mem_ctx,
     733             :                                      union smb_fileinfo *info, 
     734             :                                      union smb_fileinfo *info2)
     735             : {
     736           0 :         int i;
     737             :         /* and convert it to the required level using results in info2 */
     738          20 :         switch (info->generic.level) {
     739           0 :         case RAW_FILEINFO_GETATTR:
     740           0 :                 info->getattr.out.attrib = info2->generic.out.attrib & 0xff;
     741           0 :                 info->getattr.out.size = info2->generic.out.size;
     742           0 :                 info->getattr.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
     743           0 :                 return NT_STATUS_OK;
     744             :                 
     745           1 :         case RAW_FILEINFO_GETATTRE:
     746           1 :                 info->getattre.out.attrib = info2->generic.out.attrib;
     747           1 :                 info->getattre.out.size = info2->generic.out.size;
     748           1 :                 info->getattre.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
     749           1 :                 info->getattre.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
     750           1 :                 info->getattre.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
     751           1 :                 info->getattre.out.alloc_size = info2->generic.out.alloc_size;
     752           1 :                 return NT_STATUS_OK;
     753             :                 
     754           0 :         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
     755           0 :                 info->network_open_information.out.create_time = info2->generic.out.create_time;
     756           0 :                 info->network_open_information.out.access_time = info2->generic.out.access_time;
     757           0 :                 info->network_open_information.out.write_time =  info2->generic.out.write_time;
     758           0 :                 info->network_open_information.out.change_time = info2->generic.out.change_time;
     759           0 :                 info->network_open_information.out.alloc_size = info2->generic.out.alloc_size;
     760           0 :                 info->network_open_information.out.size = info2->generic.out.size;
     761           0 :                 info->network_open_information.out.attrib = info2->generic.out.attrib;
     762           0 :                 return NT_STATUS_OK;
     763             : 
     764           2 :         case RAW_FILEINFO_ALL_INFO:
     765             :         case RAW_FILEINFO_ALL_INFORMATION:
     766           2 :                 info->all_info.out.create_time = info2->generic.out.create_time;
     767           2 :                 info->all_info.out.access_time = info2->generic.out.access_time;
     768           2 :                 info->all_info.out.write_time =  info2->generic.out.write_time;
     769           2 :                 info->all_info.out.change_time = info2->generic.out.change_time;
     770           2 :                 info->all_info.out.attrib = info2->generic.out.attrib;
     771           2 :                 info->all_info.out.alloc_size = info2->generic.out.alloc_size;
     772           2 :                 info->all_info.out.size = info2->generic.out.size;
     773           2 :                 info->all_info.out.nlink = info2->generic.out.nlink;
     774           2 :                 info->all_info.out.delete_pending = info2->generic.out.delete_pending;
     775           2 :                 info->all_info.out.directory = info2->generic.out.directory;
     776           2 :                 info->all_info.out.ea_size = info2->generic.out.ea_size;
     777           2 :                 info->all_info.out.fname.s = info2->generic.out.fname.s;
     778           2 :                 info->all_info.out.fname.private_length = info2->generic.out.fname.private_length;
     779           2 :                 return NT_STATUS_OK;
     780             : 
     781           2 :         case RAW_FILEINFO_BASIC_INFO:
     782             :         case RAW_FILEINFO_BASIC_INFORMATION:
     783           2 :                 info->basic_info.out.create_time = info2->generic.out.create_time;
     784           2 :                 info->basic_info.out.access_time = info2->generic.out.access_time;
     785           2 :                 info->basic_info.out.write_time = info2->generic.out.write_time;
     786           2 :                 info->basic_info.out.change_time = info2->generic.out.change_time;
     787           2 :                 info->basic_info.out.attrib = info2->generic.out.attrib;
     788           2 :                 return NT_STATUS_OK;
     789             : 
     790           1 :         case RAW_FILEINFO_STANDARD:
     791           1 :                 info->standard.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
     792           1 :                 info->standard.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
     793           1 :                 info->standard.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
     794           1 :                 info->standard.out.size = info2->generic.out.size;
     795           1 :                 info->standard.out.alloc_size = info2->generic.out.alloc_size;
     796           1 :                 info->standard.out.attrib = info2->generic.out.attrib;
     797           1 :                 return NT_STATUS_OK;
     798             : 
     799           1 :         case RAW_FILEINFO_EA_SIZE:
     800           1 :                 info->ea_size.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
     801           1 :                 info->ea_size.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
     802           1 :                 info->ea_size.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
     803           1 :                 info->ea_size.out.size = info2->generic.out.size;
     804           1 :                 info->ea_size.out.alloc_size = info2->generic.out.alloc_size;
     805           1 :                 info->ea_size.out.attrib = info2->generic.out.attrib;
     806           1 :                 info->ea_size.out.ea_size = info2->generic.out.ea_size;
     807           1 :                 return NT_STATUS_OK;
     808             : 
     809           2 :         case RAW_FILEINFO_STANDARD_INFO:
     810             :         case RAW_FILEINFO_STANDARD_INFORMATION:
     811           2 :                 info->standard_info.out.alloc_size = info2->generic.out.alloc_size;
     812           2 :                 info->standard_info.out.size = info2->generic.out.size;
     813           2 :                 info->standard_info.out.nlink = info2->generic.out.nlink;
     814           2 :                 info->standard_info.out.delete_pending = info2->generic.out.delete_pending;
     815           2 :                 info->standard_info.out.directory = info2->generic.out.directory;
     816           2 :                 return NT_STATUS_OK;
     817             : 
     818           1 :         case RAW_FILEINFO_INTERNAL_INFORMATION:
     819           1 :                 info->internal_information.out.file_id = info2->generic.out.file_id;
     820           1 :                 return NT_STATUS_OK;
     821             : 
     822           2 :         case RAW_FILEINFO_EA_INFO:
     823             :         case RAW_FILEINFO_EA_INFORMATION:
     824           2 :                 info->ea_info.out.ea_size = info2->generic.out.ea_size;
     825           2 :                 return NT_STATUS_OK;
     826             : 
     827           0 :         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
     828           0 :                 info->attribute_tag_information.out.attrib = info2->generic.out.attrib;
     829           0 :                 info->attribute_tag_information.out.reparse_tag = info2->generic.out.reparse_tag;
     830           0 :                 return NT_STATUS_OK;
     831             : 
     832           0 :         case RAW_FILEINFO_STREAM_INFO:
     833             :         case RAW_FILEINFO_STREAM_INFORMATION:
     834           0 :                 info->stream_info.out.num_streams = info2->generic.out.num_streams;
     835           0 :                 if (info->stream_info.out.num_streams > 0) {
     836           0 :                         info->stream_info.out.streams = 
     837           0 :                                 talloc_array(mem_ctx, 
     838             :                                                struct stream_struct,
     839             :                                                info->stream_info.out.num_streams);
     840           0 :                         if (!info->stream_info.out.streams) {
     841           0 :                                 DEBUG(2,("ntvfs_map_fileinfo: no memory for %d streams\n",
     842             :                                         info->stream_info.out.num_streams));
     843           0 :                                 return NT_STATUS_NO_MEMORY;
     844             :                         }
     845           0 :                         for (i=0; i < info->stream_info.out.num_streams; i++) {
     846           0 :                                 info->stream_info.out.streams[i] = info2->generic.out.streams[i];
     847           0 :                                 info->stream_info.out.streams[i].stream_name.s = 
     848           0 :                                         talloc_strdup(info->stream_info.out.streams,
     849           0 :                                                       info2->generic.out.streams[i].stream_name.s);
     850           0 :                                 if (!info->stream_info.out.streams[i].stream_name.s) {
     851           0 :                                         DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
     852           0 :                                         return NT_STATUS_NO_MEMORY;
     853             :                                 }
     854             :                         }
     855             :                 }
     856           0 :                 return NT_STATUS_OK;
     857             : 
     858           2 :         case RAW_FILEINFO_NAME_INFO:
     859             :         case RAW_FILEINFO_NAME_INFORMATION:
     860           2 :                 info->name_info.out.fname.s = talloc_strdup(mem_ctx, info2->generic.out.fname.s);
     861           2 :                 NT_STATUS_HAVE_NO_MEMORY(info->name_info.out.fname.s);
     862           2 :                 info->name_info.out.fname.private_length = info2->generic.out.fname.private_length;
     863           2 :                 return NT_STATUS_OK;
     864             :                 
     865           0 :         case RAW_FILEINFO_ALT_NAME_INFO:
     866             :         case RAW_FILEINFO_ALT_NAME_INFORMATION:
     867             :         case RAW_FILEINFO_SMB2_ALT_NAME_INFORMATION:
     868           0 :                 info->alt_name_info.out.fname.s = talloc_strdup(mem_ctx, info2->generic.out.alt_fname.s);
     869           0 :                 NT_STATUS_HAVE_NO_MEMORY(info->alt_name_info.out.fname.s);
     870           0 :                 info->alt_name_info.out.fname.private_length = info2->generic.out.alt_fname.private_length;
     871           0 :                 return NT_STATUS_OK;
     872             :         
     873           1 :         case RAW_FILEINFO_POSITION_INFORMATION:
     874           1 :                 info->position_information.out.position = info2->generic.out.position;
     875           1 :                 return NT_STATUS_OK;
     876             :         
     877           0 :         case RAW_FILEINFO_ALL_EAS:
     878           0 :                 info->all_eas.out.num_eas = info2->generic.out.num_eas;
     879           0 :                 if (info->all_eas.out.num_eas > 0) {
     880           0 :                         info->all_eas.out.eas = talloc_array(mem_ctx, 
     881             :                                                                struct ea_struct,
     882             :                                                                info->all_eas.out.num_eas);
     883           0 :                         if (!info->all_eas.out.eas) {
     884           0 :                                 DEBUG(2,("ntvfs_map_fileinfo: no memory for %d eas\n",
     885             :                                         info->all_eas.out.num_eas));
     886           0 :                                 return NT_STATUS_NO_MEMORY;
     887             :                         }
     888           0 :                         for (i = 0; i < info->all_eas.out.num_eas; i++) {
     889           0 :                                 info->all_eas.out.eas[i] = info2->generic.out.eas[i];
     890           0 :                                 info->all_eas.out.eas[i].name.s = 
     891           0 :                                         talloc_strdup(info->all_eas.out.eas,
     892           0 :                                                       info2->generic.out.eas[i].name.s);
     893           0 :                                 if (!info->all_eas.out.eas[i].name.s) {
     894           0 :                                         DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
     895           0 :                                         return NT_STATUS_NO_MEMORY;
     896             :                                 }
     897           0 :                                 info->all_eas.out.eas[i].value.data = 
     898           0 :                                         (uint8_t *)talloc_memdup(info->all_eas.out.eas,
     899             :                                                 info2->generic.out.eas[i].value.data,
     900             :                                                 info2->generic.out.eas[i].value.length);
     901           0 :                                 if (!info->all_eas.out.eas[i].value.data) {
     902           0 :                                         DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
     903           0 :                                         return NT_STATUS_NO_MEMORY;
     904             :                                 }
     905             :                         }
     906             :                 }
     907           0 :                 return NT_STATUS_OK;
     908             :                 
     909           0 :         case RAW_FILEINFO_IS_NAME_VALID:
     910           0 :                 return NT_STATUS_OK;
     911             :                 
     912           0 :         case RAW_FILEINFO_COMPRESSION_INFO:
     913             :         case RAW_FILEINFO_COMPRESSION_INFORMATION:
     914           0 :                 info->compression_info.out.compressed_size = info2->generic.out.compressed_size;
     915           0 :                 info->compression_info.out.format = info2->generic.out.format;
     916           0 :                 info->compression_info.out.unit_shift = info2->generic.out.unit_shift;
     917           0 :                 info->compression_info.out.chunk_shift = info2->generic.out.chunk_shift;
     918           0 :                 info->compression_info.out.cluster_shift = info2->generic.out.cluster_shift;
     919           0 :                 return NT_STATUS_OK;
     920             :                 
     921           1 :         case RAW_FILEINFO_ACCESS_INFORMATION:
     922           1 :                 info->access_information.out.access_flags = info2->generic.out.access_flags;
     923           1 :                 return NT_STATUS_OK;
     924             :                 
     925           1 :         case RAW_FILEINFO_MODE_INFORMATION:
     926           1 :                 info->mode_information.out.mode = info2->generic.out.mode;
     927           1 :                 return NT_STATUS_OK;
     928             :                 
     929           1 :         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
     930           1 :                 info->alignment_information.out.alignment_requirement =
     931           1 :                         info2->generic.out.alignment_requirement;
     932           1 :                 return NT_STATUS_OK;
     933           1 :         case RAW_FILEINFO_UNIX_BASIC:
     934             : #if 1
     935           1 :                 return NT_STATUS_INVALID_LEVEL;
     936             : #else
     937             :                 info->unix_basic_info.out.end_of_file = info2->generic.out.end_of_file;
     938             :                 info->unix_basic_info.out.num_bytes = info2->generic.out.size;
     939             :                 info->unix_basic_info.out.status_change_time = info2->generic.out.change_time;
     940             :                 info->unix_basic_info.out.access_time = info2->generic.out.access_time;
     941             :                 info->unix_basic_info.out.change_time = info2->generic.out.change_time;
     942             :                 info->unix_basic_info.out.uid = info2->generic.out.uid;
     943             :                 info->unix_basic_info.out.gid = info2->generic.out.gid;
     944             :                 info->unix_basic_info.out.file_type = info2->generic.out.file_type;
     945             :                 info->unix_basic_info.out.dev_major = info2->generic.out.device;
     946             :                 info->unix_basic_info.out.dev_minor = info2->generic.out.device;
     947             :                 info->unix_basic_info.out.unique_id = info2->generic.out.inode;
     948             :                 info->unix_basic_info.out.permissions = info2->generic.out.permissions;
     949             :                 info->unix_basic_info.out.nlink = info2->generic.out.nlink;
     950             :                 return NT_STATUS_OK;
     951             : #endif
     952           1 :         case RAW_FILEINFO_UNIX_LINK:
     953             : #if 1
     954           1 :                 return NT_STATUS_INVALID_LEVEL;
     955             : #else
     956             :                 info->unix_link_info.out.link_dest = info2->generic.out.link_dest;
     957             :                 return NT_STATUS_OK;
     958             : #endif
     959           0 :         case RAW_FILEINFO_GENERIC:
     960             :         case RAW_FILEINFO_SEC_DESC:
     961             :         case RAW_FILEINFO_EA_LIST:
     962             :         case RAW_FILEINFO_UNIX_INFO2:
     963             :         case RAW_FILEINFO_SMB2_ALL_EAS:
     964             :         case RAW_FILEINFO_SMB2_ALL_INFORMATION:
     965           0 :                 return NT_STATUS_INVALID_LEVEL;
     966           0 :         case RAW_FILEINFO_NORMALIZED_NAME_INFORMATION:
     967           0 :                 return NT_STATUS_NOT_SUPPORTED;
     968             :         }
     969             : 
     970           0 :         return NT_STATUS_INVALID_LEVEL;
     971             : }
     972             : 
     973             : /* 
     974             :    NTVFS any to fileinfo mapper
     975             : */
     976          20 : static NTSTATUS ntvfs_map_qfileinfo_finish(struct ntvfs_module_context *ntvfs,
     977             :                                       struct ntvfs_request *req,
     978             :                                       union smb_fileinfo *info,
     979             :                                       union smb_fileinfo *info2,
     980             :                                       NTSTATUS status)
     981             : {
     982          20 :         if (!NT_STATUS_IS_OK(status)) {
     983           0 :                 return status;
     984             :         }
     985             : 
     986          20 :         return ntvfs_map_fileinfo(req, info, info2);
     987             : }
     988             : 
     989             : /*
     990             :    NTVFS fileinfo generic to any mapper
     991             : */
     992          20 : NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs,
     993             :                                       struct ntvfs_request *req,
     994             :                                       union smb_fileinfo *info)
     995             : {
     996           0 :         NTSTATUS status;
     997           0 :         union smb_fileinfo *info2;
     998             : 
     999          20 :         info2 = talloc(req, union smb_fileinfo);
    1000          20 :         if (info2 == NULL) {
    1001           0 :                 return NT_STATUS_NO_MEMORY;
    1002             :         }
    1003             : 
    1004          20 :         if (info->generic.level == RAW_FILEINFO_GENERIC) {
    1005           0 :                 return NT_STATUS_INVALID_LEVEL;
    1006             :         }
    1007             : 
    1008          20 :         status = ntvfs_map_async_setup(ntvfs, req, info, info2,
    1009             :                                        (second_stage_t)ntvfs_map_qfileinfo_finish);
    1010          20 :         if (!NT_STATUS_IS_OK(status)) {
    1011           0 :                 return status;
    1012             :         }
    1013             : 
    1014             :         /* ask the backend for the generic info */
    1015          20 :         info2->generic.level = RAW_FILEINFO_GENERIC;
    1016          20 :         info2->generic.in.file.ntvfs= info->generic.in.file.ntvfs;
    1017             : 
    1018          20 :         status = ntvfs->ops->qfileinfo_fn(ntvfs, req, info2);
    1019          20 :         return ntvfs_map_async_finish(req, status);
    1020             : }
    1021             : 
    1022             : /*
    1023             :    NTVFS any to fileinfo mapper
    1024             : */
    1025          29 : static NTSTATUS ntvfs_map_qpathinfo_finish(struct ntvfs_module_context *ntvfs,
    1026             :                                       struct ntvfs_request *req,
    1027             :                                       union smb_fileinfo *info,
    1028             :                                       union smb_fileinfo *info2,
    1029             :                                       NTSTATUS status)
    1030             : {
    1031          29 :         if (!NT_STATUS_IS_OK(status)) {
    1032          29 :                 return status;
    1033             :         }
    1034             : 
    1035           0 :         return ntvfs_map_fileinfo(req, info, info2);
    1036             : }
    1037             : 
    1038             : /* 
    1039             :    NTVFS pathinfo generic to any mapper
    1040             : */
    1041          29 : NTSTATUS ntvfs_map_qpathinfo(struct ntvfs_module_context *ntvfs,
    1042             :                                       struct ntvfs_request *req,
    1043             :                                       union smb_fileinfo *info)
    1044             : {
    1045           0 :         NTSTATUS status;
    1046           0 :         union smb_fileinfo *info2;
    1047             : 
    1048          29 :         info2 = talloc(req, union smb_fileinfo);
    1049          29 :         if (info2 == NULL) {
    1050           0 :                 return NT_STATUS_NO_MEMORY;
    1051             :         }
    1052             : 
    1053          29 :         if (info->generic.level == RAW_FILEINFO_GENERIC) {
    1054           0 :                 return NT_STATUS_INVALID_LEVEL;
    1055             :         }
    1056             : 
    1057          29 :         status = ntvfs_map_async_setup(ntvfs, req, info, info2,
    1058             :                                        (second_stage_t)ntvfs_map_qpathinfo_finish);
    1059          29 :         if (!NT_STATUS_IS_OK(status)) {
    1060           0 :                 return status;
    1061             :         }
    1062             : 
    1063             :         /* ask the backend for the generic info */
    1064          29 :         info2->generic.level         = RAW_FILEINFO_GENERIC;
    1065          29 :         info2->generic.in.file.path  = info->generic.in.file.path;
    1066             : 
    1067          29 :         status = ntvfs->ops->qpathinfo_fn(ntvfs, req, info2);
    1068          29 :         return ntvfs_map_async_finish(req, status);
    1069             : }
    1070             : 
    1071             : 
    1072             : /* 
    1073             :    NTVFS lock generic to any mapper
    1074             : */
    1075         462 : NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs,
    1076             :                         struct ntvfs_request *req,
    1077             :                         union smb_lock *lck)
    1078             : {
    1079           0 :         union smb_lock *lck2;
    1080           0 :         struct smb_lock_entry *locks;
    1081             : 
    1082         462 :         lck2 = talloc(req, union smb_lock);
    1083         462 :         if (lck2 == NULL) {
    1084           0 :                 return NT_STATUS_NO_MEMORY;
    1085             :         }
    1086             : 
    1087         462 :         locks = talloc_array(lck2, struct smb_lock_entry, 1);
    1088         462 :         if (locks == NULL) {
    1089           0 :                 return NT_STATUS_NO_MEMORY;
    1090             :         }
    1091             : 
    1092         462 :         switch (lck->generic.level) {
    1093           0 :         case RAW_LOCK_LOCKX:
    1094           9 :                 return NT_STATUS_INVALID_LEVEL;
    1095             : 
    1096          23 :         case RAW_LOCK_LOCK:
    1097          23 :                 lck2->generic.level = RAW_LOCK_GENERIC;
    1098          23 :                 lck2->generic.in.file.ntvfs= lck->lock.in.file.ntvfs;
    1099          23 :                 lck2->generic.in.mode = 0;
    1100          23 :                 lck2->generic.in.timeout = 0;
    1101          23 :                 lck2->generic.in.ulock_cnt = 0;
    1102          23 :                 lck2->generic.in.lock_cnt = 1;
    1103          23 :                 lck2->generic.in.locks = locks;
    1104          23 :                 locks->pid = req->smbpid;
    1105          23 :                 locks->offset = lck->lock.in.offset;
    1106          23 :                 locks->count = lck->lock.in.count;
    1107         453 :                 break;
    1108             : 
    1109          16 :         case RAW_LOCK_UNLOCK:
    1110          16 :                 lck2->generic.level = RAW_LOCK_GENERIC;
    1111          16 :                 lck2->generic.in.file.ntvfs= lck->unlock.in.file.ntvfs;
    1112          16 :                 lck2->generic.in.mode = 0;
    1113          16 :                 lck2->generic.in.timeout = 0;
    1114          16 :                 lck2->generic.in.ulock_cnt = 1;
    1115          16 :                 lck2->generic.in.lock_cnt = 0;
    1116          16 :                 lck2->generic.in.locks = locks;
    1117          16 :                 locks->pid = req->smbpid;
    1118          16 :                 locks->offset = lck->unlock.in.offset;
    1119          16 :                 locks->count = lck->unlock.in.count;
    1120          16 :                 break;
    1121             : 
    1122         381 :         case RAW_LOCK_SMB2: {
    1123             :                 /* this is only approximate! We need to change the
    1124             :                    generic structure to fix this properly */
    1125           0 :                 int i;
    1126           0 :                 bool isunlock;
    1127         381 :                 if (lck->smb2.in.lock_count < 1) {
    1128           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1129             :                 }
    1130             : 
    1131         381 :                 lck2->generic.level = RAW_LOCK_GENERIC;
    1132         381 :                 lck2->generic.in.file.ntvfs= lck->smb2.in.file.ntvfs;
    1133         381 :                 lck2->generic.in.timeout = UINT32_MAX;
    1134         381 :                 lck2->generic.in.mode = 0;
    1135         381 :                 lck2->generic.in.lock_cnt = 0;
    1136         381 :                 lck2->generic.in.ulock_cnt = 0;
    1137         381 :                 lck2->generic.in.locks = talloc_zero_array(lck2, struct smb_lock_entry, 
    1138             :                                                            lck->smb2.in.lock_count);
    1139         381 :                 if (lck2->generic.in.locks == NULL) {
    1140           0 :                         return NT_STATUS_NO_MEMORY;
    1141             :                 }
    1142             :                 /* only the first lock gives the UNLOCK bit - see
    1143             :                    MS-SMB2 3.3.5.14 */
    1144         381 :                 if (lck->smb2.in.locks[0].flags & SMB2_LOCK_FLAG_UNLOCK) {
    1145         136 :                         if (lck->smb2.in.locks[0].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) {
    1146           1 :                                 return NT_STATUS_INVALID_PARAMETER;
    1147             :                         }
    1148         135 :                         lck2->generic.in.ulock_cnt = lck->smb2.in.lock_count;
    1149         135 :                         isunlock = true;
    1150             :                 } else {
    1151         245 :                         lck2->generic.in.lock_cnt = lck->smb2.in.lock_count;
    1152         245 :                         isunlock = false;
    1153             :                 }
    1154         759 :                 for (i=0;i<lck->smb2.in.lock_count;i++) {
    1155         387 :                         if (!isunlock &&
    1156         248 :                             lck->smb2.in.locks[i].flags == SMB2_LOCK_FLAG_NONE) {
    1157           2 :                                 return NT_STATUS_INVALID_PARAMETER;
    1158             :                         }
    1159             : 
    1160         385 :                         if (lck->smb2.in.locks[i].flags & ~SMB2_LOCK_FLAG_ALL_MASK) {
    1161           1 :                                 return NT_STATUS_INVALID_PARAMETER;
    1162             :                         }
    1163             : 
    1164         384 :                         if (isunlock && 
    1165         139 :                             (lck->smb2.in.locks[i].flags & 
    1166             :                              (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE))) {
    1167           5 :                                 return NT_STATUS_INVALID_PARAMETER;
    1168             :                         }
    1169         379 :                         if (!isunlock && 
    1170         245 :                             (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK)) {
    1171           0 :                                 return NT_STATUS_INVALID_PARAMETER;
    1172             :                         }
    1173         379 :                         lck2->generic.in.locks[i].pid    = req->smbpid;
    1174         379 :                         lck2->generic.in.locks[i].offset = lck->smb2.in.locks[i].offset;
    1175         379 :                         lck2->generic.in.locks[i].count  = lck->smb2.in.locks[i].length;
    1176         379 :                         if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE)) {
    1177         167 :                                 lck2->generic.in.mode = LOCKING_ANDX_SHARED_LOCK;
    1178             :                         }
    1179         379 :                         if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) {
    1180         224 :                                 lck2->generic.in.timeout = 0;
    1181             :                         }
    1182             :                 }
    1183             :                 /* initialize output value */
    1184         372 :                 lck->smb2.out.reserved = 0;
    1185         372 :                 break;
    1186             :         }
    1187             : 
    1188          42 :         case RAW_LOCK_SMB2_BREAK:
    1189          42 :                 lck2->generic.level          = RAW_LOCK_GENERIC;
    1190          42 :                 lck2->generic.in.file.ntvfs  = lck->smb2_break.in.file.ntvfs;
    1191          42 :                 lck2->generic.in.mode                = LOCKING_ANDX_OPLOCK_RELEASE |
    1192          42 :                                                   ((lck->smb2_break.in.oplock_level << 8) & 0xFF00);
    1193          42 :                 lck2->generic.in.timeout     = 0;
    1194          42 :                 lck2->generic.in.ulock_cnt   = 0;
    1195          42 :                 lck2->generic.in.lock_cnt    = 0;
    1196          42 :                 lck2->generic.in.locks               = NULL;
    1197             : 
    1198             :                 /* initialize output value */
    1199          42 :                 lck->smb2_break.out.oplock_level= lck->smb2_break.in.oplock_level;
    1200          42 :                 lck->smb2_break.out.reserved = lck->smb2_break.in.reserved;
    1201          42 :                 lck->smb2_break.out.reserved2        = lck->smb2_break.in.reserved2;
    1202          42 :                 lck->smb2_break.out.file     = lck->smb2_break.in.file;
    1203          42 :                 break;
    1204             :         }
    1205             : 
    1206             :         /* 
    1207             :          * we don't need to call ntvfs_map_async_setup() here,
    1208             :          * as lock() doesn't have any output fields
    1209             :          */
    1210             : 
    1211         453 :         return ntvfs->ops->lock_fn(ntvfs, req, lck2);
    1212             : }
    1213             : 
    1214             : 
    1215             : /* 
    1216             :    NTVFS write generic to any mapper
    1217             : */
    1218        1852 : static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs,
    1219             :                                        struct ntvfs_request *req,
    1220             :                                        union smb_write *wr, 
    1221             :                                        union smb_write *wr2, 
    1222             :                                        NTSTATUS status)
    1223             : {
    1224           0 :         union smb_lock *lck;
    1225           0 :         union smb_close *cl;
    1226           0 :         unsigned int state;
    1227             : 
    1228        1852 :         if (NT_STATUS_IS_ERR(status)) {
    1229          45 :                 return status;
    1230             :         }
    1231             : 
    1232        1807 :         switch (wr->generic.level) {
    1233          16 :         case RAW_WRITE_WRITE:
    1234          16 :                 wr->write.out.nwritten    = wr2->generic.out.nwritten;
    1235          16 :                 break;
    1236             : 
    1237           6 :         case RAW_WRITE_WRITEUNLOCK:
    1238           6 :                 wr->writeunlock.out.nwritten = wr2->generic.out.nwritten;
    1239             : 
    1240           6 :                 lck = talloc(wr2, union smb_lock);
    1241           6 :                 if (lck == NULL) {
    1242           0 :                         return NT_STATUS_NO_MEMORY;
    1243             :                 }
    1244             : 
    1245           6 :                 lck->unlock.level            = RAW_LOCK_UNLOCK;
    1246           6 :                 lck->unlock.in.file.ntvfs    = wr->writeunlock.in.file.ntvfs;
    1247           6 :                 lck->unlock.in.count         = wr->writeunlock.in.count;
    1248           6 :                 lck->unlock.in.offset                = wr->writeunlock.in.offset;
    1249             : 
    1250           6 :                 if (lck->unlock.in.count != 0) {
    1251             :                         /* do the lock sync for now */
    1252           5 :                         state = req->async_states->state;
    1253           5 :                         req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
    1254           5 :                         status = ntvfs->ops->lock_fn(ntvfs, req, lck);
    1255           5 :                         req->async_states->state = state;
    1256             :                 }
    1257           6 :                 break;
    1258             : 
    1259           6 :         case RAW_WRITE_WRITECLOSE:
    1260           6 :                 wr->writeclose.out.nwritten    = wr2->generic.out.nwritten;
    1261             : 
    1262           6 :                 cl = talloc(wr2, union smb_close);
    1263           6 :                 if (cl == NULL) {
    1264           0 :                         return NT_STATUS_NO_MEMORY;
    1265             :                 }
    1266             : 
    1267           6 :                 cl->close.level              = RAW_CLOSE_CLOSE;
    1268           6 :                 cl->close.in.file.ntvfs      = wr->writeclose.in.file.ntvfs;
    1269           6 :                 cl->close.in.write_time      = wr->writeclose.in.mtime;
    1270             : 
    1271           6 :                 if (wr2->generic.in.count != 0) {
    1272             :                         /* do the close sync for now */
    1273           4 :                         state = req->async_states->state;
    1274           4 :                         req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
    1275           4 :                         status = ntvfs->ops->close_fn(ntvfs, req, cl);
    1276           4 :                         req->async_states->state = state;
    1277             :                 }
    1278           6 :                 break;
    1279             : 
    1280           0 :         case RAW_WRITE_SPLWRITE:
    1281           0 :                 break;
    1282             : 
    1283        1779 :         case RAW_WRITE_SMB2:
    1284        1779 :                 wr->smb2.out._pad    = 0;
    1285        1779 :                 wr->smb2.out.nwritten        = wr2->generic.out.nwritten;
    1286        1779 :                 wr->smb2.out.unknown1        = 0;
    1287        1779 :                 break;
    1288             : 
    1289           0 :         default:
    1290           0 :                 return NT_STATUS_INVALID_LEVEL;
    1291             :         }
    1292             : 
    1293        1807 :         return status;
    1294             : }
    1295             : 
    1296             : 
    1297             : /* 
    1298             :    NTVFS write generic to any mapper
    1299             : */
    1300        1852 : NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
    1301             :                                   struct ntvfs_request *req,
    1302             :                                   union smb_write *wr)
    1303             : {
    1304           0 :         union smb_write *wr2;
    1305           0 :         NTSTATUS status;
    1306             : 
    1307        1852 :         wr2 = talloc(req, union smb_write);
    1308        1852 :         if (wr2 == NULL) {
    1309           0 :                 return NT_STATUS_NO_MEMORY;
    1310             :         }
    1311             : 
    1312        1852 :         status = ntvfs_map_async_setup(ntvfs, req, wr, wr2, 
    1313             :                                        (second_stage_t)ntvfs_map_write_finish);
    1314        1852 :         if (!NT_STATUS_IS_OK(status)) {
    1315           0 :                 return status;
    1316             :         }
    1317             : 
    1318        1852 :         wr2->writex.level = RAW_WRITE_GENERIC;
    1319             : 
    1320        1852 :         switch (wr->generic.level) {
    1321           0 :         case RAW_WRITE_WRITEX:
    1322           0 :                 status = NT_STATUS_INVALID_LEVEL;
    1323          29 :                 break;
    1324             : 
    1325          17 :         case RAW_WRITE_WRITE:
    1326          17 :                 wr2->writex.in.file.ntvfs= wr->write.in.file.ntvfs;
    1327          17 :                 wr2->writex.in.offset    = wr->write.in.offset;
    1328          17 :                 wr2->writex.in.wmode     = 0;
    1329          17 :                 wr2->writex.in.remaining = wr->write.in.remaining;
    1330          17 :                 wr2->writex.in.count     = wr->write.in.count;
    1331          17 :                 wr2->writex.in.data      = wr->write.in.data;
    1332          17 :                 status = ntvfs->ops->write_fn(ntvfs, req, wr2);
    1333          17 :                 break;
    1334             : 
    1335           6 :         case RAW_WRITE_WRITEUNLOCK:
    1336           6 :                 wr2->writex.in.file.ntvfs= wr->writeunlock.in.file.ntvfs;
    1337           6 :                 wr2->writex.in.offset    = wr->writeunlock.in.offset;
    1338           6 :                 wr2->writex.in.wmode     = 0;
    1339           6 :                 wr2->writex.in.remaining = wr->writeunlock.in.remaining;
    1340           6 :                 wr2->writex.in.count     = wr->writeunlock.in.count;
    1341           6 :                 wr2->writex.in.data      = wr->writeunlock.in.data;
    1342           6 :                 status = ntvfs->ops->write_fn(ntvfs, req, wr2);
    1343           6 :                 break;
    1344             : 
    1345           6 :         case RAW_WRITE_WRITECLOSE:
    1346           6 :                 wr2->writex.in.file.ntvfs= wr->writeclose.in.file.ntvfs;
    1347           6 :                 wr2->writex.in.offset    = wr->writeclose.in.offset;
    1348           6 :                 wr2->writex.in.wmode     = 0;
    1349           6 :                 wr2->writex.in.remaining = 0;
    1350           6 :                 wr2->writex.in.count     = wr->writeclose.in.count;
    1351           6 :                 wr2->writex.in.data      = wr->writeclose.in.data;
    1352           6 :                 status = ntvfs->ops->write_fn(ntvfs, req, wr2);
    1353           6 :                 break;
    1354             : 
    1355           0 :         case RAW_WRITE_SPLWRITE:
    1356           0 :                 wr2->writex.in.file.ntvfs= wr->splwrite.in.file.ntvfs;
    1357           0 :                 wr2->writex.in.offset    = 0;
    1358           0 :                 wr2->writex.in.wmode     = 0;
    1359           0 :                 wr2->writex.in.remaining = 0;
    1360           0 :                 wr2->writex.in.count     = wr->splwrite.in.count;
    1361           0 :                 wr2->writex.in.data      = wr->splwrite.in.data;
    1362           0 :                 status = ntvfs->ops->write_fn(ntvfs, req, wr2);
    1363           0 :                 break;
    1364             : 
    1365        1823 :         case RAW_WRITE_SMB2:
    1366        1823 :                 wr2->writex.in.file.ntvfs= wr->smb2.in.file.ntvfs;
    1367        1823 :                 wr2->writex.in.offset    = wr->smb2.in.offset;
    1368        1823 :                 wr2->writex.in.wmode     = 0;
    1369        1823 :                 wr2->writex.in.remaining = 0;
    1370        1823 :                 wr2->writex.in.count     = wr->smb2.in.data.length;
    1371        1823 :                 wr2->writex.in.data      = wr->smb2.in.data.data;
    1372        1823 :                 status = ntvfs->ops->write_fn(ntvfs, req, wr2);
    1373             :         }
    1374             : 
    1375        1852 :         return ntvfs_map_async_finish(req, status);
    1376             : }
    1377             : 
    1378             : 
    1379             : /* 
    1380             :    NTVFS read generic to any mapper - finish the out mapping
    1381             : */
    1382        1647 : static NTSTATUS ntvfs_map_read_finish(struct ntvfs_module_context *ntvfs,
    1383             :                                       struct ntvfs_request *req, 
    1384             :                                       union smb_read *rd, 
    1385             :                                       union smb_read *rd2,
    1386             :                                       NTSTATUS status)
    1387             : {
    1388        1647 :         switch (rd->generic.level) {
    1389           7 :         case RAW_READ_READ:
    1390           7 :                 rd->read.out.nread   = rd2->generic.out.nread;
    1391           7 :                 break;
    1392          11 :         case RAW_READ_READBRAW:
    1393          11 :                 rd->readbraw.out.nread       = rd2->generic.out.nread;
    1394          11 :                 break;
    1395          12 :         case RAW_READ_LOCKREAD:
    1396          12 :                 rd->lockread.out.nread       = rd2->generic.out.nread;
    1397          12 :                 break;
    1398        1617 :         case RAW_READ_SMB2:
    1399        1617 :                 rd->smb2.out.data.length= rd2->generic.out.nread;
    1400        1617 :                 rd->smb2.out.remaining       = 0;
    1401        1617 :                 rd->smb2.out.reserved        = 0;
    1402        1617 :                 break;
    1403           0 :         default:
    1404           0 :                 return NT_STATUS_INVALID_LEVEL;
    1405             :         }
    1406             : 
    1407        1647 :         return status;
    1408             : }
    1409             : 
    1410             : /* 
    1411             :    NTVFS read* to readx mapper
    1412             : */
    1413        1647 : NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
    1414             :                                  struct ntvfs_request *req,
    1415             :                                  union smb_read *rd)
    1416             : {
    1417           0 :         union smb_read *rd2;
    1418           0 :         union smb_lock *lck;
    1419           0 :         NTSTATUS status;
    1420           0 :         unsigned int state;
    1421             : 
    1422        1647 :         rd2 = talloc(req, union smb_read);
    1423        1647 :         if (rd2 == NULL) {
    1424           0 :                 return NT_STATUS_NO_MEMORY;
    1425             :         }
    1426             : 
    1427        1647 :         status = ntvfs_map_async_setup(ntvfs, req, rd, rd2, 
    1428             :                                        (second_stage_t)ntvfs_map_read_finish);
    1429        1647 :         if (!NT_STATUS_IS_OK(status)) {
    1430           0 :                 return status;
    1431             :         }
    1432             : 
    1433        1647 :         rd2->readx.level = RAW_READ_READX;
    1434        1647 :         rd2->readx.in.read_for_execute = false;
    1435             : 
    1436        1647 :         switch (rd->generic.level) {
    1437           0 :         case RAW_READ_READX:
    1438           0 :                 status = NT_STATUS_INVALID_LEVEL;
    1439        1647 :                 break;
    1440             : 
    1441           7 :         case RAW_READ_READ:
    1442           7 :                 rd2->readx.in.file.ntvfs= rd->read.in.file.ntvfs;
    1443           7 :                 rd2->readx.in.offset    = rd->read.in.offset;
    1444           7 :                 rd2->readx.in.mincnt    = rd->read.in.count;
    1445           7 :                 rd2->readx.in.maxcnt    = rd->read.in.count;
    1446           7 :                 rd2->readx.in.remaining = rd->read.in.remaining;
    1447           7 :                 rd2->readx.out.data     = rd->read.out.data;
    1448           7 :                 status = ntvfs->ops->read_fn(ntvfs, req, rd2);
    1449           7 :                 break;
    1450             : 
    1451          11 :         case RAW_READ_READBRAW:
    1452          11 :                 rd2->readx.in.file.ntvfs= rd->readbraw.in.file.ntvfs;
    1453          11 :                 rd2->readx.in.offset    = rd->readbraw.in.offset;
    1454          11 :                 rd2->readx.in.mincnt    = rd->readbraw.in.mincnt;
    1455          11 :                 rd2->readx.in.maxcnt    = rd->readbraw.in.maxcnt;
    1456          11 :                 rd2->readx.in.remaining = 0;
    1457          11 :                 rd2->readx.out.data     = rd->readbraw.out.data;
    1458          11 :                 status = ntvfs->ops->read_fn(ntvfs, req, rd2);
    1459          11 :                 break;
    1460             : 
    1461          12 :         case RAW_READ_LOCKREAD:
    1462             :                 /* do the initial lock sync for now */
    1463          12 :                 state = req->async_states->state;
    1464          12 :                 req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
    1465             : 
    1466          12 :                 lck = talloc(rd2, union smb_lock);
    1467          12 :                 if (lck == NULL) {
    1468           0 :                         status = NT_STATUS_NO_MEMORY;
    1469           0 :                         goto done;
    1470             :                 }
    1471          12 :                 lck->lock.level              = RAW_LOCK_LOCK;
    1472          12 :                 lck->lock.in.file.ntvfs      = rd->lockread.in.file.ntvfs;
    1473          12 :                 lck->lock.in.count   = rd->lockread.in.count;
    1474          12 :                 lck->lock.in.offset  = rd->lockread.in.offset;
    1475          12 :                 status = ntvfs->ops->lock_fn(ntvfs, req, lck);
    1476          12 :                 req->async_states->state = state;
    1477             : 
    1478          12 :                 rd2->readx.in.file.ntvfs= rd->lockread.in.file.ntvfs;
    1479          12 :                 rd2->readx.in.offset    = rd->lockread.in.offset;
    1480          12 :                 rd2->readx.in.mincnt    = rd->lockread.in.count;
    1481          12 :                 rd2->readx.in.maxcnt    = rd->lockread.in.count;
    1482          12 :                 rd2->readx.in.remaining = rd->lockread.in.remaining;
    1483          12 :                 rd2->readx.out.data     = rd->lockread.out.data;
    1484             : 
    1485          12 :                 if (NT_STATUS_IS_OK(status)) {
    1486           6 :                         status = ntvfs->ops->read_fn(ntvfs, req, rd2);
    1487             :                 }
    1488          12 :                 break;
    1489             : 
    1490        1617 :         case RAW_READ_SMB2:
    1491        1617 :                 rd2->readx.in.file.ntvfs= rd->smb2.in.file.ntvfs;
    1492        1617 :                 rd2->readx.in.offset    = rd->smb2.in.offset;
    1493        1617 :                 rd2->readx.in.mincnt    = rd->smb2.in.min_count;
    1494        1617 :                 rd2->readx.in.maxcnt    = rd->smb2.in.length;
    1495        1617 :                 rd2->readx.in.remaining = 0;
    1496        1617 :                 rd2->readx.out.data     = rd->smb2.out.data.data;
    1497        1617 :                 status = ntvfs->ops->read_fn(ntvfs, req, rd2);
    1498        1617 :                 break;
    1499             :         }
    1500             : 
    1501        1647 : done:
    1502        1647 :         return ntvfs_map_async_finish(req, status);
    1503             : }
    1504             : 
    1505             : 
    1506             : /* 
    1507             :    NTVFS close generic to any mapper
    1508             : */
    1509      204181 : static NTSTATUS ntvfs_map_close_finish(struct ntvfs_module_context *ntvfs,
    1510             :                                         struct ntvfs_request *req,
    1511             :                                         union smb_close *cl, 
    1512             :                                         union smb_close *cl2, 
    1513             :                                         NTSTATUS status)
    1514             : {
    1515      204181 :         NT_STATUS_NOT_OK_RETURN(status);
    1516             : 
    1517      204181 :         switch (cl->generic.level) {
    1518      142663 :         case RAW_CLOSE_SMB2:
    1519      142663 :                 cl->smb2.out.flags        = cl2->generic.out.flags;
    1520      142663 :                 cl->smb2.out._pad         = 0;
    1521      142663 :                 cl->smb2.out.create_time  = cl2->generic.out.create_time;
    1522      142663 :                 cl->smb2.out.access_time  = cl2->generic.out.access_time;
    1523      142663 :                 cl->smb2.out.write_time   = cl2->generic.out.write_time;
    1524      142663 :                 cl->smb2.out.change_time  = cl2->generic.out.change_time;
    1525      142663 :                 cl->smb2.out.alloc_size   = cl2->generic.out.alloc_size;
    1526      142663 :                 cl->smb2.out.size         = cl2->generic.out.size;
    1527      142663 :                 cl->smb2.out.file_attr    = cl2->generic.out.file_attr;
    1528      142663 :                 break;
    1529       61518 :         default:
    1530       61518 :                 break;
    1531             :         }
    1532             : 
    1533      204181 :         return status;
    1534             : }
    1535             : 
    1536             : /* 
    1537             :    NTVFS close generic to any mapper
    1538             : */
    1539      204181 : NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs,
    1540             :                                   struct ntvfs_request *req,
    1541             :                                   union smb_close *cl)
    1542             : {
    1543           0 :         union smb_close *cl2;
    1544           0 :         NTSTATUS status;
    1545             : 
    1546      204181 :         cl2 = talloc(req, union smb_close);
    1547      204181 :         if (cl2 == NULL) {
    1548           0 :                 return NT_STATUS_NO_MEMORY;
    1549             :         }
    1550             : 
    1551      204181 :         switch (cl->generic.level) {
    1552           0 :         case RAW_CLOSE_GENERIC:
    1553           0 :                 return NT_STATUS_INVALID_LEVEL;
    1554             : 
    1555       61518 :         case RAW_CLOSE_CLOSE:
    1556       61518 :                 cl2->generic.level           = RAW_CLOSE_GENERIC;
    1557       61518 :                 cl2->generic.in.file         = cl->close.in.file;
    1558       61518 :                 cl2->generic.in.write_time   = cl->close.in.write_time;
    1559       61518 :                 cl2->generic.in.flags                = 0;
    1560      204181 :                 break;
    1561             : 
    1562           0 :         case RAW_CLOSE_SPLCLOSE:
    1563           0 :                 cl2->generic.level           = RAW_CLOSE_GENERIC;
    1564           0 :                 cl2->generic.in.file         = cl->splclose.in.file;
    1565           0 :                 cl2->generic.in.write_time   = 0;
    1566           0 :                 cl2->generic.in.flags                = 0;
    1567           0 :                 break;
    1568             : 
    1569      142663 :         case RAW_CLOSE_SMB2:
    1570      142663 :                 cl2->generic.level           = RAW_CLOSE_GENERIC;
    1571      142663 :                 cl2->generic.in.file         = cl->smb2.in.file;
    1572      142663 :                 cl2->generic.in.write_time   = 0;
    1573      142663 :                 cl2->generic.in.flags                = cl->smb2.in.flags;
    1574      142663 :                 break;
    1575             :         }
    1576             : 
    1577      204181 :         status = ntvfs_map_async_setup(ntvfs, req, cl, cl2, 
    1578             :                                        (second_stage_t)ntvfs_map_close_finish);
    1579      204181 :         NT_STATUS_NOT_OK_RETURN(status);
    1580             : 
    1581      204181 :         status = ntvfs->ops->close_fn(ntvfs, req, cl2);
    1582             : 
    1583      204181 :         return ntvfs_map_async_finish(req, status);
    1584             : }
    1585             : 
    1586             : /* 
    1587             :    NTVFS notify generic to any mapper
    1588             : */
    1589           0 : static NTSTATUS ntvfs_map_notify_finish(struct ntvfs_module_context *ntvfs,
    1590             :                                         struct ntvfs_request *req,
    1591             :                                         union smb_notify *nt, 
    1592             :                                         union smb_notify *nt2, 
    1593             :                                         NTSTATUS status)
    1594             : {
    1595           0 :         NT_STATUS_NOT_OK_RETURN(status);
    1596             : 
    1597           0 :         switch (nt->nttrans.level) {
    1598           0 :         case RAW_NOTIFY_SMB2:
    1599           0 :                 if (nt2->nttrans.out.num_changes == 0) {
    1600           0 :                         return NT_STATUS_NOTIFY_ENUM_DIR;
    1601             :                 }
    1602           0 :                 nt->smb2.out.num_changes     = nt2->nttrans.out.num_changes;
    1603           0 :                 nt->smb2.out.changes         = talloc_steal(req, nt2->nttrans.out.changes);
    1604           0 :                 break;
    1605             : 
    1606           0 :         default:
    1607           0 :                 return NT_STATUS_INVALID_LEVEL;
    1608             :         }
    1609             : 
    1610           0 :         return status;
    1611             : }
    1612             : 
    1613             : 
    1614             : /* 
    1615             :    NTVFS notify generic to any mapper
    1616             : */
    1617           0 : NTSTATUS ntvfs_map_notify(struct ntvfs_module_context *ntvfs,
    1618             :                                    struct ntvfs_request *req,
    1619             :                                    union smb_notify *nt)
    1620             : {
    1621           0 :         union smb_notify *nt2;
    1622           0 :         NTSTATUS status;
    1623             : 
    1624           0 :         nt2 = talloc(req, union smb_notify);
    1625           0 :         NT_STATUS_HAVE_NO_MEMORY(nt2);
    1626             : 
    1627           0 :         status = ntvfs_map_async_setup(ntvfs, req, nt, nt2, 
    1628             :                                        (second_stage_t)ntvfs_map_notify_finish);
    1629           0 :         NT_STATUS_NOT_OK_RETURN(status);
    1630             : 
    1631           0 :         nt2->nttrans.level = RAW_NOTIFY_NTTRANS;
    1632             : 
    1633           0 :         switch (nt->nttrans.level) {
    1634           0 :         case RAW_NOTIFY_NTTRANS:
    1635           0 :                 status = NT_STATUS_INVALID_LEVEL;
    1636           0 :                 break;
    1637             : 
    1638           0 :         case RAW_NOTIFY_SMB2:
    1639           0 :                 nt2->nttrans.in.file.ntvfs           = nt->smb2.in.file.ntvfs;
    1640           0 :                 nt2->nttrans.in.buffer_size          = nt->smb2.in.buffer_size;
    1641           0 :                 nt2->nttrans.in.completion_filter    = nt->smb2.in.completion_filter;
    1642           0 :                 nt2->nttrans.in.recursive            = nt->smb2.in.recursive;
    1643           0 :                 status = ntvfs->ops->notify_fn(ntvfs, req, nt2);
    1644           0 :                 break;
    1645             :         }
    1646             : 
    1647           0 :         return ntvfs_map_async_finish(req, status);
    1648             : }

Generated by: LCOV version 1.14