s3: VFS: Remove SMB_VFS_FCHMOD_ACL().
[samba.git] / source3 / smbd / vfs.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    VFS initialisation and support functions
5    Copyright (C) Tim Potter 1999
6    Copyright (C) Alexander Bokovoy 2002
7    Copyright (C) James Peach 2006
8    Copyright (C) Volker Lendecke 2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23    This work was sponsored by Optifacio Software Services, Inc.
24 */
25
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "../lib/util/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(NULL);
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_t *)(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  * Ensure this module catches all VFS functions.
321  */
322 #ifdef DEVELOPER
323 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
324                             const char *module)
325 {
326         bool missing_fn = false;
327         unsigned int idx;
328         const uintptr_t *end = (const uintptr_t *)(fns + 1);
329
330         for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
331                 if (*((const uintptr_t *)fns + idx) == 0) {
332                         DBG_ERR("VFS function at index %d not implemented "
333                                 "in module %s\n", idx, module);
334                         missing_fn = true;
335                 }
336         }
337
338         if (missing_fn) {
339                 smb_panic("Required VFS function not implemented in module.\n");
340         }
341 }
342 #else
343 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
344                             const char *module)
345 {
346 }
347 #endif
348
349 /*****************************************************************
350  Generic VFS init.
351 ******************************************************************/
352
353 bool smbd_vfs_init(connection_struct *conn)
354 {
355         const char **vfs_objects;
356         unsigned int i = 0;
357         int j = 0;
358
359         /* Normal share - initialise with disk access functions */
360         vfs_init_default(conn);
361
362         /* No need to load vfs modules for printer connections */
363         if (conn->printer) {
364                 return True;
365         }
366
367         vfs_objects = lp_vfs_objects(SNUM(conn));
368
369         /* Override VFS functions if 'vfs object' was not specified*/
370         if (!vfs_objects || !vfs_objects[0])
371                 return True;
372
373         for (i=0; vfs_objects[i] ;) {
374                 i++;
375         }
376
377         for (j=i-1; j >= 0; j--) {
378                 if (!vfs_init_custom(conn, vfs_objects[j])) {
379                         DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
380                         return False;
381                 }
382         }
383         return True;
384 }
385
386 /*******************************************************************
387  Check if a file exists in the vfs.
388 ********************************************************************/
389
390 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
391 {
392         /* Only return OK if stat was successful and S_ISREG */
393         if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
394             S_ISREG(smb_fname->st.st_ex_mode)) {
395                 return NT_STATUS_OK;
396         }
397
398         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
399 }
400
401 ssize_t vfs_pwrite_data(struct smb_request *req,
402                         files_struct *fsp,
403                         const char *buffer,
404                         size_t N,
405                         off_t offset)
406 {
407         size_t total=0;
408         ssize_t ret;
409
410         if (req && req->unread_bytes) {
411                 int sockfd = req->xconn->transport.sock;
412                 SMB_ASSERT(req->unread_bytes == N);
413                 /* VFS_RECVFILE must drain the socket
414                  * before returning. */
415                 req->unread_bytes = 0;
416                 /*
417                  * Leave the socket non-blocking and
418                  * use SMB_VFS_RECVFILE. If it returns
419                  * EAGAIN || EWOULDBLOCK temporarily set
420                  * the socket blocking and retry
421                  * the RECVFILE.
422                  */
423                 while (total < N) {
424                         ret = SMB_VFS_RECVFILE(sockfd,
425                                                 fsp,
426                                                 offset + total,
427                                                 N - total);
428                         if (ret == 0 || (ret == -1 &&
429                                          (errno == EAGAIN ||
430                                           errno == EWOULDBLOCK))) {
431                                 int old_flags;
432                                 /* Ensure the socket is blocking. */
433                                 old_flags = fcntl(sockfd, F_GETFL, 0);
434                                 if (set_blocking(sockfd, true) == -1) {
435                                         return (ssize_t)-1;
436                                 }
437                                 ret = SMB_VFS_RECVFILE(sockfd,
438                                                         fsp,
439                                                         offset + total,
440                                                         N - total);
441                                 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
442                                         return (ssize_t)-1;
443                                 }
444                                 if (ret == -1) {
445                                         return (ssize_t)-1;
446                                 }
447                                 total += ret;
448                                 return (ssize_t)total;
449                         }
450                         /* Any other error case. */
451                         if (ret == -1) {
452                                 return ret;
453                         }
454                         total += ret;
455                 }
456                 return (ssize_t)total;
457         }
458
459         while (total < N) {
460                 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
461                                      offset + total);
462
463                 if (ret == -1)
464                         return -1;
465                 if (ret == 0)
466                         return total;
467
468                 total += ret;
469         }
470         return (ssize_t)total;
471 }
472 /****************************************************************************
473  An allocate file space call using the vfs interface.
474  Allocates space for a file from a filedescriptor.
475  Returns 0 on success, -1 on failure.
476 ****************************************************************************/
477
478 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
479 {
480         int ret;
481         connection_struct *conn = fsp->conn;
482         uint64_t space_avail;
483         uint64_t bsize,dfree,dsize;
484         NTSTATUS status;
485
486         /*
487          * Actually try and commit the space on disk....
488          */
489
490         DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
491                   fsp_str_dbg(fsp), (double)len));
492
493         if (((off_t)len) < 0) {
494                 DEBUG(0,("vfs_allocate_file_space: %s negative len "
495                          "requested.\n", fsp_str_dbg(fsp)));
496                 errno = EINVAL;
497                 return -1;
498         }
499
500         status = vfs_stat_fsp(fsp);
501         if (!NT_STATUS_IS_OK(status)) {
502                 return -1;
503         }
504
505         if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
506                 return 0;
507
508         if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
509                 /* Shrink - use ftruncate. */
510
511                 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
512                           "size %.0f\n", fsp_str_dbg(fsp),
513                           (double)fsp->fsp_name->st.st_ex_size));
514
515                 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
516
517                 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
518                 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
519                         set_filelen_write_cache(fsp, len);
520                 }
521
522                 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
523
524                 return ret;
525         }
526
527         /* Grow - we need to test if we have enough space. */
528
529         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
530
531         if (lp_strict_allocate(SNUM(fsp->conn))) {
532                 /* See if we have a syscall that will allocate beyond
533                    end-of-file without changing EOF. */
534                 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
535                                         0, len);
536         } else {
537                 ret = 0;
538         }
539
540         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
541
542         if (ret == 0) {
543                 /* We changed the allocation size on disk, but not
544                    EOF - exactly as required. We're done ! */
545                 return 0;
546         }
547
548         if (ret == -1 && errno == ENOSPC) {
549                 return -1;
550         }
551
552         len -= fsp->fsp_name->st.st_ex_size;
553         len /= 1024; /* Len is now number of 1k blocks needed. */
554         space_avail =
555             get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
556         if (space_avail == (uint64_t)-1) {
557                 return -1;
558         }
559
560         DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
561                   "needed blocks = %.0f, space avail = %.0f\n",
562                   fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
563                   (double)space_avail));
564
565         if (len > space_avail) {
566                 errno = ENOSPC;
567                 return -1;
568         }
569
570         return 0;
571 }
572
573 /****************************************************************************
574  A vfs set_filelen call.
575  set the length of a file from a filedescriptor.
576  Returns 0 on success, -1 on failure.
577 ****************************************************************************/
578
579 int vfs_set_filelen(files_struct *fsp, off_t len)
580 {
581         int ret;
582
583         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
584
585         DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
586                   fsp_str_dbg(fsp), (double)len));
587         flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
588         if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
589                 set_filelen_write_cache(fsp, len);
590                 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
591                              FILE_NOTIFY_CHANGE_SIZE
592                              | FILE_NOTIFY_CHANGE_ATTRIBUTES,
593                              fsp->fsp_name->base_name);
594         }
595
596         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
597
598         return ret;
599 }
600
601 /****************************************************************************
602  A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
603  fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
604  as this is also called from the default SMB_VFS_FTRUNCATE code.
605  Always extends the file size.
606  Returns 0 on success, -1 on failure.
607 ****************************************************************************/
608
609 #define SPARSE_BUF_WRITE_SIZE (32*1024)
610
611 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
612 {
613         ssize_t pwrite_ret;
614         size_t total = 0;
615
616         if (!sparse_buf) {
617                 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
618                 if (!sparse_buf) {
619                         errno = ENOMEM;
620                         return -1;
621                 }
622         }
623
624         while (total < len) {
625                 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
626
627                 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
628                 if (pwrite_ret == -1) {
629                         int saved_errno = errno;
630                         DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
631                                   "%s failed with error %s\n",
632                                   fsp_str_dbg(fsp), strerror(saved_errno)));
633                         errno = saved_errno;
634                         return -1;
635                 }
636                 total += pwrite_ret;
637         }
638
639         return 0;
640 }
641
642 /****************************************************************************
643  A vfs fill sparse call.
644  Writes zeros from the end of file to len, if len is greater than EOF.
645  Used only by strict_sync.
646  Returns 0 on success, -1 on failure.
647 ****************************************************************************/
648
649 int vfs_fill_sparse(files_struct *fsp, off_t len)
650 {
651         int ret;
652         NTSTATUS status;
653         off_t offset;
654         size_t num_to_write;
655
656         status = vfs_stat_fsp(fsp);
657         if (!NT_STATUS_IS_OK(status)) {
658                 return -1;
659         }
660
661         if (len <= fsp->fsp_name->st.st_ex_size) {
662                 return 0;
663         }
664
665 #ifdef S_ISFIFO
666         if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
667                 return 0;
668         }
669 #endif
670
671         DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
672                   "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
673                   (double)fsp->fsp_name->st.st_ex_size, (double)len,
674                   (double)(len - fsp->fsp_name->st.st_ex_size)));
675
676         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
677
678         flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
679
680         offset = fsp->fsp_name->st.st_ex_size;
681         num_to_write = len - fsp->fsp_name->st.st_ex_size;
682
683         /* Only do this on non-stream file handles. */
684         if (fsp->base_fsp == NULL) {
685                 /* for allocation try fallocate first. This can fail on some
686                  * platforms e.g. when the filesystem doesn't support it and no
687                  * emulation is being done by the libc (like on AIX with JFS1). In that
688                  * case we do our own emulation. fallocate implementations can
689                  * return ENOTSUP or EINVAL in cases like that. */
690                 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
691                 if (ret == -1 && errno == ENOSPC) {
692                         goto out;
693                 }
694                 if (ret == 0) {
695                         goto out;
696                 }
697                 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
698                         "error %d. Falling back to slow manual allocation\n", ret));
699         }
700
701         ret = vfs_slow_fallocate(fsp, offset, num_to_write);
702
703  out:
704
705         if (ret == 0) {
706                 set_filelen_write_cache(fsp, len);
707         }
708
709         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
710         return ret;
711 }
712
713 /****************************************************************************
714  Transfer some data (n bytes) between two file_struct's.
715 ****************************************************************************/
716
717 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
718 {
719         struct files_struct *fsp = (struct files_struct *)file;
720
721         return SMB_VFS_PREAD(fsp, buf, len, offset);
722 }
723
724 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
725 {
726         struct files_struct *fsp = (struct files_struct *)file;
727
728         return SMB_VFS_PWRITE(fsp, buf, len, offset);
729 }
730
731 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
732 {
733         return transfer_file_internal((void *)in, (void *)out, n,
734                                       vfs_pread_fn, vfs_pwrite_fn);
735 }
736
737 /*******************************************************************
738  A vfs_readdir wrapper which just returns the file name.
739 ********************************************************************/
740
741 const char *vfs_readdirname(connection_struct *conn, void *p,
742                             SMB_STRUCT_STAT *sbuf, char **talloced)
743 {
744         struct dirent *ptr= NULL;
745         const char *dname;
746         char *translated;
747         NTSTATUS status;
748
749         if (!p)
750                 return(NULL);
751
752         ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
753         if (!ptr)
754                 return(NULL);
755
756         dname = ptr->d_name;
757
758
759 #ifdef NEXT2
760         if (telldir(p) < 0)
761                 return(NULL);
762 #endif
763
764 #ifdef HAVE_BROKEN_READDIR_NAME
765         /* using /usr/ucb/cc is BAD */
766         dname = dname - 2;
767 #endif
768
769         status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
770                                         talloc_tos(), &translated);
771         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
772                 *talloced = NULL;
773                 return dname;
774         }
775         *talloced = translated;
776         if (!NT_STATUS_IS_OK(status)) {
777                 return NULL;
778         }
779         return translated;
780 }
781
782 /*******************************************************************
783  A wrapper for vfs_chdir().
784 ********************************************************************/
785
786 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
787 {
788         int ret;
789         int saved_errno = 0;
790         struct smb_filename *saved_cwd = NULL;
791
792         if (!LastDir) {
793                 LastDir = SMB_STRDUP("");
794         }
795
796         if (ISDOT(smb_fname->base_name)) {
797                 return 0;
798         }
799
800         if (*smb_fname->base_name == '/' &&
801                         strcsequal(LastDir,smb_fname->base_name)) {
802                 return 0;
803         }
804
805         if (conn->cwd_fname != NULL) {
806                 /*
807                  * Save off where we are in case we need to return
808                  * on vfs_GetWd() failure after successful SMB_VFS_CHDIR().
809                  */
810                 saved_cwd = cp_smb_filename(conn, conn->cwd_fname);
811                 if (saved_cwd == NULL) {
812                         return -1;
813                 }
814         }
815
816         DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
817
818         ret = SMB_VFS_CHDIR(conn, smb_fname);
819         if (ret != 0) {
820                 saved_errno = errno;
821                 TALLOC_FREE(saved_cwd);
822                 errno = saved_errno;
823                 return -1;
824         }
825
826         /*
827          * Always replace conn->cwd_fname. We
828          * don't know if it's been modified by
829          * VFS modules in the stack.
830          */
831
832         /* conn cache. */
833         TALLOC_FREE(conn->cwd_fname);
834         conn->cwd_fname = vfs_GetWd(conn, conn);
835         if (conn->cwd_fname == NULL) {
836                 /*
837                  * vfs_GetWd() failed.
838                  * We must be able to read cwd.
839                  * Return to original directory
840                  * and return -1.
841                  */
842                 saved_errno = errno;
843
844                 if (saved_cwd == NULL) {
845                         /*
846                          * Failed on the very first chdir()+getwd()
847                          * for this connection. We can't
848                          * continue.
849                          */
850                         smb_panic("conn->cwd getwd failed\n");
851                         /* NOTREACHED */
852                         return -1;
853                 }
854
855                 /* Return to the previous $cwd. */
856                 ret = SMB_VFS_CHDIR(conn, saved_cwd);
857                 if (ret != 0) {
858                         smb_panic("conn->cwd getwd failed\n");
859                         /* NOTREACHED */
860                         return -1;
861                 }
862                 /* Restore original conn->cwd_fname. */
863                 conn->cwd_fname = saved_cwd;
864                 errno = saved_errno;
865                 /* And fail the chdir(). */
866                 return -1;
867         }
868
869         /* vfs_GetWd() succeeded. */
870         /* Replace global cache. */
871         SAFE_FREE(LastDir);
872         LastDir = SMB_STRDUP(smb_fname->base_name);
873
874         DEBUG(4,("vfs_ChDir got %s\n", conn->cwd_fname->base_name));
875
876         TALLOC_FREE(saved_cwd);
877         if (saved_errno != 0) {
878                 errno = saved_errno;
879         }
880         return ret;
881 }
882
883 /*******************************************************************
884  Return the absolute current directory path - given a UNIX pathname.
885  Note that this path is returned in DOS format, not UNIX
886  format. Note this can be called with conn == NULL.
887 ********************************************************************/
888
889 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
890 {
891         struct smb_filename *current_dir_fname = NULL;
892         struct file_id key;
893         struct smb_filename *smb_fname_dot = NULL;
894         struct smb_filename *smb_fname_full = NULL;
895         struct smb_filename *result = NULL;
896
897         if (!lp_getwd_cache()) {
898                 goto nocache;
899         }
900
901         smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
902         if (smb_fname_dot == NULL) {
903                 errno = ENOMEM;
904                 goto out;
905         }
906
907         if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
908                 /*
909                  * Known to fail for root: the directory may be NFS-mounted
910                  * and exported with root_squash (so has no root access).
911                  */
912                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
913                          "(NFS problem ?)\n", strerror(errno) ));
914                 goto nocache;
915         }
916
917         key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
918
919         smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
920                                         smbd_memcache(),
921                                         GETWD_CACHE,
922                                         data_blob_const(&key, sizeof(key)));
923
924         if (smb_fname_full == NULL) {
925                 goto nocache;
926         }
927
928         if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
929             (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
930             (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
931             (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
932                 /*
933                  * Ok, we're done
934                  * Note: smb_fname_full is owned by smbd_memcache()
935                  * so we must make a copy to return.
936                  */
937                 result = cp_smb_filename(ctx, smb_fname_full);
938                 if (result == NULL) {
939                         errno = ENOMEM;
940                 }
941                 goto out;
942         }
943
944  nocache:
945
946         /*
947          * We don't have the information to hand so rely on traditional
948          * methods. The very slow getcwd, which spawns a process on some
949          * systems, or the not quite so bad getwd.
950          */
951
952         current_dir_fname = SMB_VFS_GETWD(conn, ctx);
953         if (current_dir_fname == NULL) {
954                 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
955                           strerror(errno)));
956                 goto out;
957         }
958
959         if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
960                 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
961
962                 /*
963                  * smbd_memcache() will own current_dir_fname after the
964                  * memcache_add_talloc call, so we must make
965                  * a copy on ctx to return.
966                  */
967                 result = cp_smb_filename(ctx, current_dir_fname);
968                 if (result == NULL) {
969                         errno = ENOMEM;
970                 }
971
972                 /*
973                  * Ensure the memory going into the cache
974                  * doesn't have a destructor so it can be
975                  * cleanly freed.
976                  */
977                 talloc_set_destructor(current_dir_fname, NULL);
978
979                 memcache_add_talloc(smbd_memcache(),
980                                 GETWD_CACHE,
981                                 data_blob_const(&key, sizeof(key)),
982                                 &current_dir_fname);
983                 /* current_dir_fname is now == NULL here. */
984         } else {
985                 /* current_dir_fname is already allocated on ctx. */
986                 result = current_dir_fname;
987         }
988
989  out:
990         TALLOC_FREE(smb_fname_dot);
991         /*
992          * Don't free current_dir_fname here. It's either been moved
993          * to the memcache or is being returned in result.
994          */
995         return result;
996 }
997
998 /*******************************************************************
999  Reduce a file name, removing .. elements and checking that
1000  it is below dir in the heirachy. This uses realpath.
1001  This function must run as root, and will return names
1002  and valid stat structs that can be checked on open.
1003 ********************************************************************/
1004
1005 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1006                         const struct smb_filename *smb_fname,
1007                         struct smb_request *smbreq)
1008 {
1009         NTSTATUS status;
1010         TALLOC_CTX *ctx = talloc_tos();
1011         const char *conn_rootdir;
1012         size_t rootdir_len;
1013         char *dir_name = NULL;
1014         char *resolved_name = NULL;
1015         const char *last_component = NULL;
1016         struct smb_filename *resolved_fname = NULL;
1017         struct smb_filename *saved_dir_fname = NULL;
1018         struct smb_filename *smb_fname_cwd = NULL;
1019         struct privilege_paths *priv_paths = NULL;
1020         int ret;
1021
1022         DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1023                         smb_fname->base_name,
1024                         conn->connectpath));
1025
1026
1027         priv_paths = talloc_zero(smbreq, struct privilege_paths);
1028         if (!priv_paths) {
1029                 status = NT_STATUS_NO_MEMORY;
1030                 goto err;
1031         }
1032
1033         if (!parent_dirname(ctx, smb_fname->base_name,
1034                         &dir_name, &last_component)) {
1035                 status = NT_STATUS_NO_MEMORY;
1036                 goto err;
1037         }
1038
1039         priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1040         priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1041
1042         if (priv_paths->parent_name.base_name == NULL ||
1043                         priv_paths->file_name.base_name == NULL) {
1044                 status = NT_STATUS_NO_MEMORY;
1045                 goto err;
1046         }
1047
1048         if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1049                 status = map_nt_error_from_unix(errno);
1050                 goto err;
1051         }
1052         /* Remember where we were. */
1053         saved_dir_fname = vfs_GetWd(ctx, conn);
1054         if (!saved_dir_fname) {
1055                 status = map_nt_error_from_unix(errno);
1056                 goto err;
1057         }
1058
1059         if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1060                 status = map_nt_error_from_unix(errno);
1061                 goto err;
1062         }
1063
1064         smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1065         if (smb_fname_cwd == NULL) {
1066                 status = NT_STATUS_NO_MEMORY;
1067                 goto err;
1068         }
1069
1070         /* Get the absolute path of the parent directory. */
1071         resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1072         if (resolved_fname == NULL) {
1073                 status = map_nt_error_from_unix(errno);
1074                 goto err;
1075         }
1076         resolved_name = resolved_fname->base_name;
1077
1078         if (*resolved_name != '/') {
1079                 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1080                         "doesn't return absolute paths !\n"));
1081                 status = NT_STATUS_OBJECT_NAME_INVALID;
1082                 goto err;
1083         }
1084
1085         DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1086                 priv_paths->parent_name.base_name,
1087                 resolved_name));
1088
1089         /* Now check the stat value is the same. */
1090         if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1091                 status = map_nt_error_from_unix(errno);
1092                 goto err;
1093         }
1094
1095         /* Ensure we're pointing at the same place. */
1096         if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1097                 DEBUG(0,("check_reduced_name_with_privilege: "
1098                         "device/inode/uid/gid on directory %s changed. "
1099                         "Denying access !\n",
1100                         priv_paths->parent_name.base_name));
1101                 status = NT_STATUS_ACCESS_DENIED;
1102                 goto err;
1103         }
1104
1105         /* Ensure we're below the connect path. */
1106
1107         conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1108         if (conn_rootdir == NULL) {
1109                 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1110                         "conn_rootdir\n"));
1111                 status = NT_STATUS_ACCESS_DENIED;
1112                 goto err;
1113         }
1114
1115         rootdir_len = strlen(conn_rootdir);
1116
1117         /*
1118          * In the case of rootdir_len == 1, we know that conn_rootdir is
1119          * "/", and we also know that resolved_name starts with a slash.
1120          * So, in this corner case, resolved_name is automatically a
1121          * sub-directory of the conn_rootdir. Thus we can skip the string
1122          * comparison and the next character checks (which are even
1123          * wrong in this case).
1124          */
1125         if (rootdir_len != 1) {
1126                 bool matched;
1127
1128                 matched = (strncmp(conn_rootdir, resolved_name,
1129                                 rootdir_len) == 0);
1130
1131                 if (!matched || (resolved_name[rootdir_len] != '/' &&
1132                                  resolved_name[rootdir_len] != '\0')) {
1133                         DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1134                                 "access attempt: %s is a symlink outside the "
1135                                 "share path\n",
1136                                 dir_name));
1137                         DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1138                         DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1139                         status = NT_STATUS_ACCESS_DENIED;
1140                         goto err;
1141                 }
1142         }
1143
1144         /* Now ensure that the last component either doesn't
1145            exist, or is *NOT* a symlink. */
1146
1147         ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1148         if (ret == -1) {
1149                 /* Errno must be ENOENT for this be ok. */
1150                 if (errno != ENOENT) {
1151                         status = map_nt_error_from_unix(errno);
1152                         DEBUG(2, ("check_reduced_name_with_privilege: "
1153                                 "LSTAT on %s failed with %s\n",
1154                                 priv_paths->file_name.base_name,
1155                                 nt_errstr(status)));
1156                         goto err;
1157                 }
1158         }
1159
1160         if (VALID_STAT(priv_paths->file_name.st) &&
1161                         S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1162                 DEBUG(2, ("check_reduced_name_with_privilege: "
1163                         "Last component %s is a symlink. Denying"
1164                         "access.\n",
1165                         priv_paths->file_name.base_name));
1166                 status = NT_STATUS_ACCESS_DENIED;
1167                 goto err;
1168         }
1169
1170         smbreq->priv_paths = priv_paths;
1171         status = NT_STATUS_OK;
1172
1173   err:
1174
1175         if (saved_dir_fname != NULL) {
1176                 vfs_ChDir(conn, saved_dir_fname);
1177                 TALLOC_FREE(saved_dir_fname);
1178         }
1179         TALLOC_FREE(resolved_fname);
1180         if (!NT_STATUS_IS_OK(status)) {
1181                 TALLOC_FREE(priv_paths);
1182         }
1183         TALLOC_FREE(dir_name);
1184         return status;
1185 }
1186
1187 /*******************************************************************
1188  Reduce a file name, removing .. elements and checking that
1189  it is below dir in the heirachy. This uses realpath.
1190
1191  If cwd_name == NULL then fname is a client given path relative
1192  to the root path of the share.
1193
1194  If cwd_name != NULL then fname is a client given path relative
1195  to cwd_name. cwd_name is relative to the root path of the share.
1196 ********************************************************************/
1197
1198 NTSTATUS check_reduced_name(connection_struct *conn,
1199                                 const struct smb_filename *cwd_fname,
1200                                 const struct smb_filename *smb_fname)
1201 {
1202         TALLOC_CTX *ctx = talloc_tos();
1203         const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1204         const char *fname = smb_fname->base_name;
1205         struct smb_filename *resolved_fname;
1206         char *resolved_name = NULL;
1207         char *new_fname = NULL;
1208         bool allow_symlinks = true;
1209         bool allow_widelinks = false;
1210
1211         DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1212
1213         resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1214
1215         if (resolved_fname == NULL) {
1216                 switch (errno) {
1217                         case ENOTDIR:
1218                                 DEBUG(3,("check_reduced_name: Component not a "
1219                                          "directory in getting realpath for "
1220                                          "%s\n", fname));
1221                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1222                         case ENOENT:
1223                         {
1224                                 char *dir_name = NULL;
1225                                 struct smb_filename dir_fname = {0};
1226                                 const char *last_component = NULL;
1227
1228                                 /* Last component didn't exist.
1229                                    Remove it and try and canonicalise
1230                                    the directory name. */
1231                                 if (!parent_dirname(ctx, fname,
1232                                                 &dir_name,
1233                                                 &last_component)) {
1234                                         return NT_STATUS_NO_MEMORY;
1235                                 }
1236
1237                                 dir_fname = (struct smb_filename)
1238                                         { .base_name = dir_name };
1239                                 resolved_fname = SMB_VFS_REALPATH(conn,
1240                                                         ctx,
1241                                                         &dir_fname);
1242                                 if (resolved_fname == NULL) {
1243                                         NTSTATUS status = map_nt_error_from_unix(errno);
1244
1245                                         if (errno == ENOENT || errno == ENOTDIR) {
1246                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1247                                         }
1248
1249                                         DEBUG(3,("check_reduce_name: "
1250                                                  "couldn't get realpath for "
1251                                                  "%s (%s)\n",
1252                                                 fname,
1253                                                 nt_errstr(status)));
1254                                         return status;
1255                                 }
1256                                 resolved_name = talloc_asprintf(ctx,
1257                                                 "%s/%s",
1258                                                 resolved_fname->base_name,
1259                                                 last_component);
1260                                 if (resolved_name == NULL) {
1261                                         return NT_STATUS_NO_MEMORY;
1262                                 }
1263                                 break;
1264                         }
1265                         default:
1266                                 DEBUG(3,("check_reduced_name: couldn't get "
1267                                          "realpath for %s\n", fname));
1268                                 return map_nt_error_from_unix(errno);
1269                 }
1270         } else {
1271                 resolved_name = resolved_fname->base_name;
1272         }
1273
1274         DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1275                   resolved_name));
1276
1277         if (*resolved_name != '/') {
1278                 DEBUG(0,("check_reduced_name: realpath doesn't return "
1279                          "absolute paths !\n"));
1280                 TALLOC_FREE(resolved_fname);
1281                 return NT_STATUS_OBJECT_NAME_INVALID;
1282         }
1283
1284         allow_widelinks = lp_widelinks(SNUM(conn));
1285         allow_symlinks = lp_follow_symlinks(SNUM(conn));
1286
1287         /* Common widelinks and symlinks checks. */
1288         if (!allow_widelinks || !allow_symlinks) {
1289                 const char *conn_rootdir;
1290                 size_t rootdir_len;
1291
1292                 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1293                 if (conn_rootdir == NULL) {
1294                         DEBUG(2, ("check_reduced_name: Could not get "
1295                                 "conn_rootdir\n"));
1296                         TALLOC_FREE(resolved_fname);
1297                         return NT_STATUS_ACCESS_DENIED;
1298                 }
1299
1300                 rootdir_len = strlen(conn_rootdir);
1301
1302                 /*
1303                  * In the case of rootdir_len == 1, we know that
1304                  * conn_rootdir is "/", and we also know that
1305                  * resolved_name starts with a slash.  So, in this
1306                  * corner case, resolved_name is automatically a
1307                  * sub-directory of the conn_rootdir. Thus we can skip
1308                  * the string comparison and the next character checks
1309                  * (which are even wrong in this case).
1310                  */
1311                 if (rootdir_len != 1) {
1312                         bool matched;
1313
1314                         matched = (strncmp(conn_rootdir, resolved_name,
1315                                         rootdir_len) == 0);
1316                         if (!matched || (resolved_name[rootdir_len] != '/' &&
1317                                          resolved_name[rootdir_len] != '\0')) {
1318                                 DEBUG(2, ("check_reduced_name: Bad access "
1319                                         "attempt: %s is a symlink outside the "
1320                                         "share path\n", fname));
1321                                 DEBUGADD(2, ("conn_rootdir =%s\n",
1322                                              conn_rootdir));
1323                                 DEBUGADD(2, ("resolved_name=%s\n",
1324                                              resolved_name));
1325                                 TALLOC_FREE(resolved_fname);
1326                                 return NT_STATUS_ACCESS_DENIED;
1327                         }
1328                 }
1329
1330                 /* Extra checks if all symlinks are disallowed. */
1331                 if (!allow_symlinks) {
1332                         /* fname can't have changed in resolved_path. */
1333                         const char *p = &resolved_name[rootdir_len];
1334
1335                         /*
1336                          * UNIX filesystem semantics, names consisting
1337                          * only of "." or ".." CANNOT be symlinks.
1338                          */
1339                         if (ISDOT(fname) || ISDOTDOT(fname)) {
1340                                 goto out;
1341                         }
1342
1343                         if (*p != '/') {
1344                                 DEBUG(2, ("check_reduced_name: logic error (%c) "
1345                                         "in resolved_name: %s\n",
1346                                         *p,
1347                                         fname));
1348                                 TALLOC_FREE(resolved_fname);
1349                                 return NT_STATUS_ACCESS_DENIED;
1350                         }
1351
1352                         p++;
1353
1354                         /*
1355                          * If cwd_name is present and not ".",
1356                          * then fname is relative to that, not
1357                          * the root of the share. Make sure the
1358                          * path we check is the one the client
1359                          * sent (cwd_name+fname).
1360                          */
1361                         if (cwd_name != NULL && !ISDOT(cwd_name)) {
1362                                 new_fname = talloc_asprintf(ctx,
1363                                                         "%s/%s",
1364                                                         cwd_name,
1365                                                         fname);
1366                                 if (new_fname == NULL) {
1367                                         TALLOC_FREE(resolved_fname);
1368                                         return NT_STATUS_NO_MEMORY;
1369                                 }
1370                                 fname = new_fname;
1371                         }
1372
1373                         if (strcmp(fname, p)!=0) {
1374                                 DEBUG(2, ("check_reduced_name: Bad access "
1375                                         "attempt: %s is a symlink to %s\n",
1376                                           fname, p));
1377                                 TALLOC_FREE(resolved_fname);
1378                                 TALLOC_FREE(new_fname);
1379                                 return NT_STATUS_ACCESS_DENIED;
1380                         }
1381                 }
1382         }
1383
1384   out:
1385
1386         DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1387         TALLOC_FREE(resolved_fname);
1388         TALLOC_FREE(new_fname);
1389         return NT_STATUS_OK;
1390 }
1391
1392 /**
1393  * XXX: This is temporary and there should be no callers of this once
1394  * smb_filename is plumbed through all path based operations.
1395  *
1396  * Called when we know stream name parsing has already been done.
1397  */
1398 int vfs_stat_smb_basename(struct connection_struct *conn,
1399                         const struct smb_filename *smb_fname_in,
1400                         SMB_STRUCT_STAT *psbuf)
1401 {
1402         struct smb_filename smb_fname = {
1403                 .base_name = discard_const_p(char, smb_fname_in->base_name),
1404                 .flags = smb_fname_in->flags
1405         };
1406         int ret;
1407
1408         if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1409                 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1410         } else {
1411                 ret = SMB_VFS_STAT(conn, &smb_fname);
1412         }
1413
1414         if (ret != -1) {
1415                 *psbuf = smb_fname.st;
1416         }
1417         return ret;
1418 }
1419
1420 /**
1421  * Ensure LSTAT is called for POSIX paths.
1422  */
1423
1424 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1425 {
1426         int ret;
1427
1428         if(fsp->fh->fd == -1) {
1429                 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1430                         ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1431                 } else {
1432                         ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1433                 }
1434                 if (ret == -1) {
1435                         return map_nt_error_from_unix(errno);
1436                 }
1437         } else {
1438                 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1439                         return map_nt_error_from_unix(errno);
1440                 }
1441         }
1442         return NT_STATUS_OK;
1443 }
1444
1445 /**
1446  * Initialize num_streams and streams, then call VFS op streaminfo
1447  */
1448 NTSTATUS vfs_streaminfo(connection_struct *conn,
1449                         struct files_struct *fsp,
1450                         const struct smb_filename *smb_fname,
1451                         TALLOC_CTX *mem_ctx,
1452                         unsigned int *num_streams,
1453                         struct stream_struct **streams)
1454 {
1455         *num_streams = 0;
1456         *streams = NULL;
1457         return SMB_VFS_STREAMINFO(conn,
1458                         fsp,
1459                         smb_fname,
1460                         mem_ctx,
1461                         num_streams,
1462                         streams);
1463 }
1464
1465 /*
1466   generate a file_id from a stat structure
1467  */
1468 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1469 {
1470         return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1471 }
1472
1473 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1474                          const char *service, const char *user)
1475 {
1476         VFS_FIND(connect);
1477         return handle->fns->connect_fn(handle, service, user);
1478 }
1479
1480 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1481 {
1482         VFS_FIND(disconnect);
1483         handle->fns->disconnect_fn(handle);
1484 }
1485
1486 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1487                                 const struct smb_filename *smb_fname,
1488                                 uint64_t *bsize,
1489                                 uint64_t *dfree,
1490                                 uint64_t *dsize)
1491 {
1492         VFS_FIND(disk_free);
1493         return handle->fns->disk_free_fn(handle, smb_fname,
1494                         bsize, dfree, dsize);
1495 }
1496
1497 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1498                                 const struct smb_filename *smb_fname,
1499                                 enum SMB_QUOTA_TYPE qtype,
1500                                 unid_t id,
1501                                 SMB_DISK_QUOTA *qt)
1502 {
1503         VFS_FIND(get_quota);
1504         return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1505 }
1506
1507 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1508                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1509                            SMB_DISK_QUOTA *qt)
1510 {
1511         VFS_FIND(set_quota);
1512         return handle->fns->set_quota_fn(handle, qtype, id, qt);
1513 }
1514
1515 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1516                                       struct files_struct *fsp,
1517                                       struct shadow_copy_data *shadow_copy_data,
1518                                       bool labels)
1519 {
1520         VFS_FIND(get_shadow_copy_data);
1521         return handle->fns->get_shadow_copy_data_fn(handle, fsp, 
1522                                                     shadow_copy_data,
1523                                                     labels);
1524 }
1525 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1526                         const struct smb_filename *smb_fname,
1527                         struct vfs_statvfs_struct *statbuf)
1528 {
1529         VFS_FIND(statvfs);
1530         return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1531 }
1532
1533 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1534                         enum timestamp_set_resolution *p_ts_res)
1535 {
1536         VFS_FIND(fs_capabilities);
1537         return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1538 }
1539
1540 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1541                                         struct dfs_GetDFSReferral *r)
1542 {
1543         VFS_FIND(get_dfs_referrals);
1544         return handle->fns->get_dfs_referrals_fn(handle, r);
1545 }
1546
1547 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1548                                         const struct smb_filename *smb_fname,
1549                                         const char *mask,
1550                                         uint32_t attributes)
1551 {
1552         VFS_FIND(opendir);
1553         return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1554 }
1555
1556 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1557                                         struct files_struct *fsp,
1558                                         const char *mask,
1559                                         uint32_t attributes)
1560 {
1561         VFS_FIND(fdopendir);
1562         return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1563 }
1564
1565 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1566                                               DIR *dirp,
1567                                               SMB_STRUCT_STAT *sbuf)
1568 {
1569         VFS_FIND(readdir);
1570         return handle->fns->readdir_fn(handle, dirp, sbuf);
1571 }
1572
1573 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1574                           DIR *dirp, long offset)
1575 {
1576         VFS_FIND(seekdir);
1577         handle->fns->seekdir_fn(handle, dirp, offset);
1578 }
1579
1580 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1581                           DIR *dirp)
1582 {
1583         VFS_FIND(telldir);
1584         return handle->fns->telldir_fn(handle, dirp);
1585 }
1586
1587 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1588                              DIR *dirp)
1589 {
1590         VFS_FIND(rewind_dir);
1591         handle->fns->rewind_dir_fn(handle, dirp);
1592 }
1593
1594 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1595                         const struct smb_filename *smb_fname,
1596                         mode_t mode)
1597 {
1598         VFS_FIND(mkdir);
1599         return handle->fns->mkdir_fn(handle, smb_fname, mode);
1600 }
1601
1602 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1603                         const struct smb_filename *smb_fname)
1604 {
1605         VFS_FIND(rmdir);
1606         return handle->fns->rmdir_fn(handle, smb_fname);
1607 }
1608
1609 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1610                           DIR *dir)
1611 {
1612         VFS_FIND(closedir);
1613         return handle->fns->closedir_fn(handle, dir);
1614 }
1615
1616 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1617                       struct smb_filename *smb_fname, struct files_struct *fsp,
1618                       int flags, mode_t mode)
1619 {
1620         VFS_FIND(open);
1621         return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1622 }
1623
1624 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1625                                   struct smb_request *req,
1626                                   uint16_t root_dir_fid,
1627                                   struct smb_filename *smb_fname,
1628                                   uint32_t access_mask,
1629                                   uint32_t share_access,
1630                                   uint32_t create_disposition,
1631                                   uint32_t create_options,
1632                                   uint32_t file_attributes,
1633                                   uint32_t oplock_request,
1634                                   struct smb2_lease *lease,
1635                                   uint64_t allocation_size,
1636                                   uint32_t private_flags,
1637                                   struct security_descriptor *sd,
1638                                   struct ea_list *ea_list,
1639                                   files_struct **result,
1640                                   int *pinfo,
1641                                   const struct smb2_create_blobs *in_context_blobs,
1642                                   struct smb2_create_blobs *out_context_blobs)
1643 {
1644         VFS_FIND(create_file);
1645         return handle->fns->create_file_fn(
1646                 handle, req, root_dir_fid, smb_fname, access_mask,
1647                 share_access, create_disposition, create_options,
1648                 file_attributes, oplock_request, lease, allocation_size,
1649                 private_flags, sd, ea_list,
1650                 result, pinfo, in_context_blobs, out_context_blobs);
1651 }
1652
1653 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1654                        struct files_struct *fsp)
1655 {
1656         VFS_FIND(close);
1657         return handle->fns->close_fn(handle, fsp);
1658 }
1659
1660 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1661                            struct files_struct *fsp, void *data, size_t n,
1662                            off_t offset)
1663 {
1664         VFS_FIND(pread);
1665         return handle->fns->pread_fn(handle, fsp, data, n, offset);
1666 }
1667
1668 struct smb_vfs_call_pread_state {
1669         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1670         ssize_t retval;
1671         struct vfs_aio_state vfs_aio_state;
1672 };
1673
1674 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1675
1676 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1677                                            TALLOC_CTX *mem_ctx,
1678                                            struct tevent_context *ev,
1679                                            struct files_struct *fsp,
1680                                            void *data,
1681                                            size_t n, off_t offset)
1682 {
1683         struct tevent_req *req, *subreq;
1684         struct smb_vfs_call_pread_state *state;
1685
1686         req = tevent_req_create(mem_ctx, &state,
1687                                 struct smb_vfs_call_pread_state);
1688         if (req == NULL) {
1689                 return NULL;
1690         }
1691         VFS_FIND(pread_send);
1692         state->recv_fn = handle->fns->pread_recv_fn;
1693
1694         subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1695                                             offset);
1696         if (tevent_req_nomem(subreq, req)) {
1697                 return tevent_req_post(req, ev);
1698         }
1699         tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1700         return req;
1701 }
1702
1703 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1704 {
1705         struct tevent_req *req = tevent_req_callback_data(
1706                 subreq, struct tevent_req);
1707         struct smb_vfs_call_pread_state *state = tevent_req_data(
1708                 req, struct smb_vfs_call_pread_state);
1709
1710         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1711         TALLOC_FREE(subreq);
1712         if (state->retval == -1) {
1713                 tevent_req_error(req, state->vfs_aio_state.error);
1714                 return;
1715         }
1716         tevent_req_done(req);
1717 }
1718
1719 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1720                            struct vfs_aio_state *vfs_aio_state)
1721 {
1722         struct smb_vfs_call_pread_state *state = tevent_req_data(
1723                 req, struct smb_vfs_call_pread_state);
1724
1725         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1726                 return -1;
1727         }
1728         *vfs_aio_state = state->vfs_aio_state;
1729         return state->retval;
1730 }
1731
1732 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1733                             struct files_struct *fsp, const void *data,
1734                             size_t n, off_t offset)
1735 {
1736         VFS_FIND(pwrite);
1737         return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1738 }
1739
1740 struct smb_vfs_call_pwrite_state {
1741         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1742         ssize_t retval;
1743         struct vfs_aio_state vfs_aio_state;
1744 };
1745
1746 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1747
1748 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1749                                             TALLOC_CTX *mem_ctx,
1750                                             struct tevent_context *ev,
1751                                             struct files_struct *fsp,
1752                                             const void *data,
1753                                             size_t n, off_t offset)
1754 {
1755         struct tevent_req *req, *subreq;
1756         struct smb_vfs_call_pwrite_state *state;
1757
1758         req = tevent_req_create(mem_ctx, &state,
1759                                 struct smb_vfs_call_pwrite_state);
1760         if (req == NULL) {
1761                 return NULL;
1762         }
1763         VFS_FIND(pwrite_send);
1764         state->recv_fn = handle->fns->pwrite_recv_fn;
1765
1766         subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1767                                              offset);
1768         if (tevent_req_nomem(subreq, req)) {
1769                 return tevent_req_post(req, ev);
1770         }
1771         tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1772         return req;
1773 }
1774
1775 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1776 {
1777         struct tevent_req *req = tevent_req_callback_data(
1778                 subreq, struct tevent_req);
1779         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1780                 req, struct smb_vfs_call_pwrite_state);
1781
1782         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1783         TALLOC_FREE(subreq);
1784         if (state->retval == -1) {
1785                 tevent_req_error(req, state->vfs_aio_state.error);
1786                 return;
1787         }
1788         tevent_req_done(req);
1789 }
1790
1791 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1792                             struct vfs_aio_state *vfs_aio_state)
1793 {
1794         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1795                 req, struct smb_vfs_call_pwrite_state);
1796
1797         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1798                 return -1;
1799         }
1800         *vfs_aio_state = state->vfs_aio_state;
1801         return state->retval;
1802 }
1803
1804 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1805                              struct files_struct *fsp, off_t offset,
1806                              int whence)
1807 {
1808         VFS_FIND(lseek);
1809         return handle->fns->lseek_fn(handle, fsp, offset, whence);
1810 }
1811
1812 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1813                               files_struct *fromfsp, const DATA_BLOB *header,
1814                               off_t offset, size_t count)
1815 {
1816         VFS_FIND(sendfile);
1817         return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1818                                         count);
1819 }
1820
1821 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1822                               files_struct *tofsp, off_t offset,
1823                               size_t count)
1824 {
1825         VFS_FIND(recvfile);
1826         return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1827 }
1828
1829 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1830                         const struct smb_filename *smb_fname_src,
1831                         const struct smb_filename *smb_fname_dst)
1832 {
1833         VFS_FIND(rename);
1834         return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1835 }
1836
1837 struct smb_vfs_call_fsync_state {
1838         int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1839         int retval;
1840         struct vfs_aio_state vfs_aio_state;
1841 };
1842
1843 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1844
1845 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1846                                            TALLOC_CTX *mem_ctx,
1847                                            struct tevent_context *ev,
1848                                            struct files_struct *fsp)
1849 {
1850         struct tevent_req *req, *subreq;
1851         struct smb_vfs_call_fsync_state *state;
1852
1853         req = tevent_req_create(mem_ctx, &state,
1854                                 struct smb_vfs_call_fsync_state);
1855         if (req == NULL) {
1856                 return NULL;
1857         }
1858         VFS_FIND(fsync_send);
1859         state->recv_fn = handle->fns->fsync_recv_fn;
1860
1861         subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1862         if (tevent_req_nomem(subreq, req)) {
1863                 return tevent_req_post(req, ev);
1864         }
1865         tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1866         return req;
1867 }
1868
1869 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1870 {
1871         struct tevent_req *req = tevent_req_callback_data(
1872                 subreq, struct tevent_req);
1873         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1874                 req, struct smb_vfs_call_fsync_state);
1875
1876         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1877         TALLOC_FREE(subreq);
1878         if (state->retval == -1) {
1879                 tevent_req_error(req, state->vfs_aio_state.error);
1880                 return;
1881         }
1882         tevent_req_done(req);
1883 }
1884
1885 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1886 {
1887         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1888                 req, struct smb_vfs_call_fsync_state);
1889
1890         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1891                 return -1;
1892         }
1893         *vfs_aio_state = state->vfs_aio_state;
1894         return state->retval;
1895 }
1896
1897 /*
1898  * Synchronous version of fsync, built from backend
1899  * async VFS primitives. Uses a temporary sub-event
1900  * context (NOT NESTED).
1901  */
1902
1903 int smb_vfs_fsync_sync(files_struct *fsp)
1904 {
1905         TALLOC_CTX *frame = talloc_stackframe();
1906         struct tevent_req *req = NULL;
1907         struct vfs_aio_state aio_state = { 0 };
1908         int ret = -1;
1909         bool ok;
1910         struct tevent_context *ev = samba_tevent_context_init(frame);
1911
1912         if (ev == NULL) {
1913                 goto out;
1914         }
1915
1916         req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
1917         if (req == NULL) {
1918                 goto out;
1919         }
1920
1921         ok = tevent_req_poll(req, ev);
1922         if (!ok) {
1923                 goto out;
1924         }
1925
1926         ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
1927
1928   out:
1929
1930         TALLOC_FREE(frame);
1931         if (aio_state.error != 0) {
1932                 errno = aio_state.error;
1933         }
1934         return ret;
1935 }
1936
1937 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1938                       struct smb_filename *smb_fname)
1939 {
1940         VFS_FIND(stat);
1941         return handle->fns->stat_fn(handle, smb_fname);
1942 }
1943
1944 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1945                        struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1946 {
1947         VFS_FIND(fstat);
1948         return handle->fns->fstat_fn(handle, fsp, sbuf);
1949 }
1950
1951 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1952                        struct smb_filename *smb_filename)
1953 {
1954         VFS_FIND(lstat);
1955         return handle->fns->lstat_fn(handle, smb_filename);
1956 }
1957
1958 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1959                                      struct files_struct *fsp,
1960                                      const SMB_STRUCT_STAT *sbuf)
1961 {
1962         VFS_FIND(get_alloc_size);
1963         return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1964 }
1965
1966 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1967                         const struct smb_filename *smb_fname)
1968 {
1969         VFS_FIND(unlink);
1970         return handle->fns->unlink_fn(handle, smb_fname);
1971 }
1972
1973 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1974                         const struct smb_filename *smb_fname,
1975                         mode_t mode)
1976 {
1977         VFS_FIND(chmod);
1978         return handle->fns->chmod_fn(handle, smb_fname, mode);
1979 }
1980
1981 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1982                         struct files_struct *fsp, mode_t mode)
1983 {
1984         VFS_FIND(fchmod);
1985         return handle->fns->fchmod_fn(handle, fsp, mode);
1986 }
1987
1988 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1989                         const struct smb_filename *smb_fname,
1990                         uid_t uid,
1991                         gid_t gid)
1992 {
1993         VFS_FIND(chown);
1994         return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1995 }
1996
1997 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1998                         struct files_struct *fsp, uid_t uid, gid_t gid)
1999 {
2000         VFS_FIND(fchown);
2001         return handle->fns->fchown_fn(handle, fsp, uid, gid);
2002 }
2003
2004 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2005                         const struct smb_filename *smb_fname,
2006                         uid_t uid,
2007                         gid_t gid)
2008 {
2009         VFS_FIND(lchown);
2010         return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2011 }
2012
2013 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2014 {
2015         int ret;
2016         bool as_root = false;
2017         NTSTATUS status;
2018
2019         if (fsp->fh->fd != -1) {
2020                 /* Try fchown. */
2021                 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2022                 if (ret == 0) {
2023                         return NT_STATUS_OK;
2024                 }
2025                 if (ret == -1 && errno != ENOSYS) {
2026                         return map_nt_error_from_unix(errno);
2027                 }
2028         }
2029
2030         as_root = (geteuid() == 0);
2031
2032         if (as_root) {
2033                 /*
2034                  * We are being asked to chown as root. Make
2035                  * sure we chdir() into the path to pin it,
2036                  * and always act using lchown to ensure we
2037                  * don't deref any symbolic links.
2038                  */
2039                 char *parent_dir = NULL;
2040                 const char *final_component = NULL;
2041                 struct smb_filename *local_smb_fname = NULL;
2042                 struct smb_filename parent_dir_fname = {0};
2043                 struct smb_filename *saved_dir_fname = NULL;
2044
2045                 saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
2046                 if (!saved_dir_fname) {
2047                         status = map_nt_error_from_unix(errno);
2048                         DEBUG(0,("vfs_chown_fsp: failed to get "
2049                                 "current working directory. Error was %s\n",
2050                                 strerror(errno)));
2051                         return status;
2052                 }
2053
2054                 if (!parent_dirname(talloc_tos(),
2055                                 fsp->fsp_name->base_name,
2056                                 &parent_dir,
2057                                 &final_component)) {
2058                         return NT_STATUS_NO_MEMORY;
2059                 }
2060
2061                 parent_dir_fname = (struct smb_filename) {
2062                         .base_name = parent_dir,
2063                         .flags = fsp->fsp_name->flags
2064                 };
2065
2066                 /* cd into the parent dir to pin it. */
2067                 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2068                 if (ret == -1) {
2069                         return map_nt_error_from_unix(errno);
2070                 }
2071
2072                 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2073                                         final_component,
2074                                         NULL,
2075                                         NULL,
2076                                         fsp->fsp_name->flags);
2077                 if (local_smb_fname == NULL) {
2078                         status = NT_STATUS_NO_MEMORY;
2079                         goto out;
2080                 }
2081
2082                 /* Must use lstat here. */
2083                 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2084                 if (ret == -1) {
2085                         status = map_nt_error_from_unix(errno);
2086                         goto out;
2087                 }
2088
2089                 /* Ensure it matches the fsp stat. */
2090                 if (!check_same_stat(&local_smb_fname->st,
2091                                 &fsp->fsp_name->st)) {
2092                         status = NT_STATUS_ACCESS_DENIED;
2093                         goto out;
2094                 }
2095
2096                 ret = SMB_VFS_LCHOWN(fsp->conn,
2097                         local_smb_fname,
2098                         uid, gid);
2099
2100                 if (ret == 0) {
2101                         status = NT_STATUS_OK;
2102                 } else {
2103                         status = map_nt_error_from_unix(errno);
2104                 }
2105
2106   out:
2107
2108                 vfs_ChDir(fsp->conn, saved_dir_fname);
2109                 TALLOC_FREE(local_smb_fname);
2110                 TALLOC_FREE(saved_dir_fname);
2111                 TALLOC_FREE(parent_dir);
2112
2113                 return status;
2114         }
2115
2116         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2117                 ret = SMB_VFS_LCHOWN(fsp->conn,
2118                         fsp->fsp_name,
2119                         uid, gid);
2120         } else {
2121                 ret = SMB_VFS_CHOWN(fsp->conn,
2122                         fsp->fsp_name,
2123                         uid, gid);
2124         }
2125
2126         if (ret == 0) {
2127                 status = NT_STATUS_OK;
2128         } else {
2129                 status = map_nt_error_from_unix(errno);
2130         }
2131         return status;
2132 }
2133
2134 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2135                         const struct smb_filename *smb_fname)
2136 {
2137         VFS_FIND(chdir);
2138         return handle->fns->chdir_fn(handle, smb_fname);
2139 }
2140
2141 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2142                                 TALLOC_CTX *ctx)
2143 {
2144         VFS_FIND(getwd);
2145         return handle->fns->getwd_fn(handle, ctx);
2146 }
2147
2148 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2149                         const struct smb_filename *smb_fname,
2150                         struct smb_file_time *ft)
2151 {
2152         VFS_FIND(ntimes);
2153         return handle->fns->ntimes_fn(handle, smb_fname, ft);
2154 }
2155
2156 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2157                            struct files_struct *fsp, off_t offset)
2158 {
2159         VFS_FIND(ftruncate);
2160         return handle->fns->ftruncate_fn(handle, fsp, offset);
2161 }
2162
2163 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2164                            struct files_struct *fsp,
2165                            uint32_t mode,
2166                            off_t offset,
2167                            off_t len)
2168 {
2169         VFS_FIND(fallocate);
2170         return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2171 }
2172
2173 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2174                               struct files_struct *fsp, uint32_t share_mode,
2175                               uint32_t access_mask)
2176 {
2177         VFS_FIND(kernel_flock);
2178         return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2179                                          access_mask);
2180 }
2181
2182 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2183                                 struct files_struct *fsp, int leasetype)
2184 {
2185         VFS_FIND(linux_setlease);
2186         return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2187 }
2188
2189 int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
2190                         const char *link_target,
2191                         const struct smb_filename *new_smb_fname)
2192 {
2193         VFS_FIND(symlink);
2194         return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
2195 }
2196
2197 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2198                         const struct smb_filename *smb_fname,
2199                         char *buf,
2200                         size_t bufsiz)
2201 {
2202         VFS_FIND(readlink);
2203         return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
2204 }
2205
2206 int smb_vfs_call_link(struct vfs_handle_struct *handle,
2207                         const struct smb_filename *old_smb_fname,
2208                         const struct smb_filename *new_smb_fname)
2209 {
2210         VFS_FIND(link);
2211         return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2212 }
2213
2214 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2215                         const struct smb_filename *smb_fname,
2216                         mode_t mode,
2217                         SMB_DEV_T dev)
2218 {
2219         VFS_FIND(mknod);
2220         return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2221 }
2222
2223 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2224                         TALLOC_CTX *ctx,
2225                         const struct smb_filename *smb_fname)
2226 {
2227         VFS_FIND(realpath);
2228         return handle->fns->realpath_fn(handle, ctx, smb_fname);
2229 }
2230
2231 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2232                         const struct smb_filename *smb_fname,
2233                         unsigned int flags)
2234 {
2235         VFS_FIND(chflags);
2236         return handle->fns->chflags_fn(handle, smb_fname, flags);
2237 }
2238
2239 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2240                                            const SMB_STRUCT_STAT *sbuf)
2241 {
2242         VFS_FIND(file_id_create);
2243         return handle->fns->file_id_create_fn(handle, sbuf);
2244 }
2245
2246 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2247                                  struct files_struct *fsp,
2248                                  const struct smb_filename *smb_fname,
2249                                  TALLOC_CTX *mem_ctx,
2250                                  unsigned int *num_streams,
2251                                  struct stream_struct **streams)
2252 {
2253         VFS_FIND(streaminfo);
2254         return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2255                                           num_streams, streams);
2256 }
2257
2258 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2259                                    const char *path, const char *name,
2260                                    TALLOC_CTX *mem_ctx, char **found_name)
2261 {
2262         VFS_FIND(get_real_filename);
2263         return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2264                                                  found_name);
2265 }
2266
2267 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2268                                  const struct smb_filename *smb_fname)
2269 {
2270         VFS_FIND(connectpath);
2271         return handle->fns->connectpath_fn(handle, smb_fname);
2272 }
2273
2274 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2275                                     struct files_struct *fsp,
2276                                     struct lock_struct *plock)
2277 {
2278         VFS_FIND(strict_lock_check);
2279         return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2280 }
2281
2282 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2283                                      const char *name,
2284                                      enum vfs_translate_direction direction,
2285                                      TALLOC_CTX *mem_ctx,
2286                                      char **mapped_name)
2287 {
2288         VFS_FIND(translate_name);
2289         return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2290                                               mapped_name);
2291 }
2292
2293 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2294                             struct files_struct *fsp,
2295                             TALLOC_CTX *ctx,
2296                             uint32_t function,
2297                             uint16_t req_flags,
2298                             const uint8_t *in_data,
2299                             uint32_t in_len,
2300                             uint8_t **out_data,
2301                             uint32_t max_out_len,
2302                             uint32_t *out_len)
2303 {
2304         VFS_FIND(fsctl);
2305         return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2306                                      in_data, in_len, out_data, max_out_len,
2307                                      out_len);
2308 }
2309
2310 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2311                                          struct smb_filename *smb_fname,
2312                                          uint32_t *dosmode)
2313 {
2314         VFS_FIND(get_dos_attributes);
2315         return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2316 }
2317
2318 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2319                                           struct files_struct *fsp,
2320                                           uint32_t *dosmode)
2321 {
2322         VFS_FIND(fget_dos_attributes);
2323         return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2324 }
2325
2326 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2327                                          const struct smb_filename *smb_fname,
2328                                          uint32_t dosmode)
2329 {
2330         VFS_FIND(set_dos_attributes);
2331         return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2332 }
2333
2334 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2335                                           struct files_struct *fsp,
2336                                           uint32_t dosmode)
2337 {
2338         VFS_FIND(set_dos_attributes);
2339         return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2340 }
2341
2342 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2343                                                   struct tevent_context *ev,
2344                                                   struct vfs_handle_struct *handle,
2345                                                   struct files_struct *fsp,
2346                                                   uint32_t fsctl,
2347                                                   uint32_t ttl,
2348                                                   off_t offset,
2349                                                   size_t to_copy)
2350 {
2351         VFS_FIND(offload_read_send);
2352         return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2353                                                  fsp, fsctl,
2354                                                  ttl, offset, to_copy);
2355 }
2356
2357 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2358                                         struct vfs_handle_struct *handle,
2359                                         TALLOC_CTX *mem_ctx,
2360                                         DATA_BLOB *token_blob)
2361 {
2362         VFS_FIND(offload_read_recv);
2363         return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2364 }
2365
2366 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2367                                                    TALLOC_CTX *mem_ctx,
2368                                                    struct tevent_context *ev,
2369                                                    uint32_t fsctl,
2370                                                    DATA_BLOB *token,
2371                                                    off_t transfer_offset,
2372                                                    struct files_struct *dest_fsp,
2373                                                    off_t dest_off,
2374                                                    off_t num)
2375 {
2376         VFS_FIND(offload_write_send);
2377         return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2378                                                token, transfer_offset,
2379                                                dest_fsp, dest_off, num);
2380 }
2381
2382 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2383                                          struct tevent_req *req,
2384                                          off_t *copied)
2385 {
2386         VFS_FIND(offload_write_recv);
2387         return handle->fns->offload_write_recv_fn(handle, req, copied);
2388 }
2389
2390 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2391                                       TALLOC_CTX *mem_ctx,
2392                                       struct files_struct *fsp,
2393                                       struct smb_filename *smb_fname,
2394                                       uint16_t *_compression_fmt)
2395 {
2396         VFS_FIND(get_compression);
2397         return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2398                                                _compression_fmt);
2399 }
2400
2401 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2402                                       TALLOC_CTX *mem_ctx,
2403                                       struct files_struct *fsp,
2404                                       uint16_t compression_fmt)
2405 {
2406         VFS_FIND(set_compression);
2407         return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2408                                                compression_fmt);
2409 }
2410
2411 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2412                                       TALLOC_CTX *mem_ctx,
2413                                       const char *service_path,
2414                                       char **base_volume)
2415 {
2416         VFS_FIND(snap_check_path);
2417         return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2418                                                base_volume);
2419 }
2420
2421 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2422                                   TALLOC_CTX *mem_ctx,
2423                                   const char *base_volume,
2424                                   time_t *tstamp,
2425                                   bool rw,
2426                                   char **base_path,
2427                                   char **snap_path)
2428 {
2429         VFS_FIND(snap_create);
2430         return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2431                                            rw, base_path, snap_path);
2432 }
2433
2434 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2435                                   TALLOC_CTX *mem_ctx,
2436                                   char *base_path,
2437                                   char *snap_path)
2438 {
2439         VFS_FIND(snap_delete);
2440         return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2441                                            snap_path);
2442 }
2443
2444 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2445                                   struct files_struct *fsp,
2446                                   uint32_t security_info,
2447                                   TALLOC_CTX *mem_ctx,
2448                                   struct security_descriptor **ppdesc)
2449 {
2450         VFS_FIND(fget_nt_acl);
2451         return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2452                                            mem_ctx, ppdesc);
2453 }
2454
2455 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2456                                  const struct smb_filename *smb_fname,
2457                                  uint32_t security_info,
2458                                  TALLOC_CTX *mem_ctx,
2459                                  struct security_descriptor **ppdesc)
2460 {
2461         VFS_FIND(get_nt_acl);
2462         return handle->fns->get_nt_acl_fn(handle,
2463                                 smb_fname,
2464                                 security_info,
2465                                 mem_ctx,
2466                                 ppdesc);
2467 }
2468
2469 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2470                                   struct files_struct *fsp,
2471                                   uint32_t security_info_sent,
2472                                   const struct security_descriptor *psd)
2473 {
2474         VFS_FIND(fset_nt_acl);
2475         return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent, 
2476                                            psd);
2477 }
2478
2479 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2480                                  struct smb_filename *file,
2481                                  struct security_acl *sacl,
2482                                  uint32_t access_requested,
2483                                  uint32_t access_denied)
2484 {
2485         VFS_FIND(audit_file);
2486         return handle->fns->audit_file_fn(handle, 
2487                                           file, 
2488                                           sacl, 
2489                                           access_requested, 
2490                                           access_denied);
2491 }
2492
2493 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2494                                         const struct smb_filename *smb_fname,
2495                                         SMB_ACL_TYPE_T type,
2496                                         TALLOC_CTX *mem_ctx)
2497 {
2498         VFS_FIND(sys_acl_get_file);
2499         return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2500 }
2501
2502 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2503                                       struct files_struct *fsp,
2504                                       TALLOC_CTX *mem_ctx)
2505 {
2506         VFS_FIND(sys_acl_get_fd);
2507         return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2508 }
2509
2510 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2511                                 const struct smb_filename *smb_fname,
2512                                 TALLOC_CTX *mem_ctx,
2513                                 char **blob_description,
2514                                 DATA_BLOB *blob)
2515 {
2516         VFS_FIND(sys_acl_blob_get_file);
2517         return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2518                         mem_ctx, blob_description, blob);
2519 }
2520
2521 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2522                                      struct files_struct *fsp,
2523                                      TALLOC_CTX *mem_ctx, 
2524                                      char **blob_description,
2525                                      DATA_BLOB *blob)
2526 {
2527         VFS_FIND(sys_acl_blob_get_fd);
2528         return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2529 }
2530
2531 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2532                                 const struct smb_filename *smb_fname,
2533                                 SMB_ACL_TYPE_T acltype,
2534                                 SMB_ACL_T theacl)
2535 {
2536         VFS_FIND(sys_acl_set_file);
2537         return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2538                                 acltype, theacl);
2539 }
2540
2541 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2542                                 struct files_struct *fsp, SMB_ACL_T theacl)
2543 {
2544         VFS_FIND(sys_acl_set_fd);
2545         return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2546 }
2547
2548 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2549                                 const struct smb_filename *smb_fname)
2550 {
2551         VFS_FIND(sys_acl_delete_def_file);
2552         return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2553 }
2554
2555 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2556                                 const struct smb_filename *smb_fname,
2557                                 const char *name,
2558                                 void *value,
2559                                 size_t size)
2560 {
2561         VFS_FIND(getxattr);
2562         return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2563 }
2564
2565 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2566                                struct files_struct *fsp, const char *name,
2567                                void *value, size_t size)
2568 {
2569         VFS_FIND(fgetxattr);
2570         return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2571 }
2572
2573 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2574                                 const struct smb_filename *smb_fname,
2575                                 char *list,
2576                                 size_t size)
2577 {
2578         VFS_FIND(listxattr);
2579         return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2580 }
2581
2582 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2583                                 struct files_struct *fsp, char *list,
2584                                 size_t size)
2585 {
2586         VFS_FIND(flistxattr);
2587         return handle->fns->flistxattr_fn(handle, fsp, list, size);
2588 }
2589
2590 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2591                                 const struct smb_filename *smb_fname,
2592                                 const char *name)
2593 {
2594         VFS_FIND(removexattr);
2595         return handle->fns->removexattr_fn(handle, smb_fname, name);
2596 }
2597
2598 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2599                               struct files_struct *fsp, const char *name)
2600 {
2601         VFS_FIND(fremovexattr);
2602         return handle->fns->fremovexattr_fn(handle, fsp, name);
2603 }
2604
2605 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2606                         const struct smb_filename *smb_fname,
2607                         const char *name,
2608                         const void *value,
2609                         size_t size,
2610                         int flags)
2611 {
2612         VFS_FIND(setxattr);
2613         return handle->fns->setxattr_fn(handle, smb_fname,
2614                         name, value, size, flags);
2615 }
2616
2617 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2618                            struct files_struct *fsp, const char *name,
2619                            const void *value, size_t size, int flags)
2620 {
2621         VFS_FIND(fsetxattr);
2622         return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2623 }
2624
2625 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2626                             struct files_struct *fsp)
2627 {
2628         VFS_FIND(aio_force);
2629         return handle->fns->aio_force_fn(handle, fsp);
2630 }
2631
2632 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2633                                      struct files_struct *fsp,
2634                                      TALLOC_CTX *mem_ctx,
2635                                      DATA_BLOB *cookie)
2636 {
2637         VFS_FIND(durable_cookie);
2638         return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2639 }
2640
2641 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2642                                          struct files_struct *fsp,
2643                                          const DATA_BLOB old_cookie,
2644                                          TALLOC_CTX *mem_ctx,
2645                                          DATA_BLOB *new_cookie)
2646 {
2647         VFS_FIND(durable_disconnect);
2648         return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2649                                                   mem_ctx, new_cookie);
2650 }
2651
2652 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2653                                         struct smb_request *smb1req,
2654                                         struct smbXsrv_open *op,
2655                                         const DATA_BLOB old_cookie,
2656                                         TALLOC_CTX *mem_ctx,
2657                                         struct files_struct **fsp,
2658                                         DATA_BLOB *new_cookie)
2659 {
2660         VFS_FIND(durable_reconnect);
2661         return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2662                                                  old_cookie, mem_ctx, fsp,
2663                                                  new_cookie);
2664 }
2665
2666 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2667                                    const struct smb_filename *fname,
2668                                    TALLOC_CTX *mem_ctx,
2669                                    struct readdir_attr_data **attr_data)
2670 {
2671         VFS_FIND(readdir_attr);
2672         return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
2673 }