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