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"
30 #include "../lib/util/memcache.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"));
136 static_init_vfs(NULL);
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_t *)(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);
320 * Ensure this module catches all VFS functions.
323 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
326 bool missing_fn = false;
328 const uintptr_t *end = (const uintptr_t *)(fns + 1);
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);
339 smb_panic("Required VFS function not implemented in module.\n");
343 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
349 /*****************************************************************
351 ******************************************************************/
353 bool smbd_vfs_init(connection_struct *conn)
355 const char **vfs_objects;
359 /* Normal share - initialise with disk access functions */
360 vfs_init_default(conn);
362 /* No need to load vfs modules for printer connections */
367 vfs_objects = lp_vfs_objects(SNUM(conn));
369 /* Override VFS functions if 'vfs object' was not specified*/
370 if (!vfs_objects || !vfs_objects[0])
373 for (i=0; vfs_objects[i] ;) {
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]));
386 /*******************************************************************
387 Check if a file exists in the vfs.
388 ********************************************************************/
390 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
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)) {
398 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
401 /****************************************************************************
402 Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
403 ****************************************************************************/
405 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
409 while (total < byte_count)
411 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
414 if (ret == 0) return total;
423 return (ssize_t)total;
426 /****************************************************************************
427 Write data to a fd on the vfs.
428 ****************************************************************************/
430 ssize_t vfs_write_data(struct smb_request *req,
438 if (req && req->unread_bytes) {
439 int sockfd = req->xconn->transport.sock;
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) {
450 ret = SMB_VFS_RECVFILE(sockfd,
454 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
461 ret = SMB_VFS_WRITE(fsp, buffer + total, N - total);
470 return (ssize_t)total;
473 ssize_t vfs_pwrite_data(struct smb_request *req,
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;
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
496 ret = SMB_VFS_RECVFILE(sockfd,
500 if (ret == 0 || (ret == -1 &&
502 errno == EWOULDBLOCK))) {
504 /* Ensure the socket is blocking. */
505 old_flags = fcntl(sockfd, F_GETFL, 0);
506 if (set_blocking(sockfd, true) == -1) {
509 ret = SMB_VFS_RECVFILE(sockfd,
513 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
520 return (ssize_t)total;
522 /* Any other error case. */
528 return (ssize_t)total;
532 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
542 return (ssize_t)total;
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 ****************************************************************************/
550 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
553 connection_struct *conn = fsp->conn;
554 uint64_t space_avail;
555 uint64_t bsize,dfree,dsize;
559 * Actually try and commit the space on disk....
562 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
563 fsp_str_dbg(fsp), (double)len));
565 if (((off_t)len) < 0) {
566 DEBUG(0,("vfs_allocate_file_space: %s negative len "
567 "requested.\n", fsp_str_dbg(fsp)));
572 status = vfs_stat_fsp(fsp);
573 if (!NT_STATUS_IS_OK(status)) {
577 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
580 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
581 /* Shrink - use ftruncate. */
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));
587 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
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);
594 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
599 /* Grow - we need to test if we have enough space. */
601 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
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,
612 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
615 /* We changed the allocation size on disk, but not
616 EOF - exactly as required. We're done ! */
620 if (ret == -1 && errno == ENOSPC) {
624 len -= fsp->fsp_name->st.st_ex_size;
625 len /= 1024; /* Len is now number of 1k blocks needed. */
627 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
628 if (space_avail == (uint64_t)-1) {
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));
637 if (len > space_avail) {
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 ****************************************************************************/
651 int vfs_set_filelen(files_struct *fsp, off_t len)
655 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
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);
668 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
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 ****************************************************************************/
681 #define SPARSE_BUF_WRITE_SIZE (32*1024)
683 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
689 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
696 while (total < len) {
697 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
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)));
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 ****************************************************************************/
721 int vfs_fill_sparse(files_struct *fsp, off_t len)
728 status = vfs_stat_fsp(fsp);
729 if (!NT_STATUS_IS_OK(status)) {
733 if (len <= fsp->fsp_name->st.st_ex_size) {
738 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
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)));
748 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
750 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
752 offset = fsp->fsp_name->st.st_ex_size;
753 num_to_write = len - fsp->fsp_name->st.st_ex_size;
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) {
769 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
770 "error %d. Falling back to slow manual allocation\n", ret));
773 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
778 set_filelen_write_cache(fsp, len);
781 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
785 /****************************************************************************
786 Transfer some data (n bytes) between two file_struct's.
787 ****************************************************************************/
789 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
791 struct files_struct *fsp = (struct files_struct *)file;
793 return SMB_VFS_PREAD(fsp, buf, len, offset);
796 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
798 struct files_struct *fsp = (struct files_struct *)file;
800 return SMB_VFS_PWRITE(fsp, buf, len, offset);
803 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
805 return transfer_file_internal((void *)in, (void *)out, n,
806 vfs_pread_fn, vfs_pwrite_fn);
809 /*******************************************************************
810 A vfs_readdir wrapper which just returns the file name.
811 ********************************************************************/
813 const char *vfs_readdirname(connection_struct *conn, void *p,
814 SMB_STRUCT_STAT *sbuf, char **talloced)
816 struct dirent *ptr= NULL;
824 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
836 #ifdef HAVE_BROKEN_READDIR_NAME
837 /* using /usr/ucb/cc is BAD */
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)) {
847 *talloced = translated;
848 if (!NT_STATUS_IS_OK(status)) {
854 /*******************************************************************
855 A wrapper for vfs_chdir().
856 ********************************************************************/
858 int vfs_ChDir(connection_struct *conn, const char *path)
863 LastDir = SMB_STRDUP("");
870 if (*path == '/' && strcsequal(LastDir,path)) {
874 DEBUG(4,("vfs_ChDir to %s\n",path));
876 ret = SMB_VFS_CHDIR(conn,path);
880 LastDir = SMB_STRDUP(path);
883 TALLOC_FREE(conn->cwd);
884 conn->cwd = vfs_GetWd(conn, conn);
885 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
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 ********************************************************************/
896 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
898 char *current_dir = NULL;
900 DATA_BLOB cache_value;
902 struct smb_filename *smb_fname_dot = NULL;
903 struct smb_filename *smb_fname_full = NULL;
905 if (!lp_getwd_cache()) {
909 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
910 if (smb_fname_dot == NULL) {
915 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
917 * Known to fail for root: the directory may be NFS-mounted
918 * and exported with root_squash (so has no root access).
920 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
921 "(NFS problem ?)\n", strerror(errno) ));
925 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
927 if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
928 data_blob_const(&key, sizeof(key)),
933 SMB_ASSERT((cache_value.length > 0)
934 && (cache_value.data[cache_value.length-1] == '\0'));
936 smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
938 if (smb_fname_full == NULL) {
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))) {
950 result = talloc_strdup(ctx, smb_fname_full->base_name);
951 if (result == NULL) {
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.
965 current_dir = SMB_VFS_GETWD(conn);
966 if (current_dir == NULL) {
967 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
972 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
973 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
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));
981 result = talloc_strdup(ctx, current_dir);
982 if (result == NULL) {
987 TALLOC_FREE(smb_fname_dot);
988 TALLOC_FREE(smb_fname_full);
989 SAFE_FREE(current_dir);
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 ********************************************************************/
1000 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1002 struct smb_request *smbreq)
1005 TALLOC_CTX *ctx = talloc_tos();
1006 const char *conn_rootdir;
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;
1016 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1018 conn->connectpath));
1021 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1023 status = NT_STATUS_NO_MEMORY;
1027 if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
1028 status = NT_STATUS_NO_MEMORY;
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);
1035 if (priv_paths->parent_name.base_name == NULL ||
1036 priv_paths->file_name.base_name == NULL) {
1037 status = NT_STATUS_NO_MEMORY;
1041 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1042 status = map_nt_error_from_unix(errno);
1045 /* Remember where we were. */
1046 saved_dir = vfs_GetWd(ctx, conn);
1048 status = map_nt_error_from_unix(errno);
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);
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);
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;
1072 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1073 priv_paths->parent_name.base_name,
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;
1083 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1084 status = map_nt_error_from_unix(errno);
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;
1098 /* Ensure we're below the connect path. */
1100 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1101 if (conn_rootdir == NULL) {
1102 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1104 status = NT_STATUS_ACCESS_DENIED;
1108 rootdir_len = strlen(conn_rootdir);
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).
1118 if (rootdir_len != 1) {
1121 matched = (strncmp(conn_rootdir, resolved_name,
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 "
1130 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1131 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1132 status = NT_STATUS_ACCESS_DENIED;
1137 /* Now ensure that the last component either doesn't
1138 exist, or is *NOT* a symlink. */
1140 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
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)));
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"
1158 priv_paths->file_name.base_name));
1159 status = NT_STATUS_ACCESS_DENIED;
1163 smbreq->priv_paths = priv_paths;
1164 status = NT_STATUS_OK;
1169 vfs_ChDir(conn, saved_dir);
1171 SAFE_FREE(resolved_name);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 TALLOC_FREE(priv_paths);
1175 TALLOC_FREE(dir_name);
1179 /*******************************************************************
1180 Reduce a file name, removing .. elements and checking that
1181 it is below dir in the heirachy. This uses realpath.
1183 If cwd_name == NULL then fname is a client given path relative
1184 to the root path of the share.
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 ********************************************************************/
1190 NTSTATUS check_reduced_name(connection_struct *conn,
1191 const char *cwd_name,
1194 char *resolved_name = NULL;
1195 char *new_fname = NULL;
1196 bool allow_symlinks = true;
1197 bool allow_widelinks = false;
1199 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1201 resolved_name = SMB_VFS_REALPATH(conn,fname);
1203 if (!resolved_name) {
1206 DEBUG(3,("check_reduced_name: Component not a "
1207 "directory in getting realpath for "
1209 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1212 TALLOC_CTX *ctx = talloc_tos();
1213 char *dir_name = NULL;
1214 const char *last_component = NULL;
1215 char *new_name = NULL;
1218 /* Last component didn't exist.
1219 Remove it and try and canonicalise
1220 the directory name. */
1221 if (!parent_dirname(ctx, fname,
1224 return NT_STATUS_NO_MEMORY;
1227 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1228 if (!resolved_name) {
1229 NTSTATUS status = map_nt_error_from_unix(errno);
1231 if (errno == ENOENT || errno == ENOTDIR) {
1232 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1235 DEBUG(3,("check_reduce_name: "
1236 "couldn't get realpath for "
1239 nt_errstr(status)));
1242 ret = asprintf(&new_name, "%s/%s",
1243 resolved_name, last_component);
1244 SAFE_FREE(resolved_name);
1246 return NT_STATUS_NO_MEMORY;
1248 resolved_name = new_name;
1252 DEBUG(3,("check_reduced_name: couldn't get "
1253 "realpath for %s\n", fname));
1254 return map_nt_error_from_unix(errno);
1258 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
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;
1268 allow_widelinks = lp_widelinks(SNUM(conn));
1269 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1271 /* Common widelinks and symlinks checks. */
1272 if (!allow_widelinks || !allow_symlinks) {
1273 const char *conn_rootdir;
1276 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1277 if (conn_rootdir == NULL) {
1278 DEBUG(2, ("check_reduced_name: Could not get "
1280 SAFE_FREE(resolved_name);
1281 return NT_STATUS_ACCESS_DENIED;
1284 rootdir_len = strlen(conn_rootdir);
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).
1295 if (rootdir_len != 1) {
1298 matched = (strncmp(conn_rootdir, resolved_name,
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",
1307 DEBUGADD(2, ("resolved_name=%s\n",
1309 SAFE_FREE(resolved_name);
1310 return NT_STATUS_ACCESS_DENIED;
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];
1320 * UNIX filesystem semantics, names consisting
1321 * only of "." or ".." CANNOT be symlinks.
1323 if (ISDOT(fname) || ISDOTDOT(fname)) {
1328 DEBUG(2, ("check_reduced_name: logic error (%c) "
1329 "in resolved_name: %s\n",
1332 SAFE_FREE(resolved_name);
1333 return NT_STATUS_ACCESS_DENIED;
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).
1345 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1346 new_fname = talloc_asprintf(talloc_tos(),
1350 if (new_fname == NULL) {
1351 SAFE_FREE(resolved_name);
1352 return NT_STATUS_NO_MEMORY;
1357 if (strcmp(fname, p)!=0) {
1358 DEBUG(2, ("check_reduced_name: Bad access "
1359 "attempt: %s is a symlink to %s\n",
1361 SAFE_FREE(resolved_name);
1362 TALLOC_FREE(new_fname);
1363 return NT_STATUS_ACCESS_DENIED;
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;
1377 * XXX: This is temporary and there should be no callers of this once
1378 * smb_filename is plumbed through all path based operations.
1380 * Called when we know stream name parsing has already been done.
1382 int vfs_stat_smb_basename(struct connection_struct *conn,
1383 const struct smb_filename *smb_fname_in,
1384 SMB_STRUCT_STAT *psbuf)
1386 struct smb_filename smb_fname = {
1387 .base_name = discard_const_p(char, smb_fname_in->base_name),
1388 .flags = smb_fname_in->flags
1392 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1393 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1395 ret = SMB_VFS_STAT(conn, &smb_fname);
1399 *psbuf = smb_fname.st;
1405 * Ensure LSTAT is called for POSIX paths.
1408 NTSTATUS vfs_stat_fsp(files_struct *fsp)
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);
1416 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1419 return map_nt_error_from_unix(errno);
1422 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1423 return map_nt_error_from_unix(errno);
1426 return NT_STATUS_OK;
1430 * Initialize num_streams and streams, then call VFS op streaminfo
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)
1441 return SMB_VFS_STREAMINFO(conn,
1450 generate a file_id from a stat structure
1452 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1454 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1457 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1458 const char *service, const char *user)
1461 return handle->fns->connect_fn(handle, service, user);
1464 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1466 VFS_FIND(disconnect);
1467 handle->fns->disconnect_fn(handle);
1470 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1471 const struct smb_filename *smb_fname,
1476 VFS_FIND(disk_free);
1477 return handle->fns->disk_free_fn(handle, smb_fname,
1478 bsize, dfree, dsize);
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,
1487 VFS_FIND(get_quota);
1488 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1491 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1492 enum SMB_QUOTA_TYPE qtype, unid_t id,
1495 VFS_FIND(set_quota);
1496 return handle->fns->set_quota_fn(handle, qtype, id, qt);
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,
1504 VFS_FIND(get_shadow_copy_data);
1505 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1509 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1510 const struct smb_filename *smb_fname,
1511 struct vfs_statvfs_struct *statbuf)
1514 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1517 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1518 enum timestamp_set_resolution *p_ts_res)
1520 VFS_FIND(fs_capabilities);
1521 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1524 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1525 struct dfs_GetDFSReferral *r)
1527 VFS_FIND(get_dfs_referrals);
1528 return handle->fns->get_dfs_referrals_fn(handle, r);
1531 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1532 const struct smb_filename *smb_fname,
1534 uint32_t attributes)
1537 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1540 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1541 struct files_struct *fsp,
1543 uint32_t attributes)
1545 VFS_FIND(fdopendir);
1546 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1549 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1551 SMB_STRUCT_STAT *sbuf)
1554 return handle->fns->readdir_fn(handle, dirp, sbuf);
1557 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1558 DIR *dirp, long offset)
1561 handle->fns->seekdir_fn(handle, dirp, offset);
1564 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1568 return handle->fns->telldir_fn(handle, dirp);
1571 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1574 VFS_FIND(rewind_dir);
1575 handle->fns->rewind_dir_fn(handle, dirp);
1578 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1579 const struct smb_filename *smb_fname,
1583 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1586 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1587 const struct smb_filename *smb_fname)
1590 return handle->fns->rmdir_fn(handle, smb_fname);
1593 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1597 return handle->fns->closedir_fn(handle, dir);
1600 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1603 VFS_FIND(init_search_op);
1604 handle->fns->init_search_op_fn(handle, dirp);
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)
1612 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
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,
1632 const struct smb2_create_blobs *in_context_blobs,
1633 struct smb2_create_blobs *out_context_blobs)
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);
1644 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1645 struct files_struct *fsp)
1648 return handle->fns->close_fn(handle, fsp);
1651 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1652 struct files_struct *fsp, void *data, size_t n)
1655 return handle->fns->read_fn(handle, fsp, data, n);
1658 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1659 struct files_struct *fsp, void *data, size_t n,
1663 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1666 struct smb_vfs_call_pread_state {
1667 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1669 struct vfs_aio_state vfs_aio_state;
1672 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
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,
1679 size_t n, off_t offset)
1681 struct tevent_req *req, *subreq;
1682 struct smb_vfs_call_pread_state *state;
1684 req = tevent_req_create(mem_ctx, &state,
1685 struct smb_vfs_call_pread_state);
1689 VFS_FIND(pread_send);
1690 state->recv_fn = handle->fns->pread_recv_fn;
1692 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1694 if (tevent_req_nomem(subreq, req)) {
1695 return tevent_req_post(req, ev);
1697 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1701 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
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);
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);
1714 tevent_req_done(req);
1717 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1718 struct vfs_aio_state *vfs_aio_state)
1720 struct smb_vfs_call_pread_state *state = tevent_req_data(
1721 req, struct smb_vfs_call_pread_state);
1723 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1726 *vfs_aio_state = state->vfs_aio_state;
1727 return state->retval;
1730 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1731 struct files_struct *fsp, const void *data,
1735 return handle->fns->write_fn(handle, fsp, data, n);
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)
1743 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1746 struct smb_vfs_call_pwrite_state {
1747 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1749 struct vfs_aio_state vfs_aio_state;
1752 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
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,
1759 size_t n, off_t offset)
1761 struct tevent_req *req, *subreq;
1762 struct smb_vfs_call_pwrite_state *state;
1764 req = tevent_req_create(mem_ctx, &state,
1765 struct smb_vfs_call_pwrite_state);
1769 VFS_FIND(pwrite_send);
1770 state->recv_fn = handle->fns->pwrite_recv_fn;
1772 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1774 if (tevent_req_nomem(subreq, req)) {
1775 return tevent_req_post(req, ev);
1777 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1781 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
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);
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);
1794 tevent_req_done(req);
1797 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1798 struct vfs_aio_state *vfs_aio_state)
1800 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1801 req, struct smb_vfs_call_pwrite_state);
1803 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1806 *vfs_aio_state = state->vfs_aio_state;
1807 return state->retval;
1810 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1811 struct files_struct *fsp, off_t offset,
1815 return handle->fns->lseek_fn(handle, fsp, offset, whence);
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)
1823 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1827 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1828 files_struct *tofsp, off_t offset,
1832 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
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)
1840 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1843 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1844 struct files_struct *fsp)
1847 return handle->fns->fsync_fn(handle, fsp);
1850 struct smb_vfs_call_fsync_state {
1851 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1853 struct vfs_aio_state vfs_aio_state;
1856 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
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)
1863 struct tevent_req *req, *subreq;
1864 struct smb_vfs_call_fsync_state *state;
1866 req = tevent_req_create(mem_ctx, &state,
1867 struct smb_vfs_call_fsync_state);
1871 VFS_FIND(fsync_send);
1872 state->recv_fn = handle->fns->fsync_recv_fn;
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);
1878 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1882 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
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);
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);
1895 tevent_req_done(req);
1898 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1900 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1901 req, struct smb_vfs_call_fsync_state);
1903 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1906 *vfs_aio_state = state->vfs_aio_state;
1907 return state->retval;
1911 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1912 struct smb_filename *smb_fname)
1915 return handle->fns->stat_fn(handle, smb_fname);
1918 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1919 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1922 return handle->fns->fstat_fn(handle, fsp, sbuf);
1925 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1926 struct smb_filename *smb_filename)
1929 return handle->fns->lstat_fn(handle, smb_filename);
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)
1936 VFS_FIND(get_alloc_size);
1937 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1940 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1941 const struct smb_filename *smb_fname)
1944 return handle->fns->unlink_fn(handle, smb_fname);
1947 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1948 const struct smb_filename *smb_fname,
1952 return handle->fns->chmod_fn(handle, smb_fname, mode);
1955 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1956 struct files_struct *fsp, mode_t mode)
1959 return handle->fns->fchmod_fn(handle, fsp, mode);
1962 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1963 const struct smb_filename *smb_fname,
1968 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1971 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1972 struct files_struct *fsp, uid_t uid, gid_t gid)
1975 return handle->fns->fchown_fn(handle, fsp, uid, gid);
1978 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
1979 const struct smb_filename *smb_fname,
1984 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
1987 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
1990 bool as_root = false;
1993 if (fsp->fh->fd != -1) {
1995 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
1997 return NT_STATUS_OK;
1999 if (ret == -1 && errno != ENOSYS) {
2000 return map_nt_error_from_unix(errno);
2004 as_root = (geteuid() == 0);
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.
2013 char *saved_dir = NULL;
2014 char *parent_dir = NULL;
2015 const char *final_component = NULL;
2016 struct smb_filename *local_smb_fname = NULL;
2018 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
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",
2027 if (!parent_dirname(talloc_tos(),
2028 fsp->fsp_name->base_name,
2030 &final_component)) {
2031 return NT_STATUS_NO_MEMORY;
2034 /* cd into the parent dir to pin it. */
2035 ret = vfs_ChDir(fsp->conn, parent_dir);
2037 return map_nt_error_from_unix(errno);
2040 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2044 fsp->fsp_name->flags);
2045 if (local_smb_fname == NULL) {
2046 status = NT_STATUS_NO_MEMORY;
2050 /* Must use lstat here. */
2051 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2053 status = map_nt_error_from_unix(errno);
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;
2064 ret = SMB_VFS_LCHOWN(fsp->conn,
2069 status = NT_STATUS_OK;
2071 status = map_nt_error_from_unix(errno);
2076 vfs_ChDir(fsp->conn,saved_dir);
2077 TALLOC_FREE(local_smb_fname);
2078 TALLOC_FREE(saved_dir);
2079 TALLOC_FREE(parent_dir);
2084 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2085 ret = SMB_VFS_LCHOWN(fsp->conn,
2089 ret = SMB_VFS_CHOWN(fsp->conn,
2095 status = NT_STATUS_OK;
2097 status = map_nt_error_from_unix(errno);
2102 int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
2105 return handle->fns->chdir_fn(handle, path);
2108 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
2111 return handle->fns->getwd_fn(handle);
2114 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2115 const struct smb_filename *smb_fname,
2116 struct smb_file_time *ft)
2119 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2122 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2123 struct files_struct *fsp, off_t offset)
2125 VFS_FIND(ftruncate);
2126 return handle->fns->ftruncate_fn(handle, fsp, offset);
2129 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2130 struct files_struct *fsp,
2135 VFS_FIND(fallocate);
2136 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
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)
2143 VFS_FIND(kernel_flock);
2144 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2148 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2149 struct files_struct *fsp, int leasetype)
2151 VFS_FIND(linux_setlease);
2152 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2155 int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
2156 const char *newpath)
2159 return handle->fns->symlink_fn(handle, oldpath, newpath);
2162 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2163 const struct smb_filename *smb_fname,
2168 return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
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)
2176 return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2179 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2180 const struct smb_filename *smb_fname,
2185 return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2188 char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
2191 return handle->fns->realpath_fn(handle, path);
2194 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2195 const struct smb_filename *smb_fname,
2199 return handle->fns->chflags_fn(handle, smb_fname, flags);
2202 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2203 const SMB_STRUCT_STAT *sbuf)
2205 VFS_FIND(file_id_create);
2206 return handle->fns->file_id_create_fn(handle, sbuf);
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)
2216 VFS_FIND(streaminfo);
2217 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2218 num_streams, streams);
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)
2225 VFS_FIND(get_real_filename);
2226 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2230 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2231 const char *filename)
2233 VFS_FIND(connectpath);
2234 return handle->fns->connectpath_fn(handle, filename);
2237 bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
2238 struct files_struct *fsp,
2239 struct lock_struct *plock)
2241 VFS_FIND(strict_lock);
2242 return handle->fns->strict_lock_fn(handle, fsp, plock);
2245 void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
2246 struct files_struct *fsp,
2247 struct lock_struct *plock)
2249 VFS_FIND(strict_unlock);
2250 handle->fns->strict_unlock_fn(handle, fsp, plock);
2253 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2255 enum vfs_translate_direction direction,
2256 TALLOC_CTX *mem_ctx,
2259 VFS_FIND(translate_name);
2260 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2264 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2265 struct files_struct *fsp,
2269 const uint8_t *in_data,
2272 uint32_t max_out_len,
2276 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2277 in_data, in_len, out_data, max_out_len,
2281 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2282 struct smb_filename *smb_fname,
2285 VFS_FIND(get_dos_attributes);
2286 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2289 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2290 struct files_struct *fsp,
2293 VFS_FIND(fget_dos_attributes);
2294 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2297 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2298 const struct smb_filename *smb_fname,
2301 VFS_FIND(set_dos_attributes);
2302 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2305 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2306 struct files_struct *fsp,
2309 VFS_FIND(set_dos_attributes);
2310 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
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,
2318 struct files_struct *dest_fsp,
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,
2329 NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
2330 struct tevent_req *req,
2333 VFS_FIND(copy_chunk_recv);
2334 return handle->fns->copy_chunk_recv_fn(handle, req, copied);
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)
2343 VFS_FIND(get_compression);
2344 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
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)
2353 VFS_FIND(set_compression);
2354 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2358 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2359 TALLOC_CTX *mem_ctx,
2360 const char *service_path,
2363 VFS_FIND(snap_check_path);
2364 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2368 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2369 TALLOC_CTX *mem_ctx,
2370 const char *base_volume,
2376 VFS_FIND(snap_create);
2377 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2378 rw, base_path, snap_path);
2381 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2382 TALLOC_CTX *mem_ctx,
2386 VFS_FIND(snap_delete);
2387 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
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)
2397 VFS_FIND(fget_nt_acl);
2398 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
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)
2408 VFS_FIND(get_nt_acl);
2409 return handle->fns->get_nt_acl_fn(handle,
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)
2421 VFS_FIND(fset_nt_acl);
2422 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
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)
2432 VFS_FIND(audit_file);
2433 return handle->fns->audit_file_fn(handle,
2440 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle,
2441 const struct smb_filename *smb_fname,
2444 VFS_FIND(chmod_acl);
2445 return handle->fns->chmod_acl_fn(handle, smb_fname, mode);
2448 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2449 struct files_struct *fsp, mode_t mode)
2451 VFS_FIND(fchmod_acl);
2452 return handle->fns->fchmod_acl_fn(handle, fsp, mode);
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)
2460 VFS_FIND(sys_acl_get_file);
2461 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
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)
2468 VFS_FIND(sys_acl_get_fd);
2469 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
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,
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);
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,
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);
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,
2498 VFS_FIND(sys_acl_set_file);
2499 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2503 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2504 struct files_struct *fsp, SMB_ACL_T theacl)
2506 VFS_FIND(sys_acl_set_fd);
2507 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2510 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2511 const struct smb_filename *smb_fname)
2513 VFS_FIND(sys_acl_delete_def_file);
2514 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2517 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2518 const struct smb_filename *smb_fname,
2524 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
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)
2531 VFS_FIND(fgetxattr);
2532 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2535 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2536 const struct smb_filename *smb_fname,
2540 VFS_FIND(listxattr);
2541 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2544 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2545 struct files_struct *fsp, char *list,
2548 VFS_FIND(flistxattr);
2549 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2552 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2553 const struct smb_filename *smb_fname,
2556 VFS_FIND(removexattr);
2557 return handle->fns->removexattr_fn(handle, smb_fname, name);
2560 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2561 struct files_struct *fsp, const char *name)
2563 VFS_FIND(fremovexattr);
2564 return handle->fns->fremovexattr_fn(handle, fsp, name);
2567 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2568 const struct smb_filename *smb_fname,
2575 return handle->fns->setxattr_fn(handle, smb_fname,
2576 name, value, size, flags);
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)
2583 VFS_FIND(fsetxattr);
2584 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2587 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2588 struct files_struct *fsp)
2590 VFS_FIND(aio_force);
2591 return handle->fns->aio_force_fn(handle, fsp);
2594 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2595 struct files_struct *fsp,
2596 TALLOC_CTX *mem_ctx,
2599 VFS_FIND(durable_cookie);
2600 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
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)
2609 VFS_FIND(durable_disconnect);
2610 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2611 mem_ctx, new_cookie);
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)
2622 VFS_FIND(durable_reconnect);
2623 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2624 old_cookie, mem_ctx, fsp,
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)
2633 VFS_FIND(readdir_attr);
2634 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);