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