3a95c588c557c56740f8d59c8d6660f1a8fdd5c6
[kai/samba.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 ret;
803
804         if (!LastDir) {
805                 LastDir = SMB_STRDUP("");
806         }
807
808         if (strcsequal(path,".")) {
809                 return 0;
810         }
811
812         if (*path == '/' && strcsequal(LastDir,path)) {
813                 return 0;
814         }
815
816         DEBUG(4,("vfs_ChDir to %s\n",path));
817
818         ret = SMB_VFS_CHDIR(conn,path);
819         if (ret == 0) {
820                 /* Global cache. */
821                 SAFE_FREE(LastDir);
822                 LastDir = SMB_STRDUP(path);
823
824                 /* conn cache. */
825                 TALLOC_FREE(conn->cwd);
826                 conn->cwd = vfs_GetWd(conn, conn);
827                 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
828         }
829         return ret;
830 }
831
832 /*******************************************************************
833  Return the absolute current directory path - given a UNIX pathname.
834  Note that this path is returned in DOS format, not UNIX
835  format. Note this can be called with conn == NULL.
836 ********************************************************************/
837
838 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
839 {
840         char *current_dir = NULL;
841         char *result = NULL;
842         DATA_BLOB cache_value;
843         struct file_id key;
844         struct smb_filename *smb_fname_dot = NULL;
845         struct smb_filename *smb_fname_full = NULL;
846         NTSTATUS status;
847
848         if (!lp_getwd_cache()) {
849                 goto nocache;
850         }
851
852         status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
853                                             &smb_fname_dot);
854         if (!NT_STATUS_IS_OK(status)) {
855                 errno = map_errno_from_nt_status(status);
856                 goto out;
857         }
858
859         if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
860                 /*
861                  * Known to fail for root: the directory may be NFS-mounted
862                  * and exported with root_squash (so has no root access).
863                  */
864                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
865                          "(NFS problem ?)\n", strerror(errno) ));
866                 goto nocache;
867         }
868
869         key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
870
871         if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
872                              data_blob_const(&key, sizeof(key)),
873                              &cache_value)) {
874                 goto nocache;
875         }
876
877         SMB_ASSERT((cache_value.length > 0)
878                    && (cache_value.data[cache_value.length-1] == '\0'));
879
880         status = create_synthetic_smb_fname(ctx, (char *)cache_value.data,
881                                             NULL, NULL, &smb_fname_full);
882         if (!NT_STATUS_IS_OK(status)) {
883                 errno = map_errno_from_nt_status(status);
884                 goto out;
885         }
886
887         if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
888             (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
889             (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
890             (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
891                 /*
892                  * Ok, we're done
893                  */
894                 result = talloc_strdup(ctx, smb_fname_full->base_name);
895                 if (result == NULL) {
896                         errno = ENOMEM;
897                 }
898                 goto out;
899         }
900
901  nocache:
902
903         /*
904          * We don't have the information to hand so rely on traditional
905          * methods. The very slow getcwd, which spawns a process on some
906          * systems, or the not quite so bad getwd.
907          */
908
909         current_dir = SMB_VFS_GETWD(conn);
910         if (current_dir == NULL) {
911                 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
912                           strerror(errno)));
913                 goto out;
914         }
915
916         if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
917                 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
918
919                 memcache_add(smbd_memcache(), GETWD_CACHE,
920                              data_blob_const(&key, sizeof(key)),
921                              data_blob_const(current_dir,
922                                                 strlen(current_dir)+1));
923         }
924
925         result = talloc_strdup(ctx, current_dir);
926         if (result == NULL) {
927                 errno = ENOMEM;
928         }
929
930  out:
931         TALLOC_FREE(smb_fname_dot);
932         TALLOC_FREE(smb_fname_full);
933         SAFE_FREE(current_dir);
934         return result;
935 }
936
937 /*******************************************************************
938  Reduce a file name, removing .. elements and checking that
939  it is below dir in the heirachy. This uses realpath.
940  This function must run as root, and will return names
941  and valid stat structs that can be checked on open.
942 ********************************************************************/
943
944 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
945                         const char *fname,
946                         struct smb_request *smbreq)
947 {
948         NTSTATUS status;
949         TALLOC_CTX *ctx = talloc_tos();
950         const char *conn_rootdir;
951         size_t rootdir_len;
952         char *dir_name = NULL;
953         const char *last_component = NULL;
954         char *resolved_name = NULL;
955         char *saved_dir = NULL;
956         struct smb_filename *smb_fname_cwd = NULL;
957         struct privilege_paths *priv_paths = NULL;
958         int ret;
959
960         DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
961                         fname,
962                         conn->connectpath));
963
964
965         priv_paths = talloc_zero(smbreq, struct privilege_paths);
966         if (!priv_paths) {
967                 status = NT_STATUS_NO_MEMORY;
968                 goto err;
969         }
970
971         if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
972                 status = NT_STATUS_NO_MEMORY;
973                 goto err;
974         }
975
976         priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
977         priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
978
979         if (priv_paths->parent_name.base_name == NULL ||
980                         priv_paths->file_name.base_name == NULL) {
981                 status = NT_STATUS_NO_MEMORY;
982                 goto err;
983         }
984
985         if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
986                 status = map_nt_error_from_unix(errno);
987                 goto err;
988         }
989         /* Remember where we were. */
990         saved_dir = vfs_GetWd(ctx, conn);
991         if (!saved_dir) {
992                 status = map_nt_error_from_unix(errno);
993                 goto err;
994         }
995
996         /* Go to the parent directory to lock in memory. */
997         if (vfs_ChDir(conn, priv_paths->parent_name.base_name) == -1) {
998                 status = map_nt_error_from_unix(errno);
999                 goto err;
1000         }
1001
1002         /* Get the absolute path of the parent directory. */
1003         resolved_name = SMB_VFS_REALPATH(conn,".");
1004         if (!resolved_name) {
1005                 status = map_nt_error_from_unix(errno);
1006                 goto err;
1007         }
1008
1009         if (*resolved_name != '/') {
1010                 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1011                         "doesn't return absolute paths !\n"));
1012                 status = NT_STATUS_OBJECT_NAME_INVALID;
1013                 goto err;
1014         }
1015
1016         DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1017                 priv_paths->parent_name.base_name,
1018                 resolved_name));
1019
1020         /* Now check the stat value is the same. */
1021         status = create_synthetic_smb_fname(talloc_tos(), ".",
1022                                         NULL, NULL,
1023                                         &smb_fname_cwd);
1024         if (!NT_STATUS_IS_OK(status)) {
1025                 goto err;
1026         }
1027
1028         if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1029                 status = map_nt_error_from_unix(errno);
1030                 goto err;
1031         }
1032
1033         /* Ensure we're pointing at the same place. */
1034         if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1035                 DEBUG(0,("check_reduced_name_with_privilege: "
1036                         "device/inode/uid/gid on directory %s changed. "
1037                         "Denying access !\n",
1038                         priv_paths->parent_name.base_name));
1039                 status = NT_STATUS_ACCESS_DENIED;
1040                 goto err;
1041         }
1042
1043         /* Ensure we're below the connect path. */
1044
1045         conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1046         if (conn_rootdir == NULL) {
1047                 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1048                         "conn_rootdir\n"));
1049                 status = NT_STATUS_ACCESS_DENIED;
1050                 goto err;
1051         }
1052
1053         rootdir_len = strlen(conn_rootdir);
1054         if (strncmp(conn_rootdir, resolved_name, rootdir_len) != 0) {
1055                 DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
1056                         "attempt: %s is a symlink outside the "
1057                         "share path\n",
1058                         dir_name));
1059                 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1060                 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1061                 status = NT_STATUS_ACCESS_DENIED;
1062                 goto err;
1063         }
1064
1065         /* Now ensure that the last component either doesn't
1066            exist, or is *NOT* a symlink. */
1067
1068         ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1069         if (ret == -1) {
1070                 /* Errno must be ENOENT for this be ok. */
1071                 if (errno != ENOENT) {
1072                         status = map_nt_error_from_unix(errno);
1073                         DEBUG(2, ("check_reduced_name_with_privilege: "
1074                                 "LSTAT on %s failed with %s\n",
1075                                 priv_paths->file_name.base_name,
1076                                 nt_errstr(status)));
1077                         goto err;
1078                 }
1079         }
1080
1081         if (VALID_STAT(priv_paths->file_name.st) &&
1082                         S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1083                 DEBUG(2, ("check_reduced_name_with_privilege: "
1084                         "Last component %s is a symlink. Denying"
1085                         "access.\n",
1086                         priv_paths->file_name.base_name));
1087                 status = NT_STATUS_ACCESS_DENIED;
1088                 goto err;
1089         }
1090
1091         smbreq->priv_paths = priv_paths;
1092         status = NT_STATUS_OK;
1093
1094   err:
1095
1096         if (saved_dir) {
1097                 vfs_ChDir(conn, saved_dir);
1098         }
1099         SAFE_FREE(resolved_name);
1100         if (!NT_STATUS_IS_OK(status)) {
1101                 TALLOC_FREE(priv_paths);
1102         }
1103         TALLOC_FREE(dir_name);
1104         return status;
1105 }
1106
1107 /*******************************************************************
1108  Reduce a file name, removing .. elements and checking that
1109  it is below dir in the heirachy. This uses realpath.
1110 ********************************************************************/
1111
1112 NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
1113 {
1114         char *resolved_name = NULL;
1115         bool allow_symlinks = true;
1116         bool allow_widelinks = false;
1117
1118         DEBUG(3,("check_reduced_name [%s] [%s]\n", fname, conn->connectpath));
1119
1120         resolved_name = SMB_VFS_REALPATH(conn,fname);
1121
1122         if (!resolved_name) {
1123                 switch (errno) {
1124                         case ENOTDIR:
1125                                 DEBUG(3,("check_reduced_name: Component not a "
1126                                          "directory in getting realpath for "
1127                                          "%s\n", fname));
1128                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1129                         case ENOENT:
1130                         {
1131                                 TALLOC_CTX *ctx = talloc_tos();
1132                                 char *dir_name = NULL;
1133                                 const char *last_component = NULL;
1134                                 char *new_name = NULL;
1135                                 int ret;
1136
1137                                 /* Last component didn't exist.
1138                                    Remove it and try and canonicalise
1139                                    the directory name. */
1140                                 if (!parent_dirname(ctx, fname,
1141                                                 &dir_name,
1142                                                 &last_component)) {
1143                                         return NT_STATUS_NO_MEMORY;
1144                                 }
1145
1146                                 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1147                                 if (!resolved_name) {
1148                                         NTSTATUS status = map_nt_error_from_unix(errno);
1149
1150                                         if (errno == ENOENT || errno == ENOTDIR) {
1151                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1152                                         }
1153
1154                                         DEBUG(3,("check_reduce_name: "
1155                                                  "couldn't get realpath for "
1156                                                  "%s (%s)\n",
1157                                                 fname,
1158                                                 nt_errstr(status)));
1159                                         return status;
1160                                 }
1161                                 ret = asprintf(&new_name, "%s/%s",
1162                                                resolved_name, last_component);
1163                                 SAFE_FREE(resolved_name);
1164                                 if (ret == -1) {
1165                                         return NT_STATUS_NO_MEMORY;
1166                                 }
1167                                 resolved_name = new_name;
1168                                 break;
1169                         }
1170                         default:
1171                                 DEBUG(3,("check_reduced_name: couldn't get "
1172                                          "realpath for %s\n", fname));
1173                                 return map_nt_error_from_unix(errno);
1174                 }
1175         }
1176
1177         DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1178                   resolved_name));
1179
1180         if (*resolved_name != '/') {
1181                 DEBUG(0,("check_reduced_name: realpath doesn't return "
1182                          "absolute paths !\n"));
1183                 SAFE_FREE(resolved_name);
1184                 return NT_STATUS_OBJECT_NAME_INVALID;
1185         }
1186
1187         allow_widelinks = lp_widelinks(SNUM(conn));
1188         allow_symlinks = lp_symlinks(SNUM(conn));
1189
1190         /* Common widelinks and symlinks checks. */
1191         if (!allow_widelinks || !allow_symlinks) {
1192                 const char *conn_rootdir;
1193                 size_t rootdir_len;
1194
1195                 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1196                 if (conn_rootdir == NULL) {
1197                         DEBUG(2, ("check_reduced_name: Could not get "
1198                                 "conn_rootdir\n"));
1199                         SAFE_FREE(resolved_name);
1200                         return NT_STATUS_ACCESS_DENIED;
1201                 }
1202
1203                 rootdir_len = strlen(conn_rootdir);
1204                 if (strncmp(conn_rootdir, resolved_name,
1205                                 rootdir_len) != 0) {
1206                         DEBUG(2, ("check_reduced_name: Bad access "
1207                                 "attempt: %s is a symlink outside the "
1208                                 "share path\n", fname));
1209                         DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1210                         DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1211                         SAFE_FREE(resolved_name);
1212                         return NT_STATUS_ACCESS_DENIED;
1213                 }
1214
1215                 /* Extra checks if all symlinks are disallowed. */
1216                 if (!allow_symlinks) {
1217                         /* fname can't have changed in resolved_path. */
1218                         const char *p = &resolved_name[rootdir_len];
1219
1220                         /* *p can be '\0' if fname was "." */
1221                         if (*p == '\0' && ISDOT(fname)) {
1222                                 goto out;
1223                         }
1224
1225                         if (*p != '/') {
1226                                 DEBUG(2, ("check_reduced_name: logic error (%c) "
1227                                         "in resolved_name: %s\n",
1228                                         *p,
1229                                         fname));
1230                                 SAFE_FREE(resolved_name);
1231                                 return NT_STATUS_ACCESS_DENIED;
1232                         }
1233
1234                         p++;
1235                         if (strcmp(fname, p)!=0) {
1236                                 DEBUG(2, ("check_reduced_name: Bad access "
1237                                         "attempt: %s is a symlink to %s\n",
1238                                           fname, p));
1239                                 SAFE_FREE(resolved_name);
1240                                 return NT_STATUS_ACCESS_DENIED;
1241                         }
1242                 }
1243         }
1244
1245   out:
1246
1247         DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
1248                  resolved_name));
1249         SAFE_FREE(resolved_name);
1250         return NT_STATUS_OK;
1251 }
1252
1253 /**
1254  * XXX: This is temporary and there should be no callers of this once
1255  * smb_filename is plumbed through all path based operations.
1256  */
1257 int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
1258                        SMB_STRUCT_STAT *psbuf)
1259 {
1260         struct smb_filename *smb_fname = NULL;
1261         NTSTATUS status;
1262         int ret;
1263
1264         status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
1265                                                   &smb_fname);
1266         if (!NT_STATUS_IS_OK(status)) {
1267                 errno = map_errno_from_nt_status(status);
1268                 return -1;
1269         }
1270
1271         if (lp_posix_pathnames()) {
1272                 ret = SMB_VFS_LSTAT(conn, smb_fname);
1273         } else {
1274                 ret = SMB_VFS_STAT(conn, smb_fname);
1275         }
1276
1277         if (ret != -1) {
1278                 *psbuf = smb_fname->st;
1279         }
1280
1281         TALLOC_FREE(smb_fname);
1282         return ret;
1283 }
1284
1285 /**
1286  * XXX: This is temporary and there should be no callers of this once
1287  * smb_filename is plumbed through all path based operations.
1288  */
1289 int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
1290                         SMB_STRUCT_STAT *psbuf)
1291 {
1292         struct smb_filename *smb_fname = NULL;
1293         NTSTATUS status;
1294         int ret;
1295
1296         status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
1297                                                   &smb_fname);
1298         if (!NT_STATUS_IS_OK(status)) {
1299                 errno = map_errno_from_nt_status(status);
1300                 return -1;
1301         }
1302
1303         ret = SMB_VFS_LSTAT(conn, smb_fname);
1304         if (ret != -1) {
1305                 *psbuf = smb_fname->st;
1306         }
1307
1308         TALLOC_FREE(smb_fname);
1309         return ret;
1310 }
1311
1312 /**
1313  * Ensure LSTAT is called for POSIX paths.
1314  */
1315
1316 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1317 {
1318         int ret;
1319
1320         if(fsp->fh->fd == -1) {
1321                 if (fsp->posix_open) {
1322                         ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1323                 } else {
1324                         ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1325                 }
1326                 if (ret == -1) {
1327                         return map_nt_error_from_unix(errno);
1328                 }
1329         } else {
1330                 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1331                         return map_nt_error_from_unix(errno);
1332                 }
1333         }
1334         return NT_STATUS_OK;
1335 }
1336
1337 /**
1338  * Initialize num_streams and streams, then call VFS op streaminfo
1339  */
1340 NTSTATUS vfs_streaminfo(connection_struct *conn,
1341                         struct files_struct *fsp,
1342                         const char *fname,
1343                         TALLOC_CTX *mem_ctx,
1344                         unsigned int *num_streams,
1345                         struct stream_struct **streams)
1346 {
1347         *num_streams = 0;
1348         *streams = NULL;
1349         return SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams);
1350 }
1351
1352 /*
1353   generate a file_id from a stat structure
1354  */
1355 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1356 {
1357         return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1358 }
1359
1360 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1361                          const char *service, const char *user)
1362 {
1363         VFS_FIND(connect);
1364         return handle->fns->connect_fn(handle, service, user);
1365 }
1366
1367 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1368 {
1369         VFS_FIND(disconnect);
1370         handle->fns->disconnect_fn(handle);
1371 }
1372
1373 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1374                                 const char *path, bool small_query,
1375                                 uint64_t *bsize, uint64_t *dfree,
1376                                 uint64_t *dsize)
1377 {
1378         VFS_FIND(disk_free);
1379         return handle->fns->disk_free_fn(handle, path, small_query, bsize, 
1380                                          dfree, dsize);
1381 }
1382
1383 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1384                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1385                            SMB_DISK_QUOTA *qt)
1386 {
1387         VFS_FIND(get_quota);
1388         return handle->fns->get_quota_fn(handle, qtype, id, qt);
1389 }
1390
1391 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1392                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1393                            SMB_DISK_QUOTA *qt)
1394 {
1395         VFS_FIND(set_quota);
1396         return handle->fns->set_quota_fn(handle, qtype, id, qt);
1397 }
1398
1399 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1400                                       struct files_struct *fsp,
1401                                       struct shadow_copy_data *shadow_copy_data,
1402                                       bool labels)
1403 {
1404         VFS_FIND(get_shadow_copy_data);
1405         return handle->fns->get_shadow_copy_data_fn(handle, fsp, 
1406                                                     shadow_copy_data,
1407                                                     labels);
1408 }
1409 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
1410                          struct vfs_statvfs_struct *statbuf)
1411 {
1412         VFS_FIND(statvfs);
1413         return handle->fns->statvfs_fn(handle, path, statbuf);
1414 }
1415
1416 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1417                         enum timestamp_set_resolution *p_ts_res)
1418 {
1419         VFS_FIND(fs_capabilities);
1420         return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1421 }
1422
1423 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1424                                         struct dfs_GetDFSReferral *r)
1425 {
1426         VFS_FIND(get_dfs_referrals);
1427         return handle->fns->get_dfs_referrals_fn(handle, r);
1428 }
1429
1430 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1431                                      const char *fname, const char *mask,
1432                                      uint32 attributes)
1433 {
1434         VFS_FIND(opendir);
1435         return handle->fns->opendir_fn(handle, fname, mask, attributes);
1436 }
1437
1438 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1439                                         struct files_struct *fsp,
1440                                         const char *mask,
1441                                         uint32 attributes)
1442 {
1443         VFS_FIND(fdopendir);
1444         return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1445 }
1446
1447 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1448                                               DIR *dirp,
1449                                               SMB_STRUCT_STAT *sbuf)
1450 {
1451         VFS_FIND(readdir);
1452         return handle->fns->readdir_fn(handle, dirp, sbuf);
1453 }
1454
1455 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1456                           DIR *dirp, long offset)
1457 {
1458         VFS_FIND(seekdir);
1459         handle->fns->seekdir_fn(handle, dirp, offset);
1460 }
1461
1462 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1463                           DIR *dirp)
1464 {
1465         VFS_FIND(telldir);
1466         return handle->fns->telldir_fn(handle, dirp);
1467 }
1468
1469 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1470                              DIR *dirp)
1471 {
1472         VFS_FIND(rewind_dir);
1473         handle->fns->rewind_dir_fn(handle, dirp);
1474 }
1475
1476 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, const char *path,
1477                        mode_t mode)
1478 {
1479         VFS_FIND(mkdir);
1480         return handle->fns->mkdir_fn(handle, path, mode);
1481 }
1482
1483 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, const char *path)
1484 {
1485         VFS_FIND(rmdir);
1486         return handle->fns->rmdir_fn(handle, path);
1487 }
1488
1489 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1490                           DIR *dir)
1491 {
1492         VFS_FIND(closedir);
1493         return handle->fns->closedir_fn(handle, dir);
1494 }
1495
1496 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1497                                  DIR *dirp)
1498 {
1499         VFS_FIND(init_search_op);
1500         handle->fns->init_search_op_fn(handle, dirp);
1501 }
1502
1503 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1504                       struct smb_filename *smb_fname, struct files_struct *fsp,
1505                       int flags, mode_t mode)
1506 {
1507         VFS_FIND(open);
1508         return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1509 }
1510
1511 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1512                                   struct smb_request *req,
1513                                   uint16_t root_dir_fid,
1514                                   struct smb_filename *smb_fname,
1515                                   uint32_t access_mask,
1516                                   uint32_t share_access,
1517                                   uint32_t create_disposition,
1518                                   uint32_t create_options,
1519                                   uint32_t file_attributes,
1520                                   uint32_t oplock_request,
1521                                   uint64_t allocation_size,
1522                                   uint32_t private_flags,
1523                                   struct security_descriptor *sd,
1524                                   struct ea_list *ea_list,
1525                                   files_struct **result,
1526                                   int *pinfo)
1527 {
1528         VFS_FIND(create_file);
1529         return handle->fns->create_file_fn(
1530                 handle, req, root_dir_fid, smb_fname, access_mask,
1531                 share_access, create_disposition, create_options,
1532                 file_attributes, oplock_request, allocation_size,
1533                 private_flags, sd, ea_list,
1534                 result, pinfo);
1535 }
1536
1537 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1538                        struct files_struct *fsp)
1539 {
1540         VFS_FIND(close);
1541         return handle->fns->close_fn(handle, fsp);
1542 }
1543
1544 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1545                           struct files_struct *fsp, void *data, size_t n)
1546 {
1547         VFS_FIND(read);
1548         return handle->fns->read_fn(handle, fsp, data, n);
1549 }
1550
1551 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1552                            struct files_struct *fsp, void *data, size_t n,
1553                            off_t offset)
1554 {
1555         VFS_FIND(pread);
1556         return handle->fns->pread_fn(handle, fsp, data, n, offset);
1557 }
1558
1559 struct smb_vfs_call_pread_state {
1560         ssize_t (*recv_fn)(struct tevent_req *req, int *err);
1561         ssize_t retval;
1562 };
1563
1564 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1565
1566 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1567                                            TALLOC_CTX *mem_ctx,
1568                                            struct tevent_context *ev,
1569                                            struct files_struct *fsp,
1570                                            void *data,
1571                                            size_t n, off_t offset)
1572 {
1573         struct tevent_req *req, *subreq;
1574         struct smb_vfs_call_pread_state *state;
1575
1576         req = tevent_req_create(mem_ctx, &state,
1577                                 struct smb_vfs_call_pread_state);
1578         if (req == NULL) {
1579                 return NULL;
1580         }
1581         VFS_FIND(pread_send);
1582         state->recv_fn = handle->fns->pread_recv_fn;
1583
1584         subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1585                                             offset);
1586         if (tevent_req_nomem(subreq, req)) {
1587                 return tevent_req_post(req, ev);
1588         }
1589         tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1590         return req;
1591 }
1592
1593 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1594 {
1595         struct tevent_req *req = tevent_req_callback_data(
1596                 subreq, struct tevent_req);
1597         struct smb_vfs_call_pread_state *state = tevent_req_data(
1598                 req, struct smb_vfs_call_pread_state);
1599         int err;
1600
1601         state->retval = state->recv_fn(subreq, &err);
1602         TALLOC_FREE(subreq);
1603         if (state->retval == -1) {
1604                 tevent_req_error(req, err);
1605                 return;
1606         }
1607         tevent_req_done(req);
1608 }
1609
1610 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno)
1611 {
1612         struct smb_vfs_call_pread_state *state = tevent_req_data(
1613                 req, struct smb_vfs_call_pread_state);
1614         int err;
1615
1616         if (tevent_req_is_unix_error(req, &err)) {
1617                 *perrno = err;
1618                 return -1;
1619         }
1620         return state->retval;
1621 }
1622
1623 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1624                            struct files_struct *fsp, const void *data,
1625                            size_t n)
1626 {
1627         VFS_FIND(write);
1628         return handle->fns->write_fn(handle, fsp, data, n);
1629 }
1630
1631 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1632                             struct files_struct *fsp, const void *data,
1633                             size_t n, off_t offset)
1634 {
1635         VFS_FIND(pwrite);
1636         return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1637 }
1638
1639 struct smb_vfs_call_pwrite_state {
1640         ssize_t (*recv_fn)(struct tevent_req *req, int *err);
1641         ssize_t retval;
1642 };
1643
1644 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1645
1646 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1647                                             TALLOC_CTX *mem_ctx,
1648                                             struct tevent_context *ev,
1649                                             struct files_struct *fsp,
1650                                             const void *data,
1651                                             size_t n, off_t offset)
1652 {
1653         struct tevent_req *req, *subreq;
1654         struct smb_vfs_call_pwrite_state *state;
1655
1656         req = tevent_req_create(mem_ctx, &state,
1657                                 struct smb_vfs_call_pwrite_state);
1658         if (req == NULL) {
1659                 return NULL;
1660         }
1661         VFS_FIND(pwrite_send);
1662         state->recv_fn = handle->fns->pwrite_recv_fn;
1663
1664         subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1665                                              offset);
1666         if (tevent_req_nomem(subreq, req)) {
1667                 return tevent_req_post(req, ev);
1668         }
1669         tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1670         return req;
1671 }
1672
1673 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1674 {
1675         struct tevent_req *req = tevent_req_callback_data(
1676                 subreq, struct tevent_req);
1677         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1678                 req, struct smb_vfs_call_pwrite_state);
1679         int err;
1680
1681         state->retval = state->recv_fn(subreq, &err);
1682         TALLOC_FREE(subreq);
1683         if (state->retval == -1) {
1684                 tevent_req_error(req, err);
1685                 return;
1686         }
1687         tevent_req_done(req);
1688 }
1689
1690 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, int *perrno)
1691 {
1692         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1693                 req, struct smb_vfs_call_pwrite_state);
1694         int err;
1695
1696         if (tevent_req_is_unix_error(req, &err)) {
1697                 *perrno = err;
1698                 return -1;
1699         }
1700         return state->retval;
1701 }
1702
1703 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1704                              struct files_struct *fsp, off_t offset,
1705                              int whence)
1706 {
1707         VFS_FIND(lseek);
1708         return handle->fns->lseek_fn(handle, fsp, offset, whence);
1709 }
1710
1711 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1712                               files_struct *fromfsp, const DATA_BLOB *header,
1713                               off_t offset, size_t count)
1714 {
1715         VFS_FIND(sendfile);
1716         return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1717                                         count);
1718 }
1719
1720 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1721                               files_struct *tofsp, off_t offset,
1722                               size_t count)
1723 {
1724         VFS_FIND(recvfile);
1725         return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1726 }
1727
1728 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1729                         const struct smb_filename *smb_fname_src,
1730                         const struct smb_filename *smb_fname_dst)
1731 {
1732         VFS_FIND(rename);
1733         return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1734 }
1735
1736 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1737                        struct files_struct *fsp)
1738 {
1739         VFS_FIND(fsync);
1740         return handle->fns->fsync_fn(handle, fsp);
1741 }
1742
1743 struct smb_vfs_call_fsync_state {
1744         int (*recv_fn)(struct tevent_req *req, int *err);
1745         int retval;
1746 };
1747
1748 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1749
1750 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1751                                            TALLOC_CTX *mem_ctx,
1752                                            struct tevent_context *ev,
1753                                            struct files_struct *fsp)
1754 {
1755         struct tevent_req *req, *subreq;
1756         struct smb_vfs_call_fsync_state *state;
1757
1758         req = tevent_req_create(mem_ctx, &state,
1759                                 struct smb_vfs_call_fsync_state);
1760         if (req == NULL) {
1761                 return NULL;
1762         }
1763         VFS_FIND(fsync_send);
1764         state->recv_fn = handle->fns->fsync_recv_fn;
1765
1766         subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1767         if (tevent_req_nomem(subreq, req)) {
1768                 return tevent_req_post(req, ev);
1769         }
1770         tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1771         return req;
1772 }
1773
1774 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1775 {
1776         struct tevent_req *req = tevent_req_callback_data(
1777                 subreq, struct tevent_req);
1778         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1779                 req, struct smb_vfs_call_fsync_state);
1780         int err;
1781
1782         state->retval = state->recv_fn(subreq, &err);
1783         TALLOC_FREE(subreq);
1784         if (state->retval == -1) {
1785                 tevent_req_error(req, err);
1786                 return;
1787         }
1788         tevent_req_done(req);
1789 }
1790
1791 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, int *perrno)
1792 {
1793         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1794                 req, struct smb_vfs_call_fsync_state);
1795         int err;
1796
1797         if (tevent_req_is_unix_error(req, &err)) {
1798                 *perrno = err;
1799                 return -1;
1800         }
1801         return state->retval;
1802 }
1803
1804
1805 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1806                       struct smb_filename *smb_fname)
1807 {
1808         VFS_FIND(stat);
1809         return handle->fns->stat_fn(handle, smb_fname);
1810 }
1811
1812 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1813                        struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1814 {
1815         VFS_FIND(fstat);
1816         return handle->fns->fstat_fn(handle, fsp, sbuf);
1817 }
1818
1819 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1820                        struct smb_filename *smb_filename)
1821 {
1822         VFS_FIND(lstat);
1823         return handle->fns->lstat_fn(handle, smb_filename);
1824 }
1825
1826 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1827                                      struct files_struct *fsp,
1828                                      const SMB_STRUCT_STAT *sbuf)
1829 {
1830         VFS_FIND(get_alloc_size);
1831         return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1832 }
1833
1834 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1835                         const struct smb_filename *smb_fname)
1836 {
1837         VFS_FIND(unlink);
1838         return handle->fns->unlink_fn(handle, smb_fname);
1839 }
1840
1841 int smb_vfs_call_chmod(struct vfs_handle_struct *handle, const char *path,
1842                        mode_t mode)
1843 {
1844         VFS_FIND(chmod);
1845         return handle->fns->chmod_fn(handle, path, mode);
1846 }
1847
1848 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1849                         struct files_struct *fsp, mode_t mode)
1850 {
1851         VFS_FIND(fchmod);
1852         return handle->fns->fchmod_fn(handle, fsp, mode);
1853 }
1854
1855 int smb_vfs_call_chown(struct vfs_handle_struct *handle, const char *path,
1856                        uid_t uid, gid_t gid)
1857 {
1858         VFS_FIND(chown);
1859         return handle->fns->chown_fn(handle, path, uid, gid);
1860 }
1861
1862 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1863                         struct files_struct *fsp, uid_t uid, gid_t gid)
1864 {
1865         VFS_FIND(fchown);
1866         return handle->fns->fchown_fn(handle, fsp, uid, gid);
1867 }
1868
1869 int smb_vfs_call_lchown(struct vfs_handle_struct *handle, const char *path,
1870                         uid_t uid, gid_t gid)
1871 {
1872         VFS_FIND(lchown);
1873         return handle->fns->lchown_fn(handle, path, uid, gid);
1874 }
1875
1876 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
1877 {
1878         int ret;
1879         bool as_root = false;
1880         const char *path;
1881         char *saved_dir = NULL;
1882         char *parent_dir = NULL;
1883         NTSTATUS status;
1884
1885         if (fsp->fh->fd != -1) {
1886                 /* Try fchown. */
1887                 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
1888                 if (ret == 0) {
1889                         return NT_STATUS_OK;
1890                 }
1891                 if (ret == -1 && errno != ENOSYS) {
1892                         return map_nt_error_from_unix(errno);
1893                 }
1894         }
1895
1896         as_root = (geteuid() == 0);
1897
1898         if (as_root) {
1899                 /*
1900                  * We are being asked to chown as root. Make
1901                  * sure we chdir() into the path to pin it,
1902                  * and always act using lchown to ensure we
1903                  * don't deref any symbolic links.
1904                  */
1905                 const char *final_component = NULL;
1906                 struct smb_filename local_fname;
1907
1908                 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
1909                 if (!saved_dir) {
1910                         status = map_nt_error_from_unix(errno);
1911                         DEBUG(0,("vfs_chown_fsp: failed to get "
1912                                 "current working directory. Error was %s\n",
1913                                 strerror(errno)));
1914                         return status;
1915                 }
1916
1917                 if (!parent_dirname(talloc_tos(),
1918                                 fsp->fsp_name->base_name,
1919                                 &parent_dir,
1920                                 &final_component)) {
1921                         return NT_STATUS_NO_MEMORY;
1922                 }
1923
1924                 /* cd into the parent dir to pin it. */
1925                 ret = vfs_ChDir(fsp->conn, parent_dir);
1926                 if (ret == -1) {
1927                         return map_nt_error_from_unix(errno);
1928                 }
1929
1930                 ZERO_STRUCT(local_fname);
1931                 local_fname.base_name = discard_const_p(char, final_component);
1932
1933                 /* Must use lstat here. */
1934                 ret = SMB_VFS_LSTAT(fsp->conn, &local_fname);
1935                 if (ret == -1) {
1936                         status = map_nt_error_from_unix(errno);
1937                         goto out;
1938                 }
1939
1940                 /* Ensure it matches the fsp stat. */
1941                 if (!check_same_stat(&local_fname.st, &fsp->fsp_name->st)) {
1942                         status = NT_STATUS_ACCESS_DENIED;
1943                         goto out;
1944                 }
1945                 path = final_component;
1946         } else {
1947                 path = fsp->fsp_name->base_name;
1948         }
1949
1950         if (fsp->posix_open || as_root) {
1951                 ret = SMB_VFS_LCHOWN(fsp->conn,
1952                         path,
1953                         uid, gid);
1954         } else {
1955                 ret = SMB_VFS_CHOWN(fsp->conn,
1956                         path,
1957                         uid, gid);
1958         }
1959
1960         if (ret == 0) {
1961                 status = NT_STATUS_OK;
1962         } else {
1963                 status = map_nt_error_from_unix(errno);
1964         }
1965
1966   out:
1967
1968         if (as_root) {
1969                 vfs_ChDir(fsp->conn,saved_dir);
1970                 TALLOC_FREE(saved_dir);
1971                 TALLOC_FREE(parent_dir);
1972         }
1973         return status;
1974 }
1975
1976 int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
1977 {
1978         VFS_FIND(chdir);
1979         return handle->fns->chdir_fn(handle, path);
1980 }
1981
1982 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
1983 {
1984         VFS_FIND(getwd);
1985         return handle->fns->getwd_fn(handle);
1986 }
1987
1988 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
1989                         const struct smb_filename *smb_fname,
1990                         struct smb_file_time *ft)
1991 {
1992         VFS_FIND(ntimes);
1993         return handle->fns->ntimes_fn(handle, smb_fname, ft);
1994 }
1995
1996 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
1997                            struct files_struct *fsp, off_t offset)
1998 {
1999         VFS_FIND(ftruncate);
2000         return handle->fns->ftruncate_fn(handle, fsp, offset);
2001 }
2002
2003 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2004                                 struct files_struct *fsp,
2005                                 enum vfs_fallocate_mode mode,
2006                                 off_t offset,
2007                                 off_t len)
2008 {
2009         VFS_FIND(fallocate);
2010         return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2011 }
2012
2013 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2014                               struct files_struct *fsp, uint32 share_mode,
2015                               uint32_t access_mask)
2016 {
2017         VFS_FIND(kernel_flock);
2018         return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2019                                          access_mask);
2020 }
2021
2022 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2023                                 struct files_struct *fsp, int leasetype)
2024 {
2025         VFS_FIND(linux_setlease);
2026         return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2027 }
2028
2029 int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
2030                          const char *newpath)
2031 {
2032         VFS_FIND(symlink);
2033         return handle->fns->symlink_fn(handle, oldpath, newpath);
2034 }
2035
2036 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2037                               const char *path, char *buf, size_t bufsiz)
2038 {
2039         VFS_FIND(readlink);
2040         return handle->fns->readlink_fn(handle, path, buf, bufsiz);
2041 }
2042
2043 int smb_vfs_call_link(struct vfs_handle_struct *handle, const char *oldpath,
2044                       const char *newpath)
2045 {
2046         VFS_FIND(link);
2047         return handle->fns->link_fn(handle, oldpath, newpath);
2048 }
2049
2050 int smb_vfs_call_mknod(struct vfs_handle_struct *handle, const char *path,
2051                        mode_t mode, SMB_DEV_T dev)
2052 {
2053         VFS_FIND(mknod);
2054         return handle->fns->mknod_fn(handle, path, mode, dev);
2055 }
2056
2057 char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
2058 {
2059         VFS_FIND(realpath);
2060         return handle->fns->realpath_fn(handle, path);
2061 }
2062
2063 NTSTATUS smb_vfs_call_notify_watch(struct vfs_handle_struct *handle,
2064                                    struct sys_notify_context *ctx,
2065                                    const char *path,
2066                                    uint32_t *filter,
2067                                    uint32_t *subdir_filter,
2068                                    void (*callback)(struct sys_notify_context *ctx,
2069                                                     void *private_data,
2070                                                     struct notify_event *ev),
2071                                    void *private_data, void *handle_p)
2072 {
2073         VFS_FIND(notify_watch);
2074         return handle->fns->notify_watch_fn(handle, ctx, path,
2075                                             filter, subdir_filter, callback,
2076                                             private_data, handle_p);
2077 }
2078
2079 int smb_vfs_call_chflags(struct vfs_handle_struct *handle, const char *path,
2080                          unsigned int flags)
2081 {
2082         VFS_FIND(chflags);
2083         return handle->fns->chflags_fn(handle, path, flags);
2084 }
2085
2086 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2087                                            const SMB_STRUCT_STAT *sbuf)
2088 {
2089         VFS_FIND(file_id_create);
2090         return handle->fns->file_id_create_fn(handle, sbuf);
2091 }
2092
2093 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2094                                  struct files_struct *fsp,
2095                                  const char *fname,
2096                                  TALLOC_CTX *mem_ctx,
2097                                  unsigned int *num_streams,
2098                                  struct stream_struct **streams)
2099 {
2100         VFS_FIND(streaminfo);
2101         return handle->fns->streaminfo_fn(handle, fsp, fname, mem_ctx,
2102                                           num_streams, streams);
2103 }
2104
2105 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2106                                    const char *path, const char *name,
2107                                    TALLOC_CTX *mem_ctx, char **found_name)
2108 {
2109         VFS_FIND(get_real_filename);
2110         return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2111                                                  found_name);
2112 }
2113
2114 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2115                                      const char *filename)
2116 {
2117         VFS_FIND(connectpath);
2118         return handle->fns->connectpath_fn(handle, filename);
2119 }
2120
2121 bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
2122                               struct files_struct *fsp,
2123                               struct lock_struct *plock)
2124 {
2125         VFS_FIND(strict_lock);
2126         return handle->fns->strict_lock_fn(handle, fsp, plock);
2127 }
2128
2129 void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
2130                                 struct files_struct *fsp,
2131                                 struct lock_struct *plock)
2132 {
2133         VFS_FIND(strict_unlock);
2134         handle->fns->strict_unlock_fn(handle, fsp, plock);
2135 }
2136
2137 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2138                                      const char *name,
2139                                      enum vfs_translate_direction direction,
2140                                      TALLOC_CTX *mem_ctx,
2141                                      char **mapped_name)
2142 {
2143         VFS_FIND(translate_name);
2144         return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2145                                               mapped_name);
2146 }
2147
2148 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2149                             struct files_struct *fsp,
2150                             TALLOC_CTX *ctx,
2151                             uint32_t function,
2152                             uint16_t req_flags,
2153                             const uint8_t *in_data,
2154                             uint32_t in_len,
2155                             uint8_t **out_data,
2156                             uint32_t max_out_len,
2157                             uint32_t *out_len)
2158 {
2159         VFS_FIND(fsctl);
2160         return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags, 
2161                                      in_data, in_len, out_data, max_out_len, 
2162                                      out_len);
2163 }
2164
2165 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2166                                   struct files_struct *fsp,
2167                                   uint32 security_info,
2168                                   TALLOC_CTX *mem_ctx,
2169                                   struct security_descriptor **ppdesc)
2170 {
2171         VFS_FIND(fget_nt_acl);
2172         return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2173                                            mem_ctx, ppdesc);
2174 }
2175
2176 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2177                                  const char *name,
2178                                  uint32 security_info,
2179                                  TALLOC_CTX *mem_ctx,
2180                                  struct security_descriptor **ppdesc)
2181 {
2182         VFS_FIND(get_nt_acl);
2183         return handle->fns->get_nt_acl_fn(handle, name, security_info, mem_ctx, ppdesc);
2184 }
2185
2186 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2187                                   struct files_struct *fsp,
2188                                   uint32 security_info_sent,
2189                                   const struct security_descriptor *psd)
2190 {
2191         VFS_FIND(fset_nt_acl);
2192         return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent, 
2193                                            psd);
2194 }
2195
2196 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2197                                  struct smb_filename *file,
2198                                  struct security_acl *sacl,
2199                                  uint32_t access_requested,
2200                                  uint32_t access_denied)
2201 {
2202         VFS_FIND(audit_file);
2203         return handle->fns->audit_file_fn(handle, 
2204                                           file, 
2205                                           sacl, 
2206                                           access_requested, 
2207                                           access_denied);
2208 }
2209
2210 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle, const char *name,
2211                            mode_t mode)
2212 {
2213         VFS_FIND(chmod_acl);
2214         return handle->fns->chmod_acl_fn(handle, name, mode);
2215 }
2216
2217 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2218                             struct files_struct *fsp, mode_t mode)
2219 {
2220         VFS_FIND(fchmod_acl);
2221         return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2222 }
2223
2224 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2225                                         const char *path_p,
2226                                         SMB_ACL_TYPE_T type,
2227                                         TALLOC_CTX *mem_ctx)
2228 {
2229         VFS_FIND(sys_acl_get_file);
2230         return handle->fns->sys_acl_get_file_fn(handle, path_p, type, mem_ctx);
2231 }
2232
2233 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2234                                       struct files_struct *fsp,
2235                                       TALLOC_CTX *mem_ctx)
2236 {
2237         VFS_FIND(sys_acl_get_fd);
2238         return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2239 }
2240
2241 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2242                                        const char *path_p,
2243                                        SMB_ACL_TYPE_T type,
2244                                        TALLOC_CTX *mem_ctx, 
2245                                        char **blob_description,
2246                                        DATA_BLOB *blob)
2247 {
2248         VFS_FIND(sys_acl_blob_get_file);
2249         return handle->fns->sys_acl_blob_get_file_fn(handle, path_p, type, mem_ctx, blob_description, blob);
2250 }
2251
2252 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2253                                      struct files_struct *fsp,
2254                                      TALLOC_CTX *mem_ctx, 
2255                                      char **blob_description,
2256                                      DATA_BLOB *blob)
2257 {
2258         VFS_FIND(sys_acl_blob_get_fd);
2259         return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2260 }
2261
2262 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2263                                   const char *name, SMB_ACL_TYPE_T acltype,
2264                                   SMB_ACL_T theacl)
2265 {
2266         VFS_FIND(sys_acl_set_file);
2267         return handle->fns->sys_acl_set_file_fn(handle, name, acltype, theacl);
2268 }
2269
2270 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2271                                 struct files_struct *fsp, SMB_ACL_T theacl)
2272 {
2273         VFS_FIND(sys_acl_set_fd);
2274         return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2275 }
2276
2277 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2278                                          const char *path)
2279 {
2280         VFS_FIND(sys_acl_delete_def_file);
2281         return handle->fns->sys_acl_delete_def_file_fn(handle, path);
2282 }
2283
2284 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2285                               const char *path, const char *name, void *value,
2286                               size_t size)
2287 {
2288         VFS_FIND(getxattr);
2289         return handle->fns->getxattr_fn(handle, path, name, value, size);
2290 }
2291
2292 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2293                                struct files_struct *fsp, const char *name,
2294                                void *value, size_t size)
2295 {
2296         VFS_FIND(fgetxattr);
2297         return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2298 }
2299
2300 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2301                                const char *path, char *list, size_t size)
2302 {
2303         VFS_FIND(listxattr);
2304         return handle->fns->listxattr_fn(handle, path, list, size);
2305 }
2306
2307 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2308                                 struct files_struct *fsp, char *list,
2309                                 size_t size)
2310 {
2311         VFS_FIND(flistxattr);
2312         return handle->fns->flistxattr_fn(handle, fsp, list, size);
2313 }
2314
2315 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2316                              const char *path, const char *name)
2317 {
2318         VFS_FIND(removexattr);
2319         return handle->fns->removexattr_fn(handle, path, name);
2320 }
2321
2322 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2323                               struct files_struct *fsp, const char *name)
2324 {
2325         VFS_FIND(fremovexattr);
2326         return handle->fns->fremovexattr_fn(handle, fsp, name);
2327 }
2328
2329 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle, const char *path,
2330                           const char *name, const void *value, size_t size,
2331                           int flags)
2332 {
2333         VFS_FIND(setxattr);
2334         return handle->fns->setxattr_fn(handle, path, name, value, size, flags);
2335 }
2336
2337 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2338                            struct files_struct *fsp, const char *name,
2339                            const void *value, size_t size, int flags)
2340 {
2341         VFS_FIND(fsetxattr);
2342         return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2343 }
2344
2345 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2346                             struct files_struct *fsp)
2347 {
2348         VFS_FIND(aio_force);
2349         return handle->fns->aio_force_fn(handle, fsp);
2350 }
2351
2352 bool smb_vfs_call_is_offline(struct vfs_handle_struct *handle,
2353                              const struct smb_filename *fname,
2354                              SMB_STRUCT_STAT *sbuf)
2355 {
2356         VFS_FIND(is_offline);
2357         return handle->fns->is_offline_fn(handle, fname, sbuf);
2358 }
2359
2360 int smb_vfs_call_set_offline(struct vfs_handle_struct *handle,
2361                              const struct smb_filename *fname)
2362 {
2363         VFS_FIND(set_offline);
2364         return handle->fns->set_offline_fn(handle, fname);
2365 }
2366
2367 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2368                                      struct files_struct *fsp,
2369                                      TALLOC_CTX *mem_ctx,
2370                                      DATA_BLOB *cookie)
2371 {
2372         VFS_FIND(durable_cookie);
2373         return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2374 }
2375
2376 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2377                                          struct files_struct *fsp,
2378                                          const DATA_BLOB old_cookie,
2379                                          TALLOC_CTX *mem_ctx,
2380                                          DATA_BLOB *new_cookie)
2381 {
2382         VFS_FIND(durable_disconnect);
2383         return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2384                                                   mem_ctx, new_cookie);
2385 }
2386
2387 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2388                                         struct smb_request *smb1req,
2389                                         struct smbXsrv_open *op,
2390                                         const DATA_BLOB old_cookie,
2391                                         TALLOC_CTX *mem_ctx,
2392                                         struct files_struct **fsp,
2393                                         DATA_BLOB *new_cookie)
2394 {
2395         VFS_FIND(durable_reconnect);
2396         return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2397                                                  old_cookie, mem_ctx, fsp,
2398                                                  new_cookie);
2399 }