40c41ed27fc29787573444414917586ccc776f44
[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);
885                 conn->cwd = vfs_GetWd(conn, conn);
886                 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
887         }
888         return ret;
889 }
890
891 /*******************************************************************
892  Return the absolute current directory path - given a UNIX pathname.
893  Note that this path is returned in DOS format, not UNIX
894  format. Note this can be called with conn == NULL.
895 ********************************************************************/
896
897 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
898 {
899         char *current_dir = NULL;
900         char *result = NULL;
901         DATA_BLOB cache_value;
902         struct file_id key;
903         struct smb_filename *smb_fname_dot = NULL;
904         struct smb_filename *smb_fname_full = NULL;
905
906         if (!lp_getwd_cache()) {
907                 goto nocache;
908         }
909
910         smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
911         if (smb_fname_dot == NULL) {
912                 errno = ENOMEM;
913                 goto out;
914         }
915
916         if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
917                 /*
918                  * Known to fail for root: the directory may be NFS-mounted
919                  * and exported with root_squash (so has no root access).
920                  */
921                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
922                          "(NFS problem ?)\n", strerror(errno) ));
923                 goto nocache;
924         }
925
926         key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
927
928         if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
929                              data_blob_const(&key, sizeof(key)),
930                              &cache_value)) {
931                 goto nocache;
932         }
933
934         SMB_ASSERT((cache_value.length > 0)
935                    && (cache_value.data[cache_value.length-1] == '\0'));
936
937         smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
938                                              NULL, NULL, 0);
939         if (smb_fname_full == NULL) {
940                 errno = ENOMEM;
941                 goto out;
942         }
943
944         if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
945             (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
946             (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
947             (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
948                 /*
949                  * Ok, we're done
950                  */
951                 result = talloc_strdup(ctx, smb_fname_full->base_name);
952                 if (result == NULL) {
953                         errno = ENOMEM;
954                 }
955                 goto out;
956         }
957
958  nocache:
959
960         /*
961          * We don't have the information to hand so rely on traditional
962          * methods. The very slow getcwd, which spawns a process on some
963          * systems, or the not quite so bad getwd.
964          */
965
966         current_dir = SMB_VFS_GETWD(conn);
967         if (current_dir == NULL) {
968                 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
969                           strerror(errno)));
970                 goto out;
971         }
972
973         if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
974                 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
975
976                 memcache_add(smbd_memcache(), GETWD_CACHE,
977                              data_blob_const(&key, sizeof(key)),
978                              data_blob_const(current_dir,
979                                                 strlen(current_dir)+1));
980         }
981
982         result = talloc_strdup(ctx, current_dir);
983         if (result == NULL) {
984                 errno = ENOMEM;
985         }
986
987  out:
988         TALLOC_FREE(smb_fname_dot);
989         TALLOC_FREE(smb_fname_full);
990         SAFE_FREE(current_dir);
991         return result;
992 }
993
994 /*******************************************************************
995  Reduce a file name, removing .. elements and checking that
996  it is below dir in the heirachy. This uses realpath.
997  This function must run as root, and will return names
998  and valid stat structs that can be checked on open.
999 ********************************************************************/
1000
1001 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1002                         const char *fname,
1003                         struct smb_request *smbreq)
1004 {
1005         NTSTATUS status;
1006         TALLOC_CTX *ctx = talloc_tos();
1007         const char *conn_rootdir;
1008         size_t rootdir_len;
1009         char *dir_name = NULL;
1010         const char *last_component = NULL;
1011         char *resolved_name = NULL;
1012         char *saved_dir = NULL;
1013         struct smb_filename *saved_dir_fname = NULL;
1014         struct smb_filename *smb_fname_cwd = NULL;
1015         struct privilege_paths *priv_paths = NULL;
1016         int ret;
1017
1018         DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1019                         fname,
1020                         conn->connectpath));
1021
1022
1023         priv_paths = talloc_zero(smbreq, struct privilege_paths);
1024         if (!priv_paths) {
1025                 status = NT_STATUS_NO_MEMORY;
1026                 goto err;
1027         }
1028
1029         if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
1030                 status = NT_STATUS_NO_MEMORY;
1031                 goto err;
1032         }
1033
1034         priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1035         priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1036
1037         if (priv_paths->parent_name.base_name == NULL ||
1038                         priv_paths->file_name.base_name == NULL) {
1039                 status = NT_STATUS_NO_MEMORY;
1040                 goto err;
1041         }
1042
1043         if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1044                 status = map_nt_error_from_unix(errno);
1045                 goto err;
1046         }
1047         /* Remember where we were. */
1048         saved_dir = vfs_GetWd(ctx, conn);
1049         if (!saved_dir) {
1050                 status = map_nt_error_from_unix(errno);
1051                 goto err;
1052         }
1053
1054         saved_dir_fname = synthetic_smb_fname(ctx,
1055                                         saved_dir,
1056                                         NULL,
1057                                         NULL,
1058                                         0);
1059         if (saved_dir_fname == NULL) {
1060                 status = NT_STATUS_NO_MEMORY;
1061                 goto err;
1062         }
1063
1064         /* Go to the parent directory to lock in memory. */
1065         if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1066                 status = map_nt_error_from_unix(errno);
1067                 goto err;
1068         }
1069
1070         /* Get the absolute path of the parent directory. */
1071         resolved_name = SMB_VFS_REALPATH(conn,".");
1072         if (!resolved_name) {
1073                 status = map_nt_error_from_unix(errno);
1074                 goto err;
1075         }
1076
1077         if (*resolved_name != '/') {
1078                 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1079                         "doesn't return absolute paths !\n"));
1080                 status = NT_STATUS_OBJECT_NAME_INVALID;
1081                 goto err;
1082         }
1083
1084         DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1085                 priv_paths->parent_name.base_name,
1086                 resolved_name));
1087
1088         /* Now check the stat value is the same. */
1089         smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1090         if (smb_fname_cwd == NULL) {
1091                 status = NT_STATUS_NO_MEMORY;
1092                 goto err;
1093         }
1094
1095         if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1096                 status = map_nt_error_from_unix(errno);
1097                 goto err;
1098         }
1099
1100         /* Ensure we're pointing at the same place. */
1101         if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1102                 DEBUG(0,("check_reduced_name_with_privilege: "
1103                         "device/inode/uid/gid on directory %s changed. "
1104                         "Denying access !\n",
1105                         priv_paths->parent_name.base_name));
1106                 status = NT_STATUS_ACCESS_DENIED;
1107                 goto err;
1108         }
1109
1110         /* Ensure we're below the connect path. */
1111
1112         conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1113         if (conn_rootdir == NULL) {
1114                 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1115                         "conn_rootdir\n"));
1116                 status = NT_STATUS_ACCESS_DENIED;
1117                 goto err;
1118         }
1119
1120         rootdir_len = strlen(conn_rootdir);
1121
1122         /*
1123          * In the case of rootdir_len == 1, we know that conn_rootdir is
1124          * "/", and we also know that resolved_name starts with a slash.
1125          * So, in this corner case, resolved_name is automatically a
1126          * sub-directory of the conn_rootdir. Thus we can skip the string
1127          * comparison and the next character checks (which are even
1128          * wrong in this case).
1129          */
1130         if (rootdir_len != 1) {
1131                 bool matched;
1132
1133                 matched = (strncmp(conn_rootdir, resolved_name,
1134                                 rootdir_len) == 0);
1135
1136                 if (!matched || (resolved_name[rootdir_len] != '/' &&
1137                                  resolved_name[rootdir_len] != '\0')) {
1138                         DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1139                                 "access attempt: %s is a symlink outside the "
1140                                 "share path\n",
1141                                 dir_name));
1142                         DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1143                         DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1144                         status = NT_STATUS_ACCESS_DENIED;
1145                         goto err;
1146                 }
1147         }
1148
1149         /* Now ensure that the last component either doesn't
1150            exist, or is *NOT* a symlink. */
1151
1152         ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1153         if (ret == -1) {
1154                 /* Errno must be ENOENT for this be ok. */
1155                 if (errno != ENOENT) {
1156                         status = map_nt_error_from_unix(errno);
1157                         DEBUG(2, ("check_reduced_name_with_privilege: "
1158                                 "LSTAT on %s failed with %s\n",
1159                                 priv_paths->file_name.base_name,
1160                                 nt_errstr(status)));
1161                         goto err;
1162                 }
1163         }
1164
1165         if (VALID_STAT(priv_paths->file_name.st) &&
1166                         S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1167                 DEBUG(2, ("check_reduced_name_with_privilege: "
1168                         "Last component %s is a symlink. Denying"
1169                         "access.\n",
1170                         priv_paths->file_name.base_name));
1171                 status = NT_STATUS_ACCESS_DENIED;
1172                 goto err;
1173         }
1174
1175         smbreq->priv_paths = priv_paths;
1176         status = NT_STATUS_OK;
1177
1178   err:
1179
1180         if (saved_dir_fname) {
1181                 vfs_ChDir(conn, saved_dir_fname);
1182                 TALLOC_FREE(saved_dir);
1183                 TALLOC_FREE(saved_dir_fname);
1184         }
1185         SAFE_FREE(resolved_name);
1186         if (!NT_STATUS_IS_OK(status)) {
1187                 TALLOC_FREE(priv_paths);
1188         }
1189         TALLOC_FREE(dir_name);
1190         return status;
1191 }
1192
1193 /*******************************************************************
1194  Reduce a file name, removing .. elements and checking that
1195  it is below dir in the heirachy. This uses realpath.
1196
1197  If cwd_name == NULL then fname is a client given path relative
1198  to the root path of the share.
1199
1200  If cwd_name != NULL then fname is a client given path relative
1201  to cwd_name. cwd_name is relative to the root path of the share.
1202 ********************************************************************/
1203
1204 NTSTATUS check_reduced_name(connection_struct *conn,
1205                                 const char *cwd_name,
1206                                 const char *fname)
1207 {
1208         char *resolved_name = NULL;
1209         char *new_fname = NULL;
1210         bool allow_symlinks = true;
1211         bool allow_widelinks = false;
1212
1213         DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1214
1215         resolved_name = SMB_VFS_REALPATH(conn,fname);
1216
1217         if (!resolved_name) {
1218                 switch (errno) {
1219                         case ENOTDIR:
1220                                 DEBUG(3,("check_reduced_name: Component not a "
1221                                          "directory in getting realpath for "
1222                                          "%s\n", fname));
1223                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1224                         case ENOENT:
1225                         {
1226                                 TALLOC_CTX *ctx = talloc_tos();
1227                                 char *dir_name = NULL;
1228                                 const char *last_component = NULL;
1229                                 char *new_name = NULL;
1230                                 int ret;
1231
1232                                 /* Last component didn't exist.
1233                                    Remove it and try and canonicalise
1234                                    the directory name. */
1235                                 if (!parent_dirname(ctx, fname,
1236                                                 &dir_name,
1237                                                 &last_component)) {
1238                                         return NT_STATUS_NO_MEMORY;
1239                                 }
1240
1241                                 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1242                                 if (!resolved_name) {
1243                                         NTSTATUS status = map_nt_error_from_unix(errno);
1244
1245                                         if (errno == ENOENT || errno == ENOTDIR) {
1246                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1247                                         }
1248
1249                                         DEBUG(3,("check_reduce_name: "
1250                                                  "couldn't get realpath for "
1251                                                  "%s (%s)\n",
1252                                                 fname,
1253                                                 nt_errstr(status)));
1254                                         return status;
1255                                 }
1256                                 ret = asprintf(&new_name, "%s/%s",
1257                                                resolved_name, last_component);
1258                                 SAFE_FREE(resolved_name);
1259                                 if (ret == -1) {
1260                                         return NT_STATUS_NO_MEMORY;
1261                                 }
1262                                 resolved_name = new_name;
1263                                 break;
1264                         }
1265                         default:
1266                                 DEBUG(3,("check_reduced_name: couldn't get "
1267                                          "realpath for %s\n", fname));
1268                                 return map_nt_error_from_unix(errno);
1269                 }
1270         }
1271
1272         DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1273                   resolved_name));
1274
1275         if (*resolved_name != '/') {
1276                 DEBUG(0,("check_reduced_name: realpath doesn't return "
1277                          "absolute paths !\n"));
1278                 SAFE_FREE(resolved_name);
1279                 return NT_STATUS_OBJECT_NAME_INVALID;
1280         }
1281
1282         allow_widelinks = lp_widelinks(SNUM(conn));
1283         allow_symlinks = lp_follow_symlinks(SNUM(conn));
1284
1285         /* Common widelinks and symlinks checks. */
1286         if (!allow_widelinks || !allow_symlinks) {
1287                 const char *conn_rootdir;
1288                 size_t rootdir_len;
1289
1290                 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1291                 if (conn_rootdir == NULL) {
1292                         DEBUG(2, ("check_reduced_name: Could not get "
1293                                 "conn_rootdir\n"));
1294                         SAFE_FREE(resolved_name);
1295                         return NT_STATUS_ACCESS_DENIED;
1296                 }
1297
1298                 rootdir_len = strlen(conn_rootdir);
1299
1300                 /*
1301                  * In the case of rootdir_len == 1, we know that
1302                  * conn_rootdir is "/", and we also know that
1303                  * resolved_name starts with a slash.  So, in this
1304                  * corner case, resolved_name is automatically a
1305                  * sub-directory of the conn_rootdir. Thus we can skip
1306                  * the string comparison and the next character checks
1307                  * (which are even wrong in this case).
1308                  */
1309                 if (rootdir_len != 1) {
1310                         bool matched;
1311
1312                         matched = (strncmp(conn_rootdir, resolved_name,
1313                                         rootdir_len) == 0);
1314                         if (!matched || (resolved_name[rootdir_len] != '/' &&
1315                                          resolved_name[rootdir_len] != '\0')) {
1316                                 DEBUG(2, ("check_reduced_name: Bad access "
1317                                         "attempt: %s is a symlink outside the "
1318                                         "share path\n", fname));
1319                                 DEBUGADD(2, ("conn_rootdir =%s\n",
1320                                              conn_rootdir));
1321                                 DEBUGADD(2, ("resolved_name=%s\n",
1322                                              resolved_name));
1323                                 SAFE_FREE(resolved_name);
1324                                 return NT_STATUS_ACCESS_DENIED;
1325                         }
1326                 }
1327
1328                 /* Extra checks if all symlinks are disallowed. */
1329                 if (!allow_symlinks) {
1330                         /* fname can't have changed in resolved_path. */
1331                         const char *p = &resolved_name[rootdir_len];
1332
1333                         /*
1334                          * UNIX filesystem semantics, names consisting
1335                          * only of "." or ".." CANNOT be symlinks.
1336                          */
1337                         if (ISDOT(fname) || ISDOTDOT(fname)) {
1338                                 goto out;
1339                         }
1340
1341                         if (*p != '/') {
1342                                 DEBUG(2, ("check_reduced_name: logic error (%c) "
1343                                         "in resolved_name: %s\n",
1344                                         *p,
1345                                         fname));
1346                                 SAFE_FREE(resolved_name);
1347                                 return NT_STATUS_ACCESS_DENIED;
1348                         }
1349
1350                         p++;
1351
1352                         /*
1353                          * If cwd_name is present and not ".",
1354                          * then fname is relative to that, not
1355                          * the root of the share. Make sure the
1356                          * path we check is the one the client
1357                          * sent (cwd_name+fname).
1358                          */
1359                         if (cwd_name != NULL && !ISDOT(cwd_name)) {
1360                                 new_fname = talloc_asprintf(talloc_tos(),
1361                                                         "%s/%s",
1362                                                         cwd_name,
1363                                                         fname);
1364                                 if (new_fname == NULL) {
1365                                         SAFE_FREE(resolved_name);
1366                                         return NT_STATUS_NO_MEMORY;
1367                                 }
1368                                 fname = new_fname;
1369                         }
1370
1371                         if (strcmp(fname, p)!=0) {
1372                                 DEBUG(2, ("check_reduced_name: Bad access "
1373                                         "attempt: %s is a symlink to %s\n",
1374                                           fname, p));
1375                                 SAFE_FREE(resolved_name);
1376                                 TALLOC_FREE(new_fname);
1377                                 return NT_STATUS_ACCESS_DENIED;
1378                         }
1379                 }
1380         }
1381
1382   out:
1383
1384         DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1385         SAFE_FREE(resolved_name);
1386         TALLOC_FREE(new_fname);
1387         return NT_STATUS_OK;
1388 }
1389
1390 /**
1391  * XXX: This is temporary and there should be no callers of this once
1392  * smb_filename is plumbed through all path based operations.
1393  *
1394  * Called when we know stream name parsing has already been done.
1395  */
1396 int vfs_stat_smb_basename(struct connection_struct *conn,
1397                         const struct smb_filename *smb_fname_in,
1398                         SMB_STRUCT_STAT *psbuf)
1399 {
1400         struct smb_filename smb_fname = {
1401                 .base_name = discard_const_p(char, smb_fname_in->base_name),
1402                 .flags = smb_fname_in->flags
1403         };
1404         int ret;
1405
1406         if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1407                 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1408         } else {
1409                 ret = SMB_VFS_STAT(conn, &smb_fname);
1410         }
1411
1412         if (ret != -1) {
1413                 *psbuf = smb_fname.st;
1414         }
1415         return ret;
1416 }
1417
1418 /**
1419  * Ensure LSTAT is called for POSIX paths.
1420  */
1421
1422 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1423 {
1424         int ret;
1425
1426         if(fsp->fh->fd == -1) {
1427                 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1428                         ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1429                 } else {
1430                         ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1431                 }
1432                 if (ret == -1) {
1433                         return map_nt_error_from_unix(errno);
1434                 }
1435         } else {
1436                 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1437                         return map_nt_error_from_unix(errno);
1438                 }
1439         }
1440         return NT_STATUS_OK;
1441 }
1442
1443 /**
1444  * Initialize num_streams and streams, then call VFS op streaminfo
1445  */
1446 NTSTATUS vfs_streaminfo(connection_struct *conn,
1447                         struct files_struct *fsp,
1448                         const struct smb_filename *smb_fname,
1449                         TALLOC_CTX *mem_ctx,
1450                         unsigned int *num_streams,
1451                         struct stream_struct **streams)
1452 {
1453         *num_streams = 0;
1454         *streams = NULL;
1455         return SMB_VFS_STREAMINFO(conn,
1456                         fsp,
1457                         smb_fname,
1458                         mem_ctx,
1459                         num_streams,
1460                         streams);
1461 }
1462
1463 /*
1464   generate a file_id from a stat structure
1465  */
1466 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1467 {
1468         return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1469 }
1470
1471 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1472                          const char *service, const char *user)
1473 {
1474         VFS_FIND(connect);
1475         return handle->fns->connect_fn(handle, service, user);
1476 }
1477
1478 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1479 {
1480         VFS_FIND(disconnect);
1481         handle->fns->disconnect_fn(handle);
1482 }
1483
1484 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1485                                 const struct smb_filename *smb_fname,
1486                                 uint64_t *bsize,
1487                                 uint64_t *dfree,
1488                                 uint64_t *dsize)
1489 {
1490         VFS_FIND(disk_free);
1491         return handle->fns->disk_free_fn(handle, smb_fname,
1492                         bsize, dfree, dsize);
1493 }
1494
1495 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1496                                 const struct smb_filename *smb_fname,
1497                                 enum SMB_QUOTA_TYPE qtype,
1498                                 unid_t id,
1499                                 SMB_DISK_QUOTA *qt)
1500 {
1501         VFS_FIND(get_quota);
1502         return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1503 }
1504
1505 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1506                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1507                            SMB_DISK_QUOTA *qt)
1508 {
1509         VFS_FIND(set_quota);
1510         return handle->fns->set_quota_fn(handle, qtype, id, qt);
1511 }
1512
1513 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1514                                       struct files_struct *fsp,
1515                                       struct shadow_copy_data *shadow_copy_data,
1516                                       bool labels)
1517 {
1518         VFS_FIND(get_shadow_copy_data);
1519         return handle->fns->get_shadow_copy_data_fn(handle, fsp, 
1520                                                     shadow_copy_data,
1521                                                     labels);
1522 }
1523 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1524                         const struct smb_filename *smb_fname,
1525                         struct vfs_statvfs_struct *statbuf)
1526 {
1527         VFS_FIND(statvfs);
1528         return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1529 }
1530
1531 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1532                         enum timestamp_set_resolution *p_ts_res)
1533 {
1534         VFS_FIND(fs_capabilities);
1535         return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1536 }
1537
1538 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1539                                         struct dfs_GetDFSReferral *r)
1540 {
1541         VFS_FIND(get_dfs_referrals);
1542         return handle->fns->get_dfs_referrals_fn(handle, r);
1543 }
1544
1545 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1546                                         const struct smb_filename *smb_fname,
1547                                         const char *mask,
1548                                         uint32_t attributes)
1549 {
1550         VFS_FIND(opendir);
1551         return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1552 }
1553
1554 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1555                                         struct files_struct *fsp,
1556                                         const char *mask,
1557                                         uint32_t attributes)
1558 {
1559         VFS_FIND(fdopendir);
1560         return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1561 }
1562
1563 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1564                                               DIR *dirp,
1565                                               SMB_STRUCT_STAT *sbuf)
1566 {
1567         VFS_FIND(readdir);
1568         return handle->fns->readdir_fn(handle, dirp, sbuf);
1569 }
1570
1571 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1572                           DIR *dirp, long offset)
1573 {
1574         VFS_FIND(seekdir);
1575         handle->fns->seekdir_fn(handle, dirp, offset);
1576 }
1577
1578 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1579                           DIR *dirp)
1580 {
1581         VFS_FIND(telldir);
1582         return handle->fns->telldir_fn(handle, dirp);
1583 }
1584
1585 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1586                              DIR *dirp)
1587 {
1588         VFS_FIND(rewind_dir);
1589         handle->fns->rewind_dir_fn(handle, dirp);
1590 }
1591
1592 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1593                         const struct smb_filename *smb_fname,
1594                         mode_t mode)
1595 {
1596         VFS_FIND(mkdir);
1597         return handle->fns->mkdir_fn(handle, smb_fname, mode);
1598 }
1599
1600 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1601                         const struct smb_filename *smb_fname)
1602 {
1603         VFS_FIND(rmdir);
1604         return handle->fns->rmdir_fn(handle, smb_fname);
1605 }
1606
1607 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1608                           DIR *dir)
1609 {
1610         VFS_FIND(closedir);
1611         return handle->fns->closedir_fn(handle, dir);
1612 }
1613
1614 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1615                                  DIR *dirp)
1616 {
1617         VFS_FIND(init_search_op);
1618         handle->fns->init_search_op_fn(handle, dirp);
1619 }
1620
1621 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1622                       struct smb_filename *smb_fname, struct files_struct *fsp,
1623                       int flags, mode_t mode)
1624 {
1625         VFS_FIND(open);
1626         return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1627 }
1628
1629 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1630                                   struct smb_request *req,
1631                                   uint16_t root_dir_fid,
1632                                   struct smb_filename *smb_fname,
1633                                   uint32_t access_mask,
1634                                   uint32_t share_access,
1635                                   uint32_t create_disposition,
1636                                   uint32_t create_options,
1637                                   uint32_t file_attributes,
1638                                   uint32_t oplock_request,
1639                                   struct smb2_lease *lease,
1640                                   uint64_t allocation_size,
1641                                   uint32_t private_flags,
1642                                   struct security_descriptor *sd,
1643                                   struct ea_list *ea_list,
1644                                   files_struct **result,
1645                                   int *pinfo,
1646                                   const struct smb2_create_blobs *in_context_blobs,
1647                                   struct smb2_create_blobs *out_context_blobs)
1648 {
1649         VFS_FIND(create_file);
1650         return handle->fns->create_file_fn(
1651                 handle, req, root_dir_fid, smb_fname, access_mask,
1652                 share_access, create_disposition, create_options,
1653                 file_attributes, oplock_request, lease, allocation_size,
1654                 private_flags, sd, ea_list,
1655                 result, pinfo, in_context_blobs, out_context_blobs);
1656 }
1657
1658 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1659                        struct files_struct *fsp)
1660 {
1661         VFS_FIND(close);
1662         return handle->fns->close_fn(handle, fsp);
1663 }
1664
1665 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1666                           struct files_struct *fsp, void *data, size_t n)
1667 {
1668         VFS_FIND(read);
1669         return handle->fns->read_fn(handle, fsp, data, n);
1670 }
1671
1672 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1673                            struct files_struct *fsp, void *data, size_t n,
1674                            off_t offset)
1675 {
1676         VFS_FIND(pread);
1677         return handle->fns->pread_fn(handle, fsp, data, n, offset);
1678 }
1679
1680 struct smb_vfs_call_pread_state {
1681         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1682         ssize_t retval;
1683         struct vfs_aio_state vfs_aio_state;
1684 };
1685
1686 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1687
1688 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1689                                            TALLOC_CTX *mem_ctx,
1690                                            struct tevent_context *ev,
1691                                            struct files_struct *fsp,
1692                                            void *data,
1693                                            size_t n, off_t offset)
1694 {
1695         struct tevent_req *req, *subreq;
1696         struct smb_vfs_call_pread_state *state;
1697
1698         req = tevent_req_create(mem_ctx, &state,
1699                                 struct smb_vfs_call_pread_state);
1700         if (req == NULL) {
1701                 return NULL;
1702         }
1703         VFS_FIND(pread_send);
1704         state->recv_fn = handle->fns->pread_recv_fn;
1705
1706         subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1707                                             offset);
1708         if (tevent_req_nomem(subreq, req)) {
1709                 return tevent_req_post(req, ev);
1710         }
1711         tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1712         return req;
1713 }
1714
1715 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1716 {
1717         struct tevent_req *req = tevent_req_callback_data(
1718                 subreq, struct tevent_req);
1719         struct smb_vfs_call_pread_state *state = tevent_req_data(
1720                 req, struct smb_vfs_call_pread_state);
1721
1722         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1723         TALLOC_FREE(subreq);
1724         if (state->retval == -1) {
1725                 tevent_req_error(req, state->vfs_aio_state.error);
1726                 return;
1727         }
1728         tevent_req_done(req);
1729 }
1730
1731 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1732                            struct vfs_aio_state *vfs_aio_state)
1733 {
1734         struct smb_vfs_call_pread_state *state = tevent_req_data(
1735                 req, struct smb_vfs_call_pread_state);
1736
1737         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1738                 return -1;
1739         }
1740         *vfs_aio_state = state->vfs_aio_state;
1741         return state->retval;
1742 }
1743
1744 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1745                            struct files_struct *fsp, const void *data,
1746                            size_t n)
1747 {
1748         VFS_FIND(write);
1749         return handle->fns->write_fn(handle, fsp, data, n);
1750 }
1751
1752 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1753                             struct files_struct *fsp, const void *data,
1754                             size_t n, off_t offset)
1755 {
1756         VFS_FIND(pwrite);
1757         return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1758 }
1759
1760 struct smb_vfs_call_pwrite_state {
1761         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1762         ssize_t retval;
1763         struct vfs_aio_state vfs_aio_state;
1764 };
1765
1766 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1767
1768 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1769                                             TALLOC_CTX *mem_ctx,
1770                                             struct tevent_context *ev,
1771                                             struct files_struct *fsp,
1772                                             const void *data,
1773                                             size_t n, off_t offset)
1774 {
1775         struct tevent_req *req, *subreq;
1776         struct smb_vfs_call_pwrite_state *state;
1777
1778         req = tevent_req_create(mem_ctx, &state,
1779                                 struct smb_vfs_call_pwrite_state);
1780         if (req == NULL) {
1781                 return NULL;
1782         }
1783         VFS_FIND(pwrite_send);
1784         state->recv_fn = handle->fns->pwrite_recv_fn;
1785
1786         subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1787                                              offset);
1788         if (tevent_req_nomem(subreq, req)) {
1789                 return tevent_req_post(req, ev);
1790         }
1791         tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1792         return req;
1793 }
1794
1795 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1796 {
1797         struct tevent_req *req = tevent_req_callback_data(
1798                 subreq, struct tevent_req);
1799         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1800                 req, struct smb_vfs_call_pwrite_state);
1801
1802         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1803         TALLOC_FREE(subreq);
1804         if (state->retval == -1) {
1805                 tevent_req_error(req, state->vfs_aio_state.error);
1806                 return;
1807         }
1808         tevent_req_done(req);
1809 }
1810
1811 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1812                             struct vfs_aio_state *vfs_aio_state)
1813 {
1814         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1815                 req, struct smb_vfs_call_pwrite_state);
1816
1817         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1818                 return -1;
1819         }
1820         *vfs_aio_state = state->vfs_aio_state;
1821         return state->retval;
1822 }
1823
1824 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1825                              struct files_struct *fsp, off_t offset,
1826                              int whence)
1827 {
1828         VFS_FIND(lseek);
1829         return handle->fns->lseek_fn(handle, fsp, offset, whence);
1830 }
1831
1832 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1833                               files_struct *fromfsp, const DATA_BLOB *header,
1834                               off_t offset, size_t count)
1835 {
1836         VFS_FIND(sendfile);
1837         return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1838                                         count);
1839 }
1840
1841 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1842                               files_struct *tofsp, off_t offset,
1843                               size_t count)
1844 {
1845         VFS_FIND(recvfile);
1846         return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1847 }
1848
1849 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1850                         const struct smb_filename *smb_fname_src,
1851                         const struct smb_filename *smb_fname_dst)
1852 {
1853         VFS_FIND(rename);
1854         return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1855 }
1856
1857 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1858                        struct files_struct *fsp)
1859 {
1860         VFS_FIND(fsync);
1861         return handle->fns->fsync_fn(handle, fsp);
1862 }
1863
1864 struct smb_vfs_call_fsync_state {
1865         int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1866         int retval;
1867         struct vfs_aio_state vfs_aio_state;
1868 };
1869
1870 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1871
1872 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1873                                            TALLOC_CTX *mem_ctx,
1874                                            struct tevent_context *ev,
1875                                            struct files_struct *fsp)
1876 {
1877         struct tevent_req *req, *subreq;
1878         struct smb_vfs_call_fsync_state *state;
1879
1880         req = tevent_req_create(mem_ctx, &state,
1881                                 struct smb_vfs_call_fsync_state);
1882         if (req == NULL) {
1883                 return NULL;
1884         }
1885         VFS_FIND(fsync_send);
1886         state->recv_fn = handle->fns->fsync_recv_fn;
1887
1888         subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1889         if (tevent_req_nomem(subreq, req)) {
1890                 return tevent_req_post(req, ev);
1891         }
1892         tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1893         return req;
1894 }
1895
1896 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1897 {
1898         struct tevent_req *req = tevent_req_callback_data(
1899                 subreq, struct tevent_req);
1900         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1901                 req, struct smb_vfs_call_fsync_state);
1902
1903         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1904         TALLOC_FREE(subreq);
1905         if (state->retval == -1) {
1906                 tevent_req_error(req, state->vfs_aio_state.error);
1907                 return;
1908         }
1909         tevent_req_done(req);
1910 }
1911
1912 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1913 {
1914         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1915                 req, struct smb_vfs_call_fsync_state);
1916
1917         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1918                 return -1;
1919         }
1920         *vfs_aio_state = state->vfs_aio_state;
1921         return state->retval;
1922 }
1923
1924
1925 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1926                       struct smb_filename *smb_fname)
1927 {
1928         VFS_FIND(stat);
1929         return handle->fns->stat_fn(handle, smb_fname);
1930 }
1931
1932 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1933                        struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1934 {
1935         VFS_FIND(fstat);
1936         return handle->fns->fstat_fn(handle, fsp, sbuf);
1937 }
1938
1939 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1940                        struct smb_filename *smb_filename)
1941 {
1942         VFS_FIND(lstat);
1943         return handle->fns->lstat_fn(handle, smb_filename);
1944 }
1945
1946 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1947                                      struct files_struct *fsp,
1948                                      const SMB_STRUCT_STAT *sbuf)
1949 {
1950         VFS_FIND(get_alloc_size);
1951         return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1952 }
1953
1954 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1955                         const struct smb_filename *smb_fname)
1956 {
1957         VFS_FIND(unlink);
1958         return handle->fns->unlink_fn(handle, smb_fname);
1959 }
1960
1961 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1962                         const struct smb_filename *smb_fname,
1963                         mode_t mode)
1964 {
1965         VFS_FIND(chmod);
1966         return handle->fns->chmod_fn(handle, smb_fname, mode);
1967 }
1968
1969 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1970                         struct files_struct *fsp, mode_t mode)
1971 {
1972         VFS_FIND(fchmod);
1973         return handle->fns->fchmod_fn(handle, fsp, mode);
1974 }
1975
1976 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1977                         const struct smb_filename *smb_fname,
1978                         uid_t uid,
1979                         gid_t gid)
1980 {
1981         VFS_FIND(chown);
1982         return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1983 }
1984
1985 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1986                         struct files_struct *fsp, uid_t uid, gid_t gid)
1987 {
1988         VFS_FIND(fchown);
1989         return handle->fns->fchown_fn(handle, fsp, uid, gid);
1990 }
1991
1992 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
1993                         const struct smb_filename *smb_fname,
1994                         uid_t uid,
1995                         gid_t gid)
1996 {
1997         VFS_FIND(lchown);
1998         return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
1999 }
2000
2001 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2002 {
2003         int ret;
2004         bool as_root = false;
2005         NTSTATUS status;
2006
2007         if (fsp->fh->fd != -1) {
2008                 /* Try fchown. */
2009                 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2010                 if (ret == 0) {
2011                         return NT_STATUS_OK;
2012                 }
2013                 if (ret == -1 && errno != ENOSYS) {
2014                         return map_nt_error_from_unix(errno);
2015                 }
2016         }
2017
2018         as_root = (geteuid() == 0);
2019
2020         if (as_root) {
2021                 /*
2022                  * We are being asked to chown as root. Make
2023                  * sure we chdir() into the path to pin it,
2024                  * and always act using lchown to ensure we
2025                  * don't deref any symbolic links.
2026                  */
2027                 char *saved_dir = NULL;
2028                 char *parent_dir = NULL;
2029                 const char *final_component = NULL;
2030                 struct smb_filename *local_smb_fname = NULL;
2031                 struct smb_filename parent_dir_fname = {0};
2032                 struct smb_filename saved_dir_fname = {0};
2033
2034                 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
2035                 if (!saved_dir) {
2036                         status = map_nt_error_from_unix(errno);
2037                         DEBUG(0,("vfs_chown_fsp: failed to get "
2038                                 "current working directory. Error was %s\n",
2039                                 strerror(errno)));
2040                         return status;
2041                 }
2042
2043                 saved_dir_fname = (struct smb_filename) {
2044                         .base_name = saved_dir
2045                 };
2046
2047                 if (!parent_dirname(talloc_tos(),
2048                                 fsp->fsp_name->base_name,
2049                                 &parent_dir,
2050                                 &final_component)) {
2051                         return NT_STATUS_NO_MEMORY;
2052                 }
2053
2054                 parent_dir_fname = (struct smb_filename) {
2055                         .base_name = parent_dir,
2056                         .flags = fsp->fsp_name->flags
2057                 };
2058
2059                 /* cd into the parent dir to pin it. */
2060                 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2061                 if (ret == -1) {
2062                         return map_nt_error_from_unix(errno);
2063                 }
2064
2065                 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2066                                         final_component,
2067                                         NULL,
2068                                         NULL,
2069                                         fsp->fsp_name->flags);
2070                 if (local_smb_fname == NULL) {
2071                         status = NT_STATUS_NO_MEMORY;
2072                         goto out;
2073                 }
2074
2075                 /* Must use lstat here. */
2076                 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2077                 if (ret == -1) {
2078                         status = map_nt_error_from_unix(errno);
2079                         goto out;
2080                 }
2081
2082                 /* Ensure it matches the fsp stat. */
2083                 if (!check_same_stat(&local_smb_fname->st,
2084                                 &fsp->fsp_name->st)) {
2085                         status = NT_STATUS_ACCESS_DENIED;
2086                         goto out;
2087                 }
2088
2089                 ret = SMB_VFS_LCHOWN(fsp->conn,
2090                         local_smb_fname,
2091                         uid, gid);
2092
2093                 if (ret == 0) {
2094                         status = NT_STATUS_OK;
2095                 } else {
2096                         status = map_nt_error_from_unix(errno);
2097                 }
2098
2099   out:
2100
2101                 vfs_ChDir(fsp->conn, &saved_dir_fname);
2102                 TALLOC_FREE(local_smb_fname);
2103                 TALLOC_FREE(saved_dir);
2104                 TALLOC_FREE(parent_dir);
2105
2106                 return status;
2107         }
2108
2109         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2110                 ret = SMB_VFS_LCHOWN(fsp->conn,
2111                         fsp->fsp_name,
2112                         uid, gid);
2113         } else {
2114                 ret = SMB_VFS_CHOWN(fsp->conn,
2115                         fsp->fsp_name,
2116                         uid, gid);
2117         }
2118
2119         if (ret == 0) {
2120                 status = NT_STATUS_OK;
2121         } else {
2122                 status = map_nt_error_from_unix(errno);
2123         }
2124         return status;
2125 }
2126
2127 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2128                         const struct smb_filename *smb_fname)
2129 {
2130         VFS_FIND(chdir);
2131         return handle->fns->chdir_fn(handle, smb_fname);
2132 }
2133
2134 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
2135 {
2136         VFS_FIND(getwd);
2137         return handle->fns->getwd_fn(handle);
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 }