LCOV - code coverage report
Current view: top level - source4/ntvfs/simple - vfs_simple.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 162 546 29.7 %
Date: 2024-02-28 12:06:22 Functions: 9 34 26.5 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    simple NTVFS filesystem backend
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       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 a very simple NTVFS filesystem backend. 
      23             :   
      24             :   this backend largely ignores the POSIX -> CIFS mappings, just doing absolutely
      25             :   minimal work to give a working backend.
      26             : */
      27             : 
      28             : #include "includes.h"
      29             : #include "system/dir.h"
      30             : #include "system/filesys.h"
      31             : #include "svfs.h"
      32             : #include "system/time.h"
      33             : #include "../lib/util/dlinklist.h"
      34             : #include "ntvfs/ntvfs.h"
      35             : #include "ntvfs/simple/proto.h"
      36             : 
      37             : #ifndef O_DIRECTORY
      38             : #define O_DIRECTORY 0
      39             : #endif
      40             : 
      41             : #define CHECK_READ_ONLY(req) do { if (share_bool_option(ntvfs->ctx->config, SHARE_READONLY, true)) return NT_STATUS_ACCESS_DENIED; } while (0)
      42             : 
      43             : /*
      44             :   connect to a share - used when a tree_connect operation comes
      45             :   in. For a disk based backend we needs to ensure that the base
      46             :   directory exists (tho it doesn't need to be accessible by the user,
      47             :   that comes later)
      48             : */
      49           2 : static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs,
      50             :                              struct ntvfs_request *req,
      51             :                              union smb_tcon* tcon)
      52             : {
      53           0 :         struct stat st;
      54           0 :         struct svfs_private *p;
      55           2 :         struct share_config *scfg = ntvfs->ctx->config;
      56           0 :         const char *sharename;
      57             : 
      58           2 :         switch (tcon->generic.level) {
      59           0 :         case RAW_TCON_TCON:
      60           0 :                 sharename = tcon->tcon.in.service;
      61           0 :                 break;
      62           2 :         case RAW_TCON_TCONX:
      63           2 :                 sharename = tcon->tconx.in.path;
      64           2 :                 break;
      65           0 :         case RAW_TCON_SMB2:
      66           0 :                 sharename = tcon->smb2.in.path;
      67           0 :                 break;
      68           0 :         default:
      69           0 :                 return NT_STATUS_INVALID_LEVEL;
      70             :         }
      71             : 
      72           2 :         if (strncmp(sharename, "\\\\", 2) == 0) {
      73           2 :                 char *p2 = strchr(sharename+2, '\\');
      74           2 :                 if (p2) {
      75           2 :                         sharename = p2 + 1;
      76             :                 }
      77             :         }
      78             : 
      79           2 :         p = talloc(ntvfs, struct svfs_private);
      80           2 :         NT_STATUS_HAVE_NO_MEMORY(p);
      81           2 :         p->ntvfs = ntvfs;
      82           2 :         p->next_search_handle = 0;
      83           2 :         p->connectpath = share_string_option(p, scfg, SHARE_PATH, "");
      84           2 :         p->open_files = NULL;
      85           2 :         p->search = NULL;
      86             : 
      87             :         /* the directory must exist */
      88           2 :         if (stat(p->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
      89           0 :                 DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", 
      90             :                          p->connectpath, sharename));
      91           0 :                 return NT_STATUS_BAD_NETWORK_NAME;
      92             :         }
      93             : 
      94           2 :         ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
      95           2 :         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
      96           2 :         ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
      97           2 :         NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);
      98             : 
      99           2 :         if (tcon->generic.level == RAW_TCON_TCONX) {
     100           2 :                 tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
     101           2 :                 tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
     102             :         }
     103             : 
     104           2 :         ntvfs->private_data = p;
     105             : 
     106           2 :         return NT_STATUS_OK;
     107             : }
     108             : 
     109             : /*
     110             :   disconnect from a share
     111             : */
     112           2 : static NTSTATUS svfs_disconnect(struct ntvfs_module_context *ntvfs)
     113             : {
     114           2 :         return NT_STATUS_OK;
     115             : }
     116             : 
     117             : /*
     118             :   find open file handle given fd
     119             : */
     120         102 : static struct svfs_file *find_fd(struct svfs_private *sp, struct ntvfs_handle *handle)
     121             : {
     122           0 :         struct svfs_file *f;
     123           0 :         void *p;
     124             : 
     125         102 :         p = ntvfs_handle_get_backend_data(handle, sp->ntvfs);
     126         102 :         if (!p) return NULL;
     127             : 
     128         102 :         f = talloc_get_type(p, struct svfs_file);
     129         102 :         if (!f) return NULL;
     130             : 
     131         102 :         return f;
     132             : }
     133             : 
     134             : /*
     135             :   delete a file - the dirtype specifies the file types to include in the search. 
     136             :   The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
     137             : */
     138           4 : static NTSTATUS svfs_unlink(struct ntvfs_module_context *ntvfs,
     139             :                             struct ntvfs_request *req,
     140             :                             union smb_unlink *unl)
     141             : {
     142           0 :         char *unix_path;
     143             : 
     144           4 :         CHECK_READ_ONLY(req);
     145             : 
     146           4 :         unix_path = svfs_unix_path(ntvfs, req, unl->unlink.in.pattern);
     147             : 
     148             :         /* ignoring wildcards ... */
     149           4 :         if (unlink(unix_path) == -1) {
     150           2 :                 return map_nt_error_from_unix_common(errno);
     151             :         }
     152             : 
     153           2 :         return NT_STATUS_OK;
     154             : }
     155             : 
     156             : 
     157             : /*
     158             :   ioctl interface - we don't do any
     159             : */
     160           0 : static NTSTATUS svfs_ioctl(struct ntvfs_module_context *ntvfs,
     161             :                            struct ntvfs_request *req, union smb_ioctl *io)
     162             : {
     163           0 :         return NT_STATUS_INVALID_PARAMETER;
     164             : }
     165             : 
     166             : /*
     167             :   check if a directory exists
     168             : */
     169           0 : static NTSTATUS svfs_chkpath(struct ntvfs_module_context *ntvfs,
     170             :                              struct ntvfs_request *req,
     171             :                              union smb_chkpath *cp)
     172             : {
     173           0 :         char *unix_path;
     174           0 :         struct stat st;
     175             : 
     176           0 :         unix_path = svfs_unix_path(ntvfs, req, cp->chkpath.in.path);
     177             : 
     178           0 :         if (stat(unix_path, &st) == -1) {
     179           0 :                 return map_nt_error_from_unix_common(errno);
     180             :         }
     181             : 
     182           0 :         if (!S_ISDIR(st.st_mode)) {
     183           0 :                 return NT_STATUS_NOT_A_DIRECTORY;
     184             :         }
     185             : 
     186           0 :         return NT_STATUS_OK;
     187             : }
     188             : 
     189             : /*
     190             :   build a file_id from a stat struct
     191             : */
     192           0 : static uint64_t svfs_file_id(struct stat *st)
     193             : {
     194           0 :         uint64_t ret = st->st_ino;
     195           0 :         ret <<= 32;
     196           0 :         ret |= st->st_dev;
     197           0 :         return ret;
     198             : }
     199             : 
     200             : /*
     201             :   approximately map a struct stat to a generic fileinfo struct
     202             : */
     203           0 : static NTSTATUS svfs_map_fileinfo(struct ntvfs_module_context *ntvfs,
     204             :                                   struct ntvfs_request *req, union smb_fileinfo *info, 
     205             :                                   struct stat *st, const char *unix_path)
     206             : {
     207           0 :         struct svfs_dir *dir = NULL;
     208           0 :         char *pattern = NULL;
     209           0 :         int i, ret;
     210           0 :         const char *s, *short_name;
     211             : 
     212           0 :         s = strrchr(unix_path, '/');
     213           0 :         if (s) {
     214           0 :                 short_name = s+1;
     215             :         } else {
     216           0 :                 short_name = "";
     217             :         }
     218             : 
     219           0 :         ret = asprintf(&pattern, "%s:*", unix_path);
     220           0 :         if (ret == -1) {
     221           0 :                 return NT_STATUS_NO_MEMORY;
     222             :         }
     223             : 
     224           0 :         if (pattern) {
     225           0 :                 dir = svfs_list_unix(req, req, pattern);
     226             :         }
     227             : 
     228           0 :         unix_to_nt_time(&info->generic.out.create_time, st->st_ctime);
     229           0 :         unix_to_nt_time(&info->generic.out.access_time, st->st_atime);
     230           0 :         unix_to_nt_time(&info->generic.out.write_time,  st->st_mtime);
     231           0 :         unix_to_nt_time(&info->generic.out.change_time, st->st_mtime);
     232           0 :         info->generic.out.alloc_size = st->st_size;
     233           0 :         info->generic.out.size = st->st_size;
     234           0 :         info->generic.out.attrib = svfs_unix_to_dos_attrib(st->st_mode);
     235           0 :         info->generic.out.alloc_size = st->st_blksize * st->st_blocks;
     236           0 :         info->generic.out.nlink = st->st_nlink;
     237           0 :         info->generic.out.directory = S_ISDIR(st->st_mode) ? 1 : 0;
     238           0 :         info->generic.out.file_id = svfs_file_id(st);
     239             :         /* REWRITE: TODO stuff in here */
     240           0 :         info->generic.out.delete_pending = 0;
     241           0 :         info->generic.out.ea_size = 0;
     242           0 :         info->generic.out.num_eas = 0;
     243           0 :         info->generic.out.fname.s = talloc_strdup(req, short_name);
     244           0 :         info->generic.out.alt_fname.s = talloc_strdup(req, short_name);
     245           0 :         info->generic.out.compressed_size = 0;
     246           0 :         info->generic.out.format = 0;
     247           0 :         info->generic.out.unit_shift = 0;
     248           0 :         info->generic.out.chunk_shift = 0;
     249           0 :         info->generic.out.cluster_shift = 0;
     250             :         
     251           0 :         info->generic.out.access_flags = 0;
     252           0 :         info->generic.out.position = 0;
     253           0 :         info->generic.out.mode = 0;
     254           0 :         info->generic.out.alignment_requirement = 0;
     255           0 :         info->generic.out.reparse_tag = 0;
     256           0 :         info->generic.out.num_streams = 0;
     257             :         /* setup a single data stream */
     258           0 :         info->generic.out.num_streams = 1 + (dir?dir->count:0);
     259           0 :         info->generic.out.streams = talloc_array(req, 
     260             :                                                    struct stream_struct,
     261             :                                                    info->generic.out.num_streams);
     262           0 :         if (!info->generic.out.streams) {
     263           0 :                 return NT_STATUS_NO_MEMORY;
     264             :         }
     265           0 :         info->generic.out.streams[0].size = st->st_size;
     266           0 :         info->generic.out.streams[0].alloc_size = st->st_size;
     267           0 :         info->generic.out.streams[0].stream_name.s = talloc_strdup(req,"::$DATA");
     268             : 
     269           0 :         for (i=0;dir && i<dir->count;i++) {
     270           0 :                 s = strchr(dir->files[i].name, ':');
     271           0 :                 info->generic.out.streams[1+i].size = dir->files[i].st.st_size;
     272           0 :                 info->generic.out.streams[1+i].alloc_size = dir->files[i].st.st_size;
     273           0 :                 info->generic.out.streams[1+i].stream_name.s = s?s:dir->files[i].name;
     274             :         }
     275             : 
     276           0 :         return NT_STATUS_OK;
     277             : }
     278             : 
     279             : /*
     280             :   return info on a pathname
     281             : */
     282           0 : static NTSTATUS svfs_qpathinfo(struct ntvfs_module_context *ntvfs,
     283             :                                struct ntvfs_request *req, union smb_fileinfo *info)
     284             : {
     285           0 :         char *unix_path;
     286           0 :         struct stat st;
     287             : 
     288           0 :         DEBUG(19,("svfs_qpathinfo: file %s level 0x%x\n", info->generic.in.file.path, info->generic.level));
     289           0 :         if (info->generic.level != RAW_FILEINFO_GENERIC) {
     290           0 :                 return ntvfs_map_qpathinfo(ntvfs, req, info);
     291             :         }
     292             :         
     293           0 :         unix_path = svfs_unix_path(ntvfs, req, info->generic.in.file.path);
     294           0 :         DEBUG(19,("svfs_qpathinfo: file %s\n", unix_path));
     295           0 :         if (stat(unix_path, &st) == -1) {
     296           0 :                 DEBUG(19,("svfs_qpathinfo: file %s errno=%d\n", unix_path, errno));
     297           0 :                 return map_nt_error_from_unix_common(errno);
     298             :         }
     299           0 :         DEBUG(19,("svfs_qpathinfo: file %s, stat done\n", unix_path));
     300           0 :         return svfs_map_fileinfo(ntvfs, req, info, &st, unix_path);
     301             : }
     302             : 
     303             : /*
     304             :   query info on a open file
     305             : */
     306           0 : static NTSTATUS svfs_qfileinfo(struct ntvfs_module_context *ntvfs,
     307             :                                struct ntvfs_request *req, union smb_fileinfo *info)
     308             : {
     309           0 :         struct svfs_private *p = ntvfs->private_data;
     310           0 :         struct svfs_file *f;
     311           0 :         struct stat st;
     312             : 
     313           0 :         if (info->generic.level != RAW_FILEINFO_GENERIC) {
     314           0 :                 return ntvfs_map_qfileinfo(ntvfs, req, info);
     315             :         }
     316             : 
     317           0 :         f = find_fd(p, info->generic.in.file.ntvfs);
     318           0 :         if (!f) {
     319           0 :                 return NT_STATUS_INVALID_HANDLE;
     320             :         }
     321             :         
     322           0 :         if (fstat(f->fd, &st) == -1) {
     323           0 :                 return map_nt_error_from_unix_common(errno);
     324             :         }
     325             : 
     326           0 :         return svfs_map_fileinfo(ntvfs, req,info, &st, f->name);
     327             : }
     328             : 
     329             : 
     330             : /*
     331             :   open a file
     332             : */
     333           8 : static NTSTATUS svfs_open(struct ntvfs_module_context *ntvfs,
     334             :                           struct ntvfs_request *req, union smb_open *io)
     335             : {
     336           8 :         struct svfs_private *p = ntvfs->private_data;
     337           0 :         char *unix_path;
     338           0 :         struct stat st;
     339           0 :         int fd, flags;
     340           0 :         struct svfs_file *f;
     341           0 :         int create_flags, rdwr_flags;
     342           0 :         bool readonly;
     343           0 :         NTSTATUS status;
     344           0 :         struct ntvfs_handle *handle;
     345             :         
     346           8 :         if (io->generic.level != RAW_OPEN_GENERIC) {
     347           4 :                 return ntvfs_map_open(ntvfs, req, io);
     348             :         }
     349             : 
     350           4 :         readonly = share_bool_option(ntvfs->ctx->config, SHARE_READONLY, SHARE_READONLY_DEFAULT);
     351           4 :         if (readonly) {
     352           0 :                 create_flags = 0;
     353           0 :                 rdwr_flags = O_RDONLY;
     354             :         } else {
     355           4 :                 create_flags = O_CREAT;
     356           4 :                 rdwr_flags = O_RDWR;
     357             :         }
     358             : 
     359           4 :         unix_path = svfs_unix_path(ntvfs, req, io->ntcreatex.in.fname);
     360             : 
     361           4 :         switch (io->generic.in.open_disposition) {
     362           0 :         case NTCREATEX_DISP_SUPERSEDE:
     363             :         case NTCREATEX_DISP_OVERWRITE_IF:
     364           0 :                 flags = create_flags | O_TRUNC;
     365           0 :                 break;
     366           2 :         case NTCREATEX_DISP_OPEN:
     367             :         case NTCREATEX_DISP_OVERWRITE:
     368           2 :                 flags = 0;
     369           2 :                 break;
     370           2 :         case NTCREATEX_DISP_CREATE:
     371           2 :                 flags = create_flags | O_EXCL;
     372           2 :                 break;
     373           0 :         case NTCREATEX_DISP_OPEN_IF:
     374           0 :                 flags = create_flags;
     375           0 :                 break;
     376           0 :         default:
     377           0 :                 flags = 0;
     378           0 :                 break;
     379             :         }
     380             :         
     381           4 :         flags |= rdwr_flags;
     382             : 
     383           4 :         if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) {
     384           0 :                 flags = O_RDONLY | O_DIRECTORY;
     385           0 :                 if (readonly) {
     386           0 :                         goto do_open;
     387             :                 }
     388           0 :                 switch (io->generic.in.open_disposition) {
     389           0 :                 case NTCREATEX_DISP_CREATE:
     390           0 :                         if (mkdir(unix_path, 0755) == -1) {
     391           0 :                                 DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno));
     392           0 :                                 return map_nt_error_from_unix_common(errno);
     393             :                         }
     394           0 :                         break;
     395           0 :                 case NTCREATEX_DISP_OPEN_IF:
     396           0 :                         if (mkdir(unix_path, 0755) == -1 && errno != EEXIST) {
     397           0 :                                 DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno));
     398           0 :                                 return map_nt_error_from_unix_common(errno);
     399             :                         }
     400           0 :                         break;
     401             :                 }
     402             :         }
     403             : 
     404           4 : do_open:
     405           4 :         fd = open(unix_path, flags, 0644);
     406           4 :         if (fd == -1) {
     407           0 :                 return map_nt_error_from_unix_common(errno);
     408             :         }
     409             : 
     410           4 :         if (fstat(fd, &st) == -1) {
     411           0 :                 DEBUG(9,("svfs_open: fstat errno=%d\n", errno));
     412           0 :                 close(fd);
     413           0 :                 return map_nt_error_from_unix_common(errno);
     414             :         }
     415             : 
     416           4 :         status = ntvfs_handle_new(ntvfs, req, &handle);
     417           4 :         NT_STATUS_NOT_OK_RETURN(status);
     418             : 
     419           4 :         f = talloc(handle, struct svfs_file);
     420           4 :         if (f == NULL) {
     421           0 :                 close(fd);
     422           0 :                 return NT_STATUS_NO_MEMORY;
     423             :         }
     424           4 :         f->fd = fd;
     425           4 :         f->name = talloc_strdup(f, unix_path);
     426           4 :         NT_STATUS_HAVE_NO_MEMORY(f->name);
     427             : 
     428           4 :         DLIST_ADD(p->open_files, f);
     429             : 
     430           4 :         status = ntvfs_handle_set_backend_data(handle, ntvfs, f);
     431           4 :         NT_STATUS_NOT_OK_RETURN(status);
     432             : 
     433           4 :         ZERO_STRUCT(io->generic.out);
     434             :         
     435           4 :         unix_to_nt_time(&io->generic.out.create_time, st.st_ctime);
     436           4 :         unix_to_nt_time(&io->generic.out.access_time, st.st_atime);
     437           4 :         unix_to_nt_time(&io->generic.out.write_time,  st.st_mtime);
     438           4 :         unix_to_nt_time(&io->generic.out.change_time, st.st_mtime);
     439           4 :         io->generic.out.file.ntvfs = handle;
     440           4 :         io->generic.out.alloc_size = st.st_size;
     441           4 :         io->generic.out.size = st.st_size;
     442           4 :         io->generic.out.attrib = svfs_unix_to_dos_attrib(st.st_mode);
     443           4 :         io->generic.out.is_directory = S_ISDIR(st.st_mode) ? 1 : 0;
     444             : 
     445           4 :         return NT_STATUS_OK;
     446             : }
     447             : 
     448             : /*
     449             :   create a directory
     450             : */
     451           0 : static NTSTATUS svfs_mkdir(struct ntvfs_module_context *ntvfs,
     452             :                            struct ntvfs_request *req, union smb_mkdir *md)
     453             : {
     454           0 :         char *unix_path;
     455             : 
     456           0 :         CHECK_READ_ONLY(req);
     457             : 
     458           0 :         if (md->generic.level != RAW_MKDIR_MKDIR) {
     459           0 :                 return NT_STATUS_INVALID_LEVEL;
     460             :         }
     461             : 
     462           0 :         unix_path = svfs_unix_path(ntvfs, req, md->mkdir.in.path);
     463             : 
     464           0 :         if (mkdir(unix_path, 0777) == -1) {
     465           0 :                 return map_nt_error_from_unix_common(errno);
     466             :         }
     467             : 
     468           0 :         return NT_STATUS_OK;
     469             : }
     470             : 
     471             : /*
     472             :   remove a directory
     473             : */
     474           0 : static NTSTATUS svfs_rmdir(struct ntvfs_module_context *ntvfs,
     475             :                            struct ntvfs_request *req, struct smb_rmdir *rd)
     476             : {
     477           0 :         char *unix_path;
     478             : 
     479           0 :         CHECK_READ_ONLY(req);
     480             : 
     481           0 :         unix_path = svfs_unix_path(ntvfs, req, rd->in.path);
     482             : 
     483           0 :         if (rmdir(unix_path) == -1) {
     484           0 :                 return map_nt_error_from_unix_common(errno);
     485             :         }
     486             : 
     487           0 :         return NT_STATUS_OK;
     488             : }
     489             : 
     490             : /*
     491             :   rename a set of files
     492             : */
     493           0 : static NTSTATUS svfs_rename(struct ntvfs_module_context *ntvfs,
     494             :                             struct ntvfs_request *req, union smb_rename *ren)
     495             : {
     496           0 :         char *unix_path1, *unix_path2;
     497             : 
     498           0 :         CHECK_READ_ONLY(req);
     499             : 
     500           0 :         if (ren->generic.level != RAW_RENAME_RENAME) {
     501           0 :                 return NT_STATUS_INVALID_LEVEL;
     502             :         }
     503             : 
     504           0 :         unix_path1 = svfs_unix_path(ntvfs, req, ren->rename.in.pattern1);
     505           0 :         unix_path2 = svfs_unix_path(ntvfs, req, ren->rename.in.pattern2);
     506             : 
     507           0 :         if (rename(unix_path1, unix_path2) == -1) {
     508           0 :                 return map_nt_error_from_unix_common(errno);
     509             :         }
     510             :         
     511           0 :         return NT_STATUS_OK;
     512             : }
     513             : 
     514             : /*
     515             :   copy a set of files
     516             : */
     517           0 : static NTSTATUS svfs_copy(struct ntvfs_module_context *ntvfs,
     518             :                           struct ntvfs_request *req, struct smb_copy *cp)
     519             : {
     520           0 :         return NT_STATUS_NOT_SUPPORTED;
     521             : }
     522             : 
     523             : /*
     524             :   read from a file
     525             : */
     526          49 : static NTSTATUS svfs_read(struct ntvfs_module_context *ntvfs,
     527             :                           struct ntvfs_request *req, union smb_read *rd)
     528             : {
     529          49 :         struct svfs_private *p = ntvfs->private_data;
     530           0 :         struct svfs_file *f;
     531           0 :         ssize_t ret;
     532             : 
     533          49 :         if (rd->generic.level != RAW_READ_READX) {
     534           0 :                 return NT_STATUS_NOT_SUPPORTED;
     535             :         }
     536             : 
     537          49 :         f = find_fd(p, rd->readx.in.file.ntvfs);
     538          49 :         if (!f) {
     539           0 :                 return NT_STATUS_INVALID_HANDLE;
     540             :         }
     541             : 
     542          49 :         ret = pread(f->fd, 
     543          49 :                     rd->readx.out.data, 
     544          49 :                     rd->readx.in.maxcnt,
     545          49 :                     rd->readx.in.offset);
     546          49 :         if (ret == -1) {
     547           0 :                 return map_nt_error_from_unix_common(errno);
     548             :         }
     549             : 
     550          49 :         rd->readx.out.nread = ret;
     551          49 :         rd->readx.out.remaining = 0; /* should fill this in? */
     552          49 :         rd->readx.out.compaction_mode = 0; 
     553             : 
     554          49 :         return NT_STATUS_OK;
     555             : }
     556             : 
     557             : /*
     558             :   write to a file
     559             : */
     560          49 : static NTSTATUS svfs_write(struct ntvfs_module_context *ntvfs,
     561             :                            struct ntvfs_request *req, union smb_write *wr)
     562             : {
     563          49 :         struct svfs_private *p = ntvfs->private_data;
     564           0 :         struct svfs_file *f;
     565           0 :         ssize_t ret;
     566             : 
     567          49 :         if (wr->generic.level != RAW_WRITE_WRITEX) {
     568           0 :                 return ntvfs_map_write(ntvfs, req, wr);
     569             :         }
     570             : 
     571          49 :         CHECK_READ_ONLY(req);
     572             : 
     573          49 :         f = find_fd(p, wr->writex.in.file.ntvfs);
     574          49 :         if (!f) {
     575           0 :                 return NT_STATUS_INVALID_HANDLE;
     576             :         }
     577             : 
     578          49 :         ret = pwrite(f->fd, 
     579          49 :                      wr->writex.in.data, 
     580          49 :                      wr->writex.in.count,
     581          49 :                      wr->writex.in.offset);
     582          49 :         if (ret == -1) {
     583           0 :                 return map_nt_error_from_unix_common(errno);
     584             :         }
     585             :                 
     586          49 :         wr->writex.out.nwritten = ret;
     587          49 :         wr->writex.out.remaining = 0; /* should fill this in? */
     588             :         
     589          49 :         return NT_STATUS_OK;
     590             : }
     591             : 
     592             : /*
     593             :   seek in a file
     594             : */
     595           0 : static NTSTATUS svfs_seek(struct ntvfs_module_context *ntvfs,
     596             :                           struct ntvfs_request *req,
     597             :                           union smb_seek *io)
     598             : {
     599           0 :         return NT_STATUS_NOT_SUPPORTED;
     600             : }
     601             : 
     602             : /*
     603             :   flush a file
     604             : */
     605           0 : static NTSTATUS svfs_flush(struct ntvfs_module_context *ntvfs,
     606             :                            struct ntvfs_request *req,
     607             :                            union smb_flush *io)
     608             : {
     609           0 :         struct svfs_private *p = ntvfs->private_data;
     610           0 :         struct svfs_file *f;
     611             : 
     612           0 :         switch (io->generic.level) {
     613           0 :         case RAW_FLUSH_FLUSH:
     614             :         case RAW_FLUSH_SMB2:
     615             :                 /* ignore the additional unknown option in SMB2 */
     616           0 :                 f = find_fd(p, io->generic.in.file.ntvfs);
     617           0 :                 if (!f) {
     618           0 :                         return NT_STATUS_INVALID_HANDLE;
     619             :                 }
     620           0 :                 fsync(f->fd);
     621           0 :                 return NT_STATUS_OK;
     622             : 
     623           0 :         case RAW_FLUSH_ALL:
     624           0 :                 for (f=p->open_files;f;f=f->next) {
     625           0 :                         fsync(f->fd);
     626             :                 }
     627           0 :                 return NT_STATUS_OK;
     628             :         }
     629             : 
     630           0 :         return NT_STATUS_INVALID_LEVEL;
     631             : }
     632             : 
     633             : /*
     634             :   close a file
     635             : */
     636           4 : static NTSTATUS svfs_close(struct ntvfs_module_context *ntvfs,
     637             :                            struct ntvfs_request *req,
     638             :                            union smb_close *io)
     639             : {
     640           4 :         struct svfs_private *p = ntvfs->private_data;
     641           0 :         struct svfs_file *f;
     642             : 
     643           4 :         if (io->generic.level != RAW_CLOSE_CLOSE) {
     644             :                 /* we need a mapping function */
     645           0 :                 return NT_STATUS_INVALID_LEVEL;
     646             :         }
     647             : 
     648           4 :         f = find_fd(p, io->close.in.file.ntvfs);
     649           4 :         if (!f) {
     650           0 :                 return NT_STATUS_INVALID_HANDLE;
     651             :         }
     652             : 
     653           4 :         if (close(f->fd) == -1) {
     654           0 :                 return map_nt_error_from_unix_common(errno);
     655             :         }
     656             : 
     657           4 :         DLIST_REMOVE(p->open_files, f);
     658           4 :         talloc_free(f->name);
     659           4 :         talloc_free(f);
     660             : 
     661           4 :         return NT_STATUS_OK;
     662             : }
     663             : 
     664             : /*
     665             :   exit - closing files
     666             : */
     667           0 : static NTSTATUS svfs_exit(struct ntvfs_module_context *ntvfs,
     668             :                           struct ntvfs_request *req)
     669             : {
     670           0 :         return NT_STATUS_NOT_SUPPORTED;
     671             : }
     672             : 
     673             : /*
     674             :   logoff - closing files
     675             : */
     676           0 : static NTSTATUS svfs_logoff(struct ntvfs_module_context *ntvfs,
     677             :                             struct ntvfs_request *req)
     678             : {
     679           0 :         return NT_STATUS_NOT_SUPPORTED;
     680             : }
     681             : 
     682             : /*
     683             :   setup for an async call
     684             : */
     685           0 : static NTSTATUS svfs_async_setup(struct ntvfs_module_context *ntvfs,
     686             :                                  struct ntvfs_request *req, 
     687             :                                  void *private_data)
     688             : {
     689           0 :         return NT_STATUS_OK;
     690             : }
     691             : 
     692             : /*
     693             :   cancel an async call
     694             : */
     695           0 : static NTSTATUS svfs_cancel(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req)
     696             : {
     697           0 :         return NT_STATUS_UNSUCCESSFUL;
     698             : }
     699             : 
     700             : /*
     701             :   lock a byte range
     702             : */
     703           0 : static NTSTATUS svfs_lock(struct ntvfs_module_context *ntvfs,
     704             :                           struct ntvfs_request *req, union smb_lock *lck)
     705             : {
     706           0 :         DEBUG(0,("REWRITE: not doing byte range locking!\n"));
     707           0 :         return NT_STATUS_OK;
     708             : }
     709             : 
     710             : /*
     711             :   set info on a pathname
     712             : */
     713           0 : static NTSTATUS svfs_setpathinfo(struct ntvfs_module_context *ntvfs,
     714             :                                  struct ntvfs_request *req, union smb_setfileinfo *st)
     715             : {
     716           0 :         CHECK_READ_ONLY(req);
     717             : 
     718           0 :         return NT_STATUS_NOT_SUPPORTED;
     719             : }
     720             : 
     721             : /*
     722             :   set info on a open file
     723             : */
     724           0 : static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs,
     725             :                                  struct ntvfs_request *req, 
     726             :                                  union smb_setfileinfo *info)
     727             : {
     728           0 :         struct svfs_private *p = ntvfs->private_data;
     729           0 :         struct svfs_file *f;
     730           0 :         struct utimbuf unix_times;
     731             : 
     732           0 :         CHECK_READ_ONLY(req);
     733             : 
     734           0 :         f = find_fd(p, info->generic.in.file.ntvfs);
     735           0 :         if (!f) {
     736           0 :                 return NT_STATUS_INVALID_HANDLE;
     737             :         }
     738             :         
     739           0 :         switch (info->generic.level) {
     740           0 :         case RAW_SFILEINFO_END_OF_FILE_INFO:
     741             :         case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
     742           0 :                 if (ftruncate(f->fd, 
     743           0 :                               info->end_of_file_info.in.size) == -1) {
     744           0 :                         return map_nt_error_from_unix_common(errno);
     745             :                 }
     746           0 :                 break;
     747           0 :         case RAW_SFILEINFO_SETATTRE:
     748           0 :                 unix_times.actime = info->setattre.in.access_time;
     749           0 :                 unix_times.modtime = info->setattre.in.write_time;
     750             : 
     751           0 :                 if (unix_times.actime == 0 && unix_times.modtime == 0) {
     752           0 :                         break;
     753             :                 } 
     754             : 
     755             :                 /* set modify time = to access time if modify time was 0 */
     756           0 :                 if (unix_times.actime != 0 && unix_times.modtime == 0) {
     757           0 :                         unix_times.modtime = unix_times.actime;
     758             :                 }
     759             : 
     760             :                 /* Set the date on this file */
     761           0 :                 if (svfs_file_utime(f->fd, &unix_times) != 0) {
     762           0 :                         return NT_STATUS_ACCESS_DENIED;
     763             :                 }
     764           0 :                 break;
     765           0 :         default:
     766           0 :                 DEBUG(2,("svfs_setfileinfo: level %d not implemented\n", 
     767             :                          info->generic.level));
     768           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     769             :         }
     770           0 :         return NT_STATUS_OK;
     771             : }
     772             : 
     773             : 
     774             : /*
     775             :   return filesystem space info
     776             : */
     777           0 : static NTSTATUS svfs_fsinfo(struct ntvfs_module_context *ntvfs,
     778             :                             struct ntvfs_request *req, union smb_fsinfo *fs)
     779             : {
     780           0 :         struct svfs_private *p = ntvfs->private_data;
     781           0 :         struct stat st;
     782             : 
     783           0 :         if (fs->generic.level != RAW_QFS_GENERIC) {
     784           0 :                 return ntvfs_map_fsinfo(ntvfs, req, fs);
     785             :         }
     786             : 
     787           0 :         if (sys_fsusage(p->connectpath,
     788             :                         &fs->generic.out.blocks_free, 
     789             :                         &fs->generic.out.blocks_total) == -1) {
     790           0 :                 return map_nt_error_from_unix_common(errno);
     791             :         }
     792             : 
     793           0 :         fs->generic.out.block_size = 512;
     794             : 
     795           0 :         if (stat(p->connectpath, &st) != 0) {
     796           0 :                 return NT_STATUS_DISK_CORRUPT_ERROR;
     797             :         }
     798             :         
     799           0 :         fs->generic.out.fs_id = st.st_ino;
     800           0 :         unix_to_nt_time(&fs->generic.out.create_time, st.st_ctime);
     801           0 :         fs->generic.out.serial_number = st.st_ino;
     802           0 :         fs->generic.out.fs_attr = 0;
     803           0 :         fs->generic.out.max_file_component_length = 255;
     804           0 :         fs->generic.out.device_type = 0;
     805           0 :         fs->generic.out.device_characteristics = 0;
     806           0 :         fs->generic.out.quota_soft = 0;
     807           0 :         fs->generic.out.quota_hard = 0;
     808           0 :         fs->generic.out.quota_flags = 0;
     809           0 :         fs->generic.out.volume_name = talloc_strdup(req, ntvfs->ctx->config->name);
     810           0 :         fs->generic.out.fs_type = ntvfs->ctx->fs_type;
     811             : 
     812           0 :         return NT_STATUS_OK;
     813             : }
     814             : 
     815             : #if 0
     816             : /*
     817             :   return filesystem attribute info
     818             : */
     819             : static NTSTATUS svfs_fsattr(struct ntvfs_module_context *ntvfs,
     820             :                             struct ntvfs_request *req, union smb_fsattr *fs)
     821             : {
     822             :         struct stat st;
     823             :         struct svfs_private *p = ntvfs->private_data;
     824             : 
     825             :         if (fs->generic.level != RAW_FSATTR_GENERIC) {
     826             :                 return ntvfs_map_fsattr(ntvfs, req, fs);
     827             :         }
     828             : 
     829             :         if (stat(p->connectpath, &st) == -1) {
     830             :                 return map_nt_error_from_unix_common(errno);
     831             :         }
     832             : 
     833             :         unix_to_nt_time(&fs->generic.out.create_time, st.st_ctime);
     834             :         fs->generic.out.fs_attr = 
     835             :                 FILE_CASE_PRESERVED_NAMES | 
     836             :                 FILE_CASE_SENSITIVE_SEARCH | 
     837             :                 FILE_PERSISTENT_ACLS;
     838             :         fs->generic.out.max_file_component_length = 255;
     839             :         fs->generic.out.serial_number = 1;
     840             :         fs->generic.out.fs_type = talloc_strdup(req, "NTFS");
     841             :         fs->generic.out.volume_name = talloc_strdup(req, 
     842             :                                                     lpcfg_servicename(req->tcon->service));
     843             : 
     844             :         return NT_STATUS_OK;
     845             : }
     846             : #endif
     847             : 
     848             : /*
     849             :   return print queue info
     850             : */
     851           0 : static NTSTATUS svfs_lpq(struct ntvfs_module_context *ntvfs,
     852             :                          struct ntvfs_request *req, union smb_lpq *lpq)
     853             : {
     854           0 :         return NT_STATUS_NOT_SUPPORTED;
     855             : }
     856             : 
     857             : /* 
     858             :    list files in a directory matching a wildcard pattern
     859             : */
     860           0 : static NTSTATUS svfs_search_first(struct ntvfs_module_context *ntvfs,
     861             :                                   struct ntvfs_request *req, union smb_search_first *io, 
     862             :                                   void *search_private, 
     863             :                                   bool (*callback)(void *, const union smb_search_data *))
     864             : {
     865           0 :         struct svfs_dir *dir;
     866           0 :         int i;
     867           0 :         struct svfs_private *p = ntvfs->private_data;
     868           0 :         struct search_state *search;
     869           0 :         union smb_search_data file;
     870           0 :         unsigned int max_count;
     871             : 
     872           0 :         if (io->generic.level != RAW_SEARCH_TRANS2) {
     873           0 :                 return NT_STATUS_NOT_SUPPORTED;
     874             :         }
     875             : 
     876           0 :         if (io->generic.data_level != RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO) {
     877           0 :                 return NT_STATUS_NOT_SUPPORTED;
     878             :         }
     879             : 
     880           0 :         search = talloc_zero(p, struct search_state);
     881           0 :         if (!search) {
     882           0 :                 return NT_STATUS_NO_MEMORY;
     883             :         }
     884             : 
     885           0 :         max_count = io->t2ffirst.in.max_count;
     886             : 
     887           0 :         dir = svfs_list(ntvfs, req, io->t2ffirst.in.pattern);
     888           0 :         if (!dir) {
     889           0 :                 return NT_STATUS_FOOBAR;
     890             :         }
     891             : 
     892           0 :         search->handle = p->next_search_handle;
     893           0 :         search->dir = dir;
     894             : 
     895           0 :         if (dir->count < max_count) {
     896           0 :                 max_count = dir->count;
     897             :         }
     898             : 
     899           0 :         for (i=0; i < max_count;i++) {
     900           0 :                 ZERO_STRUCT(file);
     901           0 :                 unix_to_nt_time(&file.both_directory_info.create_time, dir->files[i].st.st_ctime);
     902           0 :                 unix_to_nt_time(&file.both_directory_info.access_time, dir->files[i].st.st_atime);
     903           0 :                 unix_to_nt_time(&file.both_directory_info.write_time,  dir->files[i].st.st_mtime);
     904           0 :                 unix_to_nt_time(&file.both_directory_info.change_time, dir->files[i].st.st_mtime);
     905           0 :                 file.both_directory_info.name.s = dir->files[i].name;
     906           0 :                 file.both_directory_info.short_name.s = dir->files[i].name;
     907           0 :                 file.both_directory_info.size = dir->files[i].st.st_size;
     908           0 :                 file.both_directory_info.attrib = svfs_unix_to_dos_attrib(dir->files[i].st.st_mode);
     909             : 
     910           0 :                 if (!callback(search_private, &file)) {
     911           0 :                         break;
     912             :                 }
     913             :         }
     914             : 
     915           0 :         search->current_index = i;
     916             : 
     917           0 :         io->t2ffirst.out.count = i;
     918           0 :         io->t2ffirst.out.handle = search->handle;
     919           0 :         io->t2ffirst.out.end_of_search = (i == dir->count) ? 1 : 0;
     920             : 
     921             :         /* work out if we are going to keep the search state */
     922           0 :         if ((io->t2ffirst.in.flags & FLAG_TRANS2_FIND_CLOSE) ||
     923           0 :             ((io->t2ffirst.in.flags & FLAG_TRANS2_FIND_CLOSE_IF_END) && (i == dir->count))) {
     924           0 :                 talloc_free(search);
     925             :         } else {
     926           0 :                 p->next_search_handle++;
     927           0 :                 DLIST_ADD(p->search, search);
     928             :         }
     929             : 
     930           0 :         return NT_STATUS_OK;
     931             : }
     932             : 
     933             : /* continue a search */
     934           0 : static NTSTATUS svfs_search_next(struct ntvfs_module_context *ntvfs,
     935             :                                  struct ntvfs_request *req, union smb_search_next *io, 
     936             :                                  void *search_private, 
     937             :                                  bool (*callback)(void *, const union smb_search_data *))
     938             : {
     939           0 :         struct svfs_dir *dir;
     940           0 :         int i;
     941           0 :         struct svfs_private *p = ntvfs->private_data;
     942           0 :         struct search_state *search;
     943           0 :         union smb_search_data file;
     944           0 :         unsigned int max_count;
     945             : 
     946           0 :         if (io->generic.level != RAW_SEARCH_TRANS2) {
     947           0 :                 return NT_STATUS_NOT_SUPPORTED;
     948             :         }
     949             : 
     950           0 :         if (io->generic.data_level != RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO) {
     951           0 :                 return NT_STATUS_NOT_SUPPORTED;
     952             :         }
     953             : 
     954           0 :         for (search=p->search; search; search = search->next) {
     955           0 :                 if (search->handle == io->t2fnext.in.handle) break;
     956             :         }
     957             :         
     958           0 :         if (!search) {
     959             :                 /* we didn't find the search handle */
     960           0 :                 return NT_STATUS_FOOBAR;
     961             :         }
     962             : 
     963           0 :         dir = search->dir;
     964             : 
     965             :         /* the client might be asking for something other than just continuing
     966             :            with the search */
     967           0 :         if (!(io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE) &&
     968           0 :             (io->t2fnext.in.flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) &&
     969           0 :             io->t2fnext.in.last_name && *io->t2fnext.in.last_name) {
     970             :                 /* look backwards first */
     971           0 :                 for (i=search->current_index; i > 0; i--) {
     972           0 :                         if (strcmp(io->t2fnext.in.last_name, dir->files[i-1].name) == 0) {
     973           0 :                                 search->current_index = i;
     974           0 :                                 goto found;
     975             :                         }
     976             :                 }
     977             : 
     978             :                 /* then look forwards */
     979           0 :                 for (i=search->current_index+1; i <= dir->count; i++) {
     980           0 :                         if (strcmp(io->t2fnext.in.last_name, dir->files[i-1].name) == 0) {
     981           0 :                                 search->current_index = i;
     982           0 :                                 goto found;
     983             :                         }
     984             :                 }
     985             :         }
     986             : 
     987           0 : found:  
     988           0 :         max_count = search->current_index + io->t2fnext.in.max_count;
     989             : 
     990           0 :         if (max_count > dir->count) {
     991           0 :                 max_count = dir->count;
     992             :         }
     993             : 
     994           0 :         for (i = search->current_index; i < max_count;i++) {
     995           0 :                 ZERO_STRUCT(file);
     996           0 :                 unix_to_nt_time(&file.both_directory_info.create_time, dir->files[i].st.st_ctime);
     997           0 :                 unix_to_nt_time(&file.both_directory_info.access_time, dir->files[i].st.st_atime);
     998           0 :                 unix_to_nt_time(&file.both_directory_info.write_time,  dir->files[i].st.st_mtime);
     999           0 :                 unix_to_nt_time(&file.both_directory_info.change_time, dir->files[i].st.st_mtime);
    1000           0 :                 file.both_directory_info.name.s = dir->files[i].name;
    1001           0 :                 file.both_directory_info.short_name.s = dir->files[i].name;
    1002           0 :                 file.both_directory_info.size = dir->files[i].st.st_size;
    1003           0 :                 file.both_directory_info.attrib = svfs_unix_to_dos_attrib(dir->files[i].st.st_mode);
    1004             : 
    1005           0 :                 if (!callback(search_private, &file)) {
    1006           0 :                         break;
    1007             :                 }
    1008             :         }
    1009             : 
    1010           0 :         io->t2fnext.out.count = i - search->current_index;
    1011           0 :         io->t2fnext.out.end_of_search = (i == dir->count) ? 1 : 0;
    1012             : 
    1013           0 :         search->current_index = i;
    1014             : 
    1015             :         /* work out if we are going to keep the search state */
    1016           0 :         if ((io->t2fnext.in.flags & FLAG_TRANS2_FIND_CLOSE) ||
    1017           0 :             ((io->t2fnext.in.flags & FLAG_TRANS2_FIND_CLOSE_IF_END) && (i == dir->count))) {
    1018           0 :                 DLIST_REMOVE(p->search, search);
    1019           0 :                 talloc_free(search);
    1020             :         }
    1021             : 
    1022           0 :         return NT_STATUS_OK;
    1023             : }
    1024             : 
    1025             : /* close a search */
    1026           0 : static NTSTATUS svfs_search_close(struct ntvfs_module_context *ntvfs,
    1027             :                                   struct ntvfs_request *req, union smb_search_close *io)
    1028             : {
    1029           0 :         struct svfs_private *p = ntvfs->private_data;
    1030           0 :         struct search_state *search;
    1031             : 
    1032           0 :         for (search=p->search; search; search = search->next) {
    1033           0 :                 if (search->handle == io->findclose.in.handle) break;
    1034             :         }
    1035             :         
    1036           0 :         if (!search) {
    1037             :                 /* we didn't find the search handle */
    1038           0 :                 return NT_STATUS_FOOBAR;
    1039             :         }
    1040             : 
    1041           0 :         DLIST_REMOVE(p->search, search);
    1042           0 :         talloc_free(search);
    1043             : 
    1044           0 :         return NT_STATUS_OK;
    1045             : }
    1046             : 
    1047             : /* SMBtrans - not used on file shares */
    1048           0 : static NTSTATUS svfs_trans(struct ntvfs_module_context *ntvfs,
    1049             :                            struct ntvfs_request *req, struct smb_trans2 *trans2)
    1050             : {
    1051           0 :         return NT_STATUS_ACCESS_DENIED;
    1052             : }
    1053             : 
    1054             : 
    1055             : /*
    1056             :   initialise the POSIX disk backend, registering ourselves with the ntvfs subsystem
    1057             :  */
    1058          68 : NTSTATUS ntvfs_simple_init(TALLOC_CTX *ctx)
    1059             : {
    1060           3 :         NTSTATUS ret;
    1061           3 :         struct ntvfs_ops ops;
    1062          68 :         NTVFS_CURRENT_CRITICAL_SIZES(vers);
    1063             : 
    1064          68 :         ZERO_STRUCT(ops);
    1065             : 
    1066             :         /* fill in all the operations */
    1067          68 :         ops.connect_fn = svfs_connect;
    1068          68 :         ops.disconnect_fn = svfs_disconnect;
    1069          68 :         ops.unlink_fn = svfs_unlink;
    1070          68 :         ops.chkpath_fn = svfs_chkpath;
    1071          68 :         ops.qpathinfo_fn = svfs_qpathinfo;
    1072          68 :         ops.setpathinfo_fn = svfs_setpathinfo;
    1073          68 :         ops.open_fn = svfs_open;
    1074          68 :         ops.mkdir_fn = svfs_mkdir;
    1075          68 :         ops.rmdir_fn = svfs_rmdir;
    1076          68 :         ops.rename_fn = svfs_rename;
    1077          68 :         ops.copy_fn = svfs_copy;
    1078          68 :         ops.ioctl_fn = svfs_ioctl;
    1079          68 :         ops.read_fn = svfs_read;
    1080          68 :         ops.write_fn = svfs_write;
    1081          68 :         ops.seek_fn = svfs_seek;
    1082          68 :         ops.flush_fn = svfs_flush;
    1083          68 :         ops.close_fn = svfs_close;
    1084          68 :         ops.exit_fn = svfs_exit;
    1085          68 :         ops.lock_fn = svfs_lock;
    1086          68 :         ops.setfileinfo_fn = svfs_setfileinfo;
    1087          68 :         ops.qfileinfo_fn = svfs_qfileinfo;
    1088          68 :         ops.fsinfo_fn = svfs_fsinfo;
    1089          68 :         ops.lpq_fn = svfs_lpq;
    1090          68 :         ops.search_first_fn = svfs_search_first;
    1091          68 :         ops.search_next_fn = svfs_search_next;
    1092          68 :         ops.search_close_fn = svfs_search_close;
    1093          68 :         ops.trans_fn = svfs_trans;
    1094          68 :         ops.logoff_fn = svfs_logoff;
    1095          68 :         ops.async_setup_fn = svfs_async_setup;
    1096          68 :         ops.cancel_fn = svfs_cancel;
    1097             : 
    1098             :         /* register ourselves with the NTVFS subsystem. We register
    1099             :            under names 'simple'
    1100             :         */
    1101             : 
    1102          68 :         ops.type = NTVFS_DISK;
    1103          68 :         ops.name = "simple";
    1104          68 :         ret = ntvfs_register(&ops, &vers);
    1105             : 
    1106          68 :         if (!NT_STATUS_IS_OK(ret)) {
    1107           0 :                 DEBUG(0,("Failed to register simple backend with name: %s!\n",
    1108             :                          ops.name));
    1109             :         }
    1110             : 
    1111          68 :         return ret;
    1112             : }

Generated by: LCOV version 1.14