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