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