2 Unix SMB/Netbios implementation.
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
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.
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.
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/>.
23 This work was sponsored by Optifacio Software Services, Inc.
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
31 #include "transfer_file.h"
33 #include "lib/util/tevent_unix.h"
36 #define DBGC_CLASS DBGC_VFS
41 struct vfs_fsp_data
*next
;
42 struct vfs_handle_struct
*owner
;
43 void (*destroy
)(void *p_data
);
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.
50 struct vfs_init_function_entry
{
52 struct vfs_init_function_entry
*prev
, *next
;
53 const struct vfs_fn_pointers
*fns
;
56 /****************************************************************************
57 maintain the list of available backends
58 ****************************************************************************/
60 static struct vfs_init_function_entry
*vfs_find_backend_entry(const char *name
)
62 struct vfs_init_function_entry
*entry
= backends
;
64 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name
));
67 if (strcmp(entry
->name
, name
)==0) return entry
;
74 NTSTATUS
smb_register_vfs(int version
, const char *name
,
75 const struct vfs_fn_pointers
*fns
)
77 struct vfs_init_function_entry
*entry
= backends
;
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
;
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
;
93 if (vfs_find_backend_entry(name
)) {
94 DEBUG(0,("VFS module %s already loaded!\n", name
));
95 return NT_STATUS_OBJECT_NAME_COLLISION
;
98 entry
= SMB_XMALLOC_P(struct vfs_init_function_entry
);
99 entry
->name
= smb_xstrdup(name
);
102 DLIST_ADD(backends
, entry
);
103 DEBUG(5, ("Successfully added vfs backend '%s'\n", name
));
107 /****************************************************************************
108 initialise default vfs hooks
109 ****************************************************************************/
111 static void vfs_init_default(connection_struct
*conn
)
113 DEBUG(3, ("Initialising default vfs hooks\n"));
114 vfs_init_custom(conn
, DEFAULT_VFS_MODULE_NAME
);
117 /****************************************************************************
118 initialise custom vfs hooks
119 ****************************************************************************/
121 bool vfs_init_custom(connection_struct
*conn
, const char *vfs_object
)
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
;
129 if (!conn
||!vfs_object
||!vfs_object
[0]) {
130 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
131 "empty vfs_object!\n"));
139 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object
));
141 module_path
= smb_xstrdup(vfs_object
);
143 p
= strchr_m(module_path
, ':');
148 trim_char(module_param
, ' ', ' ');
151 trim_char(module_path
, ' ', ' ');
153 module_name
= smb_xstrdup(module_path
);
155 if ((module_name
[0] == '/') &&
156 (strcmp(module_path
, DEFAULT_VFS_MODULE_NAME
) != 0)) {
159 * Extract the module name from the path. Just use the base
160 * name of the last path component.
163 SAFE_FREE(module_name
);
164 module_name
= smb_xstrdup(strrchr_m(module_path
, '/')+1);
166 p
= strchr_m(module_name
, '.');
173 /* First, try to load the module with the new module system */
174 entry
= vfs_find_backend_entry(module_name
);
178 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
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
)));
188 entry
= vfs_find_backend_entry(module_name
);
190 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object
));
195 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object
));
197 handle
= talloc_zero(conn
, vfs_handle_struct
);
199 DEBUG(0,("TALLOC_ZERO() failed!\n"));
203 handle
->fns
= entry
->fns
;
205 handle
->param
= talloc_strdup(conn
, module_param
);
207 DLIST_ADD(conn
->vfs_handles
, handle
);
209 SAFE_FREE(module_path
);
210 SAFE_FREE(module_name
);
214 SAFE_FREE(module_path
);
215 SAFE_FREE(module_name
);
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 ******************************************************************/
225 #define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data))
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
))
231 struct vfs_fsp_data
*ext
;
234 /* Prevent VFS modules adding multiple extensions. */
235 if ((ext_data
= vfs_fetch_fsp_extension(handle
, fsp
))) {
239 ext
= (struct vfs_fsp_data
*)TALLOC_ZERO(
240 handle
->conn
, sizeof(struct vfs_fsp_data
) + ext_size
);
246 ext
->next
= fsp
->vfs_extension
;
247 ext
->destroy
= destroy_fn
;
248 fsp
->vfs_extension
= ext
;
249 return EXT_DATA_AREA(ext
);
252 void vfs_remove_fsp_extension(vfs_handle_struct
*handle
, files_struct
*fsp
)
254 struct vfs_fsp_data
*curr
;
255 struct vfs_fsp_data
*prev
;
257 for (curr
= fsp
->vfs_extension
, prev
= NULL
;
259 prev
= curr
, curr
= curr
->next
) {
260 if (curr
->owner
== handle
) {
262 prev
->next
= curr
->next
;
264 fsp
->vfs_extension
= curr
->next
;
267 curr
->destroy(EXT_DATA_AREA(curr
));
275 void vfs_remove_all_fsp_extensions(files_struct
*fsp
)
277 struct vfs_fsp_data
*curr
;
278 struct vfs_fsp_data
*next
;
280 for (curr
= fsp
->vfs_extension
; curr
; curr
= next
) {
283 fsp
->vfs_extension
= next
;
286 curr
->destroy(EXT_DATA_AREA(curr
));
292 void *vfs_memctx_fsp_extension(vfs_handle_struct
*handle
, files_struct
*fsp
)
294 struct vfs_fsp_data
*head
;
296 for (head
= fsp
->vfs_extension
; head
; head
= head
->next
) {
297 if (head
->owner
== handle
) {
305 void *vfs_fetch_fsp_extension(vfs_handle_struct
*handle
, files_struct
*fsp
)
307 struct vfs_fsp_data
*head
;
309 head
= (struct vfs_fsp_data
*)vfs_memctx_fsp_extension(handle
, fsp
);
311 return EXT_DATA_AREA(head
);
319 /*****************************************************************
321 ******************************************************************/
323 bool smbd_vfs_init(connection_struct
*conn
)
325 const char **vfs_objects
;
329 /* Normal share - initialise with disk access functions */
330 vfs_init_default(conn
);
332 /* No need to load vfs modules for printer connections */
337 vfs_objects
= lp_vfs_objects(SNUM(conn
));
339 /* Override VFS functions if 'vfs object' was not specified*/
340 if (!vfs_objects
|| !vfs_objects
[0])
343 for (i
=0; vfs_objects
[i
] ;) {
347 for (j
=i
-1; j
>= 0; j
--) {
348 if (!vfs_init_custom(conn
, vfs_objects
[j
])) {
349 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects
[j
]));
356 /*******************************************************************
357 Check if a file exists in the vfs.
358 ********************************************************************/
360 NTSTATUS
vfs_file_exist(connection_struct
*conn
, struct smb_filename
*smb_fname
)
362 /* Only return OK if stat was successful and S_ISREG */
363 if ((SMB_VFS_STAT(conn
, smb_fname
) != -1) &&
364 S_ISREG(smb_fname
->st
.st_ex_mode
)) {
368 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
371 /****************************************************************************
372 Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
373 ****************************************************************************/
375 ssize_t
vfs_read_data(files_struct
*fsp
, char *buf
, size_t byte_count
)
379 while (total
< byte_count
)
381 ssize_t ret
= SMB_VFS_READ(fsp
, buf
+ total
,
384 if (ret
== 0) return total
;
393 return (ssize_t
)total
;
396 ssize_t
vfs_pread_data(files_struct
*fsp
, char *buf
,
397 size_t byte_count
, off_t offset
)
401 while (total
< byte_count
)
403 ssize_t ret
= SMB_VFS_PREAD(fsp
, buf
+ total
,
404 byte_count
- total
, offset
+ total
);
406 if (ret
== 0) return total
;
415 return (ssize_t
)total
;
418 /****************************************************************************
419 Write data to a fd on the vfs.
420 ****************************************************************************/
422 ssize_t
vfs_write_data(struct smb_request
*req
,
430 if (req
&& req
->unread_bytes
) {
431 int sockfd
= req
->sconn
->sock
;
433 SMB_ASSERT(req
->unread_bytes
== N
);
434 /* VFS_RECVFILE must drain the socket
435 * before returning. */
436 req
->unread_bytes
= 0;
437 /* Ensure the socket is blocking. */
438 old_flags
= fcntl(sockfd
, F_GETFL
, 0);
439 if (set_blocking(sockfd
, true) == -1) {
442 ret
= SMB_VFS_RECVFILE(sockfd
,
446 if (fcntl(sockfd
, F_SETFL
, old_flags
) == -1) {
453 ret
= SMB_VFS_WRITE(fsp
, buffer
+ total
, N
- total
);
462 return (ssize_t
)total
;
465 ssize_t
vfs_pwrite_data(struct smb_request
*req
,
474 if (req
&& req
->unread_bytes
) {
475 int sockfd
= req
->sconn
->sock
;
477 SMB_ASSERT(req
->unread_bytes
== N
);
478 /* VFS_RECVFILE must drain the socket
479 * before returning. */
480 req
->unread_bytes
= 0;
481 /* Ensure the socket is blocking. */
482 old_flags
= fcntl(sockfd
, F_GETFL
, 0);
483 if (set_blocking(sockfd
, true) == -1) {
486 ret
= SMB_VFS_RECVFILE(sockfd
,
490 if (fcntl(sockfd
, F_SETFL
, old_flags
) == -1) {
497 ret
= SMB_VFS_PWRITE(fsp
, buffer
+ total
, N
- total
,
507 return (ssize_t
)total
;
509 /****************************************************************************
510 An allocate file space call using the vfs interface.
511 Allocates space for a file from a filedescriptor.
512 Returns 0 on success, -1 on failure.
513 ****************************************************************************/
515 int vfs_allocate_file_space(files_struct
*fsp
, uint64_t len
)
518 connection_struct
*conn
= fsp
->conn
;
519 uint64_t space_avail
;
520 uint64_t bsize
,dfree
,dsize
;
524 * Actually try and commit the space on disk....
527 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
528 fsp_str_dbg(fsp
), (double)len
));
530 if (((off_t
)len
) < 0) {
531 DEBUG(0,("vfs_allocate_file_space: %s negative len "
532 "requested.\n", fsp_str_dbg(fsp
)));
537 status
= vfs_stat_fsp(fsp
);
538 if (!NT_STATUS_IS_OK(status
)) {
542 if (len
== (uint64_t)fsp
->fsp_name
->st
.st_ex_size
)
545 if (len
< (uint64_t)fsp
->fsp_name
->st
.st_ex_size
) {
546 /* Shrink - use ftruncate. */
548 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
549 "size %.0f\n", fsp_str_dbg(fsp
),
550 (double)fsp
->fsp_name
->st
.st_ex_size
));
552 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_ALLOC_SHRINK
);
554 flush_write_cache(fsp
, SIZECHANGE_FLUSH
);
555 if ((ret
= SMB_VFS_FTRUNCATE(fsp
, (off_t
)len
)) != -1) {
556 set_filelen_write_cache(fsp
, len
);
559 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_ALLOC_SHRINK
);
564 if (!lp_strict_allocate(SNUM(fsp
->conn
)))
567 /* Grow - we need to test if we have enough space. */
569 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_ALLOC_GROW
);
571 /* See if we have a syscall that will allocate beyond end-of-file
572 without changing EOF. */
573 ret
= SMB_VFS_FALLOCATE(fsp
, VFS_FALLOCATE_KEEP_SIZE
, 0, len
);
575 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_ALLOC_GROW
);
578 /* We changed the allocation size on disk, but not
579 EOF - exactly as required. We're done ! */
583 len
-= fsp
->fsp_name
->st
.st_ex_size
;
584 len
/= 1024; /* Len is now number of 1k blocks needed. */
585 space_avail
= get_dfree_info(conn
, fsp
->fsp_name
->base_name
, false,
586 &bsize
, &dfree
, &dsize
);
587 if (space_avail
== (uint64_t)-1) {
591 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
592 "needed blocks = %.0f, space avail = %.0f\n",
593 fsp_str_dbg(fsp
), (double)fsp
->fsp_name
->st
.st_ex_size
, (double)len
,
594 (double)space_avail
));
596 if (len
> space_avail
) {
604 /****************************************************************************
605 A vfs set_filelen call.
606 set the length of a file from a filedescriptor.
607 Returns 0 on success, -1 on failure.
608 ****************************************************************************/
610 int vfs_set_filelen(files_struct
*fsp
, off_t len
)
614 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_SET_FILE_LEN
);
616 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
617 fsp_str_dbg(fsp
), (double)len
));
618 flush_write_cache(fsp
, SIZECHANGE_FLUSH
);
619 if ((ret
= SMB_VFS_FTRUNCATE(fsp
, len
)) != -1) {
620 set_filelen_write_cache(fsp
, len
);
621 notify_fname(fsp
->conn
, NOTIFY_ACTION_MODIFIED
,
622 FILE_NOTIFY_CHANGE_SIZE
623 | FILE_NOTIFY_CHANGE_ATTRIBUTES
,
624 fsp
->fsp_name
->base_name
);
627 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_SET_FILE_LEN
);
632 /****************************************************************************
633 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
634 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
635 as this is also called from the default SMB_VFS_FTRUNCATE code.
636 Always extends the file size.
637 Returns 0 on success, errno on failure.
638 ****************************************************************************/
640 #define SPARSE_BUF_WRITE_SIZE (32*1024)
642 int vfs_slow_fallocate(files_struct
*fsp
, off_t offset
, off_t len
)
648 sparse_buf
= SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE
);
655 while (total
< len
) {
656 size_t curr_write_size
= MIN(SPARSE_BUF_WRITE_SIZE
, (len
- total
));
658 pwrite_ret
= SMB_VFS_PWRITE(fsp
, sparse_buf
, curr_write_size
, offset
+ total
);
659 if (pwrite_ret
== -1) {
660 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
661 "%s failed with error %s\n",
662 fsp_str_dbg(fsp
), strerror(errno
)));
671 /****************************************************************************
672 A vfs fill sparse call.
673 Writes zeros from the end of file to len, if len is greater than EOF.
674 Used only by strict_sync.
675 Returns 0 on success, -1 on failure.
676 ****************************************************************************/
678 int vfs_fill_sparse(files_struct
*fsp
, off_t len
)
685 status
= vfs_stat_fsp(fsp
);
686 if (!NT_STATUS_IS_OK(status
)) {
690 if (len
<= fsp
->fsp_name
->st
.st_ex_size
) {
695 if (S_ISFIFO(fsp
->fsp_name
->st
.st_ex_mode
)) {
700 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
701 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp
),
702 (double)fsp
->fsp_name
->st
.st_ex_size
, (double)len
,
703 (double)(len
- fsp
->fsp_name
->st
.st_ex_size
)));
705 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_FILL_SPARSE
);
707 flush_write_cache(fsp
, SIZECHANGE_FLUSH
);
709 offset
= fsp
->fsp_name
->st
.st_ex_size
;
710 num_to_write
= len
- fsp
->fsp_name
->st
.st_ex_size
;
712 /* Only do this on non-stream file handles. */
713 if (fsp
->base_fsp
== NULL
) {
714 /* for allocation try fallocate first. This can fail on some
715 * platforms e.g. when the filesystem doesn't support it and no
716 * emulation is being done by the libc (like on AIX with JFS1). In that
717 * case we do our own emulation. fallocate implementations can
718 * return ENOTSUP or EINVAL in cases like that. */
719 ret
= SMB_VFS_FALLOCATE(fsp
, VFS_FALLOCATE_EXTEND_SIZE
,
720 offset
, num_to_write
);
729 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
730 "error %d. Falling back to slow manual allocation\n", ret
));
733 ret
= vfs_slow_fallocate(fsp
, offset
, num_to_write
);
742 set_filelen_write_cache(fsp
, len
);
745 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_FILL_SPARSE
);
749 /****************************************************************************
750 Transfer some data (n bytes) between two file_struct's.
751 ****************************************************************************/
753 static ssize_t
vfs_read_fn(void *file
, void *buf
, size_t len
)
755 struct files_struct
*fsp
= (struct files_struct
*)file
;
757 return SMB_VFS_READ(fsp
, buf
, len
);
760 static ssize_t
vfs_write_fn(void *file
, const void *buf
, size_t len
)
762 struct files_struct
*fsp
= (struct files_struct
*)file
;
764 return SMB_VFS_WRITE(fsp
, buf
, len
);
767 off_t
vfs_transfer_file(files_struct
*in
, files_struct
*out
, off_t n
)
769 return transfer_file_internal((void *)in
, (void *)out
, n
,
770 vfs_read_fn
, vfs_write_fn
);
773 /*******************************************************************
774 A vfs_readdir wrapper which just returns the file name.
775 ********************************************************************/
777 const char *vfs_readdirname(connection_struct
*conn
, void *p
,
778 SMB_STRUCT_STAT
*sbuf
, char **talloced
)
780 struct dirent
*ptr
= NULL
;
788 ptr
= SMB_VFS_READDIR(conn
, (DIR *)p
, sbuf
);
800 #ifdef HAVE_BROKEN_READDIR_NAME
801 /* using /usr/ucb/cc is BAD */
805 status
= SMB_VFS_TRANSLATE_NAME(conn
, dname
, vfs_translate_to_windows
,
806 talloc_tos(), &translated
);
807 if (NT_STATUS_EQUAL(status
, NT_STATUS_NONE_MAPPED
)) {
811 *talloced
= translated
;
812 if (!NT_STATUS_IS_OK(status
)) {
818 /*******************************************************************
819 A wrapper for vfs_chdir().
820 ********************************************************************/
822 int vfs_ChDir(connection_struct
*conn
, const char *path
)
827 LastDir
= SMB_STRDUP("");
830 if (strcsequal(path
,".")) {
834 if (*path
== '/' && strcsequal(LastDir
,path
)) {
838 DEBUG(4,("vfs_ChDir to %s\n",path
));
840 ret
= SMB_VFS_CHDIR(conn
,path
);
844 LastDir
= SMB_STRDUP(path
);
847 TALLOC_FREE(conn
->cwd
);
848 conn
->cwd
= vfs_GetWd(conn
, conn
);
849 DEBUG(4,("vfs_ChDir got %s\n",conn
->cwd
));
854 /*******************************************************************
855 Return the absolute current directory path - given a UNIX pathname.
856 Note that this path is returned in DOS format, not UNIX
857 format. Note this can be called with conn == NULL.
858 ********************************************************************/
860 char *vfs_GetWd(TALLOC_CTX
*ctx
, connection_struct
*conn
)
862 char *current_dir
= NULL
;
864 DATA_BLOB cache_value
;
866 struct smb_filename
*smb_fname_dot
= NULL
;
867 struct smb_filename
*smb_fname_full
= NULL
;
869 if (!lp_getwd_cache()) {
873 smb_fname_dot
= synthetic_smb_fname(ctx
, ".", NULL
, NULL
);
874 if (smb_fname_dot
== NULL
) {
879 if (SMB_VFS_STAT(conn
, smb_fname_dot
) == -1) {
881 * Known to fail for root: the directory may be NFS-mounted
882 * and exported with root_squash (so has no root access).
884 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
885 "(NFS problem ?)\n", strerror(errno
) ));
889 key
= vfs_file_id_from_sbuf(conn
, &smb_fname_dot
->st
);
891 if (!memcache_lookup(smbd_memcache(), GETWD_CACHE
,
892 data_blob_const(&key
, sizeof(key
)),
897 SMB_ASSERT((cache_value
.length
> 0)
898 && (cache_value
.data
[cache_value
.length
-1] == '\0'));
900 smb_fname_full
= synthetic_smb_fname(ctx
, (char *)cache_value
.data
,
902 if (smb_fname_full
== NULL
) {
907 if ((SMB_VFS_STAT(conn
, smb_fname_full
) == 0) &&
908 (smb_fname_dot
->st
.st_ex_dev
== smb_fname_full
->st
.st_ex_dev
) &&
909 (smb_fname_dot
->st
.st_ex_ino
== smb_fname_full
->st
.st_ex_ino
) &&
910 (S_ISDIR(smb_fname_dot
->st
.st_ex_mode
))) {
914 result
= talloc_strdup(ctx
, smb_fname_full
->base_name
);
915 if (result
== NULL
) {
924 * We don't have the information to hand so rely on traditional
925 * methods. The very slow getcwd, which spawns a process on some
926 * systems, or the not quite so bad getwd.
929 current_dir
= SMB_VFS_GETWD(conn
);
930 if (current_dir
== NULL
) {
931 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
936 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot
->st
)) {
937 key
= vfs_file_id_from_sbuf(conn
, &smb_fname_dot
->st
);
939 memcache_add(smbd_memcache(), GETWD_CACHE
,
940 data_blob_const(&key
, sizeof(key
)),
941 data_blob_const(current_dir
,
942 strlen(current_dir
)+1));
945 result
= talloc_strdup(ctx
, current_dir
);
946 if (result
== NULL
) {
951 TALLOC_FREE(smb_fname_dot
);
952 TALLOC_FREE(smb_fname_full
);
953 SAFE_FREE(current_dir
);
957 /*******************************************************************
958 Reduce a file name, removing .. elements and checking that
959 it is below dir in the heirachy. This uses realpath.
960 This function must run as root, and will return names
961 and valid stat structs that can be checked on open.
962 ********************************************************************/
964 NTSTATUS
check_reduced_name_with_privilege(connection_struct
*conn
,
966 struct smb_request
*smbreq
)
969 TALLOC_CTX
*ctx
= talloc_tos();
970 const char *conn_rootdir
;
972 char *dir_name
= NULL
;
973 const char *last_component
= NULL
;
974 char *resolved_name
= NULL
;
975 char *saved_dir
= NULL
;
976 struct smb_filename
*smb_fname_cwd
= NULL
;
977 struct privilege_paths
*priv_paths
= NULL
;
980 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
985 priv_paths
= talloc_zero(smbreq
, struct privilege_paths
);
987 status
= NT_STATUS_NO_MEMORY
;
991 if (!parent_dirname(ctx
, fname
, &dir_name
, &last_component
)) {
992 status
= NT_STATUS_NO_MEMORY
;
996 priv_paths
->parent_name
.base_name
= talloc_strdup(priv_paths
, dir_name
);
997 priv_paths
->file_name
.base_name
= talloc_strdup(priv_paths
, last_component
);
999 if (priv_paths
->parent_name
.base_name
== NULL
||
1000 priv_paths
->file_name
.base_name
== NULL
) {
1001 status
= NT_STATUS_NO_MEMORY
;
1005 if (SMB_VFS_STAT(conn
, &priv_paths
->parent_name
) != 0) {
1006 status
= map_nt_error_from_unix(errno
);
1009 /* Remember where we were. */
1010 saved_dir
= vfs_GetWd(ctx
, conn
);
1012 status
= map_nt_error_from_unix(errno
);
1016 /* Go to the parent directory to lock in memory. */
1017 if (vfs_ChDir(conn
, priv_paths
->parent_name
.base_name
) == -1) {
1018 status
= map_nt_error_from_unix(errno
);
1022 /* Get the absolute path of the parent directory. */
1023 resolved_name
= SMB_VFS_REALPATH(conn
,".");
1024 if (!resolved_name
) {
1025 status
= map_nt_error_from_unix(errno
);
1029 if (*resolved_name
!= '/') {
1030 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1031 "doesn't return absolute paths !\n"));
1032 status
= NT_STATUS_OBJECT_NAME_INVALID
;
1036 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1037 priv_paths
->parent_name
.base_name
,
1040 /* Now check the stat value is the same. */
1041 smb_fname_cwd
= synthetic_smb_fname(talloc_tos(), ".", NULL
, NULL
);
1042 if (smb_fname_cwd
== NULL
) {
1043 status
= NT_STATUS_NO_MEMORY
;
1047 if (SMB_VFS_LSTAT(conn
, smb_fname_cwd
) != 0) {
1048 status
= map_nt_error_from_unix(errno
);
1052 /* Ensure we're pointing at the same place. */
1053 if (!check_same_stat(&smb_fname_cwd
->st
, &priv_paths
->parent_name
.st
)) {
1054 DEBUG(0,("check_reduced_name_with_privilege: "
1055 "device/inode/uid/gid on directory %s changed. "
1056 "Denying access !\n",
1057 priv_paths
->parent_name
.base_name
));
1058 status
= NT_STATUS_ACCESS_DENIED
;
1062 /* Ensure we're below the connect path. */
1064 conn_rootdir
= SMB_VFS_CONNECTPATH(conn
, fname
);
1065 if (conn_rootdir
== NULL
) {
1066 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1068 status
= NT_STATUS_ACCESS_DENIED
;
1072 rootdir_len
= strlen(conn_rootdir
);
1073 if (strncmp(conn_rootdir
, resolved_name
, rootdir_len
) != 0) {
1074 DEBUG(2, ("check_reduced_name_with_privilege: Bad access "
1075 "attempt: %s is a symlink outside the "
1078 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir
));
1079 DEBUGADD(2, ("resolved_name=%s\n", resolved_name
));
1080 status
= NT_STATUS_ACCESS_DENIED
;
1084 /* Now ensure that the last component either doesn't
1085 exist, or is *NOT* a symlink. */
1087 ret
= SMB_VFS_LSTAT(conn
, &priv_paths
->file_name
);
1089 /* Errno must be ENOENT for this be ok. */
1090 if (errno
!= ENOENT
) {
1091 status
= map_nt_error_from_unix(errno
);
1092 DEBUG(2, ("check_reduced_name_with_privilege: "
1093 "LSTAT on %s failed with %s\n",
1094 priv_paths
->file_name
.base_name
,
1095 nt_errstr(status
)));
1100 if (VALID_STAT(priv_paths
->file_name
.st
) &&
1101 S_ISLNK(priv_paths
->file_name
.st
.st_ex_mode
)) {
1102 DEBUG(2, ("check_reduced_name_with_privilege: "
1103 "Last component %s is a symlink. Denying"
1105 priv_paths
->file_name
.base_name
));
1106 status
= NT_STATUS_ACCESS_DENIED
;
1110 smbreq
->priv_paths
= priv_paths
;
1111 status
= NT_STATUS_OK
;
1116 vfs_ChDir(conn
, saved_dir
);
1118 SAFE_FREE(resolved_name
);
1119 if (!NT_STATUS_IS_OK(status
)) {
1120 TALLOC_FREE(priv_paths
);
1122 TALLOC_FREE(dir_name
);
1126 /*******************************************************************
1127 Reduce a file name, removing .. elements and checking that
1128 it is below dir in the heirachy. This uses realpath.
1129 ********************************************************************/
1131 NTSTATUS
check_reduced_name(connection_struct
*conn
, const char *fname
)
1133 char *resolved_name
= NULL
;
1134 bool allow_symlinks
= true;
1135 bool allow_widelinks
= false;
1137 DEBUG(3,("check_reduced_name [%s] [%s]\n", fname
, conn
->connectpath
));
1139 resolved_name
= SMB_VFS_REALPATH(conn
,fname
);
1141 if (!resolved_name
) {
1144 DEBUG(3,("check_reduced_name: Component not a "
1145 "directory in getting realpath for "
1147 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1150 TALLOC_CTX
*ctx
= talloc_tos();
1151 char *dir_name
= NULL
;
1152 const char *last_component
= NULL
;
1153 char *new_name
= NULL
;
1156 /* Last component didn't exist.
1157 Remove it and try and canonicalise
1158 the directory name. */
1159 if (!parent_dirname(ctx
, fname
,
1162 return NT_STATUS_NO_MEMORY
;
1165 resolved_name
= SMB_VFS_REALPATH(conn
,dir_name
);
1166 if (!resolved_name
) {
1167 NTSTATUS status
= map_nt_error_from_unix(errno
);
1169 if (errno
== ENOENT
|| errno
== ENOTDIR
) {
1170 status
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
1173 DEBUG(3,("check_reduce_name: "
1174 "couldn't get realpath for "
1177 nt_errstr(status
)));
1180 ret
= asprintf(&new_name
, "%s/%s",
1181 resolved_name
, last_component
);
1182 SAFE_FREE(resolved_name
);
1184 return NT_STATUS_NO_MEMORY
;
1186 resolved_name
= new_name
;
1190 DEBUG(3,("check_reduced_name: couldn't get "
1191 "realpath for %s\n", fname
));
1192 return map_nt_error_from_unix(errno
);
1196 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname
,
1199 if (*resolved_name
!= '/') {
1200 DEBUG(0,("check_reduced_name: realpath doesn't return "
1201 "absolute paths !\n"));
1202 SAFE_FREE(resolved_name
);
1203 return NT_STATUS_OBJECT_NAME_INVALID
;
1206 allow_widelinks
= lp_widelinks(SNUM(conn
));
1207 allow_symlinks
= lp_symlinks(SNUM(conn
));
1209 /* Common widelinks and symlinks checks. */
1210 if (!allow_widelinks
|| !allow_symlinks
) {
1211 const char *conn_rootdir
;
1214 conn_rootdir
= SMB_VFS_CONNECTPATH(conn
, fname
);
1215 if (conn_rootdir
== NULL
) {
1216 DEBUG(2, ("check_reduced_name: Could not get "
1218 SAFE_FREE(resolved_name
);
1219 return NT_STATUS_ACCESS_DENIED
;
1222 rootdir_len
= strlen(conn_rootdir
);
1223 if (strncmp(conn_rootdir
, resolved_name
,
1224 rootdir_len
) != 0) {
1225 DEBUG(2, ("check_reduced_name: Bad access "
1226 "attempt: %s is a symlink outside the "
1227 "share path\n", fname
));
1228 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir
));
1229 DEBUGADD(2, ("resolved_name=%s\n", resolved_name
));
1230 SAFE_FREE(resolved_name
);
1231 return NT_STATUS_ACCESS_DENIED
;
1234 /* Extra checks if all symlinks are disallowed. */
1235 if (!allow_symlinks
) {
1236 /* fname can't have changed in resolved_path. */
1237 const char *p
= &resolved_name
[rootdir_len
];
1239 /* *p can be '\0' if fname was "." */
1240 if (*p
== '\0' && ISDOT(fname
)) {
1245 DEBUG(2, ("check_reduced_name: logic error (%c) "
1246 "in resolved_name: %s\n",
1249 SAFE_FREE(resolved_name
);
1250 return NT_STATUS_ACCESS_DENIED
;
1254 if (strcmp(fname
, p
)!=0) {
1255 DEBUG(2, ("check_reduced_name: Bad access "
1256 "attempt: %s is a symlink to %s\n",
1258 SAFE_FREE(resolved_name
);
1259 return NT_STATUS_ACCESS_DENIED
;
1266 DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname
,
1268 SAFE_FREE(resolved_name
);
1269 return NT_STATUS_OK
;
1273 * XXX: This is temporary and there should be no callers of this once
1274 * smb_filename is plumbed through all path based operations.
1276 int vfs_stat_smb_fname(struct connection_struct
*conn
, const char *fname
,
1277 SMB_STRUCT_STAT
*psbuf
)
1279 struct smb_filename
*smb_fname
;
1282 smb_fname
= synthetic_smb_fname_split(talloc_tos(), fname
, NULL
);
1283 if (smb_fname
== NULL
) {
1288 if (lp_posix_pathnames()) {
1289 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
1291 ret
= SMB_VFS_STAT(conn
, smb_fname
);
1295 *psbuf
= smb_fname
->st
;
1298 TALLOC_FREE(smb_fname
);
1303 * XXX: This is temporary and there should be no callers of this once
1304 * smb_filename is plumbed through all path based operations.
1306 int vfs_lstat_smb_fname(struct connection_struct
*conn
, const char *fname
,
1307 SMB_STRUCT_STAT
*psbuf
)
1309 struct smb_filename
*smb_fname
;
1312 smb_fname
= synthetic_smb_fname_split(talloc_tos(), fname
, NULL
);
1313 if (smb_fname
== NULL
) {
1318 ret
= SMB_VFS_LSTAT(conn
, smb_fname
);
1320 *psbuf
= smb_fname
->st
;
1323 TALLOC_FREE(smb_fname
);
1328 * Ensure LSTAT is called for POSIX paths.
1331 NTSTATUS
vfs_stat_fsp(files_struct
*fsp
)
1335 if(fsp
->fh
->fd
== -1) {
1336 if (fsp
->posix_open
) {
1337 ret
= SMB_VFS_LSTAT(fsp
->conn
, fsp
->fsp_name
);
1339 ret
= SMB_VFS_STAT(fsp
->conn
, fsp
->fsp_name
);
1342 return map_nt_error_from_unix(errno
);
1345 if(SMB_VFS_FSTAT(fsp
, &fsp
->fsp_name
->st
) != 0) {
1346 return map_nt_error_from_unix(errno
);
1349 return NT_STATUS_OK
;
1353 * Initialize num_streams and streams, then call VFS op streaminfo
1355 NTSTATUS
vfs_streaminfo(connection_struct
*conn
,
1356 struct files_struct
*fsp
,
1358 TALLOC_CTX
*mem_ctx
,
1359 unsigned int *num_streams
,
1360 struct stream_struct
**streams
)
1364 return SMB_VFS_STREAMINFO(conn
, fsp
, fname
, mem_ctx
, num_streams
, streams
);
1368 generate a file_id from a stat structure
1370 struct file_id
vfs_file_id_from_sbuf(connection_struct
*conn
, const SMB_STRUCT_STAT
*sbuf
)
1372 return SMB_VFS_FILE_ID_CREATE(conn
, sbuf
);
1375 int smb_vfs_call_connect(struct vfs_handle_struct
*handle
,
1376 const char *service
, const char *user
)
1379 return handle
->fns
->connect_fn(handle
, service
, user
);
1382 void smb_vfs_call_disconnect(struct vfs_handle_struct
*handle
)
1384 VFS_FIND(disconnect
);
1385 handle
->fns
->disconnect_fn(handle
);
1388 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct
*handle
,
1389 const char *path
, bool small_query
,
1390 uint64_t *bsize
, uint64_t *dfree
,
1393 VFS_FIND(disk_free
);
1394 return handle
->fns
->disk_free_fn(handle
, path
, small_query
, bsize
,
1398 int smb_vfs_call_get_quota(struct vfs_handle_struct
*handle
,
1399 enum SMB_QUOTA_TYPE qtype
, unid_t id
,
1402 VFS_FIND(get_quota
);
1403 return handle
->fns
->get_quota_fn(handle
, qtype
, id
, qt
);
1406 int smb_vfs_call_set_quota(struct vfs_handle_struct
*handle
,
1407 enum SMB_QUOTA_TYPE qtype
, unid_t id
,
1410 VFS_FIND(set_quota
);
1411 return handle
->fns
->set_quota_fn(handle
, qtype
, id
, qt
);
1414 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct
*handle
,
1415 struct files_struct
*fsp
,
1416 struct shadow_copy_data
*shadow_copy_data
,
1419 VFS_FIND(get_shadow_copy_data
);
1420 return handle
->fns
->get_shadow_copy_data_fn(handle
, fsp
,
1424 int smb_vfs_call_statvfs(struct vfs_handle_struct
*handle
, const char *path
,
1425 struct vfs_statvfs_struct
*statbuf
)
1428 return handle
->fns
->statvfs_fn(handle
, path
, statbuf
);
1431 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct
*handle
,
1432 enum timestamp_set_resolution
*p_ts_res
)
1434 VFS_FIND(fs_capabilities
);
1435 return handle
->fns
->fs_capabilities_fn(handle
, p_ts_res
);
1438 NTSTATUS
smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct
*handle
,
1439 struct dfs_GetDFSReferral
*r
)
1441 VFS_FIND(get_dfs_referrals
);
1442 return handle
->fns
->get_dfs_referrals_fn(handle
, r
);
1445 DIR *smb_vfs_call_opendir(struct vfs_handle_struct
*handle
,
1446 const char *fname
, const char *mask
,
1450 return handle
->fns
->opendir_fn(handle
, fname
, mask
, attributes
);
1453 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct
*handle
,
1454 struct files_struct
*fsp
,
1458 VFS_FIND(fdopendir
);
1459 return handle
->fns
->fdopendir_fn(handle
, fsp
, mask
, attributes
);
1462 struct dirent
*smb_vfs_call_readdir(struct vfs_handle_struct
*handle
,
1464 SMB_STRUCT_STAT
*sbuf
)
1467 return handle
->fns
->readdir_fn(handle
, dirp
, sbuf
);
1470 void smb_vfs_call_seekdir(struct vfs_handle_struct
*handle
,
1471 DIR *dirp
, long offset
)
1474 handle
->fns
->seekdir_fn(handle
, dirp
, offset
);
1477 long smb_vfs_call_telldir(struct vfs_handle_struct
*handle
,
1481 return handle
->fns
->telldir_fn(handle
, dirp
);
1484 void smb_vfs_call_rewind_dir(struct vfs_handle_struct
*handle
,
1487 VFS_FIND(rewind_dir
);
1488 handle
->fns
->rewind_dir_fn(handle
, dirp
);
1491 int smb_vfs_call_mkdir(struct vfs_handle_struct
*handle
, const char *path
,
1495 return handle
->fns
->mkdir_fn(handle
, path
, mode
);
1498 int smb_vfs_call_rmdir(struct vfs_handle_struct
*handle
, const char *path
)
1501 return handle
->fns
->rmdir_fn(handle
, path
);
1504 int smb_vfs_call_closedir(struct vfs_handle_struct
*handle
,
1508 return handle
->fns
->closedir_fn(handle
, dir
);
1511 void smb_vfs_call_init_search_op(struct vfs_handle_struct
*handle
,
1514 VFS_FIND(init_search_op
);
1515 handle
->fns
->init_search_op_fn(handle
, dirp
);
1518 int smb_vfs_call_open(struct vfs_handle_struct
*handle
,
1519 struct smb_filename
*smb_fname
, struct files_struct
*fsp
,
1520 int flags
, mode_t mode
)
1523 return handle
->fns
->open_fn(handle
, smb_fname
, fsp
, flags
, mode
);
1526 NTSTATUS
smb_vfs_call_create_file(struct vfs_handle_struct
*handle
,
1527 struct smb_request
*req
,
1528 uint16_t root_dir_fid
,
1529 struct smb_filename
*smb_fname
,
1530 uint32_t access_mask
,
1531 uint32_t share_access
,
1532 uint32_t create_disposition
,
1533 uint32_t create_options
,
1534 uint32_t file_attributes
,
1535 uint32_t oplock_request
,
1536 uint64_t allocation_size
,
1537 uint32_t private_flags
,
1538 struct security_descriptor
*sd
,
1539 struct ea_list
*ea_list
,
1540 files_struct
**result
,
1543 VFS_FIND(create_file
);
1544 return handle
->fns
->create_file_fn(
1545 handle
, req
, root_dir_fid
, smb_fname
, access_mask
,
1546 share_access
, create_disposition
, create_options
,
1547 file_attributes
, oplock_request
, allocation_size
,
1548 private_flags
, sd
, ea_list
,
1552 int smb_vfs_call_close(struct vfs_handle_struct
*handle
,
1553 struct files_struct
*fsp
)
1556 return handle
->fns
->close_fn(handle
, fsp
);
1559 ssize_t
smb_vfs_call_read(struct vfs_handle_struct
*handle
,
1560 struct files_struct
*fsp
, void *data
, size_t n
)
1563 return handle
->fns
->read_fn(handle
, fsp
, data
, n
);
1566 ssize_t
smb_vfs_call_pread(struct vfs_handle_struct
*handle
,
1567 struct files_struct
*fsp
, void *data
, size_t n
,
1571 return handle
->fns
->pread_fn(handle
, fsp
, data
, n
, offset
);
1574 struct smb_vfs_call_pread_state
{
1575 ssize_t (*recv_fn
)(struct tevent_req
*req
, int *err
);
1579 static void smb_vfs_call_pread_done(struct tevent_req
*subreq
);
1581 struct tevent_req
*smb_vfs_call_pread_send(struct vfs_handle_struct
*handle
,
1582 TALLOC_CTX
*mem_ctx
,
1583 struct tevent_context
*ev
,
1584 struct files_struct
*fsp
,
1586 size_t n
, off_t offset
)
1588 struct tevent_req
*req
, *subreq
;
1589 struct smb_vfs_call_pread_state
*state
;
1591 req
= tevent_req_create(mem_ctx
, &state
,
1592 struct smb_vfs_call_pread_state
);
1596 VFS_FIND(pread_send
);
1597 state
->recv_fn
= handle
->fns
->pread_recv_fn
;
1599 subreq
= handle
->fns
->pread_send_fn(handle
, state
, ev
, fsp
, data
, n
,
1601 if (tevent_req_nomem(subreq
, req
)) {
1602 return tevent_req_post(req
, ev
);
1604 tevent_req_set_callback(subreq
, smb_vfs_call_pread_done
, req
);
1608 static void smb_vfs_call_pread_done(struct tevent_req
*subreq
)
1610 struct tevent_req
*req
= tevent_req_callback_data(
1611 subreq
, struct tevent_req
);
1612 struct smb_vfs_call_pread_state
*state
= tevent_req_data(
1613 req
, struct smb_vfs_call_pread_state
);
1616 state
->retval
= state
->recv_fn(subreq
, &err
);
1617 TALLOC_FREE(subreq
);
1618 if (state
->retval
== -1) {
1619 tevent_req_error(req
, err
);
1622 tevent_req_done(req
);
1625 ssize_t
SMB_VFS_PREAD_RECV(struct tevent_req
*req
, int *perrno
)
1627 struct smb_vfs_call_pread_state
*state
= tevent_req_data(
1628 req
, struct smb_vfs_call_pread_state
);
1631 if (tevent_req_is_unix_error(req
, &err
)) {
1635 return state
->retval
;
1638 ssize_t
smb_vfs_call_write(struct vfs_handle_struct
*handle
,
1639 struct files_struct
*fsp
, const void *data
,
1643 return handle
->fns
->write_fn(handle
, fsp
, data
, n
);
1646 ssize_t
smb_vfs_call_pwrite(struct vfs_handle_struct
*handle
,
1647 struct files_struct
*fsp
, const void *data
,
1648 size_t n
, off_t offset
)
1651 return handle
->fns
->pwrite_fn(handle
, fsp
, data
, n
, offset
);
1654 struct smb_vfs_call_pwrite_state
{
1655 ssize_t (*recv_fn
)(struct tevent_req
*req
, int *err
);
1659 static void smb_vfs_call_pwrite_done(struct tevent_req
*subreq
);
1661 struct tevent_req
*smb_vfs_call_pwrite_send(struct vfs_handle_struct
*handle
,
1662 TALLOC_CTX
*mem_ctx
,
1663 struct tevent_context
*ev
,
1664 struct files_struct
*fsp
,
1666 size_t n
, off_t offset
)
1668 struct tevent_req
*req
, *subreq
;
1669 struct smb_vfs_call_pwrite_state
*state
;
1671 req
= tevent_req_create(mem_ctx
, &state
,
1672 struct smb_vfs_call_pwrite_state
);
1676 VFS_FIND(pwrite_send
);
1677 state
->recv_fn
= handle
->fns
->pwrite_recv_fn
;
1679 subreq
= handle
->fns
->pwrite_send_fn(handle
, state
, ev
, fsp
, data
, n
,
1681 if (tevent_req_nomem(subreq
, req
)) {
1682 return tevent_req_post(req
, ev
);
1684 tevent_req_set_callback(subreq
, smb_vfs_call_pwrite_done
, req
);
1688 static void smb_vfs_call_pwrite_done(struct tevent_req
*subreq
)
1690 struct tevent_req
*req
= tevent_req_callback_data(
1691 subreq
, struct tevent_req
);
1692 struct smb_vfs_call_pwrite_state
*state
= tevent_req_data(
1693 req
, struct smb_vfs_call_pwrite_state
);
1696 state
->retval
= state
->recv_fn(subreq
, &err
);
1697 TALLOC_FREE(subreq
);
1698 if (state
->retval
== -1) {
1699 tevent_req_error(req
, err
);
1702 tevent_req_done(req
);
1705 ssize_t
SMB_VFS_PWRITE_RECV(struct tevent_req
*req
, int *perrno
)
1707 struct smb_vfs_call_pwrite_state
*state
= tevent_req_data(
1708 req
, struct smb_vfs_call_pwrite_state
);
1711 if (tevent_req_is_unix_error(req
, &err
)) {
1715 return state
->retval
;
1718 off_t
smb_vfs_call_lseek(struct vfs_handle_struct
*handle
,
1719 struct files_struct
*fsp
, off_t offset
,
1723 return handle
->fns
->lseek_fn(handle
, fsp
, offset
, whence
);
1726 ssize_t
smb_vfs_call_sendfile(struct vfs_handle_struct
*handle
, int tofd
,
1727 files_struct
*fromfsp
, const DATA_BLOB
*header
,
1728 off_t offset
, size_t count
)
1731 return handle
->fns
->sendfile_fn(handle
, tofd
, fromfsp
, header
, offset
,
1735 ssize_t
smb_vfs_call_recvfile(struct vfs_handle_struct
*handle
, int fromfd
,
1736 files_struct
*tofsp
, off_t offset
,
1740 return handle
->fns
->recvfile_fn(handle
, fromfd
, tofsp
, offset
, count
);
1743 int smb_vfs_call_rename(struct vfs_handle_struct
*handle
,
1744 const struct smb_filename
*smb_fname_src
,
1745 const struct smb_filename
*smb_fname_dst
)
1748 return handle
->fns
->rename_fn(handle
, smb_fname_src
, smb_fname_dst
);
1751 int smb_vfs_call_fsync(struct vfs_handle_struct
*handle
,
1752 struct files_struct
*fsp
)
1755 return handle
->fns
->fsync_fn(handle
, fsp
);
1758 struct smb_vfs_call_fsync_state
{
1759 int (*recv_fn
)(struct tevent_req
*req
, int *err
);
1763 static void smb_vfs_call_fsync_done(struct tevent_req
*subreq
);
1765 struct tevent_req
*smb_vfs_call_fsync_send(struct vfs_handle_struct
*handle
,
1766 TALLOC_CTX
*mem_ctx
,
1767 struct tevent_context
*ev
,
1768 struct files_struct
*fsp
)
1770 struct tevent_req
*req
, *subreq
;
1771 struct smb_vfs_call_fsync_state
*state
;
1773 req
= tevent_req_create(mem_ctx
, &state
,
1774 struct smb_vfs_call_fsync_state
);
1778 VFS_FIND(fsync_send
);
1779 state
->recv_fn
= handle
->fns
->fsync_recv_fn
;
1781 subreq
= handle
->fns
->fsync_send_fn(handle
, state
, ev
, fsp
);
1782 if (tevent_req_nomem(subreq
, req
)) {
1783 return tevent_req_post(req
, ev
);
1785 tevent_req_set_callback(subreq
, smb_vfs_call_fsync_done
, req
);
1789 static void smb_vfs_call_fsync_done(struct tevent_req
*subreq
)
1791 struct tevent_req
*req
= tevent_req_callback_data(
1792 subreq
, struct tevent_req
);
1793 struct smb_vfs_call_fsync_state
*state
= tevent_req_data(
1794 req
, struct smb_vfs_call_fsync_state
);
1797 state
->retval
= state
->recv_fn(subreq
, &err
);
1798 TALLOC_FREE(subreq
);
1799 if (state
->retval
== -1) {
1800 tevent_req_error(req
, err
);
1803 tevent_req_done(req
);
1806 int SMB_VFS_FSYNC_RECV(struct tevent_req
*req
, int *perrno
)
1808 struct smb_vfs_call_fsync_state
*state
= tevent_req_data(
1809 req
, struct smb_vfs_call_fsync_state
);
1812 if (tevent_req_is_unix_error(req
, &err
)) {
1816 return state
->retval
;
1820 int smb_vfs_call_stat(struct vfs_handle_struct
*handle
,
1821 struct smb_filename
*smb_fname
)
1824 return handle
->fns
->stat_fn(handle
, smb_fname
);
1827 int smb_vfs_call_fstat(struct vfs_handle_struct
*handle
,
1828 struct files_struct
*fsp
, SMB_STRUCT_STAT
*sbuf
)
1831 return handle
->fns
->fstat_fn(handle
, fsp
, sbuf
);
1834 int smb_vfs_call_lstat(struct vfs_handle_struct
*handle
,
1835 struct smb_filename
*smb_filename
)
1838 return handle
->fns
->lstat_fn(handle
, smb_filename
);
1841 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct
*handle
,
1842 struct files_struct
*fsp
,
1843 const SMB_STRUCT_STAT
*sbuf
)
1845 VFS_FIND(get_alloc_size
);
1846 return handle
->fns
->get_alloc_size_fn(handle
, fsp
, sbuf
);
1849 int smb_vfs_call_unlink(struct vfs_handle_struct
*handle
,
1850 const struct smb_filename
*smb_fname
)
1853 return handle
->fns
->unlink_fn(handle
, smb_fname
);
1856 int smb_vfs_call_chmod(struct vfs_handle_struct
*handle
, const char *path
,
1860 return handle
->fns
->chmod_fn(handle
, path
, mode
);
1863 int smb_vfs_call_fchmod(struct vfs_handle_struct
*handle
,
1864 struct files_struct
*fsp
, mode_t mode
)
1867 return handle
->fns
->fchmod_fn(handle
, fsp
, mode
);
1870 int smb_vfs_call_chown(struct vfs_handle_struct
*handle
, const char *path
,
1871 uid_t uid
, gid_t gid
)
1874 return handle
->fns
->chown_fn(handle
, path
, uid
, gid
);
1877 int smb_vfs_call_fchown(struct vfs_handle_struct
*handle
,
1878 struct files_struct
*fsp
, uid_t uid
, gid_t gid
)
1881 return handle
->fns
->fchown_fn(handle
, fsp
, uid
, gid
);
1884 int smb_vfs_call_lchown(struct vfs_handle_struct
*handle
, const char *path
,
1885 uid_t uid
, gid_t gid
)
1888 return handle
->fns
->lchown_fn(handle
, path
, uid
, gid
);
1891 NTSTATUS
vfs_chown_fsp(files_struct
*fsp
, uid_t uid
, gid_t gid
)
1894 bool as_root
= false;
1896 char *saved_dir
= NULL
;
1897 char *parent_dir
= NULL
;
1900 if (fsp
->fh
->fd
!= -1) {
1902 ret
= SMB_VFS_FCHOWN(fsp
, uid
, gid
);
1904 return NT_STATUS_OK
;
1906 if (ret
== -1 && errno
!= ENOSYS
) {
1907 return map_nt_error_from_unix(errno
);
1911 as_root
= (geteuid() == 0);
1915 * We are being asked to chown as root. Make
1916 * sure we chdir() into the path to pin it,
1917 * and always act using lchown to ensure we
1918 * don't deref any symbolic links.
1920 const char *final_component
= NULL
;
1921 struct smb_filename local_fname
;
1923 saved_dir
= vfs_GetWd(talloc_tos(),fsp
->conn
);
1925 status
= map_nt_error_from_unix(errno
);
1926 DEBUG(0,("vfs_chown_fsp: failed to get "
1927 "current working directory. Error was %s\n",
1932 if (!parent_dirname(talloc_tos(),
1933 fsp
->fsp_name
->base_name
,
1935 &final_component
)) {
1936 return NT_STATUS_NO_MEMORY
;
1939 /* cd into the parent dir to pin it. */
1940 ret
= vfs_ChDir(fsp
->conn
, parent_dir
);
1942 return map_nt_error_from_unix(errno
);
1945 ZERO_STRUCT(local_fname
);
1946 local_fname
.base_name
= discard_const_p(char, final_component
);
1948 /* Must use lstat here. */
1949 ret
= SMB_VFS_LSTAT(fsp
->conn
, &local_fname
);
1951 status
= map_nt_error_from_unix(errno
);
1955 /* Ensure it matches the fsp stat. */
1956 if (!check_same_stat(&local_fname
.st
, &fsp
->fsp_name
->st
)) {
1957 status
= NT_STATUS_ACCESS_DENIED
;
1960 path
= final_component
;
1962 path
= fsp
->fsp_name
->base_name
;
1965 if (fsp
->posix_open
|| as_root
) {
1966 ret
= SMB_VFS_LCHOWN(fsp
->conn
,
1970 ret
= SMB_VFS_CHOWN(fsp
->conn
,
1976 status
= NT_STATUS_OK
;
1978 status
= map_nt_error_from_unix(errno
);
1984 vfs_ChDir(fsp
->conn
,saved_dir
);
1985 TALLOC_FREE(saved_dir
);
1986 TALLOC_FREE(parent_dir
);
1991 int smb_vfs_call_chdir(struct vfs_handle_struct
*handle
, const char *path
)
1994 return handle
->fns
->chdir_fn(handle
, path
);
1997 char *smb_vfs_call_getwd(struct vfs_handle_struct
*handle
)
2000 return handle
->fns
->getwd_fn(handle
);
2003 int smb_vfs_call_ntimes(struct vfs_handle_struct
*handle
,
2004 const struct smb_filename
*smb_fname
,
2005 struct smb_file_time
*ft
)
2008 return handle
->fns
->ntimes_fn(handle
, smb_fname
, ft
);
2011 int smb_vfs_call_ftruncate(struct vfs_handle_struct
*handle
,
2012 struct files_struct
*fsp
, off_t offset
)
2014 VFS_FIND(ftruncate
);
2015 return handle
->fns
->ftruncate_fn(handle
, fsp
, offset
);
2018 int smb_vfs_call_fallocate(struct vfs_handle_struct
*handle
,
2019 struct files_struct
*fsp
,
2020 enum vfs_fallocate_mode mode
,
2024 VFS_FIND(fallocate
);
2025 return handle
->fns
->fallocate_fn(handle
, fsp
, mode
, offset
, len
);
2028 int smb_vfs_call_kernel_flock(struct vfs_handle_struct
*handle
,
2029 struct files_struct
*fsp
, uint32 share_mode
,
2030 uint32_t access_mask
)
2032 VFS_FIND(kernel_flock
);
2033 return handle
->fns
->kernel_flock_fn(handle
, fsp
, share_mode
,
2037 int smb_vfs_call_linux_setlease(struct vfs_handle_struct
*handle
,
2038 struct files_struct
*fsp
, int leasetype
)
2040 VFS_FIND(linux_setlease
);
2041 return handle
->fns
->linux_setlease_fn(handle
, fsp
, leasetype
);
2044 int smb_vfs_call_symlink(struct vfs_handle_struct
*handle
, const char *oldpath
,
2045 const char *newpath
)
2048 return handle
->fns
->symlink_fn(handle
, oldpath
, newpath
);
2051 int smb_vfs_call_readlink(struct vfs_handle_struct
*handle
,
2052 const char *path
, char *buf
, size_t bufsiz
)
2055 return handle
->fns
->readlink_fn(handle
, path
, buf
, bufsiz
);
2058 int smb_vfs_call_link(struct vfs_handle_struct
*handle
, const char *oldpath
,
2059 const char *newpath
)
2062 return handle
->fns
->link_fn(handle
, oldpath
, newpath
);
2065 int smb_vfs_call_mknod(struct vfs_handle_struct
*handle
, const char *path
,
2066 mode_t mode
, SMB_DEV_T dev
)
2069 return handle
->fns
->mknod_fn(handle
, path
, mode
, dev
);
2072 char *smb_vfs_call_realpath(struct vfs_handle_struct
*handle
, const char *path
)
2075 return handle
->fns
->realpath_fn(handle
, path
);
2078 NTSTATUS
smb_vfs_call_notify_watch(struct vfs_handle_struct
*handle
,
2079 struct sys_notify_context
*ctx
,
2082 uint32_t *subdir_filter
,
2083 void (*callback
)(struct sys_notify_context
*ctx
,
2085 struct notify_event
*ev
),
2086 void *private_data
, void *handle_p
)
2088 VFS_FIND(notify_watch
);
2089 return handle
->fns
->notify_watch_fn(handle
, ctx
, path
,
2090 filter
, subdir_filter
, callback
,
2091 private_data
, handle_p
);
2094 int smb_vfs_call_chflags(struct vfs_handle_struct
*handle
, const char *path
,
2098 return handle
->fns
->chflags_fn(handle
, path
, flags
);
2101 struct file_id
smb_vfs_call_file_id_create(struct vfs_handle_struct
*handle
,
2102 const SMB_STRUCT_STAT
*sbuf
)
2104 VFS_FIND(file_id_create
);
2105 return handle
->fns
->file_id_create_fn(handle
, sbuf
);
2108 NTSTATUS
smb_vfs_call_streaminfo(struct vfs_handle_struct
*handle
,
2109 struct files_struct
*fsp
,
2111 TALLOC_CTX
*mem_ctx
,
2112 unsigned int *num_streams
,
2113 struct stream_struct
**streams
)
2115 VFS_FIND(streaminfo
);
2116 return handle
->fns
->streaminfo_fn(handle
, fsp
, fname
, mem_ctx
,
2117 num_streams
, streams
);
2120 int smb_vfs_call_get_real_filename(struct vfs_handle_struct
*handle
,
2121 const char *path
, const char *name
,
2122 TALLOC_CTX
*mem_ctx
, char **found_name
)
2124 VFS_FIND(get_real_filename
);
2125 return handle
->fns
->get_real_filename_fn(handle
, path
, name
, mem_ctx
,
2129 const char *smb_vfs_call_connectpath(struct vfs_handle_struct
*handle
,
2130 const char *filename
)
2132 VFS_FIND(connectpath
);
2133 return handle
->fns
->connectpath_fn(handle
, filename
);
2136 bool smb_vfs_call_strict_lock(struct vfs_handle_struct
*handle
,
2137 struct files_struct
*fsp
,
2138 struct lock_struct
*plock
)
2140 VFS_FIND(strict_lock
);
2141 return handle
->fns
->strict_lock_fn(handle
, fsp
, plock
);
2144 void smb_vfs_call_strict_unlock(struct vfs_handle_struct
*handle
,
2145 struct files_struct
*fsp
,
2146 struct lock_struct
*plock
)
2148 VFS_FIND(strict_unlock
);
2149 handle
->fns
->strict_unlock_fn(handle
, fsp
, plock
);
2152 NTSTATUS
smb_vfs_call_translate_name(struct vfs_handle_struct
*handle
,
2154 enum vfs_translate_direction direction
,
2155 TALLOC_CTX
*mem_ctx
,
2158 VFS_FIND(translate_name
);
2159 return handle
->fns
->translate_name_fn(handle
, name
, direction
, mem_ctx
,
2163 NTSTATUS
smb_vfs_call_fsctl(struct vfs_handle_struct
*handle
,
2164 struct files_struct
*fsp
,
2168 const uint8_t *in_data
,
2171 uint32_t max_out_len
,
2175 return handle
->fns
->fsctl_fn(handle
, fsp
, ctx
, function
, req_flags
,
2176 in_data
, in_len
, out_data
, max_out_len
,
2180 struct tevent_req
*smb_vfs_call_copy_chunk_send(struct vfs_handle_struct
*handle
,
2181 TALLOC_CTX
*mem_ctx
,
2182 struct tevent_context
*ev
,
2183 struct files_struct
*src_fsp
,
2185 struct files_struct
*dest_fsp
,
2189 VFS_FIND(copy_chunk_send
);
2190 return handle
->fns
->copy_chunk_send_fn(handle
, mem_ctx
, ev
, src_fsp
,
2191 src_off
, dest_fsp
, dest_off
, num
);
2194 NTSTATUS
smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct
*handle
,
2195 struct tevent_req
*req
,
2198 VFS_FIND(copy_chunk_recv
);
2199 return handle
->fns
->copy_chunk_recv_fn(handle
, req
, copied
);
2202 NTSTATUS
smb_vfs_call_fget_nt_acl(struct vfs_handle_struct
*handle
,
2203 struct files_struct
*fsp
,
2204 uint32 security_info
,
2205 TALLOC_CTX
*mem_ctx
,
2206 struct security_descriptor
**ppdesc
)
2208 VFS_FIND(fget_nt_acl
);
2209 return handle
->fns
->fget_nt_acl_fn(handle
, fsp
, security_info
,
2213 NTSTATUS
smb_vfs_call_get_nt_acl(struct vfs_handle_struct
*handle
,
2215 uint32 security_info
,
2216 TALLOC_CTX
*mem_ctx
,
2217 struct security_descriptor
**ppdesc
)
2219 VFS_FIND(get_nt_acl
);
2220 return handle
->fns
->get_nt_acl_fn(handle
, name
, security_info
, mem_ctx
, ppdesc
);
2223 NTSTATUS
smb_vfs_call_fset_nt_acl(struct vfs_handle_struct
*handle
,
2224 struct files_struct
*fsp
,
2225 uint32 security_info_sent
,
2226 const struct security_descriptor
*psd
)
2228 VFS_FIND(fset_nt_acl
);
2229 return handle
->fns
->fset_nt_acl_fn(handle
, fsp
, security_info_sent
,
2233 NTSTATUS
smb_vfs_call_audit_file(struct vfs_handle_struct
*handle
,
2234 struct smb_filename
*file
,
2235 struct security_acl
*sacl
,
2236 uint32_t access_requested
,
2237 uint32_t access_denied
)
2239 VFS_FIND(audit_file
);
2240 return handle
->fns
->audit_file_fn(handle
,
2247 int smb_vfs_call_chmod_acl(struct vfs_handle_struct
*handle
, const char *name
,
2250 VFS_FIND(chmod_acl
);
2251 return handle
->fns
->chmod_acl_fn(handle
, name
, mode
);
2254 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct
*handle
,
2255 struct files_struct
*fsp
, mode_t mode
)
2257 VFS_FIND(fchmod_acl
);
2258 return handle
->fns
->fchmod_acl_fn(handle
, fsp
, mode
);
2261 SMB_ACL_T
smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct
*handle
,
2263 SMB_ACL_TYPE_T type
,
2264 TALLOC_CTX
*mem_ctx
)
2266 VFS_FIND(sys_acl_get_file
);
2267 return handle
->fns
->sys_acl_get_file_fn(handle
, path_p
, type
, mem_ctx
);
2270 SMB_ACL_T
smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct
*handle
,
2271 struct files_struct
*fsp
,
2272 TALLOC_CTX
*mem_ctx
)
2274 VFS_FIND(sys_acl_get_fd
);
2275 return handle
->fns
->sys_acl_get_fd_fn(handle
, fsp
, mem_ctx
);
2278 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct
*handle
,
2280 TALLOC_CTX
*mem_ctx
,
2281 char **blob_description
,
2284 VFS_FIND(sys_acl_blob_get_file
);
2285 return handle
->fns
->sys_acl_blob_get_file_fn(handle
, path_p
, mem_ctx
, blob_description
, blob
);
2288 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct
*handle
,
2289 struct files_struct
*fsp
,
2290 TALLOC_CTX
*mem_ctx
,
2291 char **blob_description
,
2294 VFS_FIND(sys_acl_blob_get_fd
);
2295 return handle
->fns
->sys_acl_blob_get_fd_fn(handle
, fsp
, mem_ctx
, blob_description
, blob
);
2298 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct
*handle
,
2299 const char *name
, SMB_ACL_TYPE_T acltype
,
2302 VFS_FIND(sys_acl_set_file
);
2303 return handle
->fns
->sys_acl_set_file_fn(handle
, name
, acltype
, theacl
);
2306 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct
*handle
,
2307 struct files_struct
*fsp
, SMB_ACL_T theacl
)
2309 VFS_FIND(sys_acl_set_fd
);
2310 return handle
->fns
->sys_acl_set_fd_fn(handle
, fsp
, theacl
);
2313 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct
*handle
,
2316 VFS_FIND(sys_acl_delete_def_file
);
2317 return handle
->fns
->sys_acl_delete_def_file_fn(handle
, path
);
2320 ssize_t
smb_vfs_call_getxattr(struct vfs_handle_struct
*handle
,
2321 const char *path
, const char *name
, void *value
,
2325 return handle
->fns
->getxattr_fn(handle
, path
, name
, value
, size
);
2328 ssize_t
smb_vfs_call_fgetxattr(struct vfs_handle_struct
*handle
,
2329 struct files_struct
*fsp
, const char *name
,
2330 void *value
, size_t size
)
2332 VFS_FIND(fgetxattr
);
2333 return handle
->fns
->fgetxattr_fn(handle
, fsp
, name
, value
, size
);
2336 ssize_t
smb_vfs_call_listxattr(struct vfs_handle_struct
*handle
,
2337 const char *path
, char *list
, size_t size
)
2339 VFS_FIND(listxattr
);
2340 return handle
->fns
->listxattr_fn(handle
, path
, list
, size
);
2343 ssize_t
smb_vfs_call_flistxattr(struct vfs_handle_struct
*handle
,
2344 struct files_struct
*fsp
, char *list
,
2347 VFS_FIND(flistxattr
);
2348 return handle
->fns
->flistxattr_fn(handle
, fsp
, list
, size
);
2351 int smb_vfs_call_removexattr(struct vfs_handle_struct
*handle
,
2352 const char *path
, const char *name
)
2354 VFS_FIND(removexattr
);
2355 return handle
->fns
->removexattr_fn(handle
, path
, name
);
2358 int smb_vfs_call_fremovexattr(struct vfs_handle_struct
*handle
,
2359 struct files_struct
*fsp
, const char *name
)
2361 VFS_FIND(fremovexattr
);
2362 return handle
->fns
->fremovexattr_fn(handle
, fsp
, name
);
2365 int smb_vfs_call_setxattr(struct vfs_handle_struct
*handle
, const char *path
,
2366 const char *name
, const void *value
, size_t size
,
2370 return handle
->fns
->setxattr_fn(handle
, path
, name
, value
, size
, flags
);
2373 int smb_vfs_call_fsetxattr(struct vfs_handle_struct
*handle
,
2374 struct files_struct
*fsp
, const char *name
,
2375 const void *value
, size_t size
, int flags
)
2377 VFS_FIND(fsetxattr
);
2378 return handle
->fns
->fsetxattr_fn(handle
, fsp
, name
, value
, size
, flags
);
2381 bool smb_vfs_call_aio_force(struct vfs_handle_struct
*handle
,
2382 struct files_struct
*fsp
)
2384 VFS_FIND(aio_force
);
2385 return handle
->fns
->aio_force_fn(handle
, fsp
);
2388 bool smb_vfs_call_is_offline(struct vfs_handle_struct
*handle
,
2389 const struct smb_filename
*fname
,
2390 SMB_STRUCT_STAT
*sbuf
)
2392 VFS_FIND(is_offline
);
2393 return handle
->fns
->is_offline_fn(handle
, fname
, sbuf
);
2396 int smb_vfs_call_set_offline(struct vfs_handle_struct
*handle
,
2397 const struct smb_filename
*fname
)
2399 VFS_FIND(set_offline
);
2400 return handle
->fns
->set_offline_fn(handle
, fname
);
2403 NTSTATUS
smb_vfs_call_durable_cookie(struct vfs_handle_struct
*handle
,
2404 struct files_struct
*fsp
,
2405 TALLOC_CTX
*mem_ctx
,
2408 VFS_FIND(durable_cookie
);
2409 return handle
->fns
->durable_cookie_fn(handle
, fsp
, mem_ctx
, cookie
);
2412 NTSTATUS
smb_vfs_call_durable_disconnect(struct vfs_handle_struct
*handle
,
2413 struct files_struct
*fsp
,
2414 const DATA_BLOB old_cookie
,
2415 TALLOC_CTX
*mem_ctx
,
2416 DATA_BLOB
*new_cookie
)
2418 VFS_FIND(durable_disconnect
);
2419 return handle
->fns
->durable_disconnect_fn(handle
, fsp
, old_cookie
,
2420 mem_ctx
, new_cookie
);
2423 NTSTATUS
smb_vfs_call_durable_reconnect(struct vfs_handle_struct
*handle
,
2424 struct smb_request
*smb1req
,
2425 struct smbXsrv_open
*op
,
2426 const DATA_BLOB old_cookie
,
2427 TALLOC_CTX
*mem_ctx
,
2428 struct files_struct
**fsp
,
2429 DATA_BLOB
*new_cookie
)
2431 VFS_FIND(durable_reconnect
);
2432 return handle
->fns
->durable_reconnect_fn(handle
, smb1req
, op
,
2433 old_cookie
, mem_ctx
, fsp
,