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