vfs: RIP SMB_VFS_SYS_ACL_SET_FILE()
[samba.git] / source3 / smbd / vfs.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    VFS initialisation and support functions
5    Copyright (C) Tim Potter 1999
6    Copyright (C) Alexander Bokovoy 2002
7    Copyright (C) James Peach 2006
8    Copyright (C) Volker Lendecke 2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23    This work was sponsored by Optifacio Software Services, Inc.
24 */
25
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "../lib/util/memcache.h"
31 #include "transfer_file.h"
32 #include "ntioctl.h"
33 #include "lib/util/tevent_unix.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
36
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
39
40 static_decl_vfs;
41
42 struct vfs_fsp_data {
43     struct vfs_fsp_data *next;
44     struct vfs_handle_struct *owner;
45     void (*destroy)(void *p_data);
46     void *_dummy_;
47     /* NOTE: This structure contains four pointers so that we can guarantee
48      * that the end of the structure is always both 4-byte and 8-byte aligned.
49      */
50 };
51
52 struct vfs_init_function_entry {
53         char *name;
54         struct vfs_init_function_entry *prev, *next;
55         const struct vfs_fn_pointers *fns;
56 };
57
58 /****************************************************************************
59     maintain the list of available backends
60 ****************************************************************************/
61
62 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
63 {
64         struct vfs_init_function_entry *entry = backends;
65
66         DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
67
68         while(entry) {
69                 if (strcmp(entry->name, name)==0) return entry;
70                 entry = entry->next;
71         }
72
73         return NULL;
74 }
75
76 NTSTATUS smb_register_vfs(int version, const char *name,
77                           const struct vfs_fn_pointers *fns)
78 {
79         struct vfs_init_function_entry *entry = backends;
80
81         if ((version != SMB_VFS_INTERFACE_VERSION)) {
82                 DEBUG(0, ("Failed to register vfs module.\n"
83                           "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
84                           "current SMB_VFS_INTERFACE_VERSION is %d.\n"
85                           "Please recompile against the current Samba Version!\n",  
86                           version, SMB_VFS_INTERFACE_VERSION));
87                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
88         }
89
90         if (!name || !name[0]) {
91                 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
92                 return NT_STATUS_INVALID_PARAMETER;
93         }
94
95         if (vfs_find_backend_entry(name)) {
96                 DEBUG(0,("VFS module %s already loaded!\n", name));
97                 return NT_STATUS_OBJECT_NAME_COLLISION;
98         }
99
100         entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
101         entry->name = smb_xstrdup(name);
102         entry->fns = fns;
103
104         DLIST_ADD(backends, entry);
105         DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
106         return NT_STATUS_OK;
107 }
108
109 /****************************************************************************
110   initialise default vfs hooks
111 ****************************************************************************/
112
113 static void vfs_init_default(connection_struct *conn)
114 {
115         DEBUG(3, ("Initialising default vfs hooks\n"));
116         vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
117 }
118
119 /****************************************************************************
120   initialise custom vfs hooks
121  ****************************************************************************/
122
123 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
124 {
125         char *module_path = NULL;
126         char *module_name = NULL;
127         char *module_param = NULL, *p;
128         vfs_handle_struct *handle;
129         const struct vfs_init_function_entry *entry;
130
131         if (!conn||!vfs_object||!vfs_object[0]) {
132                 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
133                           "empty vfs_object!\n"));
134                 return False;
135         }
136
137         if(!backends) {
138                 static_init_vfs(NULL);
139         }
140
141         DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
142
143         module_path = smb_xstrdup(vfs_object);
144
145         p = strchr_m(module_path, ':');
146
147         if (p) {
148                 *p = 0;
149                 module_param = p+1;
150                 trim_char(module_param, ' ', ' ');
151         }
152
153         trim_char(module_path, ' ', ' ');
154
155         module_name = smb_xstrdup(module_path);
156
157         if ((module_name[0] == '/') &&
158             (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
159
160                 /*
161                  * Extract the module name from the path. Just use the base
162                  * name of the last path component.
163                  */
164
165                 SAFE_FREE(module_name);
166                 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
167
168                 p = strchr_m(module_name, '.');
169
170                 if (p != NULL) {
171                         *p = '\0';
172                 }
173         }
174
175         /* First, try to load the module with the new module system */
176         entry = vfs_find_backend_entry(module_name);
177         if (!entry) {
178                 NTSTATUS status;
179
180                 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
181                           vfs_object));
182
183                 status = smb_load_module("vfs", module_path);
184                 if (!NT_STATUS_IS_OK(status)) {
185                         DEBUG(0, ("error probing vfs module '%s': %s\n",
186                                   module_path, nt_errstr(status)));
187                         goto fail;
188                 }
189
190                 entry = vfs_find_backend_entry(module_name);
191                 if (!entry) {
192                         DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
193                         goto fail;
194                 }
195         }
196
197         DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
198
199         handle = talloc_zero(conn, vfs_handle_struct);
200         if (!handle) {
201                 DEBUG(0,("TALLOC_ZERO() failed!\n"));
202                 goto fail;
203         }
204         handle->conn = conn;
205         handle->fns = entry->fns;
206         if (module_param) {
207                 handle->param = talloc_strdup(conn, module_param);
208         }
209         DLIST_ADD(conn->vfs_handles, handle);
210
211         SAFE_FREE(module_path);
212         SAFE_FREE(module_name);
213         return True;
214
215  fail:
216         SAFE_FREE(module_path);
217         SAFE_FREE(module_name);
218         return False;
219 }
220
221 /*****************************************************************
222  Allow VFS modules to extend files_struct with VFS-specific state.
223  This will be ok for small numbers of extensions, but might need to
224  be refactored if it becomes more widely used.
225 ******************************************************************/
226
227 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
228
229 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
230                                    files_struct *fsp, size_t ext_size,
231                                    void (*destroy_fn)(void *p_data))
232 {
233         struct vfs_fsp_data *ext;
234         void * ext_data;
235
236         /* Prevent VFS modules adding multiple extensions. */
237         if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
238                 return ext_data;
239         }
240
241         ext = (struct vfs_fsp_data *)TALLOC_ZERO(
242                 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
243         if (ext == NULL) {
244                 return NULL;
245         }
246
247         ext->owner = handle;
248         ext->next = fsp->vfs_extension;
249         ext->destroy = destroy_fn;
250         fsp->vfs_extension = ext;
251         return EXT_DATA_AREA(ext);
252 }
253
254 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
255 {
256         struct vfs_fsp_data *curr;
257         struct vfs_fsp_data *prev;
258
259         for (curr = fsp->vfs_extension, prev = NULL;
260              curr;
261              prev = curr, curr = curr->next) {
262                 if (curr->owner == handle) {
263                     if (prev) {
264                             prev->next = curr->next;
265                     } else {
266                             fsp->vfs_extension = curr->next;
267                     }
268                     if (curr->destroy) {
269                             curr->destroy(EXT_DATA_AREA(curr));
270                     }
271                     TALLOC_FREE(curr);
272                     return;
273                 }
274         }
275 }
276
277 void vfs_remove_all_fsp_extensions(files_struct *fsp)
278 {
279         struct vfs_fsp_data *curr;
280         struct vfs_fsp_data *next;
281
282         for (curr = fsp->vfs_extension; curr; curr = next) {
283
284                 next = curr->next;
285                 fsp->vfs_extension = next;
286
287                 if (curr->destroy) {
288                         curr->destroy(EXT_DATA_AREA(curr));
289                 }
290                 TALLOC_FREE(curr);
291         }
292 }
293
294 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
295 {
296         struct vfs_fsp_data *head;
297
298         for (head = fsp->vfs_extension; head; head = head->next) {
299                 if (head->owner == handle) {
300                         return head;
301                 }
302         }
303
304         return NULL;
305 }
306
307 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
308 {
309         struct vfs_fsp_data *head;
310
311         head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
312         if (head != NULL) {
313                 return EXT_DATA_AREA(head);
314         }
315
316         return NULL;
317 }
318
319 #undef EXT_DATA_AREA
320
321 /*
322  * Ensure this module catches all VFS functions.
323  */
324 #ifdef DEVELOPER
325 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
326                             const char *module)
327 {
328         bool missing_fn = false;
329         unsigned int idx;
330         const uintptr_t *end = (const uintptr_t *)(fns + 1);
331
332         for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
333                 if (*((const uintptr_t *)fns + idx) == 0) {
334                         DBG_ERR("VFS function at index %d not implemented "
335                                 "in module %s\n", idx, module);
336                         missing_fn = true;
337                 }
338         }
339
340         if (missing_fn) {
341                 smb_panic("Required VFS function not implemented in module.\n");
342         }
343 }
344 #else
345 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
346                             const char *module)
347 {
348 }
349 #endif
350
351 /*****************************************************************
352  Generic VFS init.
353 ******************************************************************/
354
355 bool smbd_vfs_init(connection_struct *conn)
356 {
357         const char **vfs_objects;
358         unsigned int i = 0;
359         int j = 0;
360
361         /* Normal share - initialise with disk access functions */
362         vfs_init_default(conn);
363
364         /* No need to load vfs modules for printer connections */
365         if (conn->printer) {
366                 return True;
367         }
368
369         if (lp_widelinks(SNUM(conn))) {
370                 /*
371                  * As the widelinks logic is now moving into a
372                  * vfs_widelinks module, we need to custom load
373                  * it after the default module is initialized.
374                  * That way no changes to smb.conf files are
375                  * needed.
376                  */
377                 bool ok = vfs_init_custom(conn, "widelinks");
378                 if (!ok) {
379                         DBG_ERR("widelinks enabled and vfs_init_custom "
380                                 "failed for vfs_widelinks module\n");
381                         return false;
382                 }
383         }
384
385         vfs_objects = lp_vfs_objects(SNUM(conn));
386
387         /* Override VFS functions if 'vfs object' was not specified*/
388         if (!vfs_objects || !vfs_objects[0])
389                 return True;
390
391         for (i=0; vfs_objects[i] ;) {
392                 i++;
393         }
394
395         for (j=i-1; j >= 0; j--) {
396                 if (!vfs_init_custom(conn, vfs_objects[j])) {
397                         DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
398                         return False;
399                 }
400         }
401         return True;
402 }
403
404 /*******************************************************************
405  Check if a file exists in the vfs.
406 ********************************************************************/
407
408 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
409 {
410         /* Only return OK if stat was successful and S_ISREG */
411         if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
412             S_ISREG(smb_fname->st.st_ex_mode)) {
413                 return NT_STATUS_OK;
414         }
415
416         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
417 }
418
419 bool vfs_valid_pread_range(off_t offset, size_t length)
420 {
421         return sys_valid_io_range(offset, length);
422 }
423
424 bool vfs_valid_pwrite_range(off_t offset, size_t length)
425 {
426         /*
427          * See MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write
428          */
429         static const uint64_t maxfilesize = 0xfffffff0000;
430         uint64_t last_byte_ofs;
431         bool ok;
432
433         ok = sys_valid_io_range(offset, length);
434         if (!ok) {
435                 return false;
436         }
437
438         if (length == 0) {
439                 return true;
440         }
441
442         last_byte_ofs = offset + length;
443         if (last_byte_ofs > maxfilesize) {
444                 return false;
445         }
446
447         return true;
448 }
449
450 ssize_t vfs_pwrite_data(struct smb_request *req,
451                         files_struct *fsp,
452                         const char *buffer,
453                         size_t N,
454                         off_t offset)
455 {
456         size_t total=0;
457         ssize_t ret;
458         bool ok;
459
460         ok = vfs_valid_pwrite_range(offset, N);
461         if (!ok) {
462                 errno = EINVAL;
463                 return -1;
464         }
465
466         if (req && req->unread_bytes) {
467                 int sockfd = req->xconn->transport.sock;
468                 SMB_ASSERT(req->unread_bytes == N);
469                 /* VFS_RECVFILE must drain the socket
470                  * before returning. */
471                 req->unread_bytes = 0;
472                 /*
473                  * Leave the socket non-blocking and
474                  * use SMB_VFS_RECVFILE. If it returns
475                  * EAGAIN || EWOULDBLOCK temporarily set
476                  * the socket blocking and retry
477                  * the RECVFILE.
478                  */
479                 while (total < N) {
480                         ret = SMB_VFS_RECVFILE(sockfd,
481                                                 fsp,
482                                                 offset + total,
483                                                 N - total);
484                         if (ret == 0 || (ret == -1 &&
485                                          (errno == EAGAIN ||
486                                           errno == EWOULDBLOCK))) {
487                                 int old_flags;
488                                 /* Ensure the socket is blocking. */
489                                 old_flags = fcntl(sockfd, F_GETFL, 0);
490                                 if (set_blocking(sockfd, true) == -1) {
491                                         return (ssize_t)-1;
492                                 }
493                                 ret = SMB_VFS_RECVFILE(sockfd,
494                                                         fsp,
495                                                         offset + total,
496                                                         N - total);
497                                 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
498                                         return (ssize_t)-1;
499                                 }
500                                 if (ret == -1) {
501                                         return (ssize_t)-1;
502                                 }
503                                 total += ret;
504                                 return (ssize_t)total;
505                         }
506                         /* Any other error case. */
507                         if (ret == -1) {
508                                 return ret;
509                         }
510                         total += ret;
511                 }
512                 return (ssize_t)total;
513         }
514
515         while (total < N) {
516                 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
517                                      offset + total);
518
519                 if (ret == -1)
520                         return -1;
521                 if (ret == 0)
522                         return total;
523
524                 total += ret;
525         }
526         return (ssize_t)total;
527 }
528 /****************************************************************************
529  An allocate file space call using the vfs interface.
530  Allocates space for a file from a filedescriptor.
531  Returns 0 on success, -1 on failure.
532 ****************************************************************************/
533
534 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
535 {
536         int ret;
537         connection_struct *conn = fsp->conn;
538         uint64_t space_avail;
539         uint64_t bsize,dfree,dsize;
540         NTSTATUS status;
541         bool ok;
542
543         /*
544          * Actually try and commit the space on disk....
545          */
546
547         DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
548                   fsp_str_dbg(fsp), (double)len));
549
550         ok = vfs_valid_pwrite_range((off_t)len, 0);
551         if (!ok) {
552                 DEBUG(0,("vfs_allocate_file_space: %s negative/invalid len "
553                          "requested.\n", fsp_str_dbg(fsp)));
554                 errno = EINVAL;
555                 return -1;
556         }
557
558         status = vfs_stat_fsp(fsp);
559         if (!NT_STATUS_IS_OK(status)) {
560                 return -1;
561         }
562
563         if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
564                 return 0;
565
566         if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
567                 /* Shrink - use ftruncate. */
568
569                 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
570                           "size %.0f\n", fsp_str_dbg(fsp),
571                           (double)fsp->fsp_name->st.st_ex_size));
572
573                 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
574
575                 ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
576
577                 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
578
579                 return ret;
580         }
581
582         /* Grow - we need to test if we have enough space. */
583
584         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
585
586         if (lp_strict_allocate(SNUM(fsp->conn))) {
587                 /* See if we have a syscall that will allocate beyond
588                    end-of-file without changing EOF. */
589                 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
590                                         0, len);
591         } else {
592                 ret = 0;
593         }
594
595         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
596
597         if (ret == 0) {
598                 /* We changed the allocation size on disk, but not
599                    EOF - exactly as required. We're done ! */
600                 return 0;
601         }
602
603         if (ret == -1 && errno == ENOSPC) {
604                 return -1;
605         }
606
607         len -= fsp->fsp_name->st.st_ex_size;
608         len /= 1024; /* Len is now number of 1k blocks needed. */
609         space_avail =
610             get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
611         if (space_avail == (uint64_t)-1) {
612                 return -1;
613         }
614
615         DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
616                   "needed blocks = %.0f, space avail = %.0f\n",
617                   fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
618                   (double)space_avail));
619
620         if (len > space_avail) {
621                 errno = ENOSPC;
622                 return -1;
623         }
624
625         return 0;
626 }
627
628 /****************************************************************************
629  A vfs set_filelen call.
630  set the length of a file from a filedescriptor.
631  Returns 0 on success, -1 on failure.
632 ****************************************************************************/
633
634 int vfs_set_filelen(files_struct *fsp, off_t len)
635 {
636         int ret;
637         bool ok;
638
639         ok = vfs_valid_pwrite_range(len, 0);
640         if (!ok) {
641                 errno = EINVAL;
642                 return -1;
643         }
644
645         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
646
647         DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
648                   fsp_str_dbg(fsp), (double)len));
649         if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
650                 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
651                              FILE_NOTIFY_CHANGE_SIZE
652                              | FILE_NOTIFY_CHANGE_ATTRIBUTES,
653                              fsp->fsp_name->base_name);
654         }
655
656         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
657
658         return ret;
659 }
660
661 /****************************************************************************
662  A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
663  fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
664  as this is also called from the default SMB_VFS_FTRUNCATE code.
665  Always extends the file size.
666  Returns 0 on success, -1 on failure.
667 ****************************************************************************/
668
669 #define SPARSE_BUF_WRITE_SIZE (32*1024)
670
671 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
672 {
673         ssize_t pwrite_ret;
674         size_t total = 0;
675         bool ok;
676
677         ok = vfs_valid_pwrite_range(offset, len);
678         if (!ok) {
679                 errno = EINVAL;
680                 return -1;
681         }
682
683         if (!sparse_buf) {
684                 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
685                 if (!sparse_buf) {
686                         errno = ENOMEM;
687                         return -1;
688                 }
689         }
690
691         while (total < len) {
692                 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
693
694                 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
695                 if (pwrite_ret == -1) {
696                         int saved_errno = errno;
697                         DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
698                                   "%s failed with error %s\n",
699                                   fsp_str_dbg(fsp), strerror(saved_errno)));
700                         errno = saved_errno;
701                         return -1;
702                 }
703                 total += pwrite_ret;
704         }
705
706         return 0;
707 }
708
709 /****************************************************************************
710  A vfs fill sparse call.
711  Writes zeros from the end of file to len, if len is greater than EOF.
712  Used only by strict_sync.
713  Returns 0 on success, -1 on failure.
714 ****************************************************************************/
715
716 int vfs_fill_sparse(files_struct *fsp, off_t len)
717 {
718         int ret;
719         NTSTATUS status;
720         off_t offset;
721         size_t num_to_write;
722         bool ok;
723
724         ok = vfs_valid_pwrite_range(len, 0);
725         if (!ok) {
726                 errno = EINVAL;
727                 return -1;
728         }
729
730         status = vfs_stat_fsp(fsp);
731         if (!NT_STATUS_IS_OK(status)) {
732                 return -1;
733         }
734
735         if (len <= fsp->fsp_name->st.st_ex_size) {
736                 return 0;
737         }
738
739 #ifdef S_ISFIFO
740         if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
741                 return 0;
742         }
743 #endif
744
745         DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
746                   "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
747                   (double)fsp->fsp_name->st.st_ex_size, (double)len,
748                   (double)(len - fsp->fsp_name->st.st_ex_size)));
749
750         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
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         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
778         return ret;
779 }
780
781 /*******************************************************************************
782  Set a fd into blocking/nonblocking mode through VFS
783 *******************************************************************************/
784
785 int vfs_set_blocking(files_struct *fsp, bool set)
786 {
787         int val;
788 #ifdef O_NONBLOCK
789 #define FLAG_TO_SET O_NONBLOCK
790 #else
791 #ifdef SYSV
792 #define FLAG_TO_SET O_NDELAY
793 #else /* BSD */
794 #define FLAG_TO_SET FNDELAY
795 #endif
796 #endif
797
798         if (fsp->fsp_flags.is_pathref) {
799                 return 0;
800         }
801
802         val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
803         if (val == -1) {
804                 return -1;
805         }
806
807         if (set) {
808                 val &= ~FLAG_TO_SET;
809         } else {
810                 val |= FLAG_TO_SET;
811         }
812
813         return SMB_VFS_FCNTL(fsp, F_SETFL, val);
814 #undef FLAG_TO_SET
815 }
816
817 /****************************************************************************
818  Transfer some data (n bytes) between two file_struct's.
819 ****************************************************************************/
820
821 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
822 {
823         struct files_struct *fsp = (struct files_struct *)file;
824
825         return SMB_VFS_PREAD(fsp, buf, len, offset);
826 }
827
828 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
829 {
830         struct files_struct *fsp = (struct files_struct *)file;
831
832         return SMB_VFS_PWRITE(fsp, buf, len, offset);
833 }
834
835 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
836 {
837         return transfer_file_internal((void *)in, (void *)out, n,
838                                       vfs_pread_fn, vfs_pwrite_fn);
839 }
840
841 /*******************************************************************
842  A vfs_readdir wrapper which just returns the file name.
843 ********************************************************************/
844
845 const char *vfs_readdirname(connection_struct *conn,
846                             struct files_struct *dirfsp,
847                             void *p,
848                             SMB_STRUCT_STAT *sbuf,
849                             char **talloced)
850 {
851         struct dirent *ptr= NULL;
852         const char *dname;
853         char *translated;
854         NTSTATUS status;
855
856         if (!p)
857                 return(NULL);
858
859         ptr = SMB_VFS_READDIR(conn, dirfsp, (DIR *)p, sbuf);
860         if (!ptr)
861                 return(NULL);
862
863         dname = ptr->d_name;
864
865         status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
866                                         talloc_tos(), &translated);
867         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
868                 *talloced = NULL;
869                 return dname;
870         }
871         *talloced = translated;
872         if (!NT_STATUS_IS_OK(status)) {
873                 return NULL;
874         }
875         return translated;
876 }
877
878 /*******************************************************************
879  A wrapper for vfs_chdir().
880 ********************************************************************/
881
882 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
883 {
884         int ret;
885         struct smb_filename *cwd = NULL;
886
887         if (!LastDir) {
888                 LastDir = SMB_STRDUP("");
889         }
890
891         if (ISDOT(smb_fname->base_name)) {
892                 /*
893                  * passing a '.' is a noop,
894                  * and we only expect this after
895                  * everything is initialized.
896                  *
897                  * So the first vfs_ChDir() on a given
898                  * connection_struct must not be '.'.
899                  *
900                  * Note: conn_new() sets
901                  * conn->cwd_fsp->fh->fd = -1
902                  * and vfs_ChDir() leaves with
903                  * conn->cwd_fsp->fh->fd = AT_FDCWD
904                  * on success!
905                  */
906                 if (fsp_get_pathref_fd(conn->cwd_fsp) != AT_FDCWD) {
907                         /*
908                          * This should never happen and
909                          * we might change this to
910                          * SMB_ASSERT() in future.
911                          */
912                         DBG_ERR("Called with '.' as first operation!\n");
913                         log_stack_trace();
914                         errno = EINVAL;
915                         return -1;
916                 }
917                 return 0;
918         }
919
920         if (smb_fname->base_name[0] == '/' &&
921             strcsequal(LastDir,smb_fname->base_name))
922         {
923                 /*
924                  * conn->cwd_fsp->fsp_name and the kernel
925                  * are already correct, but conn->cwd_fsp->fh->fd
926                  * might still be -1 as initialized in conn_new().
927                  *
928                  * This can happen when a client made a 2nd
929                  * tree connect to a share with the same underlying
930                  * path (may or may not the same share).
931                  */
932                 fsp_set_fd(conn->cwd_fsp, AT_FDCWD);
933                 return 0;
934         }
935
936         DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
937
938         ret = SMB_VFS_CHDIR(conn, smb_fname);
939         if (ret != 0) {
940                 return -1;
941         }
942
943         /*
944          * Always replace conn->cwd_fsp. We
945          * don't know if it's been modified by
946          * VFS modules in the stack.
947          */
948
949         /* conn cache. */
950         cwd = vfs_GetWd(conn, conn);
951         if (cwd == NULL) {
952                 /*
953                  * vfs_GetWd() failed.
954                  * We must be able to read cwd.
955                  * Return to original directory
956                  * and return -1.
957                  */
958                 int saved_errno = errno;
959
960                 if (conn->cwd_fsp->fsp_name == NULL) {
961                         /*
962                          * Failed on the very first chdir()+getwd()
963                          * for this connection. We can't
964                          * continue.
965                          */
966                         smb_panic("conn->cwd getwd failed\n");
967                         /* NOTREACHED */
968                         return -1;
969                 }
970
971                 /* Return to the previous $cwd. */
972                 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
973                 if (ret != 0) {
974                         smb_panic("conn->cwd getwd failed\n");
975                         /* NOTREACHED */
976                         return -1;
977                 }
978                 errno = saved_errno;
979                 /* And fail the chdir(). */
980                 return -1;
981         }
982
983         /* vfs_GetWd() succeeded. */
984         /* Replace global cache. */
985         SAFE_FREE(LastDir);
986         LastDir = SMB_STRDUP(smb_fname->base_name);
987
988         /*
989          * (Indirect) Callers of vfs_ChDir() may still hold references to the
990          * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
991          * callers can use it for the lifetime of the SMB request.
992          */
993         talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
994
995         conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
996         fsp_set_fd(conn->cwd_fsp, AT_FDCWD);
997
998         DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
999
1000         return ret;
1001 }
1002
1003 /*******************************************************************
1004  Return the absolute current directory path - given a UNIX pathname.
1005  Note that this path is returned in DOS format, not UNIX
1006  format. Note this can be called with conn == NULL.
1007 ********************************************************************/
1008
1009 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
1010 {
1011         struct smb_filename *current_dir_fname = NULL;
1012         struct file_id key;
1013         struct smb_filename *smb_fname_dot = NULL;
1014         struct smb_filename *smb_fname_full = NULL;
1015         struct smb_filename *result = NULL;
1016
1017         if (!lp_getwd_cache()) {
1018                 goto nocache;
1019         }
1020
1021         smb_fname_dot = synthetic_smb_fname(ctx,
1022                                             ".",
1023                                             NULL,
1024                                             NULL,
1025                                             0,
1026                                             0);
1027         if (smb_fname_dot == NULL) {
1028                 errno = ENOMEM;
1029                 goto out;
1030         }
1031
1032         if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
1033                 /*
1034                  * Known to fail for root: the directory may be NFS-mounted
1035                  * and exported with root_squash (so has no root access).
1036                  */
1037                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
1038                          "(NFS problem ?)\n", strerror(errno) ));
1039                 goto nocache;
1040         }
1041
1042         key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1043
1044         smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
1045                                         smbd_memcache(),
1046                                         GETWD_CACHE,
1047                                         data_blob_const(&key, sizeof(key)));
1048
1049         if (smb_fname_full == NULL) {
1050                 goto nocache;
1051         }
1052
1053         if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
1054             (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
1055             (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
1056             (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
1057                 /*
1058                  * Ok, we're done
1059                  * Note: smb_fname_full is owned by smbd_memcache()
1060                  * so we must make a copy to return.
1061                  */
1062                 result = cp_smb_filename(ctx, smb_fname_full);
1063                 if (result == NULL) {
1064                         errno = ENOMEM;
1065                 }
1066                 goto out;
1067         }
1068
1069  nocache:
1070
1071         /*
1072          * We don't have the information to hand so rely on traditional
1073          * methods. The very slow getcwd, which spawns a process on some
1074          * systems, or the not quite so bad getwd.
1075          */
1076
1077         current_dir_fname = SMB_VFS_GETWD(conn, ctx);
1078         if (current_dir_fname == NULL) {
1079                 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
1080                           strerror(errno)));
1081                 goto out;
1082         }
1083
1084         if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
1085                 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1086
1087                 /*
1088                  * smbd_memcache() will own current_dir_fname after the
1089                  * memcache_add_talloc call, so we must make
1090                  * a copy on ctx to return.
1091                  */
1092                 result = cp_smb_filename(ctx, current_dir_fname);
1093                 if (result == NULL) {
1094                         errno = ENOMEM;
1095                 }
1096
1097                 /*
1098                  * Ensure the memory going into the cache
1099                  * doesn't have a destructor so it can be
1100                  * cleanly freed.
1101                  */
1102                 talloc_set_destructor(current_dir_fname, NULL);
1103
1104                 memcache_add_talloc(smbd_memcache(),
1105                                 GETWD_CACHE,
1106                                 data_blob_const(&key, sizeof(key)),
1107                                 &current_dir_fname);
1108                 /* current_dir_fname is now == NULL here. */
1109         } else {
1110                 /* current_dir_fname is already allocated on ctx. */
1111                 result = current_dir_fname;
1112         }
1113
1114  out:
1115         TALLOC_FREE(smb_fname_dot);
1116         /*
1117          * Don't free current_dir_fname here. It's either been moved
1118          * to the memcache or is being returned in result.
1119          */
1120         return result;
1121 }
1122
1123 /*******************************************************************
1124  Reduce a file name, removing .. elements and checking that
1125  it is below dir in the hierarchy. This uses realpath.
1126  This function must run as root, and will return names
1127  and valid stat structs that can be checked on open.
1128 ********************************************************************/
1129
1130 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1131                         const struct smb_filename *smb_fname,
1132                         struct smb_request *smbreq)
1133 {
1134         NTSTATUS status;
1135         TALLOC_CTX *ctx = talloc_tos();
1136         const char *conn_rootdir;
1137         size_t rootdir_len;
1138         char *resolved_name = NULL;
1139         struct smb_filename *resolved_fname = NULL;
1140         struct smb_filename *saved_dir_fname = NULL;
1141         struct smb_filename *smb_fname_cwd = NULL;
1142         int ret;
1143         struct smb_filename *parent_name = NULL;
1144         struct smb_filename *file_name = NULL;
1145         bool ok;
1146
1147         DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1148                         smb_fname->base_name,
1149                         conn->connectpath));
1150
1151
1152         ok = parent_smb_fname(ctx,
1153                               smb_fname,
1154                               &parent_name,
1155                               &file_name);
1156         if (!ok) {
1157                 status = NT_STATUS_NO_MEMORY;
1158                 goto err;
1159         }
1160
1161         if (SMB_VFS_STAT(conn, parent_name) != 0) {
1162                 status = map_nt_error_from_unix(errno);
1163                 goto err;
1164         }
1165         /* Remember where we were. */
1166         saved_dir_fname = vfs_GetWd(ctx, conn);
1167         if (!saved_dir_fname) {
1168                 status = map_nt_error_from_unix(errno);
1169                 goto err;
1170         }
1171
1172         if (vfs_ChDir(conn, parent_name) == -1) {
1173                 status = map_nt_error_from_unix(errno);
1174                 goto err;
1175         }
1176
1177         smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
1178                                             ".",
1179                                             NULL,
1180                                             NULL,
1181                                             parent_name->twrp,
1182                                             0);
1183         if (smb_fname_cwd == NULL) {
1184                 status = NT_STATUS_NO_MEMORY;
1185                 goto err;
1186         }
1187
1188         /* Get the absolute path of the parent directory. */
1189         resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1190         if (resolved_fname == NULL) {
1191                 status = map_nt_error_from_unix(errno);
1192                 goto err;
1193         }
1194         resolved_name = resolved_fname->base_name;
1195
1196         if (*resolved_name != '/') {
1197                 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1198                         "doesn't return absolute paths !\n"));
1199                 status = NT_STATUS_OBJECT_NAME_INVALID;
1200                 goto err;
1201         }
1202
1203         DBG_DEBUG("realpath [%s] -> [%s]\n",
1204                   smb_fname_str_dbg(parent_name),
1205                   resolved_name);
1206
1207         /* Now check the stat value is the same. */
1208         if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1209                 status = map_nt_error_from_unix(errno);
1210                 goto err;
1211         }
1212
1213         /* Ensure we're pointing at the same place. */
1214         if (!check_same_stat(&smb_fname_cwd->st, &parent_name->st)) {
1215                 DBG_ERR("device/inode/uid/gid on directory %s changed. "
1216                         "Denying access !\n",
1217                         smb_fname_str_dbg(parent_name));
1218                 status = NT_STATUS_ACCESS_DENIED;
1219                 goto err;
1220         }
1221
1222         /* Ensure we're below the connect path. */
1223
1224         conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1225         if (conn_rootdir == NULL) {
1226                 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1227                         "conn_rootdir\n"));
1228                 status = NT_STATUS_ACCESS_DENIED;
1229                 goto err;
1230         }
1231
1232         rootdir_len = strlen(conn_rootdir);
1233
1234         /*
1235          * In the case of rootdir_len == 1, we know that conn_rootdir is
1236          * "/", and we also know that resolved_name starts with a slash.
1237          * So, in this corner case, resolved_name is automatically a
1238          * sub-directory of the conn_rootdir. Thus we can skip the string
1239          * comparison and the next character checks (which are even
1240          * wrong in this case).
1241          */
1242         if (rootdir_len != 1) {
1243                 bool matched;
1244
1245                 matched = (strncmp(conn_rootdir, resolved_name,
1246                                 rootdir_len) == 0);
1247
1248                 if (!matched || (resolved_name[rootdir_len] != '/' &&
1249                                  resolved_name[rootdir_len] != '\0')) {
1250                         DBG_WARNING("%s is a symlink outside the "
1251                                     "share path\n",
1252                                     smb_fname_str_dbg(parent_name));
1253                         DEBUGADD(1, ("conn_rootdir =%s\n", conn_rootdir));
1254                         DEBUGADD(1, ("resolved_name=%s\n", resolved_name));
1255                         status = NT_STATUS_ACCESS_DENIED;
1256                         goto err;
1257                 }
1258         }
1259
1260         /* Now ensure that the last component either doesn't
1261            exist, or is *NOT* a symlink. */
1262
1263         ret = SMB_VFS_LSTAT(conn, file_name);
1264         if (ret == -1) {
1265                 /* Errno must be ENOENT for this be ok. */
1266                 if (errno != ENOENT) {
1267                         status = map_nt_error_from_unix(errno);
1268                         DBG_WARNING("LSTAT on %s failed with %s\n",
1269                                     smb_fname_str_dbg(file_name),
1270                                     nt_errstr(status));
1271                         goto err;
1272                 }
1273         }
1274
1275         if (VALID_STAT(file_name->st) &&
1276             S_ISLNK(file_name->st.st_ex_mode))
1277         {
1278                 DBG_WARNING("Last component %s is a symlink. Denying"
1279                             "access.\n",
1280                             smb_fname_str_dbg(file_name));
1281                 status = NT_STATUS_ACCESS_DENIED;
1282                 goto err;
1283         }
1284
1285         status = NT_STATUS_OK;
1286
1287   err:
1288
1289         if (saved_dir_fname != NULL) {
1290                 vfs_ChDir(conn, saved_dir_fname);
1291                 TALLOC_FREE(saved_dir_fname);
1292         }
1293         TALLOC_FREE(resolved_fname);
1294         TALLOC_FREE(parent_name);
1295         return status;
1296 }
1297
1298 /*******************************************************************
1299  Reduce a file name, removing .. elements and checking that
1300  it is below dir in the hierarchy. This uses realpath.
1301
1302  If cwd_name == NULL then fname is a client given path relative
1303  to the root path of the share.
1304
1305  If cwd_name != NULL then fname is a client given path relative
1306  to cwd_name. cwd_name is relative to the root path of the share.
1307 ********************************************************************/
1308
1309 NTSTATUS check_reduced_name(connection_struct *conn,
1310                                 const struct smb_filename *cwd_fname,
1311                                 const struct smb_filename *smb_fname)
1312 {
1313         TALLOC_CTX *ctx = talloc_tos();
1314         const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1315         const char *fname = smb_fname->base_name;
1316         struct smb_filename *resolved_fname;
1317         char *resolved_name = NULL;
1318         char *new_fname = NULL;
1319         bool allow_symlinks = true;
1320         const char *conn_rootdir;
1321         size_t rootdir_len;
1322         bool ok;
1323
1324         DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1325
1326         resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1327
1328         if (resolved_fname == NULL) {
1329                 struct smb_filename *dir_fname = NULL;
1330                 struct smb_filename *last_component = NULL;
1331
1332                 if (errno == ENOTDIR) {
1333                         DBG_NOTICE("Component not a directory in getting "
1334                                    "realpath for %s\n",
1335                                    fname);
1336                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1337                 }
1338                 if (errno != ENOENT) {
1339                         NTSTATUS status = map_nt_error_from_unix(errno);
1340                         DBG_NOTICE("couldn't get realpath for %s: %s\n",
1341                                    fname,
1342                                    strerror(errno));
1343                         return status;
1344                 }
1345
1346                 /* errno == ENOENT */
1347
1348                 /*
1349                  * Last component didn't exist. Remove it and try and
1350                  * canonicalise the directory name.
1351                  */
1352
1353                 ok = parent_smb_fname(ctx,
1354                                       smb_fname,
1355                                       &dir_fname,
1356                                       &last_component);
1357                 if (!ok) {
1358                         return NT_STATUS_NO_MEMORY;
1359                 }
1360
1361                 resolved_fname = SMB_VFS_REALPATH(conn, ctx, dir_fname);
1362                 if (resolved_fname == NULL) {
1363                         NTSTATUS status = map_nt_error_from_unix(errno);
1364
1365                         if (errno == ENOENT || errno == ENOTDIR) {
1366                                 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1367                         }
1368
1369                         DBG_NOTICE("couldn't get realpath for "
1370                                    "%s (%s)\n",
1371                                    smb_fname_str_dbg(dir_fname),
1372                                    nt_errstr(status));
1373                         return status;
1374                 }
1375                 resolved_name = talloc_asprintf(ctx,
1376                                                 "%s/%s",
1377                                                 resolved_fname->base_name,
1378                                                 last_component->base_name);
1379                 if (resolved_name == NULL) {
1380                         return NT_STATUS_NO_MEMORY;
1381                 }
1382         } else {
1383                 resolved_name = resolved_fname->base_name;
1384         }
1385
1386         DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1387                   resolved_name));
1388
1389         if (*resolved_name != '/') {
1390                 DEBUG(0,("check_reduced_name: realpath doesn't return "
1391                          "absolute paths !\n"));
1392                 TALLOC_FREE(resolved_fname);
1393                 return NT_STATUS_OBJECT_NAME_INVALID;
1394         }
1395
1396         /* Common widelinks and symlinks checks. */
1397         conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1398         if (conn_rootdir == NULL) {
1399                 DBG_NOTICE("Could not get conn_rootdir\n");
1400                 TALLOC_FREE(resolved_fname);
1401                 return NT_STATUS_ACCESS_DENIED;
1402         }
1403
1404         rootdir_len = strlen(conn_rootdir);
1405
1406         /*
1407          * In the case of rootdir_len == 1, we know that
1408          * conn_rootdir is "/", and we also know that
1409          * resolved_name starts with a slash.  So, in this
1410          * corner case, resolved_name is automatically a
1411          * sub-directory of the conn_rootdir. Thus we can skip
1412          * the string comparison and the next character checks
1413          * (which are even wrong in this case).
1414          */
1415         if (rootdir_len != 1) {
1416                 bool matched;
1417
1418                 matched = (strncmp(conn_rootdir, resolved_name,
1419                                 rootdir_len) == 0);
1420                 if (!matched || (resolved_name[rootdir_len] != '/' &&
1421                                  resolved_name[rootdir_len] != '\0')) {
1422                         DBG_NOTICE("Bad access attempt: %s is a symlink "
1423                                 "outside the "
1424                                 "share path\n"
1425                                 "conn_rootdir =%s\n"
1426                                 "resolved_name=%s\n",
1427                                 fname,
1428                                 conn_rootdir,
1429                                 resolved_name);
1430                         TALLOC_FREE(resolved_fname);
1431                         return NT_STATUS_ACCESS_DENIED;
1432                 }
1433         }
1434
1435         /* Extra checks if all symlinks are disallowed. */
1436         allow_symlinks = lp_follow_symlinks(SNUM(conn));
1437         if (!allow_symlinks) {
1438                 /* fname can't have changed in resolved_path. */
1439                 const char *p = &resolved_name[rootdir_len];
1440
1441                 /*
1442                  * UNIX filesystem semantics, names consisting
1443                  * only of "." or ".." CANNOT be symlinks.
1444                  */
1445                 if (ISDOT(fname) || ISDOTDOT(fname)) {
1446                         goto out;
1447                 }
1448
1449                 if (*p != '/') {
1450                         DBG_NOTICE("logic error (%c) "
1451                                 "in resolved_name: %s\n",
1452                                 *p,
1453                                 fname);
1454                         TALLOC_FREE(resolved_fname);
1455                         return NT_STATUS_ACCESS_DENIED;
1456                 }
1457
1458                 p++;
1459
1460                 /*
1461                  * If cwd_name is present and not ".",
1462                  * then fname is relative to that, not
1463                  * the root of the share. Make sure the
1464                  * path we check is the one the client
1465                  * sent (cwd_name+fname).
1466                  */
1467                 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1468                         new_fname = talloc_asprintf(ctx,
1469                                                 "%s/%s",
1470                                                 cwd_name,
1471                                                 fname);
1472                         if (new_fname == NULL) {
1473                                 TALLOC_FREE(resolved_fname);
1474                                 return NT_STATUS_NO_MEMORY;
1475                         }
1476                         fname = new_fname;
1477                 }
1478
1479                 if (strcmp(fname, p)!=0) {
1480                         DBG_NOTICE("Bad access "
1481                                 "attempt: %s is a symlink to %s\n",
1482                                 fname,
1483                                 p);
1484                         TALLOC_FREE(resolved_fname);
1485                         TALLOC_FREE(new_fname);
1486                         return NT_STATUS_ACCESS_DENIED;
1487                 }
1488         }
1489
1490   out:
1491
1492         DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1493         TALLOC_FREE(resolved_fname);
1494         TALLOC_FREE(new_fname);
1495         return NT_STATUS_OK;
1496 }
1497
1498 /*
1499  * Ensure LSTAT is called for POSIX paths.
1500  */
1501 int vfs_stat(struct connection_struct *conn,
1502              struct smb_filename *smb_fname)
1503 {
1504         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1505                 return SMB_VFS_LSTAT(conn, smb_fname);
1506         }
1507         return SMB_VFS_STAT(conn, smb_fname);
1508 }
1509
1510 /**
1511  * XXX: This is temporary and there should be no callers of this once
1512  * smb_filename is plumbed through all path based operations.
1513  *
1514  * Called when we know stream name parsing has already been done.
1515  */
1516 int vfs_stat_smb_basename(struct connection_struct *conn,
1517                         const struct smb_filename *smb_fname_in,
1518                         SMB_STRUCT_STAT *psbuf)
1519 {
1520         struct smb_filename smb_fname = {
1521                 .base_name = discard_const_p(char, smb_fname_in->base_name),
1522                 .flags = smb_fname_in->flags,
1523                 .twrp = smb_fname_in->twrp,
1524         };
1525         int ret;
1526
1527         if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1528                 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1529         } else {
1530                 ret = SMB_VFS_STAT(conn, &smb_fname);
1531         }
1532
1533         if (ret != -1) {
1534                 *psbuf = smb_fname.st;
1535         }
1536         return ret;
1537 }
1538
1539 /**
1540  * Ensure LSTAT is called for POSIX paths.
1541  */
1542
1543 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1544 {
1545         int ret;
1546         struct stat_ex saved_stat = fsp->fsp_name->st;
1547
1548         if (fsp_get_pathref_fd(fsp) == -1) {
1549                 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1550                         ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1551                 } else {
1552                         ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1553                 }
1554         } else {
1555                 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1556         }
1557         if (ret == -1) {
1558                 return map_nt_error_from_unix(errno);
1559         }
1560         update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat);
1561         return NT_STATUS_OK;
1562 }
1563
1564 void init_smb_file_time(struct smb_file_time *ft)
1565 {
1566         *ft = (struct smb_file_time) {
1567                 .atime = make_omit_timespec(),
1568                 .ctime = make_omit_timespec(),
1569                 .mtime = make_omit_timespec(),
1570                 .create_time = make_omit_timespec()
1571         };
1572 }
1573
1574 /**
1575  * Initialize num_streams and streams, then call VFS op streaminfo
1576  */
1577 NTSTATUS vfs_streaminfo(connection_struct *conn,
1578                         struct files_struct *fsp,
1579                         const struct smb_filename *smb_fname,
1580                         TALLOC_CTX *mem_ctx,
1581                         unsigned int *num_streams,
1582                         struct stream_struct **streams)
1583 {
1584         *num_streams = 0;
1585         *streams = NULL;
1586         return SMB_VFS_STREAMINFO(conn,
1587                         fsp,
1588                         smb_fname,
1589                         mem_ctx,
1590                         num_streams,
1591                         streams);
1592 }
1593
1594 int vfs_fake_fd(void)
1595 {
1596         int pipe_fds[2];
1597         int ret;
1598
1599         /*
1600          * Return a valid fd, but ensure any attempt to use
1601          * it returns an error (EPIPE).
1602          */
1603         ret = pipe(pipe_fds);
1604         if (ret != 0) {
1605                 return -1;
1606         }
1607
1608         close(pipe_fds[1]);
1609         return pipe_fds[0];
1610 }
1611
1612 /*
1613   generate a file_id from a stat structure
1614  */
1615 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1616 {
1617         return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1618 }
1619
1620 NTSTATUS vfs_at_fspcwd(TALLOC_CTX *mem_ctx,
1621                        struct connection_struct *conn,
1622                        struct files_struct **_fsp)
1623 {
1624         struct files_struct *fsp = NULL;
1625
1626         fsp = talloc_zero(mem_ctx, struct files_struct);
1627         if (fsp == NULL) {
1628                 return NT_STATUS_NO_MEMORY;
1629         }
1630
1631         fsp->fsp_name = synthetic_smb_fname(fsp, ".", NULL, NULL, 0, 0);
1632         if (fsp->fsp_name == NULL) {
1633                 TALLOC_FREE(fsp);
1634                 return NT_STATUS_NO_MEMORY;
1635         }
1636
1637         fsp->fh = fd_handle_create(fsp);
1638         if (fsp->fh == NULL) {
1639                 TALLOC_FREE(fsp);
1640                 return NT_STATUS_NO_MEMORY;
1641         }
1642
1643         fsp_set_fd(fsp, AT_FDCWD);
1644         fsp->fnum = FNUM_FIELD_INVALID;
1645         fsp->conn = conn;
1646
1647         *_fsp = fsp;
1648         return NT_STATUS_OK;
1649 }
1650
1651 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1652                          const char *service, const char *user)
1653 {
1654         VFS_FIND(connect);
1655         return handle->fns->connect_fn(handle, service, user);
1656 }
1657
1658 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1659 {
1660         VFS_FIND(disconnect);
1661         handle->fns->disconnect_fn(handle);
1662 }
1663
1664 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1665                                 const struct smb_filename *smb_fname,
1666                                 uint64_t *bsize,
1667                                 uint64_t *dfree,
1668                                 uint64_t *dsize)
1669 {
1670         VFS_FIND(disk_free);
1671         return handle->fns->disk_free_fn(handle, smb_fname,
1672                         bsize, dfree, dsize);
1673 }
1674
1675 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1676                                 const struct smb_filename *smb_fname,
1677                                 enum SMB_QUOTA_TYPE qtype,
1678                                 unid_t id,
1679                                 SMB_DISK_QUOTA *qt)
1680 {
1681         VFS_FIND(get_quota);
1682         return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1683 }
1684
1685 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1686                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1687                            SMB_DISK_QUOTA *qt)
1688 {
1689         VFS_FIND(set_quota);
1690         return handle->fns->set_quota_fn(handle, qtype, id, qt);
1691 }
1692
1693 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1694                                       struct files_struct *fsp,
1695                                       struct shadow_copy_data *shadow_copy_data,
1696                                       bool labels)
1697 {
1698         VFS_FIND(get_shadow_copy_data);
1699         return handle->fns->get_shadow_copy_data_fn(handle, fsp, 
1700                                                     shadow_copy_data,
1701                                                     labels);
1702 }
1703 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1704                         const struct smb_filename *smb_fname,
1705                         struct vfs_statvfs_struct *statbuf)
1706 {
1707         VFS_FIND(statvfs);
1708         return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1709 }
1710
1711 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1712                         enum timestamp_set_resolution *p_ts_res)
1713 {
1714         VFS_FIND(fs_capabilities);
1715         return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1716 }
1717
1718 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1719                                         struct dfs_GetDFSReferral *r)
1720 {
1721         VFS_FIND(get_dfs_referrals);
1722         return handle->fns->get_dfs_referrals_fn(handle, r);
1723 }
1724
1725 NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
1726                                 struct files_struct *dirfsp,
1727                                 const struct smb_filename *smb_fname,
1728                                 const struct referral *reflist,
1729                                 size_t referral_count)
1730 {
1731         VFS_FIND(create_dfs_pathat);
1732         return handle->fns->create_dfs_pathat_fn(handle,
1733                                                 dirfsp,
1734                                                 smb_fname,
1735                                                 reflist,
1736                                                 referral_count);
1737 }
1738
1739 NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
1740                                 TALLOC_CTX *mem_ctx,
1741                                 struct files_struct *dirfsp,
1742                                 struct smb_filename *smb_fname,
1743                                 struct referral **ppreflist,
1744                                 size_t *preferral_count)
1745 {
1746         VFS_FIND(read_dfs_pathat);
1747         return handle->fns->read_dfs_pathat_fn(handle,
1748                                                 mem_ctx,
1749                                                 dirfsp,
1750                                                 smb_fname,
1751                                                 ppreflist,
1752                                                 preferral_count);
1753 }
1754
1755 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1756                                         struct files_struct *fsp,
1757                                         const char *mask,
1758                                         uint32_t attributes)
1759 {
1760         VFS_FIND(fdopendir);
1761         return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1762 }
1763
1764 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1765                                     struct files_struct *dirfsp,
1766                                     DIR *dirp,
1767                                     SMB_STRUCT_STAT *sbuf)
1768 {
1769         VFS_FIND(readdir);
1770         return handle->fns->readdir_fn(handle, dirfsp, dirp, sbuf);
1771 }
1772
1773 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1774                           DIR *dirp, long offset)
1775 {
1776         VFS_FIND(seekdir);
1777         handle->fns->seekdir_fn(handle, dirp, offset);
1778 }
1779
1780 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1781                           DIR *dirp)
1782 {
1783         VFS_FIND(telldir);
1784         return handle->fns->telldir_fn(handle, dirp);
1785 }
1786
1787 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1788                              DIR *dirp)
1789 {
1790         VFS_FIND(rewind_dir);
1791         handle->fns->rewind_dir_fn(handle, dirp);
1792 }
1793
1794 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1795                         struct files_struct *dirfsp,
1796                         const struct smb_filename *smb_fname,
1797                         mode_t mode)
1798 {
1799         VFS_FIND(mkdirat);
1800         return handle->fns->mkdirat_fn(handle,
1801                         dirfsp,
1802                         smb_fname,
1803                         mode);
1804 }
1805
1806 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1807                           DIR *dir)
1808 {
1809         VFS_FIND(closedir);
1810         return handle->fns->closedir_fn(handle, dir);
1811 }
1812
1813 int smb_vfs_call_openat(struct vfs_handle_struct *handle,
1814                         const struct files_struct *dirfsp,
1815                         const struct smb_filename *smb_fname,
1816                         struct files_struct *fsp,
1817                         int flags,
1818                         mode_t mode)
1819 {
1820         VFS_FIND(openat);
1821         return handle->fns->openat_fn(handle,
1822                                       dirfsp,
1823                                       smb_fname,
1824                                       fsp,
1825                                       flags,
1826                                       mode);
1827 }
1828
1829 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1830                                   struct smb_request *req,
1831                                   struct smb_filename *smb_fname,
1832                                   uint32_t access_mask,
1833                                   uint32_t share_access,
1834                                   uint32_t create_disposition,
1835                                   uint32_t create_options,
1836                                   uint32_t file_attributes,
1837                                   uint32_t oplock_request,
1838                                   const struct smb2_lease *lease,
1839                                   uint64_t allocation_size,
1840                                   uint32_t private_flags,
1841                                   struct security_descriptor *sd,
1842                                   struct ea_list *ea_list,
1843                                   files_struct **result,
1844                                   int *pinfo,
1845                                   const struct smb2_create_blobs *in_context_blobs,
1846                                   struct smb2_create_blobs *out_context_blobs)
1847 {
1848         VFS_FIND(create_file);
1849         return handle->fns->create_file_fn(
1850                 handle, req, smb_fname,
1851                 access_mask, share_access, create_disposition, create_options,
1852                 file_attributes, oplock_request, lease, allocation_size,
1853                 private_flags, sd, ea_list,
1854                 result, pinfo, in_context_blobs, out_context_blobs);
1855 }
1856
1857 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1858                        struct files_struct *fsp)
1859 {
1860         VFS_FIND(close);
1861         return handle->fns->close_fn(handle, fsp);
1862 }
1863
1864 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1865                            struct files_struct *fsp, void *data, size_t n,
1866                            off_t offset)
1867 {
1868         VFS_FIND(pread);
1869         return handle->fns->pread_fn(handle, fsp, data, n, offset);
1870 }
1871
1872 struct smb_vfs_call_pread_state {
1873         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1874         ssize_t retval;
1875         struct vfs_aio_state vfs_aio_state;
1876 };
1877
1878 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1879
1880 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1881                                            TALLOC_CTX *mem_ctx,
1882                                            struct tevent_context *ev,
1883                                            struct files_struct *fsp,
1884                                            void *data,
1885                                            size_t n, off_t offset)
1886 {
1887         struct tevent_req *req, *subreq;
1888         struct smb_vfs_call_pread_state *state;
1889
1890         req = tevent_req_create(mem_ctx, &state,
1891                                 struct smb_vfs_call_pread_state);
1892         if (req == NULL) {
1893                 return NULL;
1894         }
1895         VFS_FIND(pread_send);
1896         state->recv_fn = handle->fns->pread_recv_fn;
1897
1898         subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1899                                             offset);
1900         if (tevent_req_nomem(subreq, req)) {
1901                 return tevent_req_post(req, ev);
1902         }
1903         tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1904         return req;
1905 }
1906
1907 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1908 {
1909         struct tevent_req *req = tevent_req_callback_data(
1910                 subreq, struct tevent_req);
1911         struct smb_vfs_call_pread_state *state = tevent_req_data(
1912                 req, struct smb_vfs_call_pread_state);
1913
1914         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1915         TALLOC_FREE(subreq);
1916         if (state->retval == -1) {
1917                 tevent_req_error(req, state->vfs_aio_state.error);
1918                 return;
1919         }
1920         tevent_req_done(req);
1921 }
1922
1923 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1924                            struct vfs_aio_state *vfs_aio_state)
1925 {
1926         struct smb_vfs_call_pread_state *state = tevent_req_data(
1927                 req, struct smb_vfs_call_pread_state);
1928         ssize_t retval;
1929
1930         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1931                 tevent_req_received(req);
1932                 return -1;
1933         }
1934         *vfs_aio_state = state->vfs_aio_state;
1935         retval = state->retval;
1936         tevent_req_received(req);
1937         return retval;
1938 }
1939
1940 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1941                             struct files_struct *fsp, const void *data,
1942                             size_t n, off_t offset)
1943 {
1944         VFS_FIND(pwrite);
1945         return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1946 }
1947
1948 struct smb_vfs_call_pwrite_state {
1949         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1950         ssize_t retval;
1951         struct vfs_aio_state vfs_aio_state;
1952 };
1953
1954 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1955
1956 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1957                                             TALLOC_CTX *mem_ctx,
1958                                             struct tevent_context *ev,
1959                                             struct files_struct *fsp,
1960                                             const void *data,
1961                                             size_t n, off_t offset)
1962 {
1963         struct tevent_req *req, *subreq;
1964         struct smb_vfs_call_pwrite_state *state;
1965
1966         req = tevent_req_create(mem_ctx, &state,
1967                                 struct smb_vfs_call_pwrite_state);
1968         if (req == NULL) {
1969                 return NULL;
1970         }
1971         VFS_FIND(pwrite_send);
1972         state->recv_fn = handle->fns->pwrite_recv_fn;
1973
1974         subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1975                                              offset);
1976         if (tevent_req_nomem(subreq, req)) {
1977                 return tevent_req_post(req, ev);
1978         }
1979         tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1980         return req;
1981 }
1982
1983 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1984 {
1985         struct tevent_req *req = tevent_req_callback_data(
1986                 subreq, struct tevent_req);
1987         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1988                 req, struct smb_vfs_call_pwrite_state);
1989
1990         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1991         TALLOC_FREE(subreq);
1992         if (state->retval == -1) {
1993                 tevent_req_error(req, state->vfs_aio_state.error);
1994                 return;
1995         }
1996         tevent_req_done(req);
1997 }
1998
1999 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
2000                             struct vfs_aio_state *vfs_aio_state)
2001 {
2002         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
2003                 req, struct smb_vfs_call_pwrite_state);
2004         ssize_t retval;
2005
2006         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2007                 tevent_req_received(req);
2008                 return -1;
2009         }
2010         *vfs_aio_state = state->vfs_aio_state;
2011         retval = state->retval;
2012         tevent_req_received(req);
2013         return retval;
2014 }
2015
2016 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
2017                              struct files_struct *fsp, off_t offset,
2018                              int whence)
2019 {
2020         VFS_FIND(lseek);
2021         return handle->fns->lseek_fn(handle, fsp, offset, whence);
2022 }
2023
2024 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
2025                               files_struct *fromfsp, const DATA_BLOB *header,
2026                               off_t offset, size_t count)
2027 {
2028         VFS_FIND(sendfile);
2029         return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
2030                                         count);
2031 }
2032
2033 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
2034                               files_struct *tofsp, off_t offset,
2035                               size_t count)
2036 {
2037         VFS_FIND(recvfile);
2038         return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
2039 }
2040
2041 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
2042                         files_struct *srcfsp,
2043                         const struct smb_filename *smb_fname_src,
2044                         files_struct *dstfsp,
2045                         const struct smb_filename *smb_fname_dst)
2046 {
2047         VFS_FIND(renameat);
2048         return handle->fns->renameat_fn(handle,
2049                                 srcfsp,
2050                                 smb_fname_src,
2051                                 dstfsp,
2052                                 smb_fname_dst);
2053 }
2054
2055 struct smb_vfs_call_fsync_state {
2056         int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
2057         int retval;
2058         struct vfs_aio_state vfs_aio_state;
2059 };
2060
2061 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
2062
2063 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
2064                                            TALLOC_CTX *mem_ctx,
2065                                            struct tevent_context *ev,
2066                                            struct files_struct *fsp)
2067 {
2068         struct tevent_req *req, *subreq;
2069         struct smb_vfs_call_fsync_state *state;
2070
2071         req = tevent_req_create(mem_ctx, &state,
2072                                 struct smb_vfs_call_fsync_state);
2073         if (req == NULL) {
2074                 return NULL;
2075         }
2076         VFS_FIND(fsync_send);
2077         state->recv_fn = handle->fns->fsync_recv_fn;
2078
2079         subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
2080         if (tevent_req_nomem(subreq, req)) {
2081                 return tevent_req_post(req, ev);
2082         }
2083         tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
2084         return req;
2085 }
2086
2087 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
2088 {
2089         struct tevent_req *req = tevent_req_callback_data(
2090                 subreq, struct tevent_req);
2091         struct smb_vfs_call_fsync_state *state = tevent_req_data(
2092                 req, struct smb_vfs_call_fsync_state);
2093
2094         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2095         TALLOC_FREE(subreq);
2096         if (state->retval == -1) {
2097                 tevent_req_error(req, state->vfs_aio_state.error);
2098                 return;
2099         }
2100         tevent_req_done(req);
2101 }
2102
2103 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
2104 {
2105         struct smb_vfs_call_fsync_state *state = tevent_req_data(
2106                 req, struct smb_vfs_call_fsync_state);
2107         ssize_t retval;
2108
2109         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2110                 tevent_req_received(req);
2111                 return -1;
2112         }
2113         *vfs_aio_state = state->vfs_aio_state;
2114         retval = state->retval;
2115         tevent_req_received(req);
2116         return retval;
2117 }
2118
2119 /*
2120  * Synchronous version of fsync, built from backend
2121  * async VFS primitives. Uses a temporary sub-event
2122  * context (NOT NESTED).
2123  */
2124
2125 int smb_vfs_fsync_sync(files_struct *fsp)
2126 {
2127         TALLOC_CTX *frame = talloc_stackframe();
2128         struct tevent_req *req = NULL;
2129         struct vfs_aio_state aio_state = { 0 };
2130         int ret = -1;
2131         bool ok;
2132         struct tevent_context *ev = samba_tevent_context_init(frame);
2133
2134         if (ev == NULL) {
2135                 goto out;
2136         }
2137
2138         req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
2139         if (req == NULL) {
2140                 goto out;
2141         }
2142
2143         ok = tevent_req_poll(req, ev);
2144         if (!ok) {
2145                 goto out;
2146         }
2147
2148         ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
2149
2150   out:
2151
2152         TALLOC_FREE(frame);
2153         if (aio_state.error != 0) {
2154                 errno = aio_state.error;
2155         }
2156         return ret;
2157 }
2158
2159 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
2160                       struct smb_filename *smb_fname)
2161 {
2162         VFS_FIND(stat);
2163         return handle->fns->stat_fn(handle, smb_fname);
2164 }
2165
2166 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2167                        struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2168 {
2169         VFS_FIND(fstat);
2170         return handle->fns->fstat_fn(handle, fsp, sbuf);
2171 }
2172
2173 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2174                        struct smb_filename *smb_filename)
2175 {
2176         VFS_FIND(lstat);
2177         return handle->fns->lstat_fn(handle, smb_filename);
2178 }
2179
2180 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2181                                      struct files_struct *fsp,
2182                                      const SMB_STRUCT_STAT *sbuf)
2183 {
2184         VFS_FIND(get_alloc_size);
2185         return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2186 }
2187
2188 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
2189                         struct files_struct *dirfsp,
2190                         const struct smb_filename *smb_fname,
2191                         int flags)
2192 {
2193         VFS_FIND(unlinkat);
2194         return handle->fns->unlinkat_fn(handle,
2195                         dirfsp,
2196                         smb_fname,
2197                         flags);
2198 }
2199
2200 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
2201                         const struct smb_filename *smb_fname,
2202                         mode_t mode)
2203 {
2204         VFS_FIND(chmod);
2205         return handle->fns->chmod_fn(handle, smb_fname, mode);
2206 }
2207
2208 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2209                         struct files_struct *fsp, mode_t mode)
2210 {
2211         VFS_FIND(fchmod);
2212         return handle->fns->fchmod_fn(handle, fsp, mode);
2213 }
2214
2215 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2216                         struct files_struct *fsp, uid_t uid, gid_t gid)
2217 {
2218         VFS_FIND(fchown);
2219         return handle->fns->fchown_fn(handle, fsp, uid, gid);
2220 }
2221
2222 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2223                         const struct smb_filename *smb_fname,
2224                         uid_t uid,
2225                         gid_t gid)
2226 {
2227         VFS_FIND(lchown);
2228         return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2229 }
2230
2231 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2232                         const struct smb_filename *smb_fname)
2233 {
2234         VFS_FIND(chdir);
2235         return handle->fns->chdir_fn(handle, smb_fname);
2236 }
2237
2238 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2239                                 TALLOC_CTX *ctx)
2240 {
2241         VFS_FIND(getwd);
2242         return handle->fns->getwd_fn(handle, ctx);
2243 }
2244
2245 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2246                         const struct smb_filename *smb_fname,
2247                         struct smb_file_time *ft)
2248 {
2249         VFS_FIND(ntimes);
2250         return handle->fns->ntimes_fn(handle, smb_fname, ft);
2251 }
2252
2253 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2254                            struct files_struct *fsp, off_t offset)
2255 {
2256         VFS_FIND(ftruncate);
2257         return handle->fns->ftruncate_fn(handle, fsp, offset);
2258 }
2259
2260 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2261                            struct files_struct *fsp,
2262                            uint32_t mode,
2263                            off_t offset,
2264                            off_t len)
2265 {
2266         VFS_FIND(fallocate);
2267         return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2268 }
2269
2270 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2271                               struct files_struct *fsp, uint32_t share_mode,
2272                               uint32_t access_mask)
2273 {
2274         VFS_FIND(kernel_flock);
2275         return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2276                                          access_mask);
2277 }
2278
2279 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2280                        struct files_struct *fsp, int cmd, ...)
2281 {
2282         int result;
2283         va_list cmd_arg;
2284
2285         VFS_FIND(fcntl);
2286
2287         va_start(cmd_arg, cmd);
2288         result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2289         va_end(cmd_arg);
2290
2291         return result;
2292 }
2293
2294 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2295                                 struct files_struct *fsp, int leasetype)
2296 {
2297         VFS_FIND(linux_setlease);
2298         return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2299 }
2300
2301 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2302                         const struct smb_filename *link_target,
2303                         struct files_struct *dirfsp,
2304                         const struct smb_filename *new_smb_fname)
2305 {
2306         VFS_FIND(symlinkat);
2307         return handle->fns->symlinkat_fn(handle,
2308                                 link_target,
2309                                 dirfsp,
2310                                 new_smb_fname);
2311 }
2312
2313 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2314                         const struct files_struct *dirfsp,
2315                         const struct smb_filename *smb_fname,
2316                         char *buf,
2317                         size_t bufsiz)
2318 {
2319         VFS_FIND(readlinkat);
2320         return handle->fns->readlinkat_fn(handle,
2321                                 dirfsp,
2322                                 smb_fname,
2323                                 buf,
2324                                 bufsiz);
2325 }
2326
2327 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2328                         struct files_struct *srcfsp,
2329                         const struct smb_filename *old_smb_fname,
2330                         struct files_struct *dstfsp,
2331                         const struct smb_filename *new_smb_fname,
2332                         int flags)
2333 {
2334         VFS_FIND(linkat);
2335         return handle->fns->linkat_fn(handle,
2336                                 srcfsp,
2337                                 old_smb_fname,
2338                                 dstfsp,
2339                                 new_smb_fname,
2340                                 flags);
2341 }
2342
2343 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2344                         struct files_struct *dirfsp,
2345                         const struct smb_filename *smb_fname,
2346                         mode_t mode,
2347                         SMB_DEV_T dev)
2348 {
2349         VFS_FIND(mknodat);
2350         return handle->fns->mknodat_fn(handle,
2351                                 dirfsp,
2352                                 smb_fname,
2353                                 mode,
2354                                 dev);
2355 }
2356
2357 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2358                         TALLOC_CTX *ctx,
2359                         const struct smb_filename *smb_fname)
2360 {
2361         VFS_FIND(realpath);
2362         return handle->fns->realpath_fn(handle, ctx, smb_fname);
2363 }
2364
2365 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2366                         const struct smb_filename *smb_fname,
2367                         unsigned int flags)
2368 {
2369         VFS_FIND(chflags);
2370         return handle->fns->chflags_fn(handle, smb_fname, flags);
2371 }
2372
2373 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2374                                            const SMB_STRUCT_STAT *sbuf)
2375 {
2376         VFS_FIND(file_id_create);
2377         return handle->fns->file_id_create_fn(handle, sbuf);
2378 }
2379
2380 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2381                                  const SMB_STRUCT_STAT *sbuf)
2382 {
2383         VFS_FIND(fs_file_id);
2384         return handle->fns->fs_file_id_fn(handle, sbuf);
2385 }
2386
2387 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2388                                  struct files_struct *fsp,
2389                                  const struct smb_filename *smb_fname,
2390                                  TALLOC_CTX *mem_ctx,
2391                                  unsigned int *num_streams,
2392                                  struct stream_struct **streams)
2393 {
2394         VFS_FIND(streaminfo);
2395         return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2396                                           num_streams, streams);
2397 }
2398
2399 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2400                                    const struct smb_filename *path,
2401                                    const char *name,
2402                                    TALLOC_CTX *mem_ctx,
2403                                    char **found_name)
2404 {
2405         VFS_FIND(get_real_filename);
2406         return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2407                                                  found_name);
2408 }
2409
2410 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2411                                  const struct smb_filename *smb_fname)
2412 {
2413         VFS_FIND(connectpath);
2414         return handle->fns->connectpath_fn(handle, smb_fname);
2415 }
2416
2417 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2418                                     struct files_struct *fsp,
2419                                     struct lock_struct *plock)
2420 {
2421         VFS_FIND(strict_lock_check);
2422         return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2423 }
2424
2425 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2426                                      const char *name,
2427                                      enum vfs_translate_direction direction,
2428                                      TALLOC_CTX *mem_ctx,
2429                                      char **mapped_name)
2430 {
2431         VFS_FIND(translate_name);
2432         return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2433                                               mapped_name);
2434 }
2435
2436 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2437                             struct files_struct *fsp,
2438                             TALLOC_CTX *ctx,
2439                             uint32_t function,
2440                             uint16_t req_flags,
2441                             const uint8_t *in_data,
2442                             uint32_t in_len,
2443                             uint8_t **out_data,
2444                             uint32_t max_out_len,
2445                             uint32_t *out_len)
2446 {
2447         VFS_FIND(fsctl);
2448         return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2449                                      in_data, in_len, out_data, max_out_len,
2450                                      out_len);
2451 }
2452
2453 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2454                                           struct files_struct *fsp,
2455                                           uint32_t *dosmode)
2456 {
2457         VFS_FIND(fget_dos_attributes);
2458         return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2459 }
2460
2461 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2462                                          const struct smb_filename *smb_fname,
2463                                          uint32_t dosmode)
2464 {
2465         VFS_FIND(set_dos_attributes);
2466         return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2467 }
2468
2469 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2470                                           struct files_struct *fsp,
2471                                           uint32_t dosmode)
2472 {
2473         VFS_FIND(set_dos_attributes);
2474         return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2475 }
2476
2477 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2478                                                   struct tevent_context *ev,
2479                                                   struct vfs_handle_struct *handle,
2480                                                   struct files_struct *fsp,
2481                                                   uint32_t fsctl,
2482                                                   uint32_t ttl,
2483                                                   off_t offset,
2484                                                   size_t to_copy)
2485 {
2486         VFS_FIND(offload_read_send);
2487         return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2488                                                  fsp, fsctl,
2489                                                  ttl, offset, to_copy);
2490 }
2491
2492 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2493                                         struct vfs_handle_struct *handle,
2494                                         TALLOC_CTX *mem_ctx,
2495                                         DATA_BLOB *token_blob)
2496 {
2497         VFS_FIND(offload_read_recv);
2498         return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2499 }
2500
2501 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2502                                                    TALLOC_CTX *mem_ctx,
2503                                                    struct tevent_context *ev,
2504                                                    uint32_t fsctl,
2505                                                    DATA_BLOB *token,
2506                                                    off_t transfer_offset,
2507                                                    struct files_struct *dest_fsp,
2508                                                    off_t dest_off,
2509                                                    off_t num)
2510 {
2511         VFS_FIND(offload_write_send);
2512         return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2513                                                token, transfer_offset,
2514                                                dest_fsp, dest_off, num);
2515 }
2516
2517 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2518                                          struct tevent_req *req,
2519                                          off_t *copied)
2520 {
2521         VFS_FIND(offload_write_recv);
2522         return handle->fns->offload_write_recv_fn(handle, req, copied);
2523 }
2524
2525 struct smb_vfs_call_get_dos_attributes_state {
2526         files_struct *dir_fsp;
2527         NTSTATUS (*recv_fn)(struct tevent_req *req,
2528                             struct vfs_aio_state *aio_state,
2529                             uint32_t *dosmode);
2530         struct vfs_aio_state aio_state;
2531         uint32_t dos_attributes;
2532 };
2533
2534 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2535
2536 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2537                         TALLOC_CTX *mem_ctx,
2538                         struct tevent_context *ev,
2539                         struct vfs_handle_struct *handle,
2540                         files_struct *dir_fsp,
2541                         struct smb_filename *smb_fname)
2542 {
2543         struct tevent_req *req = NULL;
2544         struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2545         struct tevent_req *subreq = NULL;
2546
2547         req = tevent_req_create(mem_ctx, &state,
2548                                 struct smb_vfs_call_get_dos_attributes_state);
2549         if (req == NULL) {
2550                 return NULL;
2551         }
2552
2553         VFS_FIND(get_dos_attributes_send);
2554
2555         *state = (struct smb_vfs_call_get_dos_attributes_state) {
2556                 .dir_fsp = dir_fsp,
2557                 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2558         };
2559
2560         subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2561                                                          ev,
2562                                                          handle,
2563                                                          dir_fsp,
2564                                                          smb_fname);
2565         if (tevent_req_nomem(subreq, req)) {
2566                 return tevent_req_post(req, ev);
2567         }
2568         tevent_req_defer_callback(req, ev);
2569
2570         tevent_req_set_callback(subreq,
2571                                 smb_vfs_call_get_dos_attributes_done,
2572                                 req);
2573
2574         return req;
2575 }
2576
2577 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2578 {
2579         struct tevent_req *req =
2580                 tevent_req_callback_data(subreq,
2581                 struct tevent_req);
2582         struct smb_vfs_call_get_dos_attributes_state *state =
2583                 tevent_req_data(req,
2584                 struct smb_vfs_call_get_dos_attributes_state);
2585         NTSTATUS status;
2586         bool ok;
2587
2588         /*
2589          * Make sure we run as the user again
2590          */
2591         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2592         SMB_ASSERT(ok);
2593
2594         status = state->recv_fn(subreq,
2595                                 &state->aio_state,
2596                                 &state->dos_attributes);
2597         TALLOC_FREE(subreq);
2598         if (tevent_req_nterror(req, status)) {
2599                 return;
2600         }
2601
2602         tevent_req_done(req);
2603 }
2604
2605 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2606                 struct tevent_req *req,
2607                 struct vfs_aio_state *aio_state,
2608                 uint32_t *dos_attributes)
2609 {
2610         struct smb_vfs_call_get_dos_attributes_state *state =
2611                 tevent_req_data(req,
2612                 struct smb_vfs_call_get_dos_attributes_state);
2613         NTSTATUS status;
2614
2615         if (tevent_req_is_nterror(req, &status)) {
2616                 tevent_req_received(req);
2617                 return status;
2618         }
2619
2620         *aio_state = state->aio_state;
2621         *dos_attributes = state->dos_attributes;
2622         tevent_req_received(req);
2623         return NT_STATUS_OK;
2624 }
2625
2626 NTSTATUS smb_vfs_call_fget_compression(vfs_handle_struct *handle,
2627                                       TALLOC_CTX *mem_ctx,
2628                                       struct files_struct *fsp,
2629                                       uint16_t *_compression_fmt)
2630 {
2631         VFS_FIND(fget_compression);
2632         return handle->fns->fget_compression_fn(handle, mem_ctx, fsp,
2633                                                _compression_fmt);
2634 }
2635
2636 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2637                                       TALLOC_CTX *mem_ctx,
2638                                       struct files_struct *fsp,
2639                                       uint16_t compression_fmt)
2640 {
2641         VFS_FIND(set_compression);
2642         return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2643                                                compression_fmt);
2644 }
2645
2646 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2647                                       TALLOC_CTX *mem_ctx,
2648                                       const char *service_path,
2649                                       char **base_volume)
2650 {
2651         VFS_FIND(snap_check_path);
2652         return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2653                                                base_volume);
2654 }
2655
2656 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2657                                   TALLOC_CTX *mem_ctx,
2658                                   const char *base_volume,
2659                                   time_t *tstamp,
2660                                   bool rw,
2661                                   char **base_path,
2662                                   char **snap_path)
2663 {
2664         VFS_FIND(snap_create);
2665         return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2666                                            rw, base_path, snap_path);
2667 }
2668
2669 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2670                                   TALLOC_CTX *mem_ctx,
2671                                   char *base_path,
2672                                   char *snap_path)
2673 {
2674         VFS_FIND(snap_delete);
2675         return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2676                                            snap_path);
2677 }
2678
2679 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2680                                   struct files_struct *fsp,
2681                                   uint32_t security_info,
2682                                   TALLOC_CTX *mem_ctx,
2683                                   struct security_descriptor **ppdesc)
2684 {
2685         VFS_FIND(fget_nt_acl);
2686         return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2687                                            mem_ctx, ppdesc);
2688 }
2689
2690 NTSTATUS smb_vfs_call_get_nt_acl_at(struct vfs_handle_struct *handle,
2691                         struct files_struct *dirfsp,
2692                         const struct smb_filename *smb_fname,
2693                         uint32_t security_info,
2694                         TALLOC_CTX *mem_ctx,
2695                         struct security_descriptor **ppdesc)
2696 {
2697         VFS_FIND(get_nt_acl_at);
2698         return handle->fns->get_nt_acl_at_fn(handle,
2699                                 dirfsp,
2700                                 smb_fname,
2701                                 security_info,
2702                                 mem_ctx,
2703                                 ppdesc);
2704 }
2705
2706 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2707                                   struct files_struct *fsp,
2708                                   uint32_t security_info_sent,
2709                                   const struct security_descriptor *psd)
2710 {
2711         VFS_FIND(fset_nt_acl);
2712         return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent, 
2713                                            psd);
2714 }
2715
2716 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2717                                  struct smb_filename *file,
2718                                  struct security_acl *sacl,
2719                                  uint32_t access_requested,
2720                                  uint32_t access_denied)
2721 {
2722         VFS_FIND(audit_file);
2723         return handle->fns->audit_file_fn(handle, 
2724                                           file, 
2725                                           sacl, 
2726                                           access_requested, 
2727                                           access_denied);
2728 }
2729
2730 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2731                                         const struct smb_filename *smb_fname,
2732                                         SMB_ACL_TYPE_T type,
2733                                         TALLOC_CTX *mem_ctx)
2734 {
2735         VFS_FIND(sys_acl_get_file);
2736         return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2737 }
2738
2739 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2740                                       struct files_struct *fsp,
2741                                       TALLOC_CTX *mem_ctx)
2742 {
2743         VFS_FIND(sys_acl_get_fd);
2744         return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2745 }
2746
2747 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2748                                 const struct smb_filename *smb_fname,
2749                                 TALLOC_CTX *mem_ctx,
2750                                 char **blob_description,
2751                                 DATA_BLOB *blob)
2752 {
2753         VFS_FIND(sys_acl_blob_get_file);
2754         return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2755                         mem_ctx, blob_description, blob);
2756 }
2757
2758 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2759                                      struct files_struct *fsp,
2760                                      TALLOC_CTX *mem_ctx, 
2761                                      char **blob_description,
2762                                      DATA_BLOB *blob)
2763 {
2764         VFS_FIND(sys_acl_blob_get_fd);
2765         return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2766 }
2767
2768 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2769                                 struct files_struct *fsp,
2770                                 SMB_ACL_TYPE_T type,
2771                                 SMB_ACL_T theacl)
2772 {
2773         VFS_FIND(sys_acl_set_fd);
2774         return handle->fns->sys_acl_set_fd_fn(handle, fsp, type, theacl);
2775 }
2776
2777 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2778                                 const struct smb_filename *smb_fname)
2779 {
2780         VFS_FIND(sys_acl_delete_def_file);
2781         return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2782 }
2783
2784 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2785                                 const struct smb_filename *smb_fname,
2786                                 const char *name,
2787                                 void *value,
2788                                 size_t size)
2789 {
2790         VFS_FIND(getxattr);
2791         return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2792 }
2793
2794
2795 struct smb_vfs_call_getxattrat_state {
2796         files_struct *dir_fsp;
2797         ssize_t (*recv_fn)(struct tevent_req *req,
2798                            struct vfs_aio_state *aio_state,
2799                            TALLOC_CTX *mem_ctx,
2800                            uint8_t **xattr_value);
2801         ssize_t retval;
2802         uint8_t *xattr_value;
2803         struct vfs_aio_state aio_state;
2804 };
2805
2806 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2807
2808 struct tevent_req *smb_vfs_call_getxattrat_send(
2809                         TALLOC_CTX *mem_ctx,
2810                         struct tevent_context *ev,
2811                         struct vfs_handle_struct *handle,
2812                         files_struct *dir_fsp,
2813                         const struct smb_filename *smb_fname,
2814                         const char *xattr_name,
2815                         size_t alloc_hint)
2816 {
2817         struct tevent_req *req = NULL;
2818         struct smb_vfs_call_getxattrat_state *state = NULL;
2819         struct tevent_req *subreq = NULL;
2820
2821         req = tevent_req_create(mem_ctx, &state,
2822                                 struct smb_vfs_call_getxattrat_state);
2823         if (req == NULL) {
2824                 return NULL;
2825         }
2826
2827         VFS_FIND(getxattrat_send);
2828
2829         *state = (struct smb_vfs_call_getxattrat_state) {
2830                 .dir_fsp = dir_fsp,
2831                 .recv_fn = handle->fns->getxattrat_recv_fn,
2832         };
2833
2834         subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2835                                                  ev,
2836                                                  handle,
2837                                                  dir_fsp,
2838                                                  smb_fname,
2839                                                  xattr_name,
2840                                                  alloc_hint);
2841         if (tevent_req_nomem(subreq, req)) {
2842                 return tevent_req_post(req, ev);
2843         }
2844         tevent_req_defer_callback(req, ev);
2845
2846         tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2847         return req;
2848 }
2849
2850 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2851 {
2852         struct tevent_req *req = tevent_req_callback_data(
2853                 subreq, struct tevent_req);
2854         struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2855                 req, struct smb_vfs_call_getxattrat_state);
2856         bool ok;
2857
2858         /*
2859          * Make sure we run as the user again
2860          */
2861         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2862         SMB_ASSERT(ok);
2863
2864         state->retval = state->recv_fn(subreq,
2865                                        &state->aio_state,
2866                                        state,
2867                                        &state->xattr_value);
2868         TALLOC_FREE(subreq);
2869         if (state->retval == -1) {
2870                 tevent_req_error(req, state->aio_state.error);
2871                 return;
2872         }
2873
2874         tevent_req_done(req);
2875 }
2876
2877 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2878                                      struct vfs_aio_state *aio_state,
2879                                      TALLOC_CTX *mem_ctx,
2880                                      uint8_t **xattr_value)
2881 {
2882         struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2883                 req, struct smb_vfs_call_getxattrat_state);
2884         size_t xattr_size;
2885
2886         if (tevent_req_is_unix_error(req, &aio_state->error)) {
2887                 tevent_req_received(req);
2888                 return -1;
2889         }
2890
2891         *aio_state = state->aio_state;
2892         xattr_size = state->retval;
2893         if (xattr_value != NULL) {
2894                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2895         }
2896
2897         tevent_req_received(req);
2898         return xattr_size;
2899 }
2900
2901 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2902                                struct files_struct *fsp, const char *name,
2903                                void *value, size_t size)
2904 {
2905         VFS_FIND(fgetxattr);
2906         return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2907 }
2908
2909 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2910                                 const struct smb_filename *smb_fname,
2911                                 char *list,
2912                                 size_t size)
2913 {
2914         VFS_FIND(listxattr);
2915         return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2916 }
2917
2918 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2919                                 struct files_struct *fsp, char *list,
2920                                 size_t size)
2921 {
2922         VFS_FIND(flistxattr);
2923         return handle->fns->flistxattr_fn(handle, fsp, list, size);
2924 }
2925
2926 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2927                                 const struct smb_filename *smb_fname,
2928                                 const char *name)
2929 {
2930         VFS_FIND(removexattr);
2931         return handle->fns->removexattr_fn(handle, smb_fname, name);
2932 }
2933
2934 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2935                               struct files_struct *fsp, const char *name)
2936 {
2937         VFS_FIND(fremovexattr);
2938         return handle->fns->fremovexattr_fn(handle, fsp, name);
2939 }
2940
2941 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2942                         const struct smb_filename *smb_fname,
2943                         const char *name,
2944                         const void *value,
2945                         size_t size,
2946                         int flags)
2947 {
2948         VFS_FIND(setxattr);
2949         return handle->fns->setxattr_fn(handle, smb_fname,
2950                         name, value, size, flags);
2951 }
2952
2953 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2954                            struct files_struct *fsp, const char *name,
2955                            const void *value, size_t size, int flags)
2956 {
2957         VFS_FIND(fsetxattr);
2958         return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2959 }
2960
2961 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2962                             struct files_struct *fsp)
2963 {
2964         VFS_FIND(aio_force);
2965         return handle->fns->aio_force_fn(handle, fsp);
2966 }
2967
2968 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2969                                      struct files_struct *fsp,
2970                                      TALLOC_CTX *mem_ctx,
2971                                      DATA_BLOB *cookie)
2972 {
2973         VFS_FIND(durable_cookie);
2974         return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2975 }
2976
2977 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2978                                          struct files_struct *fsp,
2979                                          const DATA_BLOB old_cookie,
2980                                          TALLOC_CTX *mem_ctx,
2981                                          DATA_BLOB *new_cookie)
2982 {
2983         VFS_FIND(durable_disconnect);
2984         return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2985                                                   mem_ctx, new_cookie);
2986 }
2987
2988 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2989                                         struct smb_request *smb1req,
2990                                         struct smbXsrv_open *op,
2991                                         const DATA_BLOB old_cookie,
2992                                         TALLOC_CTX *mem_ctx,
2993                                         struct files_struct **fsp,
2994                                         DATA_BLOB *new_cookie)
2995 {
2996         VFS_FIND(durable_reconnect);
2997         return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2998                                                  old_cookie, mem_ctx, fsp,
2999                                                  new_cookie);
3000 }
3001
3002 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
3003                                    const struct smb_filename *fname,
3004                                    TALLOC_CTX *mem_ctx,
3005                                    struct readdir_attr_data **attr_data)
3006 {
3007         VFS_FIND(readdir_attr);
3008         return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
3009 }