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