vfs: remove SMB_VFS_INIT_SEARCH_OP
[nivanova/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         int saved_errno = 0;
862         struct smb_filename *saved_cwd = NULL;
863
864         if (!LastDir) {
865                 LastDir = SMB_STRDUP("");
866         }
867
868         if (ISDOT(smb_fname->base_name)) {
869                 return 0;
870         }
871
872         if (*smb_fname->base_name == '/' &&
873                         strcsequal(LastDir,smb_fname->base_name)) {
874                 return 0;
875         }
876
877         if (conn->cwd_fname != NULL) {
878                 /*
879                  * Save off where we are in case we need to return
880                  * on vfs_GetWd() failure after successful SMB_VFS_CHDIR().
881                  */
882                 saved_cwd = cp_smb_filename(conn, conn->cwd_fname);
883                 if (saved_cwd == NULL) {
884                         return -1;
885                 }
886         }
887
888         DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
889
890         ret = SMB_VFS_CHDIR(conn, smb_fname);
891         if (ret != 0) {
892                 saved_errno = errno;
893                 TALLOC_FREE(saved_cwd);
894                 errno = saved_errno;
895                 return -1;
896         }
897
898         /*
899          * Always replace conn->cwd_fname. We
900          * don't know if it's been modified by
901          * VFS modules in the stack.
902          */
903
904         /* conn cache. */
905         TALLOC_FREE(conn->cwd_fname);
906         conn->cwd_fname = vfs_GetWd(conn, conn);
907         if (conn->cwd_fname == NULL) {
908                 /*
909                  * vfs_GetWd() failed.
910                  * We must be able to read cwd.
911                  * Return to original directory
912                  * and return -1.
913                  */
914                 saved_errno = errno;
915
916                 if (saved_cwd == NULL) {
917                         /*
918                          * Failed on the very first chdir()+getwd()
919                          * for this connection. We can't
920                          * continue.
921                          */
922                         smb_panic("conn->cwd getwd failed\n");
923                         /* NOTREACHED */
924                         return -1;
925                 }
926
927                 /* Return to the previous $cwd. */
928                 ret = SMB_VFS_CHDIR(conn, saved_cwd);
929                 if (ret != 0) {
930                         smb_panic("conn->cwd getwd failed\n");
931                         /* NOTREACHED */
932                         return -1;
933                 }
934                 /* Restore original conn->cwd_fname. */
935                 conn->cwd_fname = saved_cwd;
936                 errno = saved_errno;
937                 /* And fail the chdir(). */
938                 return -1;
939         }
940
941         /* vfs_GetWd() succeeded. */
942         /* Replace global cache. */
943         SAFE_FREE(LastDir);
944         LastDir = SMB_STRDUP(smb_fname->base_name);
945
946         DEBUG(4,("vfs_ChDir got %s\n", conn->cwd_fname->base_name));
947
948         TALLOC_FREE(saved_cwd);
949         if (saved_errno != 0) {
950                 errno = saved_errno;
951         }
952         return ret;
953 }
954
955 /*******************************************************************
956  Return the absolute current directory path - given a UNIX pathname.
957  Note that this path is returned in DOS format, not UNIX
958  format. Note this can be called with conn == NULL.
959 ********************************************************************/
960
961 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
962 {
963         struct smb_filename *current_dir_fname = NULL;
964         struct file_id key;
965         struct smb_filename *smb_fname_dot = NULL;
966         struct smb_filename *smb_fname_full = NULL;
967         struct smb_filename *result = NULL;
968
969         if (!lp_getwd_cache()) {
970                 goto nocache;
971         }
972
973         smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
974         if (smb_fname_dot == NULL) {
975                 errno = ENOMEM;
976                 goto out;
977         }
978
979         if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
980                 /*
981                  * Known to fail for root: the directory may be NFS-mounted
982                  * and exported with root_squash (so has no root access).
983                  */
984                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
985                          "(NFS problem ?)\n", strerror(errno) ));
986                 goto nocache;
987         }
988
989         key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
990
991         smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
992                                         smbd_memcache(),
993                                         GETWD_CACHE,
994                                         data_blob_const(&key, sizeof(key)));
995
996         if (smb_fname_full == NULL) {
997                 goto nocache;
998         }
999
1000         if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
1001             (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
1002             (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
1003             (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
1004                 /*
1005                  * Ok, we're done
1006                  * Note: smb_fname_full is owned by smbd_memcache()
1007                  * so we must make a copy to return.
1008                  */
1009                 result = cp_smb_filename(ctx, smb_fname_full);
1010                 if (result == NULL) {
1011                         errno = ENOMEM;
1012                 }
1013                 goto out;
1014         }
1015
1016  nocache:
1017
1018         /*
1019          * We don't have the information to hand so rely on traditional
1020          * methods. The very slow getcwd, which spawns a process on some
1021          * systems, or the not quite so bad getwd.
1022          */
1023
1024         current_dir_fname = SMB_VFS_GETWD(conn, ctx);
1025         if (current_dir_fname == NULL) {
1026                 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
1027                           strerror(errno)));
1028                 goto out;
1029         }
1030
1031         if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
1032                 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1033
1034                 /*
1035                  * smbd_memcache() will own current_dir_fname after the
1036                  * memcache_add_talloc call, so we must make
1037                  * a copy on ctx to return.
1038                  */
1039                 result = cp_smb_filename(ctx, current_dir_fname);
1040                 if (result == NULL) {
1041                         errno = ENOMEM;
1042                 }
1043
1044                 /*
1045                  * Ensure the memory going into the cache
1046                  * doesn't have a destructor so it can be
1047                  * cleanly freed.
1048                  */
1049                 talloc_set_destructor(current_dir_fname, NULL);
1050
1051                 memcache_add_talloc(smbd_memcache(),
1052                                 GETWD_CACHE,
1053                                 data_blob_const(&key, sizeof(key)),
1054                                 &current_dir_fname);
1055                 /* current_dir_fname is now == NULL here. */
1056         } else {
1057                 /* current_dir_fname is already allocated on ctx. */
1058                 result = current_dir_fname;
1059         }
1060
1061  out:
1062         TALLOC_FREE(smb_fname_dot);
1063         /*
1064          * Don't free current_dir_fname here. It's either been moved
1065          * to the memcache or is being returned in result.
1066          */
1067         return result;
1068 }
1069
1070 /*******************************************************************
1071  Reduce a file name, removing .. elements and checking that
1072  it is below dir in the heirachy. This uses realpath.
1073  This function must run as root, and will return names
1074  and valid stat structs that can be checked on open.
1075 ********************************************************************/
1076
1077 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1078                         const struct smb_filename *smb_fname,
1079                         struct smb_request *smbreq)
1080 {
1081         NTSTATUS status;
1082         TALLOC_CTX *ctx = talloc_tos();
1083         const char *conn_rootdir;
1084         size_t rootdir_len;
1085         char *dir_name = NULL;
1086         char *resolved_name = NULL;
1087         const char *last_component = NULL;
1088         struct smb_filename *resolved_fname = NULL;
1089         struct smb_filename *saved_dir_fname = NULL;
1090         struct smb_filename *smb_fname_cwd = NULL;
1091         struct privilege_paths *priv_paths = NULL;
1092         int ret;
1093
1094         DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1095                         smb_fname->base_name,
1096                         conn->connectpath));
1097
1098
1099         priv_paths = talloc_zero(smbreq, struct privilege_paths);
1100         if (!priv_paths) {
1101                 status = NT_STATUS_NO_MEMORY;
1102                 goto err;
1103         }
1104
1105         if (!parent_dirname(ctx, smb_fname->base_name,
1106                         &dir_name, &last_component)) {
1107                 status = NT_STATUS_NO_MEMORY;
1108                 goto err;
1109         }
1110
1111         priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1112         priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1113
1114         if (priv_paths->parent_name.base_name == NULL ||
1115                         priv_paths->file_name.base_name == NULL) {
1116                 status = NT_STATUS_NO_MEMORY;
1117                 goto err;
1118         }
1119
1120         if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1121                 status = map_nt_error_from_unix(errno);
1122                 goto err;
1123         }
1124         /* Remember where we were. */
1125         saved_dir_fname = vfs_GetWd(ctx, conn);
1126         if (!saved_dir_fname) {
1127                 status = map_nt_error_from_unix(errno);
1128                 goto err;
1129         }
1130
1131         if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1132                 status = map_nt_error_from_unix(errno);
1133                 goto err;
1134         }
1135
1136         smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1137         if (smb_fname_cwd == NULL) {
1138                 status = NT_STATUS_NO_MEMORY;
1139                 goto err;
1140         }
1141
1142         /* Get the absolute path of the parent directory. */
1143         resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1144         if (resolved_fname == NULL) {
1145                 status = map_nt_error_from_unix(errno);
1146                 goto err;
1147         }
1148         resolved_name = resolved_fname->base_name;
1149
1150         if (*resolved_name != '/') {
1151                 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1152                         "doesn't return absolute paths !\n"));
1153                 status = NT_STATUS_OBJECT_NAME_INVALID;
1154                 goto err;
1155         }
1156
1157         DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1158                 priv_paths->parent_name.base_name,
1159                 resolved_name));
1160
1161         /* Now check the stat value is the same. */
1162         if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1163                 status = map_nt_error_from_unix(errno);
1164                 goto err;
1165         }
1166
1167         /* Ensure we're pointing at the same place. */
1168         if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1169                 DEBUG(0,("check_reduced_name_with_privilege: "
1170                         "device/inode/uid/gid on directory %s changed. "
1171                         "Denying access !\n",
1172                         priv_paths->parent_name.base_name));
1173                 status = NT_STATUS_ACCESS_DENIED;
1174                 goto err;
1175         }
1176
1177         /* Ensure we're below the connect path. */
1178
1179         conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1180         if (conn_rootdir == NULL) {
1181                 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1182                         "conn_rootdir\n"));
1183                 status = NT_STATUS_ACCESS_DENIED;
1184                 goto err;
1185         }
1186
1187         rootdir_len = strlen(conn_rootdir);
1188
1189         /*
1190          * In the case of rootdir_len == 1, we know that conn_rootdir is
1191          * "/", and we also know that resolved_name starts with a slash.
1192          * So, in this corner case, resolved_name is automatically a
1193          * sub-directory of the conn_rootdir. Thus we can skip the string
1194          * comparison and the next character checks (which are even
1195          * wrong in this case).
1196          */
1197         if (rootdir_len != 1) {
1198                 bool matched;
1199
1200                 matched = (strncmp(conn_rootdir, resolved_name,
1201                                 rootdir_len) == 0);
1202
1203                 if (!matched || (resolved_name[rootdir_len] != '/' &&
1204                                  resolved_name[rootdir_len] != '\0')) {
1205                         DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1206                                 "access attempt: %s is a symlink outside the "
1207                                 "share path\n",
1208                                 dir_name));
1209                         DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1210                         DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1211                         status = NT_STATUS_ACCESS_DENIED;
1212                         goto err;
1213                 }
1214         }
1215
1216         /* Now ensure that the last component either doesn't
1217            exist, or is *NOT* a symlink. */
1218
1219         ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1220         if (ret == -1) {
1221                 /* Errno must be ENOENT for this be ok. */
1222                 if (errno != ENOENT) {
1223                         status = map_nt_error_from_unix(errno);
1224                         DEBUG(2, ("check_reduced_name_with_privilege: "
1225                                 "LSTAT on %s failed with %s\n",
1226                                 priv_paths->file_name.base_name,
1227                                 nt_errstr(status)));
1228                         goto err;
1229                 }
1230         }
1231
1232         if (VALID_STAT(priv_paths->file_name.st) &&
1233                         S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1234                 DEBUG(2, ("check_reduced_name_with_privilege: "
1235                         "Last component %s is a symlink. Denying"
1236                         "access.\n",
1237                         priv_paths->file_name.base_name));
1238                 status = NT_STATUS_ACCESS_DENIED;
1239                 goto err;
1240         }
1241
1242         smbreq->priv_paths = priv_paths;
1243         status = NT_STATUS_OK;
1244
1245   err:
1246
1247         if (saved_dir_fname != NULL) {
1248                 vfs_ChDir(conn, saved_dir_fname);
1249                 TALLOC_FREE(saved_dir_fname);
1250         }
1251         TALLOC_FREE(resolved_fname);
1252         if (!NT_STATUS_IS_OK(status)) {
1253                 TALLOC_FREE(priv_paths);
1254         }
1255         TALLOC_FREE(dir_name);
1256         return status;
1257 }
1258
1259 /*******************************************************************
1260  Reduce a file name, removing .. elements and checking that
1261  it is below dir in the heirachy. This uses realpath.
1262
1263  If cwd_name == NULL then fname is a client given path relative
1264  to the root path of the share.
1265
1266  If cwd_name != NULL then fname is a client given path relative
1267  to cwd_name. cwd_name is relative to the root path of the share.
1268 ********************************************************************/
1269
1270 NTSTATUS check_reduced_name(connection_struct *conn,
1271                                 const struct smb_filename *cwd_fname,
1272                                 const struct smb_filename *smb_fname)
1273 {
1274         TALLOC_CTX *ctx = talloc_tos();
1275         const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1276         const char *fname = smb_fname->base_name;
1277         struct smb_filename *resolved_fname;
1278         char *resolved_name = NULL;
1279         char *new_fname = NULL;
1280         bool allow_symlinks = true;
1281         bool allow_widelinks = false;
1282
1283         DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1284
1285         resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1286
1287         if (resolved_fname == NULL) {
1288                 switch (errno) {
1289                         case ENOTDIR:
1290                                 DEBUG(3,("check_reduced_name: Component not a "
1291                                          "directory in getting realpath for "
1292                                          "%s\n", fname));
1293                                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1294                         case ENOENT:
1295                         {
1296                                 char *dir_name = NULL;
1297                                 struct smb_filename dir_fname = {0};
1298                                 const char *last_component = NULL;
1299
1300                                 /* Last component didn't exist.
1301                                    Remove it and try and canonicalise
1302                                    the directory name. */
1303                                 if (!parent_dirname(ctx, fname,
1304                                                 &dir_name,
1305                                                 &last_component)) {
1306                                         return NT_STATUS_NO_MEMORY;
1307                                 }
1308
1309                                 dir_fname = (struct smb_filename)
1310                                         { .base_name = dir_name };
1311                                 resolved_fname = SMB_VFS_REALPATH(conn,
1312                                                         ctx,
1313                                                         &dir_fname);
1314                                 if (resolved_fname == NULL) {
1315                                         NTSTATUS status = map_nt_error_from_unix(errno);
1316
1317                                         if (errno == ENOENT || errno == ENOTDIR) {
1318                                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1319                                         }
1320
1321                                         DEBUG(3,("check_reduce_name: "
1322                                                  "couldn't get realpath for "
1323                                                  "%s (%s)\n",
1324                                                 fname,
1325                                                 nt_errstr(status)));
1326                                         return status;
1327                                 }
1328                                 resolved_name = talloc_asprintf(ctx,
1329                                                 "%s/%s",
1330                                                 resolved_fname->base_name,
1331                                                 last_component);
1332                                 if (resolved_name == NULL) {
1333                                         return NT_STATUS_NO_MEMORY;
1334                                 }
1335                                 break;
1336                         }
1337                         default:
1338                                 DEBUG(3,("check_reduced_name: couldn't get "
1339                                          "realpath for %s\n", fname));
1340                                 return map_nt_error_from_unix(errno);
1341                 }
1342         } else {
1343                 resolved_name = resolved_fname->base_name;
1344         }
1345
1346         DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1347                   resolved_name));
1348
1349         if (*resolved_name != '/') {
1350                 DEBUG(0,("check_reduced_name: realpath doesn't return "
1351                          "absolute paths !\n"));
1352                 TALLOC_FREE(resolved_fname);
1353                 return NT_STATUS_OBJECT_NAME_INVALID;
1354         }
1355
1356         allow_widelinks = lp_widelinks(SNUM(conn));
1357         allow_symlinks = lp_follow_symlinks(SNUM(conn));
1358
1359         /* Common widelinks and symlinks checks. */
1360         if (!allow_widelinks || !allow_symlinks) {
1361                 const char *conn_rootdir;
1362                 size_t rootdir_len;
1363
1364                 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1365                 if (conn_rootdir == NULL) {
1366                         DEBUG(2, ("check_reduced_name: Could not get "
1367                                 "conn_rootdir\n"));
1368                         TALLOC_FREE(resolved_fname);
1369                         return NT_STATUS_ACCESS_DENIED;
1370                 }
1371
1372                 rootdir_len = strlen(conn_rootdir);
1373
1374                 /*
1375                  * In the case of rootdir_len == 1, we know that
1376                  * conn_rootdir is "/", and we also know that
1377                  * resolved_name starts with a slash.  So, in this
1378                  * corner case, resolved_name is automatically a
1379                  * sub-directory of the conn_rootdir. Thus we can skip
1380                  * the string comparison and the next character checks
1381                  * (which are even wrong in this case).
1382                  */
1383                 if (rootdir_len != 1) {
1384                         bool matched;
1385
1386                         matched = (strncmp(conn_rootdir, resolved_name,
1387                                         rootdir_len) == 0);
1388                         if (!matched || (resolved_name[rootdir_len] != '/' &&
1389                                          resolved_name[rootdir_len] != '\0')) {
1390                                 DEBUG(2, ("check_reduced_name: Bad access "
1391                                         "attempt: %s is a symlink outside the "
1392                                         "share path\n", fname));
1393                                 DEBUGADD(2, ("conn_rootdir =%s\n",
1394                                              conn_rootdir));
1395                                 DEBUGADD(2, ("resolved_name=%s\n",
1396                                              resolved_name));
1397                                 TALLOC_FREE(resolved_fname);
1398                                 return NT_STATUS_ACCESS_DENIED;
1399                         }
1400                 }
1401
1402                 /* Extra checks if all symlinks are disallowed. */
1403                 if (!allow_symlinks) {
1404                         /* fname can't have changed in resolved_path. */
1405                         const char *p = &resolved_name[rootdir_len];
1406
1407                         /*
1408                          * UNIX filesystem semantics, names consisting
1409                          * only of "." or ".." CANNOT be symlinks.
1410                          */
1411                         if (ISDOT(fname) || ISDOTDOT(fname)) {
1412                                 goto out;
1413                         }
1414
1415                         if (*p != '/') {
1416                                 DEBUG(2, ("check_reduced_name: logic error (%c) "
1417                                         "in resolved_name: %s\n",
1418                                         *p,
1419                                         fname));
1420                                 TALLOC_FREE(resolved_fname);
1421                                 return NT_STATUS_ACCESS_DENIED;
1422                         }
1423
1424                         p++;
1425
1426                         /*
1427                          * If cwd_name is present and not ".",
1428                          * then fname is relative to that, not
1429                          * the root of the share. Make sure the
1430                          * path we check is the one the client
1431                          * sent (cwd_name+fname).
1432                          */
1433                         if (cwd_name != NULL && !ISDOT(cwd_name)) {
1434                                 new_fname = talloc_asprintf(ctx,
1435                                                         "%s/%s",
1436                                                         cwd_name,
1437                                                         fname);
1438                                 if (new_fname == NULL) {
1439                                         TALLOC_FREE(resolved_fname);
1440                                         return NT_STATUS_NO_MEMORY;
1441                                 }
1442                                 fname = new_fname;
1443                         }
1444
1445                         if (strcmp(fname, p)!=0) {
1446                                 DEBUG(2, ("check_reduced_name: Bad access "
1447                                         "attempt: %s is a symlink to %s\n",
1448                                           fname, p));
1449                                 TALLOC_FREE(resolved_fname);
1450                                 TALLOC_FREE(new_fname);
1451                                 return NT_STATUS_ACCESS_DENIED;
1452                         }
1453                 }
1454         }
1455
1456   out:
1457
1458         DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1459         TALLOC_FREE(resolved_fname);
1460         TALLOC_FREE(new_fname);
1461         return NT_STATUS_OK;
1462 }
1463
1464 /**
1465  * XXX: This is temporary and there should be no callers of this once
1466  * smb_filename is plumbed through all path based operations.
1467  *
1468  * Called when we know stream name parsing has already been done.
1469  */
1470 int vfs_stat_smb_basename(struct connection_struct *conn,
1471                         const struct smb_filename *smb_fname_in,
1472                         SMB_STRUCT_STAT *psbuf)
1473 {
1474         struct smb_filename smb_fname = {
1475                 .base_name = discard_const_p(char, smb_fname_in->base_name),
1476                 .flags = smb_fname_in->flags
1477         };
1478         int ret;
1479
1480         if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1481                 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1482         } else {
1483                 ret = SMB_VFS_STAT(conn, &smb_fname);
1484         }
1485
1486         if (ret != -1) {
1487                 *psbuf = smb_fname.st;
1488         }
1489         return ret;
1490 }
1491
1492 /**
1493  * Ensure LSTAT is called for POSIX paths.
1494  */
1495
1496 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1497 {
1498         int ret;
1499
1500         if(fsp->fh->fd == -1) {
1501                 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1502                         ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1503                 } else {
1504                         ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1505                 }
1506                 if (ret == -1) {
1507                         return map_nt_error_from_unix(errno);
1508                 }
1509         } else {
1510                 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1511                         return map_nt_error_from_unix(errno);
1512                 }
1513         }
1514         return NT_STATUS_OK;
1515 }
1516
1517 /**
1518  * Initialize num_streams and streams, then call VFS op streaminfo
1519  */
1520 NTSTATUS vfs_streaminfo(connection_struct *conn,
1521                         struct files_struct *fsp,
1522                         const struct smb_filename *smb_fname,
1523                         TALLOC_CTX *mem_ctx,
1524                         unsigned int *num_streams,
1525                         struct stream_struct **streams)
1526 {
1527         *num_streams = 0;
1528         *streams = NULL;
1529         return SMB_VFS_STREAMINFO(conn,
1530                         fsp,
1531                         smb_fname,
1532                         mem_ctx,
1533                         num_streams,
1534                         streams);
1535 }
1536
1537 /*
1538   generate a file_id from a stat structure
1539  */
1540 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1541 {
1542         return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1543 }
1544
1545 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1546                          const char *service, const char *user)
1547 {
1548         VFS_FIND(connect);
1549         return handle->fns->connect_fn(handle, service, user);
1550 }
1551
1552 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1553 {
1554         VFS_FIND(disconnect);
1555         handle->fns->disconnect_fn(handle);
1556 }
1557
1558 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1559                                 const struct smb_filename *smb_fname,
1560                                 uint64_t *bsize,
1561                                 uint64_t *dfree,
1562                                 uint64_t *dsize)
1563 {
1564         VFS_FIND(disk_free);
1565         return handle->fns->disk_free_fn(handle, smb_fname,
1566                         bsize, dfree, dsize);
1567 }
1568
1569 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1570                                 const struct smb_filename *smb_fname,
1571                                 enum SMB_QUOTA_TYPE qtype,
1572                                 unid_t id,
1573                                 SMB_DISK_QUOTA *qt)
1574 {
1575         VFS_FIND(get_quota);
1576         return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1577 }
1578
1579 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1580                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1581                            SMB_DISK_QUOTA *qt)
1582 {
1583         VFS_FIND(set_quota);
1584         return handle->fns->set_quota_fn(handle, qtype, id, qt);
1585 }
1586
1587 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1588                                       struct files_struct *fsp,
1589                                       struct shadow_copy_data *shadow_copy_data,
1590                                       bool labels)
1591 {
1592         VFS_FIND(get_shadow_copy_data);
1593         return handle->fns->get_shadow_copy_data_fn(handle, fsp, 
1594                                                     shadow_copy_data,
1595                                                     labels);
1596 }
1597 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1598                         const struct smb_filename *smb_fname,
1599                         struct vfs_statvfs_struct *statbuf)
1600 {
1601         VFS_FIND(statvfs);
1602         return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1603 }
1604
1605 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1606                         enum timestamp_set_resolution *p_ts_res)
1607 {
1608         VFS_FIND(fs_capabilities);
1609         return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1610 }
1611
1612 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1613                                         struct dfs_GetDFSReferral *r)
1614 {
1615         VFS_FIND(get_dfs_referrals);
1616         return handle->fns->get_dfs_referrals_fn(handle, r);
1617 }
1618
1619 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1620                                         const struct smb_filename *smb_fname,
1621                                         const char *mask,
1622                                         uint32_t attributes)
1623 {
1624         VFS_FIND(opendir);
1625         return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1626 }
1627
1628 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1629                                         struct files_struct *fsp,
1630                                         const char *mask,
1631                                         uint32_t attributes)
1632 {
1633         VFS_FIND(fdopendir);
1634         return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1635 }
1636
1637 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1638                                               DIR *dirp,
1639                                               SMB_STRUCT_STAT *sbuf)
1640 {
1641         VFS_FIND(readdir);
1642         return handle->fns->readdir_fn(handle, dirp, sbuf);
1643 }
1644
1645 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1646                           DIR *dirp, long offset)
1647 {
1648         VFS_FIND(seekdir);
1649         handle->fns->seekdir_fn(handle, dirp, offset);
1650 }
1651
1652 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1653                           DIR *dirp)
1654 {
1655         VFS_FIND(telldir);
1656         return handle->fns->telldir_fn(handle, dirp);
1657 }
1658
1659 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1660                              DIR *dirp)
1661 {
1662         VFS_FIND(rewind_dir);
1663         handle->fns->rewind_dir_fn(handle, dirp);
1664 }
1665
1666 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1667                         const struct smb_filename *smb_fname,
1668                         mode_t mode)
1669 {
1670         VFS_FIND(mkdir);
1671         return handle->fns->mkdir_fn(handle, smb_fname, mode);
1672 }
1673
1674 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1675                         const struct smb_filename *smb_fname)
1676 {
1677         VFS_FIND(rmdir);
1678         return handle->fns->rmdir_fn(handle, smb_fname);
1679 }
1680
1681 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1682                           DIR *dir)
1683 {
1684         VFS_FIND(closedir);
1685         return handle->fns->closedir_fn(handle, dir);
1686 }
1687
1688 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1689                       struct smb_filename *smb_fname, struct files_struct *fsp,
1690                       int flags, mode_t mode)
1691 {
1692         VFS_FIND(open);
1693         return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1694 }
1695
1696 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1697                                   struct smb_request *req,
1698                                   uint16_t root_dir_fid,
1699                                   struct smb_filename *smb_fname,
1700                                   uint32_t access_mask,
1701                                   uint32_t share_access,
1702                                   uint32_t create_disposition,
1703                                   uint32_t create_options,
1704                                   uint32_t file_attributes,
1705                                   uint32_t oplock_request,
1706                                   struct smb2_lease *lease,
1707                                   uint64_t allocation_size,
1708                                   uint32_t private_flags,
1709                                   struct security_descriptor *sd,
1710                                   struct ea_list *ea_list,
1711                                   files_struct **result,
1712                                   int *pinfo,
1713                                   const struct smb2_create_blobs *in_context_blobs,
1714                                   struct smb2_create_blobs *out_context_blobs)
1715 {
1716         VFS_FIND(create_file);
1717         return handle->fns->create_file_fn(
1718                 handle, req, root_dir_fid, smb_fname, access_mask,
1719                 share_access, create_disposition, create_options,
1720                 file_attributes, oplock_request, lease, allocation_size,
1721                 private_flags, sd, ea_list,
1722                 result, pinfo, in_context_blobs, out_context_blobs);
1723 }
1724
1725 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1726                        struct files_struct *fsp)
1727 {
1728         VFS_FIND(close);
1729         return handle->fns->close_fn(handle, fsp);
1730 }
1731
1732 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1733                           struct files_struct *fsp, void *data, size_t n)
1734 {
1735         VFS_FIND(read);
1736         return handle->fns->read_fn(handle, fsp, data, n);
1737 }
1738
1739 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1740                            struct files_struct *fsp, void *data, size_t n,
1741                            off_t offset)
1742 {
1743         VFS_FIND(pread);
1744         return handle->fns->pread_fn(handle, fsp, data, n, offset);
1745 }
1746
1747 struct smb_vfs_call_pread_state {
1748         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1749         ssize_t retval;
1750         struct vfs_aio_state vfs_aio_state;
1751 };
1752
1753 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1754
1755 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1756                                            TALLOC_CTX *mem_ctx,
1757                                            struct tevent_context *ev,
1758                                            struct files_struct *fsp,
1759                                            void *data,
1760                                            size_t n, off_t offset)
1761 {
1762         struct tevent_req *req, *subreq;
1763         struct smb_vfs_call_pread_state *state;
1764
1765         req = tevent_req_create(mem_ctx, &state,
1766                                 struct smb_vfs_call_pread_state);
1767         if (req == NULL) {
1768                 return NULL;
1769         }
1770         VFS_FIND(pread_send);
1771         state->recv_fn = handle->fns->pread_recv_fn;
1772
1773         subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1774                                             offset);
1775         if (tevent_req_nomem(subreq, req)) {
1776                 return tevent_req_post(req, ev);
1777         }
1778         tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1779         return req;
1780 }
1781
1782 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1783 {
1784         struct tevent_req *req = tevent_req_callback_data(
1785                 subreq, struct tevent_req);
1786         struct smb_vfs_call_pread_state *state = tevent_req_data(
1787                 req, struct smb_vfs_call_pread_state);
1788
1789         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1790         TALLOC_FREE(subreq);
1791         if (state->retval == -1) {
1792                 tevent_req_error(req, state->vfs_aio_state.error);
1793                 return;
1794         }
1795         tevent_req_done(req);
1796 }
1797
1798 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1799                            struct vfs_aio_state *vfs_aio_state)
1800 {
1801         struct smb_vfs_call_pread_state *state = tevent_req_data(
1802                 req, struct smb_vfs_call_pread_state);
1803
1804         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1805                 return -1;
1806         }
1807         *vfs_aio_state = state->vfs_aio_state;
1808         return state->retval;
1809 }
1810
1811 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1812                            struct files_struct *fsp, const void *data,
1813                            size_t n)
1814 {
1815         VFS_FIND(write);
1816         return handle->fns->write_fn(handle, fsp, data, n);
1817 }
1818
1819 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1820                             struct files_struct *fsp, const void *data,
1821                             size_t n, off_t offset)
1822 {
1823         VFS_FIND(pwrite);
1824         return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1825 }
1826
1827 struct smb_vfs_call_pwrite_state {
1828         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1829         ssize_t retval;
1830         struct vfs_aio_state vfs_aio_state;
1831 };
1832
1833 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1834
1835 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1836                                             TALLOC_CTX *mem_ctx,
1837                                             struct tevent_context *ev,
1838                                             struct files_struct *fsp,
1839                                             const void *data,
1840                                             size_t n, off_t offset)
1841 {
1842         struct tevent_req *req, *subreq;
1843         struct smb_vfs_call_pwrite_state *state;
1844
1845         req = tevent_req_create(mem_ctx, &state,
1846                                 struct smb_vfs_call_pwrite_state);
1847         if (req == NULL) {
1848                 return NULL;
1849         }
1850         VFS_FIND(pwrite_send);
1851         state->recv_fn = handle->fns->pwrite_recv_fn;
1852
1853         subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1854                                              offset);
1855         if (tevent_req_nomem(subreq, req)) {
1856                 return tevent_req_post(req, ev);
1857         }
1858         tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1859         return req;
1860 }
1861
1862 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1863 {
1864         struct tevent_req *req = tevent_req_callback_data(
1865                 subreq, struct tevent_req);
1866         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1867                 req, struct smb_vfs_call_pwrite_state);
1868
1869         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1870         TALLOC_FREE(subreq);
1871         if (state->retval == -1) {
1872                 tevent_req_error(req, state->vfs_aio_state.error);
1873                 return;
1874         }
1875         tevent_req_done(req);
1876 }
1877
1878 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1879                             struct vfs_aio_state *vfs_aio_state)
1880 {
1881         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1882                 req, struct smb_vfs_call_pwrite_state);
1883
1884         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1885                 return -1;
1886         }
1887         *vfs_aio_state = state->vfs_aio_state;
1888         return state->retval;
1889 }
1890
1891 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1892                              struct files_struct *fsp, off_t offset,
1893                              int whence)
1894 {
1895         VFS_FIND(lseek);
1896         return handle->fns->lseek_fn(handle, fsp, offset, whence);
1897 }
1898
1899 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1900                               files_struct *fromfsp, const DATA_BLOB *header,
1901                               off_t offset, size_t count)
1902 {
1903         VFS_FIND(sendfile);
1904         return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1905                                         count);
1906 }
1907
1908 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1909                               files_struct *tofsp, off_t offset,
1910                               size_t count)
1911 {
1912         VFS_FIND(recvfile);
1913         return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1914 }
1915
1916 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1917                         const struct smb_filename *smb_fname_src,
1918                         const struct smb_filename *smb_fname_dst)
1919 {
1920         VFS_FIND(rename);
1921         return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1922 }
1923
1924 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1925                        struct files_struct *fsp)
1926 {
1927         VFS_FIND(fsync);
1928         return handle->fns->fsync_fn(handle, fsp);
1929 }
1930
1931 struct smb_vfs_call_fsync_state {
1932         int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1933         int retval;
1934         struct vfs_aio_state vfs_aio_state;
1935 };
1936
1937 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1938
1939 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1940                                            TALLOC_CTX *mem_ctx,
1941                                            struct tevent_context *ev,
1942                                            struct files_struct *fsp)
1943 {
1944         struct tevent_req *req, *subreq;
1945         struct smb_vfs_call_fsync_state *state;
1946
1947         req = tevent_req_create(mem_ctx, &state,
1948                                 struct smb_vfs_call_fsync_state);
1949         if (req == NULL) {
1950                 return NULL;
1951         }
1952         VFS_FIND(fsync_send);
1953         state->recv_fn = handle->fns->fsync_recv_fn;
1954
1955         subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1956         if (tevent_req_nomem(subreq, req)) {
1957                 return tevent_req_post(req, ev);
1958         }
1959         tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1960         return req;
1961 }
1962
1963 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1964 {
1965         struct tevent_req *req = tevent_req_callback_data(
1966                 subreq, struct tevent_req);
1967         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1968                 req, struct smb_vfs_call_fsync_state);
1969
1970         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1971         TALLOC_FREE(subreq);
1972         if (state->retval == -1) {
1973                 tevent_req_error(req, state->vfs_aio_state.error);
1974                 return;
1975         }
1976         tevent_req_done(req);
1977 }
1978
1979 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1980 {
1981         struct smb_vfs_call_fsync_state *state = tevent_req_data(
1982                 req, struct smb_vfs_call_fsync_state);
1983
1984         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1985                 return -1;
1986         }
1987         *vfs_aio_state = state->vfs_aio_state;
1988         return state->retval;
1989 }
1990
1991
1992 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1993                       struct smb_filename *smb_fname)
1994 {
1995         VFS_FIND(stat);
1996         return handle->fns->stat_fn(handle, smb_fname);
1997 }
1998
1999 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2000                        struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2001 {
2002         VFS_FIND(fstat);
2003         return handle->fns->fstat_fn(handle, fsp, sbuf);
2004 }
2005
2006 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2007                        struct smb_filename *smb_filename)
2008 {
2009         VFS_FIND(lstat);
2010         return handle->fns->lstat_fn(handle, smb_filename);
2011 }
2012
2013 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2014                                      struct files_struct *fsp,
2015                                      const SMB_STRUCT_STAT *sbuf)
2016 {
2017         VFS_FIND(get_alloc_size);
2018         return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2019 }
2020
2021 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
2022                         const struct smb_filename *smb_fname)
2023 {
2024         VFS_FIND(unlink);
2025         return handle->fns->unlink_fn(handle, smb_fname);
2026 }
2027
2028 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
2029                         const struct smb_filename *smb_fname,
2030                         mode_t mode)
2031 {
2032         VFS_FIND(chmod);
2033         return handle->fns->chmod_fn(handle, smb_fname, mode);
2034 }
2035
2036 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2037                         struct files_struct *fsp, mode_t mode)
2038 {
2039         VFS_FIND(fchmod);
2040         return handle->fns->fchmod_fn(handle, fsp, mode);
2041 }
2042
2043 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
2044                         const struct smb_filename *smb_fname,
2045                         uid_t uid,
2046                         gid_t gid)
2047 {
2048         VFS_FIND(chown);
2049         return handle->fns->chown_fn(handle, smb_fname, uid, gid);
2050 }
2051
2052 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2053                         struct files_struct *fsp, uid_t uid, gid_t gid)
2054 {
2055         VFS_FIND(fchown);
2056         return handle->fns->fchown_fn(handle, fsp, uid, gid);
2057 }
2058
2059 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2060                         const struct smb_filename *smb_fname,
2061                         uid_t uid,
2062                         gid_t gid)
2063 {
2064         VFS_FIND(lchown);
2065         return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2066 }
2067
2068 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2069 {
2070         int ret;
2071         bool as_root = false;
2072         NTSTATUS status;
2073
2074         if (fsp->fh->fd != -1) {
2075                 /* Try fchown. */
2076                 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2077                 if (ret == 0) {
2078                         return NT_STATUS_OK;
2079                 }
2080                 if (ret == -1 && errno != ENOSYS) {
2081                         return map_nt_error_from_unix(errno);
2082                 }
2083         }
2084
2085         as_root = (geteuid() == 0);
2086
2087         if (as_root) {
2088                 /*
2089                  * We are being asked to chown as root. Make
2090                  * sure we chdir() into the path to pin it,
2091                  * and always act using lchown to ensure we
2092                  * don't deref any symbolic links.
2093                  */
2094                 char *parent_dir = NULL;
2095                 const char *final_component = NULL;
2096                 struct smb_filename *local_smb_fname = NULL;
2097                 struct smb_filename parent_dir_fname = {0};
2098                 struct smb_filename *saved_dir_fname = NULL;
2099
2100                 saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
2101                 if (!saved_dir_fname) {
2102                         status = map_nt_error_from_unix(errno);
2103                         DEBUG(0,("vfs_chown_fsp: failed to get "
2104                                 "current working directory. Error was %s\n",
2105                                 strerror(errno)));
2106                         return status;
2107                 }
2108
2109                 if (!parent_dirname(talloc_tos(),
2110                                 fsp->fsp_name->base_name,
2111                                 &parent_dir,
2112                                 &final_component)) {
2113                         return NT_STATUS_NO_MEMORY;
2114                 }
2115
2116                 parent_dir_fname = (struct smb_filename) {
2117                         .base_name = parent_dir,
2118                         .flags = fsp->fsp_name->flags
2119                 };
2120
2121                 /* cd into the parent dir to pin it. */
2122                 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2123                 if (ret == -1) {
2124                         return map_nt_error_from_unix(errno);
2125                 }
2126
2127                 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2128                                         final_component,
2129                                         NULL,
2130                                         NULL,
2131                                         fsp->fsp_name->flags);
2132                 if (local_smb_fname == NULL) {
2133                         status = NT_STATUS_NO_MEMORY;
2134                         goto out;
2135                 }
2136
2137                 /* Must use lstat here. */
2138                 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2139                 if (ret == -1) {
2140                         status = map_nt_error_from_unix(errno);
2141                         goto out;
2142                 }
2143
2144                 /* Ensure it matches the fsp stat. */
2145                 if (!check_same_stat(&local_smb_fname->st,
2146                                 &fsp->fsp_name->st)) {
2147                         status = NT_STATUS_ACCESS_DENIED;
2148                         goto out;
2149                 }
2150
2151                 ret = SMB_VFS_LCHOWN(fsp->conn,
2152                         local_smb_fname,
2153                         uid, gid);
2154
2155                 if (ret == 0) {
2156                         status = NT_STATUS_OK;
2157                 } else {
2158                         status = map_nt_error_from_unix(errno);
2159                 }
2160
2161   out:
2162
2163                 vfs_ChDir(fsp->conn, saved_dir_fname);
2164                 TALLOC_FREE(local_smb_fname);
2165                 TALLOC_FREE(saved_dir_fname);
2166                 TALLOC_FREE(parent_dir);
2167
2168                 return status;
2169         }
2170
2171         if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2172                 ret = SMB_VFS_LCHOWN(fsp->conn,
2173                         fsp->fsp_name,
2174                         uid, gid);
2175         } else {
2176                 ret = SMB_VFS_CHOWN(fsp->conn,
2177                         fsp->fsp_name,
2178                         uid, gid);
2179         }
2180
2181         if (ret == 0) {
2182                 status = NT_STATUS_OK;
2183         } else {
2184                 status = map_nt_error_from_unix(errno);
2185         }
2186         return status;
2187 }
2188
2189 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2190                         const struct smb_filename *smb_fname)
2191 {
2192         VFS_FIND(chdir);
2193         return handle->fns->chdir_fn(handle, smb_fname);
2194 }
2195
2196 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2197                                 TALLOC_CTX *ctx)
2198 {
2199         VFS_FIND(getwd);
2200         return handle->fns->getwd_fn(handle, ctx);
2201 }
2202
2203 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2204                         const struct smb_filename *smb_fname,
2205                         struct smb_file_time *ft)
2206 {
2207         VFS_FIND(ntimes);
2208         return handle->fns->ntimes_fn(handle, smb_fname, ft);
2209 }
2210
2211 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2212                            struct files_struct *fsp, off_t offset)
2213 {
2214         VFS_FIND(ftruncate);
2215         return handle->fns->ftruncate_fn(handle, fsp, offset);
2216 }
2217
2218 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2219                            struct files_struct *fsp,
2220                            uint32_t mode,
2221                            off_t offset,
2222                            off_t len)
2223 {
2224         VFS_FIND(fallocate);
2225         return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2226 }
2227
2228 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2229                               struct files_struct *fsp, uint32_t share_mode,
2230                               uint32_t access_mask)
2231 {
2232         VFS_FIND(kernel_flock);
2233         return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2234                                          access_mask);
2235 }
2236
2237 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2238                                 struct files_struct *fsp, int leasetype)
2239 {
2240         VFS_FIND(linux_setlease);
2241         return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2242 }
2243
2244 int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
2245                         const char *link_target,
2246                         const struct smb_filename *new_smb_fname)
2247 {
2248         VFS_FIND(symlink);
2249         return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
2250 }
2251
2252 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2253                         const struct smb_filename *smb_fname,
2254                         char *buf,
2255                         size_t bufsiz)
2256 {
2257         VFS_FIND(readlink);
2258         return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
2259 }
2260
2261 int smb_vfs_call_link(struct vfs_handle_struct *handle,
2262                         const struct smb_filename *old_smb_fname,
2263                         const struct smb_filename *new_smb_fname)
2264 {
2265         VFS_FIND(link);
2266         return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2267 }
2268
2269 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2270                         const struct smb_filename *smb_fname,
2271                         mode_t mode,
2272                         SMB_DEV_T dev)
2273 {
2274         VFS_FIND(mknod);
2275         return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2276 }
2277
2278 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2279                         TALLOC_CTX *ctx,
2280                         const struct smb_filename *smb_fname)
2281 {
2282         VFS_FIND(realpath);
2283         return handle->fns->realpath_fn(handle, ctx, smb_fname);
2284 }
2285
2286 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2287                         const struct smb_filename *smb_fname,
2288                         unsigned int flags)
2289 {
2290         VFS_FIND(chflags);
2291         return handle->fns->chflags_fn(handle, smb_fname, flags);
2292 }
2293
2294 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2295                                            const SMB_STRUCT_STAT *sbuf)
2296 {
2297         VFS_FIND(file_id_create);
2298         return handle->fns->file_id_create_fn(handle, sbuf);
2299 }
2300
2301 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2302                                  struct files_struct *fsp,
2303                                  const struct smb_filename *smb_fname,
2304                                  TALLOC_CTX *mem_ctx,
2305                                  unsigned int *num_streams,
2306                                  struct stream_struct **streams)
2307 {
2308         VFS_FIND(streaminfo);
2309         return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2310                                           num_streams, streams);
2311 }
2312
2313 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2314                                    const char *path, const char *name,
2315                                    TALLOC_CTX *mem_ctx, char **found_name)
2316 {
2317         VFS_FIND(get_real_filename);
2318         return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2319                                                  found_name);
2320 }
2321
2322 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2323                                  const struct smb_filename *smb_fname)
2324 {
2325         VFS_FIND(connectpath);
2326         return handle->fns->connectpath_fn(handle, smb_fname);
2327 }
2328
2329 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2330                                     struct files_struct *fsp,
2331                                     struct lock_struct *plock)
2332 {
2333         VFS_FIND(strict_lock_check);
2334         return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2335 }
2336
2337 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2338                                      const char *name,
2339                                      enum vfs_translate_direction direction,
2340                                      TALLOC_CTX *mem_ctx,
2341                                      char **mapped_name)
2342 {
2343         VFS_FIND(translate_name);
2344         return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2345                                               mapped_name);
2346 }
2347
2348 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2349                             struct files_struct *fsp,
2350                             TALLOC_CTX *ctx,
2351                             uint32_t function,
2352                             uint16_t req_flags,
2353                             const uint8_t *in_data,
2354                             uint32_t in_len,
2355                             uint8_t **out_data,
2356                             uint32_t max_out_len,
2357                             uint32_t *out_len)
2358 {
2359         VFS_FIND(fsctl);
2360         return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2361                                      in_data, in_len, out_data, max_out_len,
2362                                      out_len);
2363 }
2364
2365 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2366                                          struct smb_filename *smb_fname,
2367                                          uint32_t *dosmode)
2368 {
2369         VFS_FIND(get_dos_attributes);
2370         return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2371 }
2372
2373 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2374                                           struct files_struct *fsp,
2375                                           uint32_t *dosmode)
2376 {
2377         VFS_FIND(fget_dos_attributes);
2378         return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2379 }
2380
2381 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2382                                          const struct smb_filename *smb_fname,
2383                                          uint32_t dosmode)
2384 {
2385         VFS_FIND(set_dos_attributes);
2386         return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2387 }
2388
2389 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2390                                           struct files_struct *fsp,
2391                                           uint32_t dosmode)
2392 {
2393         VFS_FIND(set_dos_attributes);
2394         return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2395 }
2396
2397 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2398                                                   struct tevent_context *ev,
2399                                                   struct vfs_handle_struct *handle,
2400                                                   struct files_struct *fsp,
2401                                                   uint32_t fsctl,
2402                                                   uint32_t ttl,
2403                                                   off_t offset,
2404                                                   size_t to_copy)
2405 {
2406         VFS_FIND(offload_read_send);
2407         return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2408                                                  fsp, fsctl,
2409                                                  ttl, offset, to_copy);
2410 }
2411
2412 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2413                                         struct vfs_handle_struct *handle,
2414                                         TALLOC_CTX *mem_ctx,
2415                                         DATA_BLOB *token_blob)
2416 {
2417         VFS_FIND(offload_read_recv);
2418         return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2419 }
2420
2421 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2422                                                    TALLOC_CTX *mem_ctx,
2423                                                    struct tevent_context *ev,
2424                                                    uint32_t fsctl,
2425                                                    DATA_BLOB *token,
2426                                                    off_t transfer_offset,
2427                                                    struct files_struct *dest_fsp,
2428                                                    off_t dest_off,
2429                                                    off_t num)
2430 {
2431         VFS_FIND(offload_write_send);
2432         return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2433                                                token, transfer_offset,
2434                                                dest_fsp, dest_off, num);
2435 }
2436
2437 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2438                                          struct tevent_req *req,
2439                                          off_t *copied)
2440 {
2441         VFS_FIND(offload_write_recv);
2442         return handle->fns->offload_write_recv_fn(handle, req, copied);
2443 }
2444
2445 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2446                                       TALLOC_CTX *mem_ctx,
2447                                       struct files_struct *fsp,
2448                                       struct smb_filename *smb_fname,
2449                                       uint16_t *_compression_fmt)
2450 {
2451         VFS_FIND(get_compression);
2452         return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2453                                                _compression_fmt);
2454 }
2455
2456 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2457                                       TALLOC_CTX *mem_ctx,
2458                                       struct files_struct *fsp,
2459                                       uint16_t compression_fmt)
2460 {
2461         VFS_FIND(set_compression);
2462         return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2463                                                compression_fmt);
2464 }
2465
2466 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2467                                       TALLOC_CTX *mem_ctx,
2468                                       const char *service_path,
2469                                       char **base_volume)
2470 {
2471         VFS_FIND(snap_check_path);
2472         return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2473                                                base_volume);
2474 }
2475
2476 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2477                                   TALLOC_CTX *mem_ctx,
2478                                   const char *base_volume,
2479                                   time_t *tstamp,
2480                                   bool rw,
2481                                   char **base_path,
2482                                   char **snap_path)
2483 {
2484         VFS_FIND(snap_create);
2485         return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2486                                            rw, base_path, snap_path);
2487 }
2488
2489 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2490                                   TALLOC_CTX *mem_ctx,
2491                                   char *base_path,
2492                                   char *snap_path)
2493 {
2494         VFS_FIND(snap_delete);
2495         return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2496                                            snap_path);
2497 }
2498
2499 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2500                                   struct files_struct *fsp,
2501                                   uint32_t security_info,
2502                                   TALLOC_CTX *mem_ctx,
2503                                   struct security_descriptor **ppdesc)
2504 {
2505         VFS_FIND(fget_nt_acl);
2506         return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2507                                            mem_ctx, ppdesc);
2508 }
2509
2510 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2511                                  const struct smb_filename *smb_fname,
2512                                  uint32_t security_info,
2513                                  TALLOC_CTX *mem_ctx,
2514                                  struct security_descriptor **ppdesc)
2515 {
2516         VFS_FIND(get_nt_acl);
2517         return handle->fns->get_nt_acl_fn(handle,
2518                                 smb_fname,
2519                                 security_info,
2520                                 mem_ctx,
2521                                 ppdesc);
2522 }
2523
2524 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2525                                   struct files_struct *fsp,
2526                                   uint32_t security_info_sent,
2527                                   const struct security_descriptor *psd)
2528 {
2529         VFS_FIND(fset_nt_acl);
2530         return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent, 
2531                                            psd);
2532 }
2533
2534 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2535                                  struct smb_filename *file,
2536                                  struct security_acl *sacl,
2537                                  uint32_t access_requested,
2538                                  uint32_t access_denied)
2539 {
2540         VFS_FIND(audit_file);
2541         return handle->fns->audit_file_fn(handle, 
2542                                           file, 
2543                                           sacl, 
2544                                           access_requested, 
2545                                           access_denied);
2546 }
2547
2548 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle,
2549                 const struct smb_filename *smb_fname,
2550                 mode_t mode)
2551 {
2552         VFS_FIND(chmod_acl);
2553         return handle->fns->chmod_acl_fn(handle, smb_fname, mode);
2554 }
2555
2556 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2557                             struct files_struct *fsp, mode_t mode)
2558 {
2559         VFS_FIND(fchmod_acl);
2560         return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2561 }
2562
2563 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2564                                         const struct smb_filename *smb_fname,
2565                                         SMB_ACL_TYPE_T type,
2566                                         TALLOC_CTX *mem_ctx)
2567 {
2568         VFS_FIND(sys_acl_get_file);
2569         return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2570 }
2571
2572 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2573                                       struct files_struct *fsp,
2574                                       TALLOC_CTX *mem_ctx)
2575 {
2576         VFS_FIND(sys_acl_get_fd);
2577         return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2578 }
2579
2580 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2581                                 const struct smb_filename *smb_fname,
2582                                 TALLOC_CTX *mem_ctx,
2583                                 char **blob_description,
2584                                 DATA_BLOB *blob)
2585 {
2586         VFS_FIND(sys_acl_blob_get_file);
2587         return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2588                         mem_ctx, blob_description, blob);
2589 }
2590
2591 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2592                                      struct files_struct *fsp,
2593                                      TALLOC_CTX *mem_ctx, 
2594                                      char **blob_description,
2595                                      DATA_BLOB *blob)
2596 {
2597         VFS_FIND(sys_acl_blob_get_fd);
2598         return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2599 }
2600
2601 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2602                                 const struct smb_filename *smb_fname,
2603                                 SMB_ACL_TYPE_T acltype,
2604                                 SMB_ACL_T theacl)
2605 {
2606         VFS_FIND(sys_acl_set_file);
2607         return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2608                                 acltype, theacl);
2609 }
2610
2611 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2612                                 struct files_struct *fsp, SMB_ACL_T theacl)
2613 {
2614         VFS_FIND(sys_acl_set_fd);
2615         return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2616 }
2617
2618 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2619                                 const struct smb_filename *smb_fname)
2620 {
2621         VFS_FIND(sys_acl_delete_def_file);
2622         return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2623 }
2624
2625 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2626                                 const struct smb_filename *smb_fname,
2627                                 const char *name,
2628                                 void *value,
2629                                 size_t size)
2630 {
2631         VFS_FIND(getxattr);
2632         return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2633 }
2634
2635 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2636                                struct files_struct *fsp, const char *name,
2637                                void *value, size_t size)
2638 {
2639         VFS_FIND(fgetxattr);
2640         return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2641 }
2642
2643 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2644                                 const struct smb_filename *smb_fname,
2645                                 char *list,
2646                                 size_t size)
2647 {
2648         VFS_FIND(listxattr);
2649         return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2650 }
2651
2652 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2653                                 struct files_struct *fsp, char *list,
2654                                 size_t size)
2655 {
2656         VFS_FIND(flistxattr);
2657         return handle->fns->flistxattr_fn(handle, fsp, list, size);
2658 }
2659
2660 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2661                                 const struct smb_filename *smb_fname,
2662                                 const char *name)
2663 {
2664         VFS_FIND(removexattr);
2665         return handle->fns->removexattr_fn(handle, smb_fname, name);
2666 }
2667
2668 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2669                               struct files_struct *fsp, const char *name)
2670 {
2671         VFS_FIND(fremovexattr);
2672         return handle->fns->fremovexattr_fn(handle, fsp, name);
2673 }
2674
2675 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2676                         const struct smb_filename *smb_fname,
2677                         const char *name,
2678                         const void *value,
2679                         size_t size,
2680                         int flags)
2681 {
2682         VFS_FIND(setxattr);
2683         return handle->fns->setxattr_fn(handle, smb_fname,
2684                         name, value, size, flags);
2685 }
2686
2687 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2688                            struct files_struct *fsp, const char *name,
2689                            const void *value, size_t size, int flags)
2690 {
2691         VFS_FIND(fsetxattr);
2692         return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2693 }
2694
2695 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2696                             struct files_struct *fsp)
2697 {
2698         VFS_FIND(aio_force);
2699         return handle->fns->aio_force_fn(handle, fsp);
2700 }
2701
2702 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2703                                      struct files_struct *fsp,
2704                                      TALLOC_CTX *mem_ctx,
2705                                      DATA_BLOB *cookie)
2706 {
2707         VFS_FIND(durable_cookie);
2708         return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2709 }
2710
2711 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2712                                          struct files_struct *fsp,
2713                                          const DATA_BLOB old_cookie,
2714                                          TALLOC_CTX *mem_ctx,
2715                                          DATA_BLOB *new_cookie)
2716 {
2717         VFS_FIND(durable_disconnect);
2718         return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2719                                                   mem_ctx, new_cookie);
2720 }
2721
2722 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2723                                         struct smb_request *smb1req,
2724                                         struct smbXsrv_open *op,
2725                                         const DATA_BLOB old_cookie,
2726                                         TALLOC_CTX *mem_ctx,
2727                                         struct files_struct **fsp,
2728                                         DATA_BLOB *new_cookie)
2729 {
2730         VFS_FIND(durable_reconnect);
2731         return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2732                                                  old_cookie, mem_ctx, fsp,
2733                                                  new_cookie);
2734 }
2735
2736 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2737                                    const struct smb_filename *fname,
2738                                    TALLOC_CTX *mem_ctx,
2739                                    struct readdir_attr_data **attr_data)
2740 {
2741         VFS_FIND(readdir_attr);
2742         return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
2743 }