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