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