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