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