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