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