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