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