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