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