12662774cd1c242417f2f374dd05d48e7d34c013
[vlendec/samba-autobuild/.git] / source3 / smbd / vfs.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    VFS initialisation and support functions
5    Copyright (C) Tim Potter 1999
6    Copyright (C) Alexander Bokovoy 2002
7    Copyright (C) James Peach 2006
8    Copyright (C) Volker Lendecke 2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
23    This work was sponsored by Optifacio Software Services, Inc.
24 */
25
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "../lib/util/memcache.h"
31 #include "transfer_file.h"
32 #include "ntioctl.h"
33 #include "lib/util/tevent_unix.h"
34 #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 = talloc_zero_size(
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,
295                                const struct files_struct *fsp)
296 {
297         struct vfs_fsp_data *head;
298
299         for (head = fsp->vfs_extension; head; head = head->next) {
300                 if (head->owner == handle) {
301                         return head;
302                 }
303         }
304
305         return NULL;
306 }
307
308 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle,
309                               const struct files_struct *fsp)
310 {
311         struct vfs_fsp_data *head;
312
313         head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
314         if (head != NULL) {
315                 return EXT_DATA_AREA(head);
316         }
317
318         return NULL;
319 }
320
321 #undef EXT_DATA_AREA
322
323 /*
324  * Ensure this module catches all VFS functions.
325  */
326 #ifdef DEVELOPER
327 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
328                             const char *module)
329 {
330         bool missing_fn = false;
331         unsigned int idx;
332         const uintptr_t *end = (const uintptr_t *)(fns + 1);
333
334         for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
335                 if (*((const uintptr_t *)fns + idx) == 0) {
336                         DBG_ERR("VFS function at index %d not implemented "
337                                 "in module %s\n", idx, module);
338                         missing_fn = true;
339                 }
340         }
341
342         if (missing_fn) {
343                 smb_panic("Required VFS function not implemented in module.\n");
344         }
345 }
346 #else
347 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
348                             const char *module)
349 {
350 }
351 #endif
352
353 /*****************************************************************
354  Generic VFS init.
355 ******************************************************************/
356
357 bool smbd_vfs_init(connection_struct *conn)
358 {
359         const char **vfs_objects;
360         unsigned int i = 0;
361         int j = 0;
362
363         /* Normal share - initialise with disk access functions */
364         vfs_init_default(conn);
365
366         /* No need to load vfs modules for printer connections */
367         if (conn->printer) {
368                 return True;
369         }
370
371         if (lp_widelinks(SNUM(conn))) {
372                 /*
373                  * As the widelinks logic is now moving into a
374                  * vfs_widelinks module, we need to custom load
375                  * it after the default module is initialized.
376                  * That way no changes to smb.conf files are
377                  * needed.
378                  */
379                 bool ok = vfs_init_custom(conn, "widelinks");
380                 if (!ok) {
381                         DBG_ERR("widelinks enabled and vfs_init_custom "
382                                 "failed for vfs_widelinks module\n");
383                         return false;
384                 }
385         }
386
387         vfs_objects = lp_vfs_objects(SNUM(conn));
388
389         /* Override VFS functions if 'vfs object' was not specified*/
390         if (!vfs_objects || !vfs_objects[0])
391                 return True;
392
393         for (i=0; vfs_objects[i] ;) {
394                 i++;
395         }
396
397         for (j=i-1; j >= 0; j--) {
398                 if (!vfs_init_custom(conn, vfs_objects[j])) {
399                         DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
400                         return False;
401                 }
402         }
403         return True;
404 }
405
406 /*******************************************************************
407  Check if a file exists in the vfs.
408 ********************************************************************/
409
410 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
411 {
412         /* Only return OK if stat was successful and S_ISREG */
413         if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
414             S_ISREG(smb_fname->st.st_ex_mode)) {
415                 return NT_STATUS_OK;
416         }
417
418         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
419 }
420
421 bool vfs_valid_pread_range(off_t offset, size_t length)
422 {
423         return sys_valid_io_range(offset, length);
424 }
425
426 bool vfs_valid_pwrite_range(off_t offset, size_t length)
427 {
428         /*
429          * See MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write
430          */
431         static const uint64_t maxfilesize = 0xfffffff0000;
432         uint64_t last_byte_ofs;
433         bool ok;
434
435         ok = sys_valid_io_range(offset, length);
436         if (!ok) {
437                 return false;
438         }
439
440         if (length == 0) {
441                 return true;
442         }
443
444         last_byte_ofs = offset + length;
445         if (last_byte_ofs > maxfilesize) {
446                 return false;
447         }
448
449         return true;
450 }
451
452 ssize_t vfs_pwrite_data(struct smb_request *req,
453                         files_struct *fsp,
454                         const char *buffer,
455                         size_t N,
456                         off_t offset)
457 {
458         size_t total=0;
459         ssize_t ret;
460         bool ok;
461
462         ok = vfs_valid_pwrite_range(offset, N);
463         if (!ok) {
464                 errno = EINVAL;
465                 return -1;
466         }
467
468         if (req && req->unread_bytes) {
469                 int sockfd = req->xconn->transport.sock;
470                 SMB_ASSERT(req->unread_bytes == N);
471                 /* VFS_RECVFILE must drain the socket
472                  * before returning. */
473                 req->unread_bytes = 0;
474                 /*
475                  * Leave the socket non-blocking and
476                  * use SMB_VFS_RECVFILE. If it returns
477                  * EAGAIN || EWOULDBLOCK temporarily set
478                  * the socket blocking and retry
479                  * the RECVFILE.
480                  */
481                 while (total < N) {
482                         ret = SMB_VFS_RECVFILE(sockfd,
483                                                 fsp,
484                                                 offset + total,
485                                                 N - total);
486                         if (ret == 0 || (ret == -1 &&
487                                          (errno == EAGAIN ||
488                                           errno == EWOULDBLOCK))) {
489                                 int old_flags;
490                                 /* Ensure the socket is blocking. */
491                                 old_flags = fcntl(sockfd, F_GETFL, 0);
492                                 if (set_blocking(sockfd, true) == -1) {
493                                         return (ssize_t)-1;
494                                 }
495                                 ret = SMB_VFS_RECVFILE(sockfd,
496                                                         fsp,
497                                                         offset + total,
498                                                         N - total);
499                                 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
500                                         return (ssize_t)-1;
501                                 }
502                                 if (ret == -1) {
503                                         return (ssize_t)-1;
504                                 }
505                                 total += ret;
506                                 return (ssize_t)total;
507                         }
508                         /* Any other error case. */
509                         if (ret == -1) {
510                                 return ret;
511                         }
512                         total += ret;
513                 }
514                 return (ssize_t)total;
515         }
516
517         while (total < N) {
518                 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
519                                      offset + total);
520
521                 if (ret == -1)
522                         return -1;
523                 if (ret == 0)
524                         return total;
525
526                 total += ret;
527         }
528         return (ssize_t)total;
529 }
530 /****************************************************************************
531  An allocate file space call using the vfs interface.
532  Allocates space for a file from a filedescriptor.
533  Returns 0 on success, -1 on failure.
534 ****************************************************************************/
535
536 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
537 {
538         int ret;
539         connection_struct *conn = fsp->conn;
540         uint64_t space_avail;
541         uint64_t bsize,dfree,dsize;
542         NTSTATUS status;
543         bool ok;
544
545         /*
546          * Actually try and commit the space on disk....
547          */
548
549         DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
550                   fsp_str_dbg(fsp), (double)len));
551
552         ok = vfs_valid_pwrite_range((off_t)len, 0);
553         if (!ok) {
554                 DEBUG(0,("vfs_allocate_file_space: %s negative/invalid len "
555                          "requested.\n", fsp_str_dbg(fsp)));
556                 errno = EINVAL;
557                 return -1;
558         }
559
560         status = vfs_stat_fsp(fsp);
561         if (!NT_STATUS_IS_OK(status)) {
562                 return -1;
563         }
564
565         if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
566                 return 0;
567
568         if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
569                 /* Shrink - use ftruncate. */
570
571                 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
572                           "size %.0f\n", fsp_str_dbg(fsp),
573                           (double)fsp->fsp_name->st.st_ex_size));
574
575                 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
576
577                 ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
578
579                 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
580
581                 return ret;
582         }
583
584         /* Grow - we need to test if we have enough space. */
585
586         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
587
588         if (lp_strict_allocate(SNUM(fsp->conn))) {
589                 /* See if we have a syscall that will allocate beyond
590                    end-of-file without changing EOF. */
591                 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
592                                         0, len);
593         } else {
594                 ret = 0;
595         }
596
597         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
598
599         if (ret == 0) {
600                 /* We changed the allocation size on disk, but not
601                    EOF - exactly as required. We're done ! */
602                 return 0;
603         }
604
605         if (ret == -1 && errno == ENOSPC) {
606                 return -1;
607         }
608
609         len -= fsp->fsp_name->st.st_ex_size;
610         len /= 1024; /* Len is now number of 1k blocks needed. */
611         space_avail =
612             get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
613         if (space_avail == (uint64_t)-1) {
614                 return -1;
615         }
616
617         DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
618                   "needed blocks = %.0f, space avail = %.0f\n",
619                   fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
620                   (double)space_avail));
621
622         if (len > space_avail) {
623                 errno = ENOSPC;
624                 return -1;
625         }
626
627         return 0;
628 }
629
630 /****************************************************************************
631  A vfs set_filelen call.
632  set the length of a file from a filedescriptor.
633  Returns 0 on success, -1 on failure.
634 ****************************************************************************/
635
636 int vfs_set_filelen(files_struct *fsp, off_t len)
637 {
638         int ret;
639         bool ok;
640
641         ok = vfs_valid_pwrite_range(len, 0);
642         if (!ok) {
643                 errno = EINVAL;
644                 return -1;
645         }
646
647         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
648
649         DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
650                   fsp_str_dbg(fsp), (double)len));
651         if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
652                 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
653                              FILE_NOTIFY_CHANGE_SIZE
654                              | FILE_NOTIFY_CHANGE_ATTRIBUTES,
655                              fsp->fsp_name->base_name);
656         }
657
658         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
659
660         return ret;
661 }
662
663 /****************************************************************************
664  A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
665  fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
666  as this is also called from the default SMB_VFS_FTRUNCATE code.
667  Always extends the file size.
668  Returns 0 on success, -1 on failure.
669 ****************************************************************************/
670
671 #define SPARSE_BUF_WRITE_SIZE (32*1024)
672
673 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
674 {
675         ssize_t pwrite_ret;
676         size_t total = 0;
677         bool ok;
678
679         ok = vfs_valid_pwrite_range(offset, len);
680         if (!ok) {
681                 errno = EINVAL;
682                 return -1;
683         }
684
685         if (!sparse_buf) {
686                 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
687                 if (!sparse_buf) {
688                         errno = ENOMEM;
689                         return -1;
690                 }
691         }
692
693         while (total < len) {
694                 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
695
696                 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
697                 if (pwrite_ret == -1) {
698                         int saved_errno = errno;
699                         DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
700                                   "%s failed with error %s\n",
701                                   fsp_str_dbg(fsp), strerror(saved_errno)));
702                         errno = saved_errno;
703                         return -1;
704                 }
705                 total += pwrite_ret;
706         }
707
708         return 0;
709 }
710
711 /****************************************************************************
712  A vfs fill sparse call.
713  Writes zeros from the end of file to len, if len is greater than EOF.
714  Used only by strict_sync.
715  Returns 0 on success, -1 on failure.
716 ****************************************************************************/
717
718 int vfs_fill_sparse(files_struct *fsp, off_t len)
719 {
720         int ret;
721         NTSTATUS status;
722         off_t offset;
723         size_t num_to_write;
724         bool ok;
725
726         ok = vfs_valid_pwrite_range(len, 0);
727         if (!ok) {
728                 errno = EINVAL;
729                 return -1;
730         }
731
732         status = vfs_stat_fsp(fsp);
733         if (!NT_STATUS_IS_OK(status)) {
734                 return -1;
735         }
736
737         if (len <= fsp->fsp_name->st.st_ex_size) {
738                 return 0;
739         }
740
741 #ifdef S_ISFIFO
742         if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
743                 return 0;
744         }
745 #endif
746
747         DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
748                   "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
749                   (double)fsp->fsp_name->st.st_ex_size, (double)len,
750                   (double)(len - fsp->fsp_name->st.st_ex_size)));
751
752         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
753
754         offset = fsp->fsp_name->st.st_ex_size;
755         num_to_write = len - fsp->fsp_name->st.st_ex_size;
756
757         /* Only do this on non-stream file handles. */
758         if (fsp->base_fsp == NULL) {
759                 /* for allocation try fallocate first. This can fail on some
760                  * platforms e.g. when the filesystem doesn't support it and no
761                  * emulation is being done by the libc (like on AIX with JFS1). In that
762                  * case we do our own emulation. fallocate implementations can
763                  * return ENOTSUP or EINVAL in cases like that. */
764                 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
765                 if (ret == -1 && errno == ENOSPC) {
766                         goto out;
767                 }
768                 if (ret == 0) {
769                         goto out;
770                 }
771                 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
772                         "error %d. Falling back to slow manual allocation\n", ret));
773         }
774
775         ret = vfs_slow_fallocate(fsp, offset, num_to_write);
776
777  out:
778
779         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
780         return ret;
781 }
782
783 /*******************************************************************************
784  Set a fd into blocking/nonblocking mode through VFS
785 *******************************************************************************/
786
787 int vfs_set_blocking(files_struct *fsp, bool set)
788 {
789         int val;
790 #ifdef O_NONBLOCK
791 #define FLAG_TO_SET O_NONBLOCK
792 #else
793 #ifdef SYSV
794 #define FLAG_TO_SET O_NDELAY
795 #else /* BSD */
796 #define FLAG_TO_SET FNDELAY
797 #endif
798 #endif
799
800         if (fsp->fsp_flags.is_pathref) {
801                 return 0;
802         }
803
804         val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
805         if (val == -1) {
806                 return -1;
807         }
808
809         if (set) {
810                 val &= ~FLAG_TO_SET;
811         } else {
812                 val |= FLAG_TO_SET;
813         }
814
815         return SMB_VFS_FCNTL(fsp, F_SETFL, val);
816 #undef FLAG_TO_SET
817 }
818
819 /****************************************************************************
820  Transfer some data (n bytes) between two file_struct's.
821 ****************************************************************************/
822
823 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
824 {
825         struct files_struct *fsp = (struct files_struct *)file;
826
827         return SMB_VFS_PREAD(fsp, buf, len, offset);
828 }
829
830 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
831 {
832         struct files_struct *fsp = (struct files_struct *)file;
833
834         return SMB_VFS_PWRITE(fsp, buf, len, offset);
835 }
836
837 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
838 {
839         return transfer_file_internal((void *)in, (void *)out, n,
840                                       vfs_pread_fn, vfs_pwrite_fn);
841 }
842
843 /*******************************************************************
844  A vfs_readdir wrapper which just returns the file name.
845 ********************************************************************/
846
847 const char *vfs_readdirname(connection_struct *conn,
848                             struct files_struct *dirfsp,
849                             void *p,
850                             SMB_STRUCT_STAT *sbuf,
851                             char **talloced)
852 {
853         struct dirent *ptr= NULL;
854         const char *dname;
855         char *translated;
856         NTSTATUS status;
857
858         if (!p)
859                 return(NULL);
860
861         ptr = SMB_VFS_READDIR(conn, dirfsp, (DIR *)p, sbuf);
862         if (!ptr)
863                 return(NULL);
864
865         dname = ptr->d_name;
866
867         status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
868                                         talloc_tos(), &translated);
869         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
870                 *talloced = NULL;
871                 return dname;
872         }
873         *talloced = translated;
874         if (!NT_STATUS_IS_OK(status)) {
875                 return NULL;
876         }
877         return translated;
878 }
879
880 /*******************************************************************
881  A wrapper for vfs_chdir().
882 ********************************************************************/
883
884 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
885 {
886         int ret;
887         struct smb_filename *cwd = NULL;
888
889         if (!LastDir) {
890                 LastDir = SMB_STRDUP("");
891         }
892
893         if (ISDOT(smb_fname->base_name)) {
894                 /*
895                  * passing a '.' is a noop,
896                  * and we only expect this after
897                  * everything is initialized.
898                  *
899                  * So the first vfs_ChDir() on a given
900                  * connection_struct must not be '.'.
901                  *
902                  * Note: conn_new() sets
903                  * conn->cwd_fsp->fh->fd = -1
904                  * and vfs_ChDir() leaves with
905                  * conn->cwd_fsp->fh->fd = AT_FDCWD
906                  * on success!
907                  */
908                 if (fsp_get_pathref_fd(conn->cwd_fsp) != AT_FDCWD) {
909                         /*
910                          * This should never happen and
911                          * we might change this to
912                          * SMB_ASSERT() in future.
913                          */
914                         DBG_ERR("Called with '.' as first operation!\n");
915                         log_stack_trace();
916                         errno = EINVAL;
917                         return -1;
918                 }
919                 return 0;
920         }
921
922         if (smb_fname->base_name[0] == '/' &&
923             strcsequal(LastDir,smb_fname->base_name))
924         {
925                 /*
926                  * conn->cwd_fsp->fsp_name and the kernel
927                  * are already correct, but conn->cwd_fsp->fh->fd
928                  * might still be -1 as initialized in conn_new().
929                  *
930                  * This can happen when a client made a 2nd
931                  * tree connect to a share with the same underlying
932                  * path (may or may not the same share).
933                  */
934                 fsp_set_fd(conn->cwd_fsp, AT_FDCWD);
935                 return 0;
936         }
937
938         DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
939
940         ret = SMB_VFS_CHDIR(conn, smb_fname);
941         if (ret != 0) {
942                 return -1;
943         }
944
945         /*
946          * Always replace conn->cwd_fsp. We
947          * don't know if it's been modified by
948          * VFS modules in the stack.
949          */
950
951         /* conn cache. */
952         cwd = vfs_GetWd(conn, conn);
953         if (cwd == NULL) {
954                 /*
955                  * vfs_GetWd() failed.
956                  * We must be able to read cwd.
957                  * Return to original directory
958                  * and return -1.
959                  */
960                 int saved_errno = errno;
961
962                 if (conn->cwd_fsp->fsp_name == NULL) {
963                         /*
964                          * Failed on the very first chdir()+getwd()
965                          * for this connection. We can't
966                          * continue.
967                          */
968                         smb_panic("conn->cwd getwd failed\n");
969                         /* NOTREACHED */
970                         return -1;
971                 }
972
973                 /* Return to the previous $cwd. */
974                 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
975                 if (ret != 0) {
976                         smb_panic("conn->cwd getwd failed\n");
977                         /* NOTREACHED */
978                         return -1;
979                 }
980                 errno = saved_errno;
981                 /* And fail the chdir(). */
982                 return -1;
983         }
984
985         /* vfs_GetWd() succeeded. */
986         /* Replace global cache. */
987         SAFE_FREE(LastDir);
988         LastDir = SMB_STRDUP(smb_fname->base_name);
989
990         /*
991          * (Indirect) Callers of vfs_ChDir() may still hold references to the
992          * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
993          * callers can use it for the lifetime of the SMB request.
994          */
995         talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
996
997         conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
998         fsp_set_fd(conn->cwd_fsp, AT_FDCWD);
999
1000         DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
1001
1002         return ret;
1003 }
1004
1005 /*******************************************************************
1006  Return the absolute current directory path - given a UNIX pathname.
1007  Note that this path is returned in DOS format, not UNIX
1008  format. Note this can be called with conn == NULL.
1009 ********************************************************************/
1010
1011 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
1012 {
1013         struct smb_filename *current_dir_fname = NULL;
1014         struct file_id key;
1015         struct smb_filename *smb_fname_dot = NULL;
1016         struct smb_filename *smb_fname_full = NULL;
1017         struct smb_filename *result = NULL;
1018
1019         if (!lp_getwd_cache()) {
1020                 goto nocache;
1021         }
1022
1023         smb_fname_dot = synthetic_smb_fname(ctx,
1024                                             ".",
1025                                             NULL,
1026                                             NULL,
1027                                             0,
1028                                             0);
1029         if (smb_fname_dot == NULL) {
1030                 errno = ENOMEM;
1031                 goto out;
1032         }
1033
1034         if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
1035                 /*
1036                  * Known to fail for root: the directory may be NFS-mounted
1037                  * and exported with root_squash (so has no root access).
1038                  */
1039                 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
1040                          "(NFS problem ?)\n", strerror(errno) ));
1041                 goto nocache;
1042         }
1043
1044         key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1045
1046         smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
1047                                         smbd_memcache(),
1048                                         GETWD_CACHE,
1049                                         data_blob_const(&key, sizeof(key)));
1050
1051         if (smb_fname_full == NULL) {
1052                 goto nocache;
1053         }
1054
1055         if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
1056             (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
1057             (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
1058             (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
1059                 /*
1060                  * Ok, we're done
1061                  * Note: smb_fname_full is owned by smbd_memcache()
1062                  * so we must make a copy to return.
1063                  */
1064                 result = cp_smb_filename(ctx, smb_fname_full);
1065                 if (result == NULL) {
1066                         errno = ENOMEM;
1067                 }
1068                 goto out;
1069         }
1070
1071  nocache:
1072
1073         /*
1074          * We don't have the information to hand so rely on traditional
1075          * methods. The very slow getcwd, which spawns a process on some
1076          * systems, or the not quite so bad getwd.
1077          */
1078
1079         current_dir_fname = SMB_VFS_GETWD(conn, ctx);
1080         if (current_dir_fname == NULL) {
1081                 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
1082                           strerror(errno)));
1083                 goto out;
1084         }
1085
1086         if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
1087                 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1088
1089                 /*
1090                  * smbd_memcache() will own current_dir_fname after the
1091                  * memcache_add_talloc call, so we must make
1092                  * a copy on ctx to return.
1093                  */
1094                 result = cp_smb_filename(ctx, current_dir_fname);
1095                 if (result == NULL) {
1096                         errno = ENOMEM;
1097                 }
1098
1099                 /*
1100                  * Ensure the memory going into the cache
1101                  * doesn't have a destructor so it can be
1102                  * cleanly freed.
1103                  */
1104                 talloc_set_destructor(current_dir_fname, NULL);
1105
1106                 memcache_add_talloc(smbd_memcache(),
1107                                 GETWD_CACHE,
1108                                 data_blob_const(&key, sizeof(key)),
1109                                 &current_dir_fname);
1110                 /* current_dir_fname is now == NULL here. */
1111         } else {
1112                 /* current_dir_fname is already allocated on ctx. */
1113                 result = current_dir_fname;
1114         }
1115
1116  out:
1117         TALLOC_FREE(smb_fname_dot);
1118         /*
1119          * Don't free current_dir_fname here. It's either been moved
1120          * to the memcache or is being returned in result.
1121          */
1122         return result;
1123 }
1124
1125 /*******************************************************************
1126  Reduce a file name, removing .. elements and checking that
1127  it is below dir in the hierarchy. This uses realpath.
1128  This function must run as root, and will return names
1129  and valid stat structs that can be checked on open.
1130 ********************************************************************/
1131
1132 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1133                         const struct smb_filename *smb_fname,
1134                         struct smb_request *smbreq)
1135 {
1136         NTSTATUS status;
1137         TALLOC_CTX *ctx = talloc_tos();
1138         const char *conn_rootdir;
1139         size_t rootdir_len;
1140         char *resolved_name = NULL;
1141         struct smb_filename *resolved_fname = NULL;
1142         struct smb_filename *saved_dir_fname = NULL;
1143         struct smb_filename *smb_fname_cwd = NULL;
1144         int ret;
1145         struct smb_filename *parent_name = NULL;
1146         struct smb_filename *file_name = NULL;
1147
1148         DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1149                         smb_fname->base_name,
1150                         conn->connectpath));
1151
1152         status = SMB_VFS_PARENT_PATHNAME(conn,
1153                                          ctx,
1154                                          smb_fname,
1155                                          &parent_name,
1156                                          &file_name);
1157         if (!NT_STATUS_IS_OK(status)) {
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
1578 NTSTATUS vfs_fstreaminfo(struct files_struct *fsp,
1579                         TALLOC_CTX *mem_ctx,
1580                         unsigned int *num_streams,
1581                         struct stream_struct **streams)
1582 {
1583         *num_streams = 0;
1584         *streams = NULL;
1585
1586         if (fsp == NULL) {
1587                 /*
1588                  * Callers may pass fsp == NULL when passing smb_fname->fsp of a
1589                  * symlink. This is ok, handle it here, by just return no
1590                  * streams on a symlink.
1591                  */
1592                 return NT_STATUS_OK;
1593         }
1594
1595         if (fsp_get_pathref_fd(fsp) == -1) {
1596                 /*
1597                  * No streams on non-real files/directories.
1598                  */
1599                 return NT_STATUS_OK;
1600         }
1601
1602         return SMB_VFS_FSTREAMINFO(fsp,
1603                         mem_ctx,
1604                         num_streams,
1605                         streams);
1606 }
1607
1608 int vfs_fake_fd(void)
1609 {
1610         int pipe_fds[2];
1611         int ret;
1612
1613         /*
1614          * Return a valid fd, but ensure any attempt to use
1615          * it returns an error (EPIPE).
1616          */
1617         ret = pipe(pipe_fds);
1618         if (ret != 0) {
1619                 return -1;
1620         }
1621
1622         close(pipe_fds[1]);
1623         return pipe_fds[0];
1624 }
1625
1626 /*
1627  * This is just a helper to make
1628  * users of vfs_fake_fd() more symetric
1629  */
1630 int vfs_fake_fd_close(int fd)
1631 {
1632         return close(fd);
1633 }
1634
1635 /*
1636   generate a file_id from a stat structure
1637  */
1638 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1639 {
1640         return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1641 }
1642
1643 NTSTATUS vfs_at_fspcwd(TALLOC_CTX *mem_ctx,
1644                        struct connection_struct *conn,
1645                        struct files_struct **_fsp)
1646 {
1647         struct files_struct *fsp = NULL;
1648
1649         fsp = talloc_zero(mem_ctx, struct files_struct);
1650         if (fsp == NULL) {
1651                 return NT_STATUS_NO_MEMORY;
1652         }
1653
1654         fsp->fsp_name = synthetic_smb_fname(fsp, ".", NULL, NULL, 0, 0);
1655         if (fsp->fsp_name == NULL) {
1656                 TALLOC_FREE(fsp);
1657                 return NT_STATUS_NO_MEMORY;
1658         }
1659
1660         fsp->fh = fd_handle_create(fsp);
1661         if (fsp->fh == NULL) {
1662                 TALLOC_FREE(fsp);
1663                 return NT_STATUS_NO_MEMORY;
1664         }
1665
1666         fsp_set_fd(fsp, AT_FDCWD);
1667         fsp->fnum = FNUM_FIELD_INVALID;
1668         fsp->conn = conn;
1669
1670         *_fsp = fsp;
1671         return NT_STATUS_OK;
1672 }
1673
1674 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1675                          const char *service, const char *user)
1676 {
1677         VFS_FIND(connect);
1678         return handle->fns->connect_fn(handle, service, user);
1679 }
1680
1681 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1682 {
1683         VFS_FIND(disconnect);
1684         handle->fns->disconnect_fn(handle);
1685 }
1686
1687 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1688                                 const struct smb_filename *smb_fname,
1689                                 uint64_t *bsize,
1690                                 uint64_t *dfree,
1691                                 uint64_t *dsize)
1692 {
1693         VFS_FIND(disk_free);
1694         return handle->fns->disk_free_fn(handle, smb_fname,
1695                         bsize, dfree, dsize);
1696 }
1697
1698 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1699                                 const struct smb_filename *smb_fname,
1700                                 enum SMB_QUOTA_TYPE qtype,
1701                                 unid_t id,
1702                                 SMB_DISK_QUOTA *qt)
1703 {
1704         VFS_FIND(get_quota);
1705         return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1706 }
1707
1708 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1709                            enum SMB_QUOTA_TYPE qtype, unid_t id,
1710                            SMB_DISK_QUOTA *qt)
1711 {
1712         VFS_FIND(set_quota);
1713         return handle->fns->set_quota_fn(handle, qtype, id, qt);
1714 }
1715
1716 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1717                                       struct files_struct *fsp,
1718                                       struct shadow_copy_data *shadow_copy_data,
1719                                       bool labels)
1720 {
1721         VFS_FIND(get_shadow_copy_data);
1722         return handle->fns->get_shadow_copy_data_fn(handle, fsp, 
1723                                                     shadow_copy_data,
1724                                                     labels);
1725 }
1726 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1727                         const struct smb_filename *smb_fname,
1728                         struct vfs_statvfs_struct *statbuf)
1729 {
1730         VFS_FIND(statvfs);
1731         return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1732 }
1733
1734 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1735                         enum timestamp_set_resolution *p_ts_res)
1736 {
1737         VFS_FIND(fs_capabilities);
1738         return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1739 }
1740
1741 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1742                                         struct dfs_GetDFSReferral *r)
1743 {
1744         VFS_FIND(get_dfs_referrals);
1745         return handle->fns->get_dfs_referrals_fn(handle, r);
1746 }
1747
1748 NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
1749                                 struct files_struct *dirfsp,
1750                                 const struct smb_filename *smb_fname,
1751                                 const struct referral *reflist,
1752                                 size_t referral_count)
1753 {
1754         VFS_FIND(create_dfs_pathat);
1755         return handle->fns->create_dfs_pathat_fn(handle,
1756                                                 dirfsp,
1757                                                 smb_fname,
1758                                                 reflist,
1759                                                 referral_count);
1760 }
1761
1762 NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
1763                                 TALLOC_CTX *mem_ctx,
1764                                 struct files_struct *dirfsp,
1765                                 struct smb_filename *smb_fname,
1766                                 struct referral **ppreflist,
1767                                 size_t *preferral_count)
1768 {
1769         VFS_FIND(read_dfs_pathat);
1770         return handle->fns->read_dfs_pathat_fn(handle,
1771                                                 mem_ctx,
1772                                                 dirfsp,
1773                                                 smb_fname,
1774                                                 ppreflist,
1775                                                 preferral_count);
1776 }
1777
1778 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1779                                         struct files_struct *fsp,
1780                                         const char *mask,
1781                                         uint32_t attributes)
1782 {
1783         VFS_FIND(fdopendir);
1784         return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1785 }
1786
1787 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1788                                     struct files_struct *dirfsp,
1789                                     DIR *dirp,
1790                                     SMB_STRUCT_STAT *sbuf)
1791 {
1792         VFS_FIND(readdir);
1793         return handle->fns->readdir_fn(handle, dirfsp, dirp, sbuf);
1794 }
1795
1796 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1797                           DIR *dirp, long offset)
1798 {
1799         VFS_FIND(seekdir);
1800         handle->fns->seekdir_fn(handle, dirp, offset);
1801 }
1802
1803 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1804                           DIR *dirp)
1805 {
1806         VFS_FIND(telldir);
1807         return handle->fns->telldir_fn(handle, dirp);
1808 }
1809
1810 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1811                              DIR *dirp)
1812 {
1813         VFS_FIND(rewind_dir);
1814         handle->fns->rewind_dir_fn(handle, dirp);
1815 }
1816
1817 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1818                         struct files_struct *dirfsp,
1819                         const struct smb_filename *smb_fname,
1820                         mode_t mode)
1821 {
1822         VFS_FIND(mkdirat);
1823         return handle->fns->mkdirat_fn(handle,
1824                         dirfsp,
1825                         smb_fname,
1826                         mode);
1827 }
1828
1829 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1830                           DIR *dir)
1831 {
1832         VFS_FIND(closedir);
1833         return handle->fns->closedir_fn(handle, dir);
1834 }
1835
1836 int smb_vfs_call_openat(struct vfs_handle_struct *handle,
1837                         const struct files_struct *dirfsp,
1838                         const struct smb_filename *smb_fname,
1839                         struct files_struct *fsp,
1840                         int flags,
1841                         mode_t mode)
1842 {
1843         VFS_FIND(openat);
1844         return handle->fns->openat_fn(handle,
1845                                       dirfsp,
1846                                       smb_fname,
1847                                       fsp,
1848                                       flags,
1849                                       mode);
1850 }
1851
1852 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1853                                   struct smb_request *req,
1854                                   struct smb_filename *smb_fname,
1855                                   uint32_t access_mask,
1856                                   uint32_t share_access,
1857                                   uint32_t create_disposition,
1858                                   uint32_t create_options,
1859                                   uint32_t file_attributes,
1860                                   uint32_t oplock_request,
1861                                   const struct smb2_lease *lease,
1862                                   uint64_t allocation_size,
1863                                   uint32_t private_flags,
1864                                   struct security_descriptor *sd,
1865                                   struct ea_list *ea_list,
1866                                   files_struct **result,
1867                                   int *pinfo,
1868                                   const struct smb2_create_blobs *in_context_blobs,
1869                                   struct smb2_create_blobs *out_context_blobs)
1870 {
1871         VFS_FIND(create_file);
1872         return handle->fns->create_file_fn(
1873                 handle, req, smb_fname,
1874                 access_mask, share_access, create_disposition, create_options,
1875                 file_attributes, oplock_request, lease, allocation_size,
1876                 private_flags, sd, ea_list,
1877                 result, pinfo, in_context_blobs, out_context_blobs);
1878 }
1879
1880 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1881                        struct files_struct *fsp)
1882 {
1883         VFS_FIND(close);
1884         return handle->fns->close_fn(handle, fsp);
1885 }
1886
1887 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1888                            struct files_struct *fsp, void *data, size_t n,
1889                            off_t offset)
1890 {
1891         VFS_FIND(pread);
1892         return handle->fns->pread_fn(handle, fsp, data, n, offset);
1893 }
1894
1895 struct smb_vfs_call_pread_state {
1896         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1897         ssize_t retval;
1898         struct vfs_aio_state vfs_aio_state;
1899 };
1900
1901 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1902
1903 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1904                                            TALLOC_CTX *mem_ctx,
1905                                            struct tevent_context *ev,
1906                                            struct files_struct *fsp,
1907                                            void *data,
1908                                            size_t n, off_t offset)
1909 {
1910         struct tevent_req *req, *subreq;
1911         struct smb_vfs_call_pread_state *state;
1912
1913         req = tevent_req_create(mem_ctx, &state,
1914                                 struct smb_vfs_call_pread_state);
1915         if (req == NULL) {
1916                 return NULL;
1917         }
1918         VFS_FIND(pread_send);
1919         state->recv_fn = handle->fns->pread_recv_fn;
1920
1921         subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1922                                             offset);
1923         if (tevent_req_nomem(subreq, req)) {
1924                 return tevent_req_post(req, ev);
1925         }
1926         tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1927         return req;
1928 }
1929
1930 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1931 {
1932         struct tevent_req *req = tevent_req_callback_data(
1933                 subreq, struct tevent_req);
1934         struct smb_vfs_call_pread_state *state = tevent_req_data(
1935                 req, struct smb_vfs_call_pread_state);
1936
1937         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1938         TALLOC_FREE(subreq);
1939         if (state->retval == -1) {
1940                 tevent_req_error(req, state->vfs_aio_state.error);
1941                 return;
1942         }
1943         tevent_req_done(req);
1944 }
1945
1946 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1947                            struct vfs_aio_state *vfs_aio_state)
1948 {
1949         struct smb_vfs_call_pread_state *state = tevent_req_data(
1950                 req, struct smb_vfs_call_pread_state);
1951         ssize_t retval;
1952
1953         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1954                 tevent_req_received(req);
1955                 return -1;
1956         }
1957         *vfs_aio_state = state->vfs_aio_state;
1958         retval = state->retval;
1959         tevent_req_received(req);
1960         return retval;
1961 }
1962
1963 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1964                             struct files_struct *fsp, const void *data,
1965                             size_t n, off_t offset)
1966 {
1967         VFS_FIND(pwrite);
1968         return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1969 }
1970
1971 struct smb_vfs_call_pwrite_state {
1972         ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1973         ssize_t retval;
1974         struct vfs_aio_state vfs_aio_state;
1975 };
1976
1977 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1978
1979 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1980                                             TALLOC_CTX *mem_ctx,
1981                                             struct tevent_context *ev,
1982                                             struct files_struct *fsp,
1983                                             const void *data,
1984                                             size_t n, off_t offset)
1985 {
1986         struct tevent_req *req, *subreq;
1987         struct smb_vfs_call_pwrite_state *state;
1988
1989         req = tevent_req_create(mem_ctx, &state,
1990                                 struct smb_vfs_call_pwrite_state);
1991         if (req == NULL) {
1992                 return NULL;
1993         }
1994         VFS_FIND(pwrite_send);
1995         state->recv_fn = handle->fns->pwrite_recv_fn;
1996
1997         subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1998                                              offset);
1999         if (tevent_req_nomem(subreq, req)) {
2000                 return tevent_req_post(req, ev);
2001         }
2002         tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
2003         return req;
2004 }
2005
2006 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
2007 {
2008         struct tevent_req *req = tevent_req_callback_data(
2009                 subreq, struct tevent_req);
2010         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
2011                 req, struct smb_vfs_call_pwrite_state);
2012
2013         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2014         TALLOC_FREE(subreq);
2015         if (state->retval == -1) {
2016                 tevent_req_error(req, state->vfs_aio_state.error);
2017                 return;
2018         }
2019         tevent_req_done(req);
2020 }
2021
2022 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
2023                             struct vfs_aio_state *vfs_aio_state)
2024 {
2025         struct smb_vfs_call_pwrite_state *state = tevent_req_data(
2026                 req, struct smb_vfs_call_pwrite_state);
2027         ssize_t retval;
2028
2029         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2030                 tevent_req_received(req);
2031                 return -1;
2032         }
2033         *vfs_aio_state = state->vfs_aio_state;
2034         retval = state->retval;
2035         tevent_req_received(req);
2036         return retval;
2037 }
2038
2039 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
2040                              struct files_struct *fsp, off_t offset,
2041                              int whence)
2042 {
2043         VFS_FIND(lseek);
2044         return handle->fns->lseek_fn(handle, fsp, offset, whence);
2045 }
2046
2047 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
2048                               files_struct *fromfsp, const DATA_BLOB *header,
2049                               off_t offset, size_t count)
2050 {
2051         VFS_FIND(sendfile);
2052         return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
2053                                         count);
2054 }
2055
2056 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
2057                               files_struct *tofsp, off_t offset,
2058                               size_t count)
2059 {
2060         VFS_FIND(recvfile);
2061         return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
2062 }
2063
2064 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
2065                         files_struct *srcfsp,
2066                         const struct smb_filename *smb_fname_src,
2067                         files_struct *dstfsp,
2068                         const struct smb_filename *smb_fname_dst)
2069 {
2070         VFS_FIND(renameat);
2071         return handle->fns->renameat_fn(handle,
2072                                 srcfsp,
2073                                 smb_fname_src,
2074                                 dstfsp,
2075                                 smb_fname_dst);
2076 }
2077
2078 struct smb_vfs_call_fsync_state {
2079         int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
2080         int retval;
2081         struct vfs_aio_state vfs_aio_state;
2082 };
2083
2084 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
2085
2086 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
2087                                            TALLOC_CTX *mem_ctx,
2088                                            struct tevent_context *ev,
2089                                            struct files_struct *fsp)
2090 {
2091         struct tevent_req *req, *subreq;
2092         struct smb_vfs_call_fsync_state *state;
2093
2094         req = tevent_req_create(mem_ctx, &state,
2095                                 struct smb_vfs_call_fsync_state);
2096         if (req == NULL) {
2097                 return NULL;
2098         }
2099         VFS_FIND(fsync_send);
2100         state->recv_fn = handle->fns->fsync_recv_fn;
2101
2102         subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
2103         if (tevent_req_nomem(subreq, req)) {
2104                 return tevent_req_post(req, ev);
2105         }
2106         tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
2107         return req;
2108 }
2109
2110 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
2111 {
2112         struct tevent_req *req = tevent_req_callback_data(
2113                 subreq, struct tevent_req);
2114         struct smb_vfs_call_fsync_state *state = tevent_req_data(
2115                 req, struct smb_vfs_call_fsync_state);
2116
2117         state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2118         TALLOC_FREE(subreq);
2119         if (state->retval == -1) {
2120                 tevent_req_error(req, state->vfs_aio_state.error);
2121                 return;
2122         }
2123         tevent_req_done(req);
2124 }
2125
2126 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
2127 {
2128         struct smb_vfs_call_fsync_state *state = tevent_req_data(
2129                 req, struct smb_vfs_call_fsync_state);
2130         ssize_t retval;
2131
2132         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2133                 tevent_req_received(req);
2134                 return -1;
2135         }
2136         *vfs_aio_state = state->vfs_aio_state;
2137         retval = state->retval;
2138         tevent_req_received(req);
2139         return retval;
2140 }
2141
2142 /*
2143  * Synchronous version of fsync, built from backend
2144  * async VFS primitives. Uses a temporary sub-event
2145  * context (NOT NESTED).
2146  */
2147
2148 int smb_vfs_fsync_sync(files_struct *fsp)
2149 {
2150         TALLOC_CTX *frame = talloc_stackframe();
2151         struct tevent_req *req = NULL;
2152         struct vfs_aio_state aio_state = { 0 };
2153         int ret = -1;
2154         bool ok;
2155         struct tevent_context *ev = samba_tevent_context_init(frame);
2156
2157         if (ev == NULL) {
2158                 goto out;
2159         }
2160
2161         req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
2162         if (req == NULL) {
2163                 goto out;
2164         }
2165
2166         ok = tevent_req_poll(req, ev);
2167         if (!ok) {
2168                 goto out;
2169         }
2170
2171         ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
2172
2173   out:
2174
2175         TALLOC_FREE(frame);
2176         if (aio_state.error != 0) {
2177                 errno = aio_state.error;
2178         }
2179         return ret;
2180 }
2181
2182 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
2183                       struct smb_filename *smb_fname)
2184 {
2185         VFS_FIND(stat);
2186         return handle->fns->stat_fn(handle, smb_fname);
2187 }
2188
2189 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2190                        struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2191 {
2192         VFS_FIND(fstat);
2193         return handle->fns->fstat_fn(handle, fsp, sbuf);
2194 }
2195
2196 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2197                        struct smb_filename *smb_filename)
2198 {
2199         VFS_FIND(lstat);
2200         return handle->fns->lstat_fn(handle, smb_filename);
2201 }
2202
2203 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2204                                      struct files_struct *fsp,
2205                                      const SMB_STRUCT_STAT *sbuf)
2206 {
2207         VFS_FIND(get_alloc_size);
2208         return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2209 }
2210
2211 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
2212                         struct files_struct *dirfsp,
2213                         const struct smb_filename *smb_fname,
2214                         int flags)
2215 {
2216         VFS_FIND(unlinkat);
2217         return handle->fns->unlinkat_fn(handle,
2218                         dirfsp,
2219                         smb_fname,
2220                         flags);
2221 }
2222
2223 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2224                         struct files_struct *fsp, mode_t mode)
2225 {
2226         VFS_FIND(fchmod);
2227         return handle->fns->fchmod_fn(handle, fsp, mode);
2228 }
2229
2230 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2231                         struct files_struct *fsp, uid_t uid, gid_t gid)
2232 {
2233         VFS_FIND(fchown);
2234         return handle->fns->fchown_fn(handle, fsp, uid, gid);
2235 }
2236
2237 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2238                         const struct smb_filename *smb_fname,
2239                         uid_t uid,
2240                         gid_t gid)
2241 {
2242         VFS_FIND(lchown);
2243         return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2244 }
2245
2246 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2247                         const struct smb_filename *smb_fname)
2248 {
2249         VFS_FIND(chdir);
2250         return handle->fns->chdir_fn(handle, smb_fname);
2251 }
2252
2253 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2254                                 TALLOC_CTX *ctx)
2255 {
2256         VFS_FIND(getwd);
2257         return handle->fns->getwd_fn(handle, ctx);
2258 }
2259
2260 int smb_vfs_call_fntimes(struct vfs_handle_struct *handle,
2261                          struct files_struct *fsp,
2262                          struct smb_file_time *ft)
2263 {
2264         VFS_FIND(fntimes);
2265         return handle->fns->fntimes_fn(handle, fsp, ft);
2266 }
2267
2268 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2269                            struct files_struct *fsp, off_t offset)
2270 {
2271         VFS_FIND(ftruncate);
2272         return handle->fns->ftruncate_fn(handle, fsp, offset);
2273 }
2274
2275 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2276                            struct files_struct *fsp,
2277                            uint32_t mode,
2278                            off_t offset,
2279                            off_t len)
2280 {
2281         VFS_FIND(fallocate);
2282         return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2283 }
2284
2285 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2286                               struct files_struct *fsp, uint32_t share_mode,
2287                               uint32_t access_mask)
2288 {
2289         VFS_FIND(kernel_flock);
2290         return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2291                                          access_mask);
2292 }
2293
2294 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2295                        struct files_struct *fsp, int cmd, ...)
2296 {
2297         int result;
2298         va_list cmd_arg;
2299
2300         VFS_FIND(fcntl);
2301
2302         va_start(cmd_arg, cmd);
2303         result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2304         va_end(cmd_arg);
2305
2306         return result;
2307 }
2308
2309 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2310                                 struct files_struct *fsp, int leasetype)
2311 {
2312         VFS_FIND(linux_setlease);
2313         return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2314 }
2315
2316 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2317                         const struct smb_filename *link_target,
2318                         struct files_struct *dirfsp,
2319                         const struct smb_filename *new_smb_fname)
2320 {
2321         VFS_FIND(symlinkat);
2322         return handle->fns->symlinkat_fn(handle,
2323                                 link_target,
2324                                 dirfsp,
2325                                 new_smb_fname);
2326 }
2327
2328 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2329                         const struct files_struct *dirfsp,
2330                         const struct smb_filename *smb_fname,
2331                         char *buf,
2332                         size_t bufsiz)
2333 {
2334         VFS_FIND(readlinkat);
2335         return handle->fns->readlinkat_fn(handle,
2336                                 dirfsp,
2337                                 smb_fname,
2338                                 buf,
2339                                 bufsiz);
2340 }
2341
2342 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2343                         struct files_struct *srcfsp,
2344                         const struct smb_filename *old_smb_fname,
2345                         struct files_struct *dstfsp,
2346                         const struct smb_filename *new_smb_fname,
2347                         int flags)
2348 {
2349         VFS_FIND(linkat);
2350         return handle->fns->linkat_fn(handle,
2351                                 srcfsp,
2352                                 old_smb_fname,
2353                                 dstfsp,
2354                                 new_smb_fname,
2355                                 flags);
2356 }
2357
2358 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2359                         struct files_struct *dirfsp,
2360                         const struct smb_filename *smb_fname,
2361                         mode_t mode,
2362                         SMB_DEV_T dev)
2363 {
2364         VFS_FIND(mknodat);
2365         return handle->fns->mknodat_fn(handle,
2366                                 dirfsp,
2367                                 smb_fname,
2368                                 mode,
2369                                 dev);
2370 }
2371
2372 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2373                         TALLOC_CTX *ctx,
2374                         const struct smb_filename *smb_fname)
2375 {
2376         VFS_FIND(realpath);
2377         return handle->fns->realpath_fn(handle, ctx, smb_fname);
2378 }
2379
2380 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2381                         const struct smb_filename *smb_fname,
2382                         unsigned int flags)
2383 {
2384         VFS_FIND(chflags);
2385         return handle->fns->chflags_fn(handle, smb_fname, flags);
2386 }
2387
2388 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2389                                            const SMB_STRUCT_STAT *sbuf)
2390 {
2391         VFS_FIND(file_id_create);
2392         return handle->fns->file_id_create_fn(handle, sbuf);
2393 }
2394
2395 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2396                                  const SMB_STRUCT_STAT *sbuf)
2397 {
2398         VFS_FIND(fs_file_id);
2399         return handle->fns->fs_file_id_fn(handle, sbuf);
2400 }
2401
2402 NTSTATUS smb_vfs_call_fstreaminfo(struct vfs_handle_struct *handle,
2403                                  struct files_struct *fsp,
2404                                  TALLOC_CTX *mem_ctx,
2405                                  unsigned int *num_streams,
2406                                  struct stream_struct **streams)
2407 {
2408         VFS_FIND(fstreaminfo);
2409         return handle->fns->fstreaminfo_fn(handle, fsp, mem_ctx,
2410                                           num_streams, streams);
2411 }
2412
2413 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2414                                    const struct smb_filename *path,
2415                                    const char *name,
2416                                    TALLOC_CTX *mem_ctx,
2417                                    char **found_name)
2418 {
2419         VFS_FIND(get_real_filename);
2420         return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2421                                                  found_name);
2422 }
2423
2424 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2425                                  const struct smb_filename *smb_fname)
2426 {
2427         VFS_FIND(connectpath);
2428         return handle->fns->connectpath_fn(handle, smb_fname);
2429 }
2430
2431 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2432                                     struct files_struct *fsp,
2433                                     struct lock_struct *plock)
2434 {
2435         VFS_FIND(strict_lock_check);
2436         return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2437 }
2438
2439 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2440                                      const char *name,
2441                                      enum vfs_translate_direction direction,
2442                                      TALLOC_CTX *mem_ctx,
2443                                      char **mapped_name)
2444 {
2445         VFS_FIND(translate_name);
2446         return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2447                                               mapped_name);
2448 }
2449
2450 NTSTATUS smb_vfs_call_parent_pathname(struct vfs_handle_struct *handle,
2451                                       TALLOC_CTX *mem_ctx,
2452                                       const struct smb_filename *smb_fname_in,
2453                                       struct smb_filename **parent_dir_out,
2454                                       struct smb_filename **atname_out)
2455 {
2456         VFS_FIND(parent_pathname);
2457         return handle->fns->parent_pathname_fn(handle,
2458                                                mem_ctx,
2459                                                smb_fname_in,
2460                                                parent_dir_out,
2461                                                atname_out);
2462 }
2463
2464 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2465                             struct files_struct *fsp,
2466                             TALLOC_CTX *ctx,
2467                             uint32_t function,
2468                             uint16_t req_flags,
2469                             const uint8_t *in_data,
2470                             uint32_t in_len,
2471                             uint8_t **out_data,
2472                             uint32_t max_out_len,
2473                             uint32_t *out_len)
2474 {
2475         VFS_FIND(fsctl);
2476         return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2477                                      in_data, in_len, out_data, max_out_len,
2478                                      out_len);
2479 }
2480
2481 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2482                                           struct files_struct *fsp,
2483                                           uint32_t *dosmode)
2484 {
2485         VFS_FIND(fget_dos_attributes);
2486         return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2487 }
2488
2489 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2490                                           struct files_struct *fsp,
2491                                           uint32_t dosmode)
2492 {
2493         VFS_FIND(fset_dos_attributes);
2494         return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2495 }
2496
2497 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2498                                                   struct tevent_context *ev,
2499                                                   struct vfs_handle_struct *handle,
2500                                                   struct files_struct *fsp,
2501                                                   uint32_t fsctl,
2502                                                   uint32_t ttl,
2503                                                   off_t offset,
2504                                                   size_t to_copy)
2505 {
2506         VFS_FIND(offload_read_send);
2507         return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2508                                                  fsp, fsctl,
2509                                                  ttl, offset, to_copy);
2510 }
2511
2512 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2513                                         struct vfs_handle_struct *handle,
2514                                         TALLOC_CTX *mem_ctx,
2515                                         DATA_BLOB *token_blob)
2516 {
2517         VFS_FIND(offload_read_recv);
2518         return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2519 }
2520
2521 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2522                                                    TALLOC_CTX *mem_ctx,
2523                                                    struct tevent_context *ev,
2524                                                    uint32_t fsctl,
2525                                                    DATA_BLOB *token,
2526                                                    off_t transfer_offset,
2527                                                    struct files_struct *dest_fsp,
2528                                                    off_t dest_off,
2529                                                    off_t num)
2530 {
2531         VFS_FIND(offload_write_send);
2532         return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2533                                                token, transfer_offset,
2534                                                dest_fsp, dest_off, num);
2535 }
2536
2537 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2538                                          struct tevent_req *req,
2539                                          off_t *copied)
2540 {
2541         VFS_FIND(offload_write_recv);
2542         return handle->fns->offload_write_recv_fn(handle, req, copied);
2543 }
2544
2545 struct smb_vfs_call_get_dos_attributes_state {
2546         files_struct *dir_fsp;
2547         NTSTATUS (*recv_fn)(struct tevent_req *req,
2548                             struct vfs_aio_state *aio_state,
2549                             uint32_t *dosmode);
2550         struct vfs_aio_state aio_state;
2551         uint32_t dos_attributes;
2552 };
2553
2554 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2555
2556 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2557                         TALLOC_CTX *mem_ctx,
2558                         struct tevent_context *ev,
2559                         struct vfs_handle_struct *handle,
2560                         files_struct *dir_fsp,
2561                         struct smb_filename *smb_fname)
2562 {
2563         struct tevent_req *req = NULL;
2564         struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2565         struct tevent_req *subreq = NULL;
2566
2567         req = tevent_req_create(mem_ctx, &state,
2568                                 struct smb_vfs_call_get_dos_attributes_state);
2569         if (req == NULL) {
2570                 return NULL;
2571         }
2572
2573         VFS_FIND(get_dos_attributes_send);
2574
2575         *state = (struct smb_vfs_call_get_dos_attributes_state) {
2576                 .dir_fsp = dir_fsp,
2577                 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2578         };
2579
2580         subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2581                                                          ev,
2582                                                          handle,
2583                                                          dir_fsp,
2584                                                          smb_fname);
2585         if (tevent_req_nomem(subreq, req)) {
2586                 return tevent_req_post(req, ev);
2587         }
2588         tevent_req_defer_callback(req, ev);
2589
2590         tevent_req_set_callback(subreq,
2591                                 smb_vfs_call_get_dos_attributes_done,
2592                                 req);
2593
2594         return req;
2595 }
2596
2597 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2598 {
2599         struct tevent_req *req =
2600                 tevent_req_callback_data(subreq,
2601                 struct tevent_req);
2602         struct smb_vfs_call_get_dos_attributes_state *state =
2603                 tevent_req_data(req,
2604                 struct smb_vfs_call_get_dos_attributes_state);
2605         NTSTATUS status;
2606         bool ok;
2607
2608         /*
2609          * Make sure we run as the user again
2610          */
2611         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2612         SMB_ASSERT(ok);
2613
2614         status = state->recv_fn(subreq,
2615                                 &state->aio_state,
2616                                 &state->dos_attributes);
2617         TALLOC_FREE(subreq);
2618         if (tevent_req_nterror(req, status)) {
2619                 return;
2620         }
2621
2622         tevent_req_done(req);
2623 }
2624
2625 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2626                 struct tevent_req *req,
2627                 struct vfs_aio_state *aio_state,
2628                 uint32_t *dos_attributes)
2629 {
2630         struct smb_vfs_call_get_dos_attributes_state *state =
2631                 tevent_req_data(req,
2632                 struct smb_vfs_call_get_dos_attributes_state);
2633         NTSTATUS status;
2634
2635         if (tevent_req_is_nterror(req, &status)) {
2636                 tevent_req_received(req);
2637                 return status;
2638         }
2639
2640         *aio_state = state->aio_state;
2641         *dos_attributes = state->dos_attributes;
2642         tevent_req_received(req);
2643         return NT_STATUS_OK;
2644 }
2645
2646 NTSTATUS smb_vfs_call_fget_compression(vfs_handle_struct *handle,
2647                                       TALLOC_CTX *mem_ctx,
2648                                       struct files_struct *fsp,
2649                                       uint16_t *_compression_fmt)
2650 {
2651         VFS_FIND(fget_compression);
2652         return handle->fns->fget_compression_fn(handle, mem_ctx, fsp,
2653                                                _compression_fmt);
2654 }
2655
2656 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2657                                       TALLOC_CTX *mem_ctx,
2658                                       struct files_struct *fsp,
2659                                       uint16_t compression_fmt)
2660 {
2661         VFS_FIND(set_compression);
2662         return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2663                                                compression_fmt);
2664 }
2665
2666 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2667                                       TALLOC_CTX *mem_ctx,
2668                                       const char *service_path,
2669                                       char **base_volume)
2670 {
2671         VFS_FIND(snap_check_path);
2672         return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2673                                                base_volume);
2674 }
2675
2676 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2677                                   TALLOC_CTX *mem_ctx,
2678                                   const char *base_volume,
2679                                   time_t *tstamp,
2680                                   bool rw,
2681                                   char **base_path,
2682                                   char **snap_path)
2683 {
2684         VFS_FIND(snap_create);
2685         return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2686                                            rw, base_path, snap_path);
2687 }
2688
2689 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2690                                   TALLOC_CTX *mem_ctx,
2691                                   char *base_path,
2692                                   char *snap_path)
2693 {
2694         VFS_FIND(snap_delete);
2695         return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2696                                            snap_path);
2697 }
2698
2699 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2700                                   struct files_struct *fsp,
2701                                   uint32_t security_info,
2702                                   TALLOC_CTX *mem_ctx,
2703                                   struct security_descriptor **ppdesc)
2704 {
2705         VFS_FIND(fget_nt_acl);
2706         return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2707                                            mem_ctx, ppdesc);
2708 }
2709
2710 NTSTATUS smb_vfs_call_get_nt_acl_at(struct vfs_handle_struct *handle,
2711                         struct files_struct *dirfsp,
2712                         const struct smb_filename *smb_fname,
2713                         uint32_t security_info,
2714                         TALLOC_CTX *mem_ctx,
2715                         struct security_descriptor **ppdesc)
2716 {
2717         VFS_FIND(get_nt_acl_at);
2718         return handle->fns->get_nt_acl_at_fn(handle,
2719                                 dirfsp,
2720                                 smb_fname,
2721                                 security_info,
2722                                 mem_ctx,
2723                                 ppdesc);
2724 }
2725
2726 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2727                                   struct files_struct *fsp,
2728                                   uint32_t security_info_sent,
2729                                   const struct security_descriptor *psd)
2730 {
2731         VFS_FIND(fset_nt_acl);
2732         return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent, 
2733                                            psd);
2734 }
2735
2736 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2737                                  struct smb_filename *file,
2738                                  struct security_acl *sacl,
2739                                  uint32_t access_requested,
2740                                  uint32_t access_denied)
2741 {
2742         VFS_FIND(audit_file);
2743         return handle->fns->audit_file_fn(handle, 
2744                                           file, 
2745                                           sacl, 
2746                                           access_requested, 
2747                                           access_denied);
2748 }
2749
2750 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2751                                         const struct smb_filename *smb_fname,
2752                                         SMB_ACL_TYPE_T type,
2753                                         TALLOC_CTX *mem_ctx)
2754 {
2755         VFS_FIND(sys_acl_get_file);
2756         return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2757 }
2758
2759 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2760                                       struct files_struct *fsp,
2761                                       TALLOC_CTX *mem_ctx)
2762 {
2763         VFS_FIND(sys_acl_get_fd);
2764         return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2765 }
2766
2767 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2768                                 const struct smb_filename *smb_fname,
2769                                 TALLOC_CTX *mem_ctx,
2770                                 char **blob_description,
2771                                 DATA_BLOB *blob)
2772 {
2773         VFS_FIND(sys_acl_blob_get_file);
2774         return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2775                         mem_ctx, blob_description, blob);
2776 }
2777
2778 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2779                                      struct files_struct *fsp,
2780                                      TALLOC_CTX *mem_ctx, 
2781                                      char **blob_description,
2782                                      DATA_BLOB *blob)
2783 {
2784         VFS_FIND(sys_acl_blob_get_fd);
2785         return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2786 }
2787
2788 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2789                                 struct files_struct *fsp,
2790                                 SMB_ACL_TYPE_T type,
2791                                 SMB_ACL_T theacl)
2792 {
2793         VFS_FIND(sys_acl_set_fd);
2794         return handle->fns->sys_acl_set_fd_fn(handle, fsp, type, theacl);
2795 }
2796
2797 int smb_vfs_call_sys_acl_delete_def_fd(struct vfs_handle_struct *handle,
2798                                 struct files_struct *fsp)
2799 {
2800         VFS_FIND(sys_acl_delete_def_fd);
2801         return handle->fns->sys_acl_delete_def_fd_fn(handle, fsp);
2802 }
2803
2804 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2805                                 const struct smb_filename *smb_fname,
2806                                 const char *name,
2807                                 void *value,
2808                                 size_t size)
2809 {
2810         VFS_FIND(getxattr);
2811         return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2812 }
2813
2814
2815 struct smb_vfs_call_getxattrat_state {
2816         files_struct *dir_fsp;
2817         ssize_t (*recv_fn)(struct tevent_req *req,
2818                            struct vfs_aio_state *aio_state,
2819                            TALLOC_CTX *mem_ctx,
2820                            uint8_t **xattr_value);
2821         ssize_t retval;
2822         uint8_t *xattr_value;
2823         struct vfs_aio_state aio_state;
2824 };
2825
2826 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2827
2828 struct tevent_req *smb_vfs_call_getxattrat_send(
2829                         TALLOC_CTX *mem_ctx,
2830                         struct tevent_context *ev,
2831                         struct vfs_handle_struct *handle,
2832                         files_struct *dir_fsp,
2833                         const struct smb_filename *smb_fname,
2834                         const char *xattr_name,
2835                         size_t alloc_hint)
2836 {
2837         struct tevent_req *req = NULL;
2838         struct smb_vfs_call_getxattrat_state *state = NULL;
2839         struct tevent_req *subreq = NULL;
2840
2841         req = tevent_req_create(mem_ctx, &state,
2842                                 struct smb_vfs_call_getxattrat_state);
2843         if (req == NULL) {
2844                 return NULL;
2845         }
2846
2847         VFS_FIND(getxattrat_send);
2848
2849         *state = (struct smb_vfs_call_getxattrat_state) {
2850                 .dir_fsp = dir_fsp,
2851                 .recv_fn = handle->fns->getxattrat_recv_fn,
2852         };
2853
2854         subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2855                                                  ev,
2856                                                  handle,
2857                                                  dir_fsp,
2858                                                  smb_fname,
2859                                                  xattr_name,
2860                                                  alloc_hint);
2861         if (tevent_req_nomem(subreq, req)) {
2862                 return tevent_req_post(req, ev);
2863         }
2864         tevent_req_defer_callback(req, ev);
2865
2866         tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2867         return req;
2868 }
2869
2870 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2871 {
2872         struct tevent_req *req = tevent_req_callback_data(
2873                 subreq, struct tevent_req);
2874         struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2875                 req, struct smb_vfs_call_getxattrat_state);
2876         bool ok;
2877
2878         /*
2879          * Make sure we run as the user again
2880          */
2881         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2882         SMB_ASSERT(ok);
2883
2884         state->retval = state->recv_fn(subreq,
2885                                        &state->aio_state,
2886                                        state,
2887                                        &state->xattr_value);
2888         TALLOC_FREE(subreq);
2889         if (state->retval == -1) {
2890                 tevent_req_error(req, state->aio_state.error);
2891                 return;
2892         }
2893
2894         tevent_req_done(req);
2895 }
2896
2897 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2898                                      struct vfs_aio_state *aio_state,
2899                                      TALLOC_CTX *mem_ctx,
2900                                      uint8_t **xattr_value)
2901 {
2902         struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2903                 req, struct smb_vfs_call_getxattrat_state);
2904         size_t xattr_size;
2905
2906         if (tevent_req_is_unix_error(req, &aio_state->error)) {
2907                 tevent_req_received(req);
2908                 return -1;
2909         }
2910
2911         *aio_state = state->aio_state;
2912         xattr_size = state->retval;
2913         if (xattr_value != NULL) {
2914                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2915         }
2916
2917         tevent_req_received(req);
2918         return xattr_size;
2919 }
2920
2921 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2922                                struct files_struct *fsp, const char *name,
2923                                void *value, size_t size)
2924 {
2925         VFS_FIND(fgetxattr);
2926         return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2927 }
2928
2929 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2930                                 struct files_struct *fsp, char *list,
2931                                 size_t size)
2932 {
2933         VFS_FIND(flistxattr);
2934         return handle->fns->flistxattr_fn(handle, fsp, list, size);
2935 }
2936
2937 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2938                               struct files_struct *fsp, const char *name)
2939 {
2940         VFS_FIND(fremovexattr);
2941         return handle->fns->fremovexattr_fn(handle, fsp, name);
2942 }
2943
2944 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2945                            struct files_struct *fsp, const char *name,
2946                            const void *value, size_t size, int flags)
2947 {
2948         VFS_FIND(fsetxattr);
2949         return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2950 }
2951
2952 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2953                             struct files_struct *fsp)
2954 {
2955         VFS_FIND(aio_force);
2956         return handle->fns->aio_force_fn(handle, fsp);
2957 }
2958
2959 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2960                                      struct files_struct *fsp,
2961                                      TALLOC_CTX *mem_ctx,
2962                                      DATA_BLOB *cookie)
2963 {
2964         VFS_FIND(durable_cookie);
2965         return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2966 }
2967
2968 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2969                                          struct files_struct *fsp,
2970                                          const DATA_BLOB old_cookie,
2971                                          TALLOC_CTX *mem_ctx,
2972                                          DATA_BLOB *new_cookie)
2973 {
2974         VFS_FIND(durable_disconnect);
2975         return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2976                                                   mem_ctx, new_cookie);
2977 }
2978
2979 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2980                                         struct smb_request *smb1req,
2981                                         struct smbXsrv_open *op,
2982                                         const DATA_BLOB old_cookie,
2983                                         TALLOC_CTX *mem_ctx,
2984                                         struct files_struct **fsp,
2985                                         DATA_BLOB *new_cookie)
2986 {
2987         VFS_FIND(durable_reconnect);
2988         return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2989                                                  old_cookie, mem_ctx, fsp,
2990                                                  new_cookie);
2991 }
2992
2993 NTSTATUS smb_vfs_call_freaddir_attr(struct vfs_handle_struct *handle,
2994                                     struct files_struct *fsp,
2995                                     TALLOC_CTX *mem_ctx,
2996                                     struct readdir_attr_data **attr_data)
2997 {
2998         VFS_FIND(freaddir_attr);
2999         return handle->fns->freaddir_attr_fn(handle,
3000                                              fsp,
3001                                              mem_ctx,
3002                                              attr_data);
3003 }