s3:vfs: add durable VFS operations
[bbaumbach/samba-autobuild/.git] / source3 / smbd / vfs.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    VFS initialisation and support functions
5    Copyright (C) Tim Potter 1999
6    Copyright (C) Alexander Bokovoy 2002
7    Copyright (C) James Peach 2006
8    Copyright (C) Volker Lendecke 2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23    This work was sponsored by Optifacio Software Services, Inc.
24 */
25
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "memcache.h"
31 #include "transfer_file.h"
32 #include "ntioctl.h"
33 #include "lib/util/tevent_unix.h"
34
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_VFS
37
38 static_decl_vfs;
39
40 struct vfs_fsp_data {
41     struct vfs_fsp_data *next;
42     struct vfs_handle_struct *owner;
43     void (*destroy)(void *p_data);
44     void *_dummy_;
45     /* NOTE: This structure contains four pointers so that we can guarantee
46      * that the end of the structure is always both 4-byte and 8-byte aligned.
47      */
48 };
49
50 struct vfs_init_function_entry {
51         char *name;
52         struct vfs_init_function_entry *prev, *next;
53         const struct vfs_fn_pointers *fns;
54 };
55
56 /****************************************************************************
57     maintain the list of available backends
58 ****************************************************************************/
59
60 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
61 {
62         struct vfs_init_function_entry *entry = backends;
63
64         DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
65
66         while(entry) {
67                 if (strcmp(entry->name, name)==0) return entry;
68                 entry = entry->next;
69         }
70
71         return NULL;
72 }
73
74 NTSTATUS smb_register_vfs(int version, const char *name,
75                           const struct vfs_fn_pointers *fns)
76 {
77         struct vfs_init_function_entry *entry = backends;
78
79         if ((version != SMB_VFS_INTERFACE_VERSION)) {
80                 DEBUG(0, ("Failed to register vfs module.\n"
81                           "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
82                           "current SMB_VFS_INTERFACE_VERSION is %d.\n"
83                           "Please recompile against the current Samba Version!\n",  
84                           version, SMB_VFS_INTERFACE_VERSION));
85                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
86         }
87
88         if (!name || !name[0]) {
89                 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
90                 return NT_STATUS_INVALID_PARAMETER;
91         }
92
93         if (vfs_find_backend_entry(name)) {
94                 DEBUG(0,("VFS module %s already loaded!\n", name));
95                 return NT_STATUS_OBJECT_NAME_COLLISION;
96         }
97
98         entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
99         entry->name = smb_xstrdup(name);
100         entry->fns = fns;
101
102         DLIST_ADD(backends, entry);
103         DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
104         return NT_STATUS_OK;
105 }
106
107 /****************************************************************************
108   initialise default vfs hooks
109 ****************************************************************************/
110
111 static void vfs_init_default(connection_struct *conn)
112 {
113         DEBUG(3, ("Initialising default vfs hooks\n"));
114         vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
115 }
116
117 /****************************************************************************
118   initialise custom vfs hooks
119  ****************************************************************************/
120
121 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
122 {
123         char *module_path = NULL;
124         char *module_name = NULL;
125         char *module_param = NULL, *p;
126         vfs_handle_struct *handle;
127         const struct vfs_init_function_entry *entry;
128
129         if (!conn||!vfs_object||!vfs_object[0]) {
130                 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
131                           "empty vfs_object!\n"));
132                 return False;
133         }
134
135         if(!backends) {
136                 static_init_vfs;
137         }
138
139         DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
140
141         module_path = smb_xstrdup(vfs_object);
142
143         p = strchr_m(module_path, ':');
144
145         if (p) {
146                 *p = 0;
147                 module_param = p+1;
148                 trim_char(module_param, ' ', ' ');
149         }
150
151         trim_char(module_path, ' ', ' ');
152
153         module_name = smb_xstrdup(module_path);
154
155         if ((module_name[0] == '/') &&
156             (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
157
158                 /*
159                  * Extract the module name from the path. Just use the base
160                  * name of the last path component.
161                  */
162
163                 SAFE_FREE(module_name);
164                 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
165
166                 p = strchr_m(module_name, '.');
167
168                 if (p != NULL) {
169                         *p = '\0';
170                 }
171         }
172
173         /* First, try to load the module with the new module system */
174         entry = vfs_find_backend_entry(module_name);
175         if (!entry) {
176                 NTSTATUS status;
177
178                 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
179                           vfs_object));
180
181                 status = smb_load_module("vfs", module_path);
182                 if (!NT_STATUS_IS_OK(status)) {
183                         DEBUG(0, ("error probing vfs module '%s': %s\n",
184                                   module_path, nt_errstr(status)));
185                         goto fail;
186                 }
187
188                 entry = vfs_find_backend_entry(module_name);
189                 if (!entry) {
190                         DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
191                         goto fail;
192                 }
193         }
194
195         DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
196
197         handle = talloc_zero(conn, vfs_handle_struct);
198         if (!handle) {
199                 DEBUG(0,("TALLOC_ZERO() failed!\n"));
200                 goto fail;
201         }
202         handle->conn = conn;
203         handle->fns = entry->fns;
204         if (module_param) {
205                 handle->param = talloc_strdup(conn, module_param);
206         }
207         DLIST_ADD(conn->vfs_handles, handle);
208
209         SAFE_FREE(module_path);
210         SAFE_FREE(module_name);
211         return True;
212
213  fail:
214         SAFE_FREE(module_path);
215         SAFE_FREE(module_name);
216         return False;
217 }
218
219 /*****************************************************************
220  Allow VFS modules to extend files_struct with VFS-specific state.
221  This will be ok for small numbers of extensions, but might need to
222  be refactored if it becomes more widely used.
223 ******************************************************************/
224
225 #define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data))
226
227 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
228                                    files_struct *fsp, size_t ext_size,
229                                    void (*destroy_fn)(void *p_data))
230 {
231         struct vfs_fsp_data *ext;
232         void * ext_data;
233
234         /* Prevent VFS modules adding multiple extensions. */
235         if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
236                 return ext_data;
237         }
238
239         ext = (struct vfs_fsp_data *)TALLOC_ZERO(
240                 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
241         if (ext == NULL) {
242                 return NULL;
243         }
244
245         ext->owner = handle;
246         ext->next = fsp->vfs_extension;
247         ext->destroy = destroy_fn;
248         fsp->vfs_extension = ext;
249         return EXT_DATA_AREA(ext);
250 }
251
252 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
253 {
254         struct vfs_fsp_data *curr;
255         struct vfs_fsp_data *prev;
256
257         for (curr = fsp->vfs_extension, prev = NULL;
258              curr;
259              prev = curr, curr = curr->next) {
260                 if (curr->owner == handle) {
261                     if (prev) {
262                             prev->next = curr->next;
263                     } else {
264                             fsp->vfs_extension = curr->next;
265                     }
266                     if (curr->destroy) {
267                             curr->destroy(EXT_DATA_AREA(curr));
268                     }
269                     TALLOC_FREE(curr);
270                     return;
271                 }
272         }
273 }
274
275 void vfs_remove_all_fsp_extensions(files_struct *fsp)
276 {
277         struct vfs_fsp_data *curr;
278         struct vfs_fsp_data *next;
279
280         for (curr = fsp->vfs_extension; curr; curr = next) {
281
282                 next = curr->next;
283                 fsp->vfs_extension = next;
284
285                 if (curr->destroy) {
286                         curr->destroy(EXT_DATA_AREA(curr));
287                 }
288                 TALLOC_FREE(curr);
289         }
290 }
291
292 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
293 {
294         struct vfs_fsp_data *head;
295
296         for (head = fsp->vfs_extension; head; head = head->next) {
297                 if (head->owner == handle) {
298                         return head;
299                 }
300         }
301
302         return NULL;
303 }
304
305 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
306 {
307         struct vfs_fsp_data *head;
308
309         head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
310         if (head != NULL) {
311                 return EXT_DATA_AREA(head);
312         }
313
314         return NULL;
315 }
316
317 #undef EXT_DATA_AREA
318
319 /*****************************************************************
320  Generic VFS init.
321 ******************************************************************/
322
323 bool smbd_vfs_init(connection_struct *conn)
324 {
325         const char **vfs_objects;
326         unsigned int i = 0;
327         int j = 0;
328
329         /* Normal share - initialise with disk access functions */
330         vfs_init_default(conn);
331
332         /* No need to load vfs modules for printer connections */
333         if (conn->printer) {
334                 return True;
335         }
336
337         vfs_objects = lp_vfs_objects(SNUM(conn));
338
339         /* Override VFS functions if 'vfs object' was not specified*/
340         if (!vfs_objects || !vfs_objects[0])
341                 return True;
342
343         for (i=0; vfs_objects[i] ;) {
344                 i++;
345         }
346
347         for (j=i-1; j >= 0; j--) {
348                 if (!vfs_init_custom(conn, vfs_objects[j])) {
349                         DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
350                         return False;
351                 }
352         }
353         return True;
354 }
355
356 /*******************************************************************
357  Check if a file exists in the vfs.
358 ********************************************************************/
359
360 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
361 {
362         /* Only return OK if stat was successful and S_ISREG */
363         if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
364             S_ISREG(smb_fname->st.st_ex_mode)) {
365                 return NT_STATUS_OK;
366         }
367
368         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
369 }
370
371 /****************************************************************************
372  Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
373 ****************************************************************************/
374
375 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
376 {
377         size_t total=0;
378
379         while (total < byte_count)
380         {
381                 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
382                                            byte_count - total);
383
384                 if (ret == 0) return total;
385                 if (ret == -1) {
386                         if (errno == EINTR)
387                                 continue;
388                         else
389                                 return -1;
390                 }
391                 total += ret;
392         }
393         return (ssize_t)total;
394 }
395
396 ssize_t vfs_pread_data(files_struct *fsp, char *buf,
397                 size_t byte_count, off_t offset)
398 {
399         size_t total=0;
400
401         while (total < byte_count)
402         {
403                 ssize_t ret = SMB_VFS_PREAD(fsp, buf + total,
404                                         byte_count - total, offset + total);
405
406                 if (ret == 0) return total;
407                 if (ret == -1) {
408                         if (errno == EINTR)
409                                 continue;
410                         else
411                                 return -1;
412                 }
413                 total += ret;
414         }
415         return (ssize_t)total;
416 }
417
418 /****************************************************************************
419  Write data to a fd on the vfs.
420 ****************************************************************************/
421
422 ssize_t vfs_write_data(struct smb_request *req,
423                         files_struct *fsp,
424                         const char *buffer,
425                         size_t N)
426 {
427         size_t total=0;
428         ssize_t ret;
429
430         if (req && req->unread_bytes) {
431                 SMB_ASSERT(req->unread_bytes == N);
432                 /* VFS_RECVFILE must drain the socket
433                  * before returning. */
434                 req->unread_bytes = 0;
435                 return SMB_VFS_RECVFILE(req->sconn->sock,
436                                         fsp,
437                                         (off_t)-1,
438                                         N);
439         }
440
441         while (total < N) {
442                 ret = SMB_VFS_WRITE(fsp, buffer + total, N - total);
443
444                 if (ret == -1)
445                         return -1;
446                 if (ret == 0)
447                         return total;
448
449                 total += ret;
450         }
451         return (ssize_t)total;
452 }
453
454 ssize_t vfs_pwrite_data(struct smb_request *req,
455                         files_struct *fsp,
456                         const char *buffer,
457                         size_t N,
458                         off_t offset)
459 {
460         size_t total=0;
461         ssize_t ret;
462
463         if (req && req->unread_bytes) {
464                 SMB_ASSERT(req->unread_bytes == N);
465                 /* VFS_RECVFILE must drain the socket
466                  * before returning. */
467                 req->unread_bytes = 0;
468                 return SMB_VFS_RECVFILE(req->sconn->sock,
469                                         fsp,
470                                         offset,
471                                         N);
472         }
473
474         while (total < N) {
475                 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
476                                      offset + total);
477
478                 if (ret == -1)
479                         return -1;
480                 if (ret == 0)
481                         return total;
482
483                 total += ret;
484         }
485         return (ssize_t)total;
486 }
487 /****************************************************************************
488  An allocate file space call using the vfs interface.
489  Allocates space for a file from a filedescriptor.
490  Returns 0 on success, -1 on failure.
491 ****************************************************************************/
492
493 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
494 {
495         int ret;
496         connection_struct *conn = fsp->conn;
497         uint64_t space_avail;
498         uint64_t bsize,dfree,dsize;
499         NTSTATUS status;
500
501         /*
502          * Actually try and commit the space on disk....
503          */
504
505         DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
506                   fsp_str_dbg(fsp), (double)len));
507
508         if (((off_t)len) < 0) {
509                 DEBUG(0,("vfs_allocate_file_space: %s negative len "
510                          "requested.\n", fsp_str_dbg(fsp)));
511                 errno = EINVAL;
512                 return -1;
513         }
514
515         status = vfs_stat_fsp(fsp);
516         if (!NT_STATUS_IS_OK(status)) {
517                 return -1;
518         }
519
520         if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
521                 return 0;
522
523         if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
524                 /* Shrink - use ftruncate. */
525
526                 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
527                           "size %.0f\n", fsp_str_dbg(fsp),
528                           (double)fsp->fsp_name->st.st_ex_size));
529
530                 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
531
532                 flush_write_cache(fsp, SIZECHANGE_FLUSH);
533                 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
534                         set_filelen_write_cache(fsp, len);
535                 }
536
537                 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
538
539                 return ret;
540         }
541
542         if (!lp_strict_allocate(SNUM(fsp->conn)))
543                 return 0;
544
545         /* Grow - we need to test if we have enough space. */
546
547         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
548
549         /* See if we have a syscall that will allocate beyond end-of-file
550            without changing EOF. */
551         ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_KEEP_SIZE, 0, len);
552
553         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
554
555         if (ret == 0) {
556                 /* We changed the allocation size on disk, but not
557                    EOF - exactly as required. We're done ! */
558                 return 0;
559         }
560
561         len -= fsp->fsp_name->st.st_ex_size;
562         len /= 1024; /* Len is now number of 1k blocks needed. */
563         space_avail = get_dfree_info(conn, fsp->fsp_name->base_name, false,
564                                      &bsize, &dfree, &dsize);
565         if (space_avail == (uint64_t)-1) {
566                 return -1;
567         }
568
569         DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
570                   "needed blocks = %.0f, space avail = %.0f\n",
571                   fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
572                   (double)space_avail));
573
574         if (len > space_avail) {
575                 errno = ENOSPC;
576                 return -1;
577         }
578
579         return 0;
580 }
581
582 /****************************************************************************
583  A vfs set_filelen call.
584  set the length of a file from a filedescriptor.
585  Returns 0 on success, -1 on failure.
586 ****************************************************************************/
587
588 int vfs_set_filelen(files_struct *fsp, off_t len)
589 {
590         int ret;
591
592         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
593
594         DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
595                   fsp_str_dbg(fsp), (double)len));
596         flush_write_cache(fsp, SIZECHANGE_FLUSH);
597         if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
598                 set_filelen_write_cache(fsp, len);
599                 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
600                              FILE_NOTIFY_CHANGE_SIZE
601                              | FILE_NOTIFY_CHANGE_ATTRIBUTES,
602                              fsp->fsp_name->base_name);
603         }
604
605         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
606
607         return ret;
608 }
609
610 /****************************************************************************
611  A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
612  fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
613  as this is also called from the default SMB_VFS_FTRUNCATE code.
614  Always extends the file size.
615  Returns 0 on success, errno on failure.
616 ****************************************************************************/
617
618 #define SPARSE_BUF_WRITE_SIZE (32*1024)
619
620 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
621 {
622         ssize_t pwrite_ret;
623         size_t total = 0;
624
625         if (!sparse_buf) {
626                 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
627                 if (!sparse_buf) {
628                         errno = ENOMEM;
629                         return ENOMEM;
630                 }
631         }
632
633         while (total < len) {
634                 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
635
636                 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
637                 if (pwrite_ret == -1) {
638                         DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
639                                   "%s failed with error %s\n",
640                                   fsp_str_dbg(fsp), strerror(errno)));
641                         return errno;
642                 }
643                 total += pwrite_ret;
644         }
645
646         return 0;
647 }
648
649 /****************************************************************************
650  A vfs fill sparse call.
651  Writes zeros from the end of file to len, if len is greater than EOF.
652  Used only by strict_sync.
653  Returns 0 on success, -1 on failure.
654 ****************************************************************************/
655
656 int vfs_fill_sparse(files_struct *fsp, off_t len)
657 {
658         int ret;
659         NTSTATUS status;
660         off_t offset;
661         size_t num_to_write;
662
663         status = vfs_stat_fsp(fsp);
664         if (!NT_STATUS_IS_OK(status)) {
665                 return -1;
666         }
667
668         if (len <= fsp->fsp_name->st.st_ex_size) {
669                 return 0;
670         }
671
672 #ifdef S_ISFIFO
673         if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
674                 return 0;
675         }
676 #endif
677
678         DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
679                   "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
680                   (double)fsp->fsp_name->st.st_ex_size, (double)len,
681                   (double)(len - fsp->fsp_name->st.st_ex_size)));
682
683         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
684
685         flush_write_cache(fsp, SIZECHANGE_FLUSH);
686
687         offset = fsp->fsp_name->st.st_ex_size;
688         num_to_write = len - fsp->fsp_name->st.st_ex_size;
689
690         /* Only do this on non-stream file handles. */
691         if (fsp->base_fsp == NULL) {
692                 /* for allocation try fallocate first. This can fail on some
693                  * platforms e.g. when the filesystem doesn't support it and no
694                  * emulation is being done by the libc (like on AIX with JFS1). In that
695                  * case we do our own emulation. fallocate implementations can
696                  * return ENOTSUP or EINVAL in cases like that. */
697                 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_EXTEND_SIZE,
698                                 offset, num_to_write);
699                 if (ret == ENOSPC) {
700                         errno = ENOSPC;
701                         ret = -1;
702                         goto out;
703                 }
704                 if (ret == 0) {
705                         goto out;
706                 }
707                 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
708                         "error %d. Falling back to slow manual allocation\n", ret));
709         }
710
711         ret = vfs_slow_fallocate(fsp, offset, num_to_write);
712         if (ret != 0) {
713                 errno = ret;
714                 ret = -1;
715         }
716
717  out:
718
719         if (ret == 0) {
720                 set_filelen_write_cache(fsp, len);
721         }
722
723         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
724         return ret;
725 }
726
727 /****************************************************************************
728  Transfer some data (n bytes) between two file_struct's.
729 ****************************************************************************/
730
731 static ssize_t vfs_read_fn(void *file, void *buf, size_t len)
732 {
733         struct files_struct *fsp = (struct files_struct *)file;
734
735         return SMB_VFS_READ(fsp, buf, len);
736 }
737
738 static ssize_t vfs_write_fn(void *file, const void *buf, size_t len)
739 {
740         struct files_struct *fsp = (struct files_struct *)file;
741
742         return SMB_VFS_WRITE(fsp, buf, len);
743 }
744
745 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
746 {
747         return transfer_file_internal((void *)in, (void *)out, n,
748                                       vfs_read_fn, vfs_write_fn);
749 }
750
751 /*******************************************************************
752  A vfs_readdir wrapper which just returns the file name.
753 ********************************************************************/
754
755 const char *vfs_readdirname(connection_struct *conn, void *p,
756                             SMB_STRUCT_STAT *sbuf, char **talloced)
757 {
758         struct dirent *ptr= NULL;
759         const char *dname;
760         char *translated;
761         NTSTATUS status;
762
763         if (!p)
764                 return(NULL);
765
766         ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
767         if (!ptr)
768                 return(NULL);
769
770         dname = ptr->d_name;
771
772
773 #ifdef NEXT2
774         if (telldir(p) < 0)
775                 return(NULL);
776 #endif
777
778 #ifdef HAVE_BROKEN_READDIR_NAME
779         /* using /usr/ucb/cc is BAD */
780         dname = dname - 2;
781 #endif
782
783         status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
784                                         talloc_tos(), &translated);
785         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
786                 *talloced = NULL;
787                 return dname;
788         }
789         *talloced = translated;
790         if (!NT_STATUS_IS_OK(status)) {
791                 return NULL;
792         }
793         return translated;
794 }
795
796 /*******************************************************************
797  A wrapper for vfs_chdir().
798 ********************************************************************/
799
800 int vfs_ChDir(connection_struct *conn, const char *path)
801 {
802         int res;
803
804         if (!LastDir) {
805                 LastDir = SMB_STRDUP("");
806         }
807
808         if (strcsequal(path,"."))
809                 return(0);
810
811         if (*path == '/' && strcsequal(LastDir,path))
812                 return(0);
813
814         DEBUG(4,("vfs_ChDir to %s\n",path));
815
816         res = SMB_VFS_CHDIR(conn,path);
817         if (!res) {
818                 SAFE_FREE(LastDir);
819                 LastDir = SMB_STRDUP(path);
820         }
821         return(res);
822 }
823
824 /*******************************************************************
825  Return the absolute current directory path - given a UNIX pathname.
826  Note that this path is returned in DOS format, not UNIX
827  format. Note this can be called with conn == NULL.
828 ********************************************************************/
829
830 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
831 {
832         char *current_dir = NULL;
833         char *result = NULL;
834         DATA_BLOB cache_value;
835         struct file_id key;
836         struct smb_filename *smb_fname_dot = NULL;
837         struct smb_filename *smb_fname_full = NULL;
838         NTSTATUS status;
839
840         if (!lp_getwd_cache()) {
841                 goto nocache;
842         }
843
844         status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
845                                             &smb_fname_dot);
846         if (!NT_STATUS_IS_OK(status)) {
847                 errno = map_errno_from_nt_status(status);
848                 goto out;
849         }
850
851         if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
852                 /*
853                  * Known to fail for root: the directory may be NFS-mounted
854                  * and exported with root_squash (so has no root access).
855                  */
856                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
857                          "(NFS problem ?)\n", strerror(errno) ));
858                 goto nocache;
859         }
860
861         key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
862
863         if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
864                              data_blob_const(&key, sizeof(key)),
865                              &cache_value)) {
866                 goto nocache;
867         }
868
869         SMB_ASSERT((cache_value.length > 0)
870                    && (cache_value.data[cache_value.length-1] == '\0'));
871
872         status = create_synthetic_smb_fname(ctx, (char *)cache_value.data,
873                                             NULL, NULL, &smb_fname_full);
874         if (!NT_STATUS_IS_OK(status)) {
875                 errno = map_errno_from_nt_status(status);
876                 goto out;
877         }
878
879         if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
880             (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
881             (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
882             (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
883                 /*
884                  * Ok, we're done
885                  */
886                 result = talloc_strdup(ctx, smb_fname_full->base_name);
887                 if (result == NULL) {
888                         errno = ENOMEM;
889                 }
890                 goto out;
891         }
892
893  nocache:
894
895         /*
896          * We don't have the information to hand so rely on traditional
897          * methods. The very slow getcwd, which spawns a process on some
898          * systems, or the not quite so bad getwd.
899          */
900
901         current_dir = SMB_VFS_GETWD(conn);
902         if (current_dir == NULL) {
903                 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
904                           strerror(errno)));
905                 goto out;
906         }
907
908         if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
909                 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
910
911                 memcache_add(smbd_memcache(), GETWD_CACHE,
912                              data_blob_const(&key, sizeof(key)),
913                              data_blob_const(current_dir,
914                                                 strlen(current_dir)+1));
915         }
916
917         result = talloc_strdup(ctx, current_dir);
918         if (result == NULL) {
919                 errno = ENOMEM;
920         }
921
922  out:
923         TALLOC_FREE(smb_fname_dot);
924         TALLOC_FREE(smb_fname_full);
925         SAFE_FREE(current_dir);
926         return result;
927 }
928
929 /*******************************************************************
930  Reduce a file name, removing .. elements and checking that
931  it is below dir in the heirachy. This uses realpath.
932  This function must run as root, and will return names
933  and valid stat structs that can be checked on open.
934 ********************************************************************/
935
936 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
937                         const char *fname,
938                         struct smb_request *smbreq)
939 {
940         NTSTATUS status;
941         TALLOC_CTX *ctx = talloc_tos();
942         const char *conn_rootdir;
943         size_t rootdir_len;
944         char *dir_name = NULL;
945         const char *last_component = NULL;
946         char *resolved_name = NULL;
947         char *saved_dir = NULL;
948         struct smb_filename *smb_fname_cwd = NULL;
949         struct privilege_paths *priv_paths = NULL;
950         int ret;
951
952         DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
953                         fname,
954                         conn->connectpath));
955
956
957         priv_paths = talloc_zero(smbreq, struct privilege_paths);
958         if (!priv_paths) {
959                 status = NT_STATUS_NO_MEMORY;
960                 goto err;
961         }
962
963         if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
964                 status = NT_STATUS_NO_MEMORY;
965                 goto err;
966         }
967
968         priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
969         priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
970
971         if (priv_paths->parent_name.base_name == NULL ||
972                         priv_paths->file_name.base_name == NULL) {
973                 status = NT_STATUS_NO_MEMORY;
974                 goto err;
975         }
976
977         if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
978                 status = map_nt_error_from_unix(errno);
979                 goto err;
980         }
981         /* Remember where we were. */
982         saved_dir = vfs_GetWd(ctx, conn);
983         if (!saved_dir) {
984                 status = map_nt_error_from_unix(errno);
985                 goto err;
986         }
987
988         /* Go to the parent directory to lock in memory. */
989         if (vfs_ChDir(conn, priv_paths->parent_name.base_name) == -1) {
990                 status = map_nt_error_from_unix(errno);
991                 goto err;
992         }
993
994         /* Get the absolute path of the parent directory. */
995         resolved_name = SMB_VFS_REALPATH(conn,".");
996         if (!resolved_name) {
997                 status = map_nt_error_from_unix(errno);
998                 goto err;
999         }
1000
1001         if (*resolved_name != '/') {
1002                 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1003                         "doesn't return absolute paths !\n"));
1004                 status = NT_STATUS_OBJECT_NAME_INVALID;
1005                 goto err;
1006         }
1007
1008         DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1009                 priv_paths->parent_name.base_name,
1010                 resolved_name));
1011
1012         /* Now check the stat value is the same. */
1013         status = create_synthetic_smb_fname(talloc_tos(), ".",
1014                                         NULL, NULL,
1015                                         &smb_fname_cwd);
1016         if (!NT_STATUS_IS_OK(status)) {
1017                 goto err;
1018         }
1019
1020         if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1021                 status = map_nt_error_from_unix(errno);
1022                 goto err;
1023         }
1024
1025         /* Ensure we're pointing at the same place. */
1026         if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1027                 DEBUG(0,("check_reduced_name_with_privilege: "
1028                         "device/inode/uid/gid on directory %s changed. "
1029                         "Denying access !\n",
1030                         priv_paths->parent_name.base_name));
1031                 status = NT_STATUS_ACCESS_DENIED;
1032                 goto err;
1033         }
1034
1035         /* Ensure we're below the connect path. */
1036
1037         conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1038         if (conn_rootdir == NULL) {
1039                 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1040                         "conn_rootdir\n"));
1041                 status = NT_STATUS_ACCESS_DENIED;
1042                 goto err;
1043         }
1044
1045         rootdir_len = strlen(conn_rootdir);
1046         if (strncmp(conn_rootdir, resolved_name, rootdir_len) != 0) {
1047                 DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
1048                         "attempt: %s is a symlink outside the "
1049                         "share path\n",
1050                         dir_name));
1051                 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1052                 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1053                 status = NT_STATUS_ACCESS_DENIED;
1054                 goto err;
1055         }
1056
1057         /* Now ensure that the last component either doesn't
1058            exist, or is *NOT* a symlink. */
1059
1060         ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1061         if (ret == -1) {
1062                 /* Errno must be ENOENT for this be ok. */
1063                 if (errno != ENOENT) {
1064                         status = map_nt_error_from_unix(errno);
1065                         DEBUG(2, ("check_reduced_name_with_privilege: "
1066                                 "LSTAT on %s failed with %s\n",
1067                                 priv_paths->file_name.base_name,
1068                                 nt_errstr(status)));
1069                         goto err;
1070                 }
1071         }
1072
1073         if (VALID_STAT(priv_paths->file_name.st) &&
1074                         S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1075                 DEBUG(2, ("check_reduced_name_with_privilege: "
1076                         "Last component %s is a symlink. Denying"
1077                         "access.\n",
1078                         priv_paths->file_name.base_name));
1079                 status = NT_STATUS_ACCESS_DENIED;
1080                 goto err;
1081         }
1082
1083         smbreq->priv_paths = priv_paths;
1084         status = NT_STATUS_OK;
1085
1086   err:
1087
1088         if (saved_dir) {
1089                 vfs_ChDir(conn, saved_dir);
1090         }
1091         SAFE_FREE(resolved_name);
1092         if (!NT_STATUS_IS_OK(status)) {
1093                 TALLOC_FREE(priv_paths);
1094         }
1095         TALLOC_FREE(dir_name);
1096         return status;
1097 }
1098
1099 /*******************************************************************
1100  Reduce a file name, removing .. elements and checking that
1101  it is below dir in the heirachy. This uses realpath.
1102 ********************************************************************/
1103
1104 NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
1105 {
1106         char *resolved_name = NULL;
1107         bool allow_symlinks = true;
1108         bool allow_widelinks = false;
1109
1110         DEBUG(3,("check_reduced_name [%s] [%s]\n", fname, conn->connectpath));
1111
1112         resolved_name = SMB_VFS_REALPATH(conn,fname);
1113
1114         if (!resolved_name) {
1115                 switch (errno) {
1116                         case ENOTDIR:
1117                                 DEBUG(3,("check_reduced_name: Component not a "
1118                                          "directory in getting realpath for "
1119                                          "%s\n", fname));
1120                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1121                         case ENOENT:
1122                         {
1123                                 TALLOC_CTX *ctx = talloc_tos();
1124                                 char *dir_name = NULL;
1125                                 const char *last_component = NULL;
1126                                 char *new_name = NULL;
1127                                 int ret;
1128
1129                                 /* Last component didn't exist.
1130                                    Remove it and try and canonicalise
1131                                    the directory name. */
1132                                 if (!parent_dirname(ctx, fname,
1133                                                 &dir_name,
1134                                                 &last_component)) {
1135                                         return NT_STATUS_NO_MEMORY;
1136                                 }
1137
1138                                 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1139                                 if (!resolved_name) {
1140                                         NTSTATUS status = map_nt_error_from_unix(errno);
1141
1142                                         if (errno == ENOENT || errno == ENOTDIR) {
1143                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1144                                         }
1145
1146                                         DEBUG(3,("check_reduce_name: "
1147                                                  "couldn't get realpath for "
1148                                                  "%s (%s)\n",
1149                                                 fname,
1150                                                 nt_errstr(status)));
1151                                         return status;
1152                                 }
1153                                 ret = asprintf(&new_name, "%s/%s",
1154                                                resolved_name, last_component);
1155                                 SAFE_FREE(resolved_name);
1156                                 if (ret == -1) {
1157                                         return NT_STATUS_NO_MEMORY;
1158                                 }
1159                                 resolved_name = new_name;
1160                                 break;
1161                         }
1162                         default:
1163                                 DEBUG(3,("check_reduced_name: couldn't get "
1164                                          "realpath for %s\n", fname));
1165                                 return map_nt_error_from_unix(errno);
1166                 }
1167         }
1168
1169         DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1170                   resolved_name));
1171
1172         if (*resolved_name != '/') {
1173                 DEBUG(0,("check_reduced_name: realpath doesn't return "
1174                          "absolute paths !\n"));
1175                 SAFE_FREE(resolved_name);
1176                 return NT_STATUS_OBJECT_NAME_INVALID;
1177         }
1178
1179         allow_widelinks = lp_widelinks(SNUM(conn));
1180         allow_symlinks = lp_symlinks(SNUM(conn));
1181
1182         /* Common widelinks and symlinks checks. */
1183         if (!allow_widelinks || !allow_symlinks) {
1184                 const char *conn_rootdir;
1185                 size_t rootdir_len;
1186
1187                 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1188                 if (conn_rootdir == NULL) {
1189                         DEBUG(2, ("check_reduced_name: Could not get "
1190                                 "conn_rootdir\n"));
1191                         SAFE_FREE(resolved_name);
1192                         return NT_STATUS_ACCESS_DENIED;
1193                 }
1194
1195                 rootdir_len = strlen(conn_rootdir);
1196                 if (strncmp(conn_rootdir, resolved_name,
1197                                 rootdir_len) != 0) {
1198                         DEBUG(2, ("check_reduced_name: Bad access "
1199                                 "attempt: %s is a symlink outside the "
1200                                 "share path\n", fname));
1201                         DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1202                         DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1203                         SAFE_FREE(resolved_name);
1204                         return NT_STATUS_ACCESS_DENIED;
1205                 }
1206
1207                 /* Extra checks if all symlinks are disallowed. */
1208                 if (!allow_symlinks) {
1209                         /* fname can't have changed in resolved_path. */
1210                         const char *p = &resolved_name[rootdir_len];
1211
1212                         /* *p can be '\0' if fname was "." */
1213                         if (*p == '\0' && ISDOT(fname)) {
1214                                 goto out;
1215                         }
1216
1217                         if (*p != '/') {
1218                                 DEBUG(2, ("check_reduced_name: logic error (%c) "
1219                                         "in resolved_name: %s\n",
1220                                         *p,
1221                                         fname));
1222                                 SAFE_FREE(resolved_name);
1223                                 return NT_STATUS_ACCESS_DENIED;
1224                         }
1225
1226                         p++;
1227                         if (strcmp(fname, p)!=0) {
1228                                 DEBUG(2, ("check_reduced_name: Bad access "
1229                                         "attempt: %s is a symlink to %s\n",
1230                                           fname, p));
1231                                 SAFE_FREE(resolved_name);
1232                                 return NT_STATUS_ACCESS_DENIED;
1233                         }
1234                 }
1235         }
1236
1237   out:
1238
1239         DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
1240                  resolved_name));
1241         SAFE_FREE(resolved_name);
1242         return NT_STATUS_OK;
1243 }
1244
1245 /**
1246  * XXX: This is temporary and there should be no callers of this once
1247  * smb_filename is plumbed through all path based operations.
1248  */
1249 int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
1250                        SMB_STRUCT_STAT *psbuf)
1251 {
1252         struct smb_filename *smb_fname = NULL;
1253         NTSTATUS status;
1254         int ret;
1255
1256         status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
1257                                                   &smb_fname);
1258         if (!NT_STATUS_IS_OK(status)) {
1259                 errno = map_errno_from_nt_status(status);
1260                 return -1;
1261         }
1262
1263         if (lp_posix_pathnames()) {
1264                 ret = SMB_VFS_LSTAT(conn, smb_fname);
1265         } else {
1266                 ret = SMB_VFS_STAT(conn, smb_fname);
1267         }
1268
1269         if (ret != -1) {
1270                 *psbuf = smb_fname->st;
1271         }
1272
1273         TALLOC_FREE(smb_fname);
1274         return ret;
1275 }
1276
1277 /**
1278  * XXX: This is temporary and there should be no callers of this once
1279  * smb_filename is plumbed through all path based operations.
1280  */
1281 int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
1282                         SMB_STRUCT_STAT *psbuf)
1283 {
1284         struct smb_filename *smb_fname = NULL;
1285         NTSTATUS status;
1286         int ret;
1287
1288         status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
1289                                                   &smb_fname);
1290         if (!NT_STATUS_IS_OK(status)) {
1291                 errno = map_errno_from_nt_status(status);
1292                 return -1;
1293         }
1294
1295         ret = SMB_VFS_LSTAT(conn, smb_fname);
1296         if (ret != -1) {
1297                 *psbuf = smb_fname->st;
1298         }
1299
1300         TALLOC_FREE(smb_fname);
1301         return ret;
1302 }
1303
1304 /**
1305  * Ensure LSTAT is called for POSIX paths.
1306  */
1307
1308 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1309 {
1310         int ret;
1311
1312         if(fsp->fh->fd == -1) {
1313                 if (fsp->posix_open) {
1314                         ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1315                 } else {
1316                         ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1317                 }
1318                 if (ret == -1) {
1319                         return map_nt_error_from_unix(errno);
1320                 }
1321         } else {
1322                 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1323                         return map_nt_error_from_unix(errno);
1324                 }
1325         }
1326         return NT_STATUS_OK;
1327 }
1328
1329 /**
1330  * Initialize num_streams and streams, then call VFS op streaminfo
1331  */
1332 NTSTATUS vfs_streaminfo(connection_struct *conn,
1333                         struct files_struct *fsp,
1334                         const char *fname,
1335                         TALLOC_CTX *mem_ctx,
1336                         unsigned int *num_streams,
1337                         struct stream_struct **streams)
1338 {
1339         *num_streams = 0;
1340         *streams = NULL;
1341         return SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams);
1342 }
1343
1344 /*
1345   generate a file_id from a stat structure
1346  */
1347 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1348 {
1349         return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1350 }
1351
1352 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1353                          const char *service, const char *user)
1354 {
1355         VFS_FIND(connect);
1356         return handle->fns->connect_fn(handle, service, user);
1357 }
1358
1359 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1360 {
1361         VFS_FIND(disconnect);
1362         handle->fns->disconnect_fn(handle);
1363 }
1364
1365 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1366                                 const char *path, bool small_query,
1367                                 uint64_t *bsize, uint64_t *dfree,
1368                                 uint64_t *dsize)
1369 {
1370         VFS_FIND(disk_free);
1371         return handle->fns->disk_free_fn(handle, path, small_query, bsize, 
1372                                          dfree, dsize);
1373 }
1374
1375 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1376                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1377                            SMB_DISK_QUOTA *qt)
1378 {
1379         VFS_FIND(get_quota);
1380         return handle->fns->get_quota_fn(handle, qtype, id, qt);
1381 }
1382
1383 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1384                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1385                            SMB_DISK_QUOTA *qt)
1386 {
1387         VFS_FIND(set_quota);
1388         return handle->fns->set_quota_fn(handle, qtype, id, qt);
1389 }
1390
1391 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1392                                       struct files_struct *fsp,
1393                                       struct shadow_copy_data *shadow_copy_data,
1394                                       bool labels)
1395 {
1396         VFS_FIND(get_shadow_copy_data);
1397         return handle->fns->get_shadow_copy_data_fn(handle, fsp, 
1398                                                     shadow_copy_data,
1399                                                     labels);
1400 }
1401 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
1402                          struct vfs_statvfs_struct *statbuf)
1403 {
1404         VFS_FIND(statvfs);
1405         return handle->fns->statvfs_fn(handle, path, statbuf);
1406 }
1407
1408 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1409                         enum timestamp_set_resolution *p_ts_res)
1410 {
1411         VFS_FIND(fs_capabilities);
1412         return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1413 }
1414
1415 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1416                                         struct dfs_GetDFSReferral *r)
1417 {
1418         VFS_FIND(get_dfs_referrals);
1419         return handle->fns->get_dfs_referrals_fn(handle, r);
1420 }
1421
1422 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1423                                      const char *fname, const char *mask,
1424                                      uint32 attributes)
1425 {
1426         VFS_FIND(opendir);
1427         return handle->fns->opendir_fn(handle, fname, mask, attributes);
1428 }
1429
1430 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1431                                         struct files_struct *fsp,
1432                                         const char *mask,
1433                                         uint32 attributes)
1434 {
1435         VFS_FIND(fdopendir);
1436         return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1437 }
1438
1439 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1440                                               DIR *dirp,
1441                                               SMB_STRUCT_STAT *sbuf)
1442 {
1443         VFS_FIND(readdir);
1444         return handle->fns->readdir_fn(handle, dirp, sbuf);
1445 }
1446
1447 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1448                           DIR *dirp, long offset)
1449 {
1450         VFS_FIND(seekdir);
1451         handle->fns->seekdir_fn(handle, dirp, offset);
1452 }
1453
1454 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1455                           DIR *dirp)
1456 {
1457         VFS_FIND(telldir);
1458         return handle->fns->telldir_fn(handle, dirp);
1459 }
1460
1461 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1462                              DIR *dirp)
1463 {
1464         VFS_FIND(rewind_dir);
1465         handle->fns->rewind_dir_fn(handle, dirp);
1466 }
1467
1468 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, const char *path,
1469                        mode_t mode)
1470 {
1471         VFS_FIND(mkdir);
1472         return handle->fns->mkdir_fn(handle, path, mode);
1473 }
1474
1475 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, const char *path)
1476 {
1477         VFS_FIND(rmdir);
1478         return handle->fns->rmdir_fn(handle, path);
1479 }
1480
1481 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1482                           DIR *dir)
1483 {
1484         VFS_FIND(closedir);
1485         return handle->fns->closedir_fn(handle, dir);
1486 }
1487
1488 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1489                                  DIR *dirp)
1490 {
1491         VFS_FIND(init_search_op);
1492         handle->fns->init_search_op_fn(handle, dirp);
1493 }
1494
1495 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1496                       struct smb_filename *smb_fname, struct files_struct *fsp,
1497                       int flags, mode_t mode)
1498 {
1499         VFS_FIND(open);
1500         return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1501 }
1502
1503 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1504                                   struct smb_request *req,
1505                                   uint16_t root_dir_fid,
1506                                   struct smb_filename *smb_fname,
1507                                   uint32_t access_mask,
1508                                   uint32_t share_access,
1509                                   uint32_t create_disposition,
1510                                   uint32_t create_options,
1511                                   uint32_t file_attributes,
1512                                   uint32_t oplock_request,
1513                                   uint64_t allocation_size,
1514                                   uint32_t private_flags,
1515                                   struct security_descriptor *sd,
1516                                   struct ea_list *ea_list,
1517                                   files_struct **result,
1518                                   int *pinfo)
1519 {
1520         VFS_FIND(create_file);
1521         return handle->fns->create_file_fn(
1522                 handle, req, root_dir_fid, smb_fname, access_mask,
1523                 share_access, create_disposition, create_options,
1524                 file_attributes, oplock_request, allocation_size,
1525                 private_flags, sd, ea_list,
1526                 result, pinfo);
1527 }
1528
1529 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1530                        struct files_struct *fsp)
1531 {
1532         VFS_FIND(close);
1533         return handle->fns->close_fn(handle, fsp);
1534 }
1535
1536 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1537                           struct files_struct *fsp, void *data, size_t n)
1538 {
1539         VFS_FIND(read);
1540         return handle->fns->read_fn(handle, fsp, data, n);
1541 }
1542
1543 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1544                            struct files_struct *fsp, void *data, size_t n,
1545                            off_t offset)
1546 {
1547         VFS_FIND(pread);
1548         return handle->fns->pread_fn(handle, fsp, data, n, offset);
1549 }
1550
1551 struct smb_vfs_call_pread_state {
1552         ssize_t (*recv_fn)(struct tevent_req *req, int *err);
1553         ssize_t retval;
1554 };
1555
1556 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1557
1558 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1559                                            TALLOC_CTX *mem_ctx,
1560                                            struct tevent_context *ev,
1561                                            struct files_struct *fsp,
1562                                            void *data,
1563                                            size_t n, off_t offset)
1564 {
1565         struct tevent_req *req, *subreq;
1566         struct smb_vfs_call_pread_state *state;
1567
1568         req = tevent_req_create(mem_ctx, &state,
1569                                 struct smb_vfs_call_pread_state);
1570         if (req == NULL) {
1571                 return NULL;
1572         }
1573         VFS_FIND(pread_send);
1574         state->recv_fn = handle->fns->pread_recv_fn;
1575
1576         subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1577                                             offset);
1578         if (tevent_req_nomem(subreq, req)) {
1579                 return tevent_req_post(req, ev);
1580         }
1581         tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1582         return req;
1583 }
1584
1585 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1586 {
1587         struct tevent_req *req = tevent_req_callback_data(
1588                 subreq, struct tevent_req);
1589         struct smb_vfs_call_pread_state *state = tevent_req_data(
1590                 req, struct smb_vfs_call_pread_state);
1591         int err;
1592
1593         state->retval = state->recv_fn(subreq, &err);
1594         TALLOC_FREE(subreq);
1595         if (state->retval == -1) {
1596                 tevent_req_error(req, err);
1597                 return;
1598         }
1599         tevent_req_done(req);
1600 }
1601
1602 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno)
1603 {
1604         struct smb_vfs_call_pread_state *state = tevent_req_data(
1605                 req, struct smb_vfs_call_pread_state);
1606         int err;
1607
1608         if (tevent_req_is_unix_error(req, &err)) {
1609                 *perrno = err;
1610                 return -1;
1611         }
1612         return state->retval;
1613 }
1614
1615 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1616                            struct files_struct *fsp, const void *data,
1617                            size_t n)
1618 {
1619         VFS_FIND(write);
1620         return handle->fns->write_fn(handle, fsp, data, n);
1621 }
1622
1623 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1624                             struct files_struct *fsp, const void *data,
1625                             size_t n, off_t offset)
1626 {
1627         VFS_FIND(pwrite);
1628         return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1629 }
1630
1631 struct smb_vfs_call_pwrite_state {
1632         ssize_t (*recv_fn)(struct tevent_req *req, int *err);
1633         ssize_t retval;
1634 };
1635
1636 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1637
1638 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1639                                             TALLOC_CTX *mem_ctx,
1640                                             struct tevent_context *ev,
1641                                             struct files_struct *fsp,
1642                                             const void *data,
1643                                             size_t n, off_t offset)
1644 {
1645         struct tevent_req *req, *subreq;
1646         struct smb_vfs_call_pwrite_state *state;
1647
1648         req = tevent_req_create(mem_ctx, &state,
1649                                 struct smb_vfs_call_pwrite_state);
1650         if (req == NULL) {
1651                 return NULL;
1652         }
1653         VFS_FIND(pwrite_send);
1654         state->recv_fn = handle->fns->pwrite_recv_fn;
1655
1656         subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1657                                              offset);
1658         if (tevent_req_nomem(subreq, req)) {
1659                 return tevent_req_post(req, ev);
1660         }
1661         tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1662         return req;
1663 }
1664
1665 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1666 {
1667         struct tevent_req *req = tevent_req_callback_data(
1668                 subreq, struct tevent_req);
1669         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1670                 req, struct smb_vfs_call_pwrite_state);
1671         int err;
1672
1673         state->retval = state->recv_fn(subreq, &err);
1674         TALLOC_FREE(subreq);
1675         if (state->retval == -1) {
1676                 tevent_req_error(req, err);
1677                 return;
1678         }
1679         tevent_req_done(req);
1680 }
1681
1682 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, int *perrno)
1683 {
1684         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1685                 req, struct smb_vfs_call_pwrite_state);
1686         int err;
1687
1688         if (tevent_req_is_unix_error(req, &err)) {
1689                 *perrno = err;
1690                 return -1;
1691         }
1692         return state->retval;
1693 }
1694
1695 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1696                              struct files_struct *fsp, off_t offset,
1697                              int whence)
1698 {
1699         VFS_FIND(lseek);
1700         return handle->fns->lseek_fn(handle, fsp, offset, whence);
1701 }
1702
1703 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1704                               files_struct *fromfsp, const DATA_BLOB *header,
1705                               off_t offset, size_t count)
1706 {
1707         VFS_FIND(sendfile);
1708         return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1709                                         count);
1710 }
1711
1712 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1713                               files_struct *tofsp, off_t offset,
1714                               size_t count)
1715 {
1716         VFS_FIND(recvfile);
1717         return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1718 }
1719
1720 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1721                         const struct smb_filename *smb_fname_src,
1722                         const struct smb_filename *smb_fname_dst)
1723 {
1724         VFS_FIND(rename);
1725         return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1726 }
1727
1728 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1729                        struct files_struct *fsp)
1730 {
1731         VFS_FIND(fsync);
1732         return handle->fns->fsync_fn(handle, fsp);
1733 }
1734
1735 struct smb_vfs_call_fsync_state {
1736         int (*recv_fn)(struct tevent_req *req, int *err);
1737         int retval;
1738 };
1739
1740 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1741
1742 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1743                                            TALLOC_CTX *mem_ctx,
1744                                            struct tevent_context *ev,
1745                                            struct files_struct *fsp)
1746 {
1747         struct tevent_req *req, *subreq;
1748         struct smb_vfs_call_fsync_state *state;
1749
1750         req = tevent_req_create(mem_ctx, &state,
1751                                 struct smb_vfs_call_fsync_state);
1752         if (req == NULL) {
1753                 return NULL;
1754         }
1755         VFS_FIND(fsync_send);
1756         state->recv_fn = handle->fns->fsync_recv_fn;
1757
1758         subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1759         if (tevent_req_nomem(subreq, req)) {
1760                 return tevent_req_post(req, ev);
1761         }
1762         tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1763         return req;
1764 }
1765
1766 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1767 {
1768         struct tevent_req *req = tevent_req_callback_data(
1769                 subreq, struct tevent_req);
1770         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1771                 req, struct smb_vfs_call_fsync_state);
1772         int err;
1773
1774         state->retval = state->recv_fn(subreq, &err);
1775         TALLOC_FREE(subreq);
1776         if (state->retval == -1) {
1777                 tevent_req_error(req, err);
1778                 return;
1779         }
1780         tevent_req_done(req);
1781 }
1782
1783 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, int *perrno)
1784 {
1785         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1786                 req, struct smb_vfs_call_fsync_state);
1787         int err;
1788
1789         if (tevent_req_is_unix_error(req, &err)) {
1790                 *perrno = err;
1791                 return -1;
1792         }
1793         return state->retval;
1794 }
1795
1796
1797 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1798                       struct smb_filename *smb_fname)
1799 {
1800         VFS_FIND(stat);
1801         return handle->fns->stat_fn(handle, smb_fname);
1802 }
1803
1804 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1805                        struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1806 {
1807         VFS_FIND(fstat);
1808         return handle->fns->fstat_fn(handle, fsp, sbuf);
1809 }
1810
1811 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1812                        struct smb_filename *smb_filename)
1813 {
1814         VFS_FIND(lstat);
1815         return handle->fns->lstat_fn(handle, smb_filename);
1816 }
1817
1818 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1819                                      struct files_struct *fsp,
1820                                      const SMB_STRUCT_STAT *sbuf)
1821 {
1822         VFS_FIND(get_alloc_size);
1823         return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1824 }
1825
1826 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1827                         const struct smb_filename *smb_fname)
1828 {
1829         VFS_FIND(unlink);
1830         return handle->fns->unlink_fn(handle, smb_fname);
1831 }
1832
1833 int smb_vfs_call_chmod(struct vfs_handle_struct *handle, const char *path,
1834                        mode_t mode)
1835 {
1836         VFS_FIND(chmod);
1837         return handle->fns->chmod_fn(handle, path, mode);
1838 }
1839
1840 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1841                         struct files_struct *fsp, mode_t mode)
1842 {
1843         VFS_FIND(fchmod);
1844         return handle->fns->fchmod_fn(handle, fsp, mode);
1845 }
1846
1847 int smb_vfs_call_chown(struct vfs_handle_struct *handle, const char *path,
1848                        uid_t uid, gid_t gid)
1849 {
1850         VFS_FIND(chown);
1851         return handle->fns->chown_fn(handle, path, uid, gid);
1852 }
1853
1854 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1855                         struct files_struct *fsp, uid_t uid, gid_t gid)
1856 {
1857         VFS_FIND(fchown);
1858         return handle->fns->fchown_fn(handle, fsp, uid, gid);
1859 }
1860
1861 int smb_vfs_call_lchown(struct vfs_handle_struct *handle, const char *path,
1862                         uid_t uid, gid_t gid)
1863 {
1864         VFS_FIND(lchown);
1865         return handle->fns->lchown_fn(handle, path, uid, gid);
1866 }
1867
1868 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
1869 {
1870         int ret;
1871         bool as_root = false;
1872         const char *path;
1873         char *saved_dir = NULL;
1874         char *parent_dir = NULL;
1875         NTSTATUS status;
1876
1877         if (fsp->fh->fd != -1) {
1878                 /* Try fchown. */
1879                 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
1880                 if (ret == 0) {
1881                         return NT_STATUS_OK;
1882                 }
1883                 if (ret == -1 && errno != ENOSYS) {
1884                         return map_nt_error_from_unix(errno);
1885                 }
1886         }
1887
1888         as_root = (geteuid() == 0);
1889
1890         if (as_root) {
1891                 /*
1892                  * We are being asked to chown as root. Make
1893                  * sure we chdir() into the path to pin it,
1894                  * and always act using lchown to ensure we
1895                  * don't deref any symbolic links.
1896                  */
1897                 const char *final_component = NULL;
1898                 struct smb_filename local_fname;
1899
1900                 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
1901                 if (!saved_dir) {
1902                         status = map_nt_error_from_unix(errno);
1903                         DEBUG(0,("vfs_chown_fsp: failed to get "
1904                                 "current working directory. Error was %s\n",
1905                                 strerror(errno)));
1906                         return status;
1907                 }
1908
1909                 if (!parent_dirname(talloc_tos(),
1910                                 fsp->fsp_name->base_name,
1911                                 &parent_dir,
1912                                 &final_component)) {
1913                         return NT_STATUS_NO_MEMORY;
1914                 }
1915
1916                 /* cd into the parent dir to pin it. */
1917                 ret = vfs_ChDir(fsp->conn, parent_dir);
1918                 if (ret == -1) {
1919                         return map_nt_error_from_unix(errno);
1920                 }
1921
1922                 ZERO_STRUCT(local_fname);
1923                 local_fname.base_name = discard_const_p(char, final_component);
1924
1925                 /* Must use lstat here. */
1926                 ret = SMB_VFS_LSTAT(fsp->conn, &local_fname);
1927                 if (ret == -1) {
1928                         status = map_nt_error_from_unix(errno);
1929                         goto out;
1930                 }
1931
1932                 /* Ensure it matches the fsp stat. */
1933                 if (!check_same_stat(&local_fname.st, &fsp->fsp_name->st)) {
1934                         status = NT_STATUS_ACCESS_DENIED;
1935                         goto out;
1936                 }
1937                 path = final_component;
1938         } else {
1939                 path = fsp->fsp_name->base_name;
1940         }
1941
1942         if (fsp->posix_open || as_root) {
1943                 ret = SMB_VFS_LCHOWN(fsp->conn,
1944                         path,
1945                         uid, gid);
1946         } else {
1947                 ret = SMB_VFS_CHOWN(fsp->conn,
1948                         path,
1949                         uid, gid);
1950         }
1951
1952         if (ret == 0) {
1953                 status = NT_STATUS_OK;
1954         } else {
1955                 status = map_nt_error_from_unix(errno);
1956         }
1957
1958   out:
1959
1960         if (as_root) {
1961                 vfs_ChDir(fsp->conn,saved_dir);
1962                 TALLOC_FREE(saved_dir);
1963                 TALLOC_FREE(parent_dir);
1964         }
1965         return status;
1966 }
1967
1968 int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
1969 {
1970         VFS_FIND(chdir);
1971         return handle->fns->chdir_fn(handle, path);
1972 }
1973
1974 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
1975 {
1976         VFS_FIND(getwd);
1977         return handle->fns->getwd_fn(handle);
1978 }
1979
1980 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
1981                         const struct smb_filename *smb_fname,
1982                         struct smb_file_time *ft)
1983 {
1984         VFS_FIND(ntimes);
1985         return handle->fns->ntimes_fn(handle, smb_fname, ft);
1986 }
1987
1988 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
1989                            struct files_struct *fsp, off_t offset)
1990 {
1991         VFS_FIND(ftruncate);
1992         return handle->fns->ftruncate_fn(handle, fsp, offset);
1993 }
1994
1995 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
1996                                 struct files_struct *fsp,
1997                                 enum vfs_fallocate_mode mode,
1998                                 off_t offset,
1999                                 off_t len)
2000 {
2001         VFS_FIND(fallocate);
2002         return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2003 }
2004
2005 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2006                               struct files_struct *fsp, uint32 share_mode,
2007                               uint32_t access_mask)
2008 {
2009         VFS_FIND(kernel_flock);
2010         return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2011                                          access_mask);
2012 }
2013
2014 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2015                                 struct files_struct *fsp, int leasetype)
2016 {
2017         VFS_FIND(linux_setlease);
2018         return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2019 }
2020
2021 int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
2022                          const char *newpath)
2023 {
2024         VFS_FIND(symlink);
2025         return handle->fns->symlink_fn(handle, oldpath, newpath);
2026 }
2027
2028 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2029                               const char *path, char *buf, size_t bufsiz)
2030 {
2031         VFS_FIND(readlink);
2032         return handle->fns->readlink_fn(handle, path, buf, bufsiz);
2033 }
2034
2035 int smb_vfs_call_link(struct vfs_handle_struct *handle, const char *oldpath,
2036                       const char *newpath)
2037 {
2038         VFS_FIND(link);
2039         return handle->fns->link_fn(handle, oldpath, newpath);
2040 }
2041
2042 int smb_vfs_call_mknod(struct vfs_handle_struct *handle, const char *path,
2043                        mode_t mode, SMB_DEV_T dev)
2044 {
2045         VFS_FIND(mknod);
2046         return handle->fns->mknod_fn(handle, path, mode, dev);
2047 }
2048
2049 char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
2050 {
2051         VFS_FIND(realpath);
2052         return handle->fns->realpath_fn(handle, path);
2053 }
2054
2055 NTSTATUS smb_vfs_call_notify_watch(struct vfs_handle_struct *handle,
2056                                    struct sys_notify_context *ctx,
2057                                    const char *path,
2058                                    uint32_t *filter,
2059                                    uint32_t *subdir_filter,
2060                                    void (*callback)(struct sys_notify_context *ctx,
2061                                                     void *private_data,
2062                                                     struct notify_event *ev),
2063                                    void *private_data, void *handle_p)
2064 {
2065         VFS_FIND(notify_watch);
2066         return handle->fns->notify_watch_fn(handle, ctx, path,
2067                                             filter, subdir_filter, callback,
2068                                             private_data, handle_p);
2069 }
2070
2071 int smb_vfs_call_chflags(struct vfs_handle_struct *handle, const char *path,
2072                          unsigned int flags)
2073 {
2074         VFS_FIND(chflags);
2075         return handle->fns->chflags_fn(handle, path, flags);
2076 }
2077
2078 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2079                                            const SMB_STRUCT_STAT *sbuf)
2080 {
2081         VFS_FIND(file_id_create);
2082         return handle->fns->file_id_create_fn(handle, sbuf);
2083 }
2084
2085 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2086                                  struct files_struct *fsp,
2087                                  const char *fname,
2088                                  TALLOC_CTX *mem_ctx,
2089                                  unsigned int *num_streams,
2090                                  struct stream_struct **streams)
2091 {
2092         VFS_FIND(streaminfo);
2093         return handle->fns->streaminfo_fn(handle, fsp, fname, mem_ctx,
2094                                           num_streams, streams);
2095 }
2096
2097 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2098                                    const char *path, const char *name,
2099                                    TALLOC_CTX *mem_ctx, char **found_name)
2100 {
2101         VFS_FIND(get_real_filename);
2102         return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2103                                                  found_name);
2104 }
2105
2106 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2107                                      const char *filename)
2108 {
2109         VFS_FIND(connectpath);
2110         return handle->fns->connectpath_fn(handle, filename);
2111 }
2112
2113 bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
2114                               struct files_struct *fsp,
2115                               struct lock_struct *plock)
2116 {
2117         VFS_FIND(strict_lock);
2118         return handle->fns->strict_lock_fn(handle, fsp, plock);
2119 }
2120
2121 void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
2122                                 struct files_struct *fsp,
2123                                 struct lock_struct *plock)
2124 {
2125         VFS_FIND(strict_unlock);
2126         handle->fns->strict_unlock_fn(handle, fsp, plock);
2127 }
2128
2129 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2130                                      const char *name,
2131                                      enum vfs_translate_direction direction,
2132                                      TALLOC_CTX *mem_ctx,
2133                                      char **mapped_name)
2134 {
2135         VFS_FIND(translate_name);
2136         return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2137                                               mapped_name);
2138 }
2139
2140 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2141                             struct files_struct *fsp,
2142                             TALLOC_CTX *ctx,
2143                             uint32_t function,
2144                             uint16_t req_flags,
2145                             const uint8_t *in_data,
2146                             uint32_t in_len,
2147                             uint8_t **out_data,
2148                             uint32_t max_out_len,
2149                             uint32_t *out_len)
2150 {
2151         VFS_FIND(fsctl);
2152         return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags, 
2153                                      in_data, in_len, out_data, max_out_len, 
2154                                      out_len);
2155 }
2156
2157 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2158                                   struct files_struct *fsp,
2159                                   uint32 security_info,
2160                                   struct security_descriptor **ppdesc)
2161 {
2162         VFS_FIND(fget_nt_acl);
2163         return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2164                                            ppdesc);
2165 }
2166
2167 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2168                                  const char *name,
2169                                  uint32 security_info,
2170                                  struct security_descriptor **ppdesc)
2171 {
2172         VFS_FIND(get_nt_acl);
2173         return handle->fns->get_nt_acl_fn(handle, name, security_info, ppdesc);
2174 }
2175
2176 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2177                                   struct files_struct *fsp,
2178                                   uint32 security_info_sent,
2179                                   const struct security_descriptor *psd)
2180 {
2181         VFS_FIND(fset_nt_acl);
2182         return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent, 
2183                                            psd);
2184 }
2185
2186 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2187                                  struct smb_filename *file,
2188                                  struct security_acl *sacl,
2189                                  uint32_t access_requested,
2190                                  uint32_t access_denied)
2191 {
2192         VFS_FIND(audit_file);
2193         return handle->fns->audit_file_fn(handle, 
2194                                           file, 
2195                                           sacl, 
2196                                           access_requested, 
2197                                           access_denied);
2198 }
2199
2200 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle, const char *name,
2201                            mode_t mode)
2202 {
2203         VFS_FIND(chmod_acl);
2204         return handle->fns->chmod_acl_fn(handle, name, mode);
2205 }
2206
2207 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2208                             struct files_struct *fsp, mode_t mode)
2209 {
2210         VFS_FIND(fchmod_acl);
2211         return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2212 }
2213
2214 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2215                                         const char *path_p,
2216                                         SMB_ACL_TYPE_T type)
2217 {
2218         VFS_FIND(sys_acl_get_file);
2219         return handle->fns->sys_acl_get_file_fn(handle, path_p, type);
2220 }
2221
2222 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2223                                       struct files_struct *fsp)
2224 {
2225         VFS_FIND(sys_acl_get_fd);
2226         return handle->fns->sys_acl_get_fd_fn(handle, fsp);
2227 }
2228
2229 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2230                                   const char *name, SMB_ACL_TYPE_T acltype,
2231                                   SMB_ACL_T theacl)
2232 {
2233         VFS_FIND(sys_acl_set_file);
2234         return handle->fns->sys_acl_set_file_fn(handle, name, acltype, theacl);
2235 }
2236
2237 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2238                                 struct files_struct *fsp, SMB_ACL_T theacl)
2239 {
2240         VFS_FIND(sys_acl_set_fd);
2241         return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2242 }
2243
2244 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2245                                          const char *path)
2246 {
2247         VFS_FIND(sys_acl_delete_def_file);
2248         return handle->fns->sys_acl_delete_def_file_fn(handle, path);
2249 }
2250
2251 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2252                               const char *path, const char *name, void *value,
2253                               size_t size)
2254 {
2255         VFS_FIND(getxattr);
2256         return handle->fns->getxattr_fn(handle, path, name, value, size);
2257 }
2258
2259 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2260                                struct files_struct *fsp, const char *name,
2261                                void *value, size_t size)
2262 {
2263         VFS_FIND(fgetxattr);
2264         return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2265 }
2266
2267 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2268                                const char *path, char *list, size_t size)
2269 {
2270         VFS_FIND(listxattr);
2271         return handle->fns->listxattr_fn(handle, path, list, size);
2272 }
2273
2274 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2275                                 struct files_struct *fsp, char *list,
2276                                 size_t size)
2277 {
2278         VFS_FIND(flistxattr);
2279         return handle->fns->flistxattr_fn(handle, fsp, list, size);
2280 }
2281
2282 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2283                              const char *path, const char *name)
2284 {
2285         VFS_FIND(removexattr);
2286         return handle->fns->removexattr_fn(handle, path, name);
2287 }
2288
2289 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2290                               struct files_struct *fsp, const char *name)
2291 {
2292         VFS_FIND(fremovexattr);
2293         return handle->fns->fremovexattr_fn(handle, fsp, name);
2294 }
2295
2296 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle, const char *path,
2297                           const char *name, const void *value, size_t size,
2298                           int flags)
2299 {
2300         VFS_FIND(setxattr);
2301         return handle->fns->setxattr_fn(handle, path, name, value, size, flags);
2302 }
2303
2304 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2305                            struct files_struct *fsp, const char *name,
2306                            const void *value, size_t size, int flags)
2307 {
2308         VFS_FIND(fsetxattr);
2309         return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2310 }
2311
2312 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2313                             struct files_struct *fsp)
2314 {
2315         VFS_FIND(aio_force);
2316         return handle->fns->aio_force_fn(handle, fsp);
2317 }
2318
2319 bool smb_vfs_call_is_offline(struct vfs_handle_struct *handle,
2320                              const struct smb_filename *fname,
2321                              SMB_STRUCT_STAT *sbuf)
2322 {
2323         VFS_FIND(is_offline);
2324         return handle->fns->is_offline_fn(handle, fname, sbuf);
2325 }
2326
2327 int smb_vfs_call_set_offline(struct vfs_handle_struct *handle,
2328                              const struct smb_filename *fname)
2329 {
2330         VFS_FIND(set_offline);
2331         return handle->fns->set_offline_fn(handle, fname);
2332 }
2333
2334 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2335                                      struct files_struct *fsp,
2336                                      TALLOC_CTX *mem_ctx,
2337                                      DATA_BLOB *cookie)
2338 {
2339         VFS_FIND(durable_cookie);
2340         return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2341 }
2342
2343 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2344                                          struct files_struct *fsp,
2345                                          const DATA_BLOB old_cookie,
2346                                          TALLOC_CTX *mem_ctx,
2347                                          DATA_BLOB *new_cookie)
2348 {
2349         VFS_FIND(durable_disconnect);
2350         return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2351                                                   mem_ctx, new_cookie);
2352 }
2353
2354 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2355                                         struct smb_request *smb1req,
2356                                         struct smbXsrv_open *op,
2357                                         const DATA_BLOB old_cookie,
2358                                         TALLOC_CTX *mem_ctx,
2359                                         struct files_struct **fsp,
2360                                         DATA_BLOB *new_cookie)
2361 {
2362         VFS_FIND(durable_reconnect);
2363         return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2364                                                  old_cookie, mem_ctx, fsp,
2365                                                  new_cookie);
2366 }