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"
34 #include "lib/util/tevent_ntstatus.h"
37 #define DBGC_CLASS DBGC_VFS
42 struct vfs_fsp_data *next;
43 struct vfs_handle_struct *owner;
44 void (*destroy)(void *p_data);
46 /* NOTE: This structure contains four pointers so that we can guarantee
47 * that the end of the structure is always both 4-byte and 8-byte aligned.
51 struct vfs_init_function_entry {
53 struct vfs_init_function_entry *prev, *next;
54 const struct vfs_fn_pointers *fns;
57 /****************************************************************************
58 maintain the list of available backends
59 ****************************************************************************/
61 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
63 struct vfs_init_function_entry *entry = backends;
65 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
68 if (strcmp(entry->name, name)==0) return entry;
75 NTSTATUS smb_register_vfs(int version, const char *name,
76 const struct vfs_fn_pointers *fns)
78 struct vfs_init_function_entry *entry = backends;
80 if ((version != SMB_VFS_INTERFACE_VERSION)) {
81 DEBUG(0, ("Failed to register vfs module.\n"
82 "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
83 "current SMB_VFS_INTERFACE_VERSION is %d.\n"
84 "Please recompile against the current Samba Version!\n",
85 version, SMB_VFS_INTERFACE_VERSION));
86 return NT_STATUS_OBJECT_TYPE_MISMATCH;
89 if (!name || !name[0]) {
90 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
91 return NT_STATUS_INVALID_PARAMETER;
94 if (vfs_find_backend_entry(name)) {
95 DEBUG(0,("VFS module %s already loaded!\n", name));
96 return NT_STATUS_OBJECT_NAME_COLLISION;
99 entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
100 entry->name = smb_xstrdup(name);
103 DLIST_ADD(backends, entry);
104 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
108 /****************************************************************************
109 initialise default vfs hooks
110 ****************************************************************************/
112 static void vfs_init_default(connection_struct *conn)
114 DEBUG(3, ("Initialising default vfs hooks\n"));
115 vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
118 /****************************************************************************
119 initialise custom vfs hooks
120 ****************************************************************************/
122 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
124 char *module_path = NULL;
125 char *module_name = NULL;
126 char *module_param = NULL, *p;
127 vfs_handle_struct *handle;
128 const struct vfs_init_function_entry *entry;
130 if (!conn||!vfs_object||!vfs_object[0]) {
131 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
132 "empty vfs_object!\n"));
137 static_init_vfs(NULL);
140 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
142 module_path = smb_xstrdup(vfs_object);
144 p = strchr_m(module_path, ':');
149 trim_char(module_param, ' ', ' ');
152 trim_char(module_path, ' ', ' ');
154 module_name = smb_xstrdup(module_path);
156 if ((module_name[0] == '/') &&
157 (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
160 * Extract the module name from the path. Just use the base
161 * name of the last path component.
164 SAFE_FREE(module_name);
165 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
167 p = strchr_m(module_name, '.');
174 /* First, try to load the module with the new module system */
175 entry = vfs_find_backend_entry(module_name);
179 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
182 status = smb_load_module("vfs", module_path);
183 if (!NT_STATUS_IS_OK(status)) {
184 DEBUG(0, ("error probing vfs module '%s': %s\n",
185 module_path, nt_errstr(status)));
189 entry = vfs_find_backend_entry(module_name);
191 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
196 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
198 handle = talloc_zero(conn, vfs_handle_struct);
200 DEBUG(0,("TALLOC_ZERO() failed!\n"));
204 handle->fns = entry->fns;
206 handle->param = talloc_strdup(conn, module_param);
208 DLIST_ADD(conn->vfs_handles, handle);
210 SAFE_FREE(module_path);
211 SAFE_FREE(module_name);
215 SAFE_FREE(module_path);
216 SAFE_FREE(module_name);
220 /*****************************************************************
221 Allow VFS modules to extend files_struct with VFS-specific state.
222 This will be ok for small numbers of extensions, but might need to
223 be refactored if it becomes more widely used.
224 ******************************************************************/
226 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
228 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
229 files_struct *fsp, size_t ext_size,
230 void (*destroy_fn)(void *p_data))
232 struct vfs_fsp_data *ext;
235 /* Prevent VFS modules adding multiple extensions. */
236 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
240 ext = (struct vfs_fsp_data *)TALLOC_ZERO(
241 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
247 ext->next = fsp->vfs_extension;
248 ext->destroy = destroy_fn;
249 fsp->vfs_extension = ext;
250 return EXT_DATA_AREA(ext);
253 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
255 struct vfs_fsp_data *curr;
256 struct vfs_fsp_data *prev;
258 for (curr = fsp->vfs_extension, prev = NULL;
260 prev = curr, curr = curr->next) {
261 if (curr->owner == handle) {
263 prev->next = curr->next;
265 fsp->vfs_extension = curr->next;
268 curr->destroy(EXT_DATA_AREA(curr));
276 void vfs_remove_all_fsp_extensions(files_struct *fsp)
278 struct vfs_fsp_data *curr;
279 struct vfs_fsp_data *next;
281 for (curr = fsp->vfs_extension; curr; curr = next) {
284 fsp->vfs_extension = next;
287 curr->destroy(EXT_DATA_AREA(curr));
293 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
295 struct vfs_fsp_data *head;
297 for (head = fsp->vfs_extension; head; head = head->next) {
298 if (head->owner == handle) {
306 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
308 struct vfs_fsp_data *head;
310 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
312 return EXT_DATA_AREA(head);
321 * Ensure this module catches all VFS functions.
324 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
327 bool missing_fn = false;
329 const uintptr_t *end = (const uintptr_t *)(fns + 1);
331 for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
332 if (*((const uintptr_t *)fns + idx) == 0) {
333 DBG_ERR("VFS function at index %d not implemented "
334 "in module %s\n", idx, module);
340 smb_panic("Required VFS function not implemented in module.\n");
344 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
350 /*****************************************************************
352 ******************************************************************/
354 bool smbd_vfs_init(connection_struct *conn)
356 const char **vfs_objects;
360 /* Normal share - initialise with disk access functions */
361 vfs_init_default(conn);
363 /* No need to load vfs modules for printer connections */
368 vfs_objects = lp_vfs_objects(SNUM(conn));
370 /* Override VFS functions if 'vfs object' was not specified*/
371 if (!vfs_objects || !vfs_objects[0])
374 for (i=0; vfs_objects[i] ;) {
378 for (j=i-1; j >= 0; j--) {
379 if (!vfs_init_custom(conn, vfs_objects[j])) {
380 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
387 /*******************************************************************
388 Check if a file exists in the vfs.
389 ********************************************************************/
391 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
393 /* Only return OK if stat was successful and S_ISREG */
394 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
395 S_ISREG(smb_fname->st.st_ex_mode)) {
399 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
402 ssize_t vfs_pwrite_data(struct smb_request *req,
411 if (req && req->unread_bytes) {
412 int sockfd = req->xconn->transport.sock;
413 SMB_ASSERT(req->unread_bytes == N);
414 /* VFS_RECVFILE must drain the socket
415 * before returning. */
416 req->unread_bytes = 0;
418 * Leave the socket non-blocking and
419 * use SMB_VFS_RECVFILE. If it returns
420 * EAGAIN || EWOULDBLOCK temporarily set
421 * the socket blocking and retry
425 ret = SMB_VFS_RECVFILE(sockfd,
429 if (ret == 0 || (ret == -1 &&
431 errno == EWOULDBLOCK))) {
433 /* Ensure the socket is blocking. */
434 old_flags = fcntl(sockfd, F_GETFL, 0);
435 if (set_blocking(sockfd, true) == -1) {
438 ret = SMB_VFS_RECVFILE(sockfd,
442 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
449 return (ssize_t)total;
451 /* Any other error case. */
457 return (ssize_t)total;
461 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
471 return (ssize_t)total;
473 /****************************************************************************
474 An allocate file space call using the vfs interface.
475 Allocates space for a file from a filedescriptor.
476 Returns 0 on success, -1 on failure.
477 ****************************************************************************/
479 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
482 connection_struct *conn = fsp->conn;
483 uint64_t space_avail;
484 uint64_t bsize,dfree,dsize;
488 * Actually try and commit the space on disk....
491 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
492 fsp_str_dbg(fsp), (double)len));
494 if (((off_t)len) < 0) {
495 DEBUG(0,("vfs_allocate_file_space: %s negative len "
496 "requested.\n", fsp_str_dbg(fsp)));
501 status = vfs_stat_fsp(fsp);
502 if (!NT_STATUS_IS_OK(status)) {
506 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
509 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
510 /* Shrink - use ftruncate. */
512 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
513 "size %.0f\n", fsp_str_dbg(fsp),
514 (double)fsp->fsp_name->st.st_ex_size));
516 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
518 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
519 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
520 set_filelen_write_cache(fsp, len);
523 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
528 /* Grow - we need to test if we have enough space. */
530 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
532 if (lp_strict_allocate(SNUM(fsp->conn))) {
533 /* See if we have a syscall that will allocate beyond
534 end-of-file without changing EOF. */
535 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
541 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
544 /* We changed the allocation size on disk, but not
545 EOF - exactly as required. We're done ! */
549 if (ret == -1 && errno == ENOSPC) {
553 len -= fsp->fsp_name->st.st_ex_size;
554 len /= 1024; /* Len is now number of 1k blocks needed. */
556 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
557 if (space_avail == (uint64_t)-1) {
561 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
562 "needed blocks = %.0f, space avail = %.0f\n",
563 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
564 (double)space_avail));
566 if (len > space_avail) {
574 /****************************************************************************
575 A vfs set_filelen call.
576 set the length of a file from a filedescriptor.
577 Returns 0 on success, -1 on failure.
578 ****************************************************************************/
580 int vfs_set_filelen(files_struct *fsp, off_t len)
584 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
586 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
587 fsp_str_dbg(fsp), (double)len));
588 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
589 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
590 set_filelen_write_cache(fsp, len);
591 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
592 FILE_NOTIFY_CHANGE_SIZE
593 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
594 fsp->fsp_name->base_name);
597 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
602 /****************************************************************************
603 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
604 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
605 as this is also called from the default SMB_VFS_FTRUNCATE code.
606 Always extends the file size.
607 Returns 0 on success, -1 on failure.
608 ****************************************************************************/
610 #define SPARSE_BUF_WRITE_SIZE (32*1024)
612 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
618 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
625 while (total < len) {
626 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
628 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
629 if (pwrite_ret == -1) {
630 int saved_errno = errno;
631 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
632 "%s failed with error %s\n",
633 fsp_str_dbg(fsp), strerror(saved_errno)));
643 /****************************************************************************
644 A vfs fill sparse call.
645 Writes zeros from the end of file to len, if len is greater than EOF.
646 Used only by strict_sync.
647 Returns 0 on success, -1 on failure.
648 ****************************************************************************/
650 int vfs_fill_sparse(files_struct *fsp, off_t len)
657 status = vfs_stat_fsp(fsp);
658 if (!NT_STATUS_IS_OK(status)) {
662 if (len <= fsp->fsp_name->st.st_ex_size) {
667 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
672 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
673 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
674 (double)fsp->fsp_name->st.st_ex_size, (double)len,
675 (double)(len - fsp->fsp_name->st.st_ex_size)));
677 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
679 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
681 offset = fsp->fsp_name->st.st_ex_size;
682 num_to_write = len - fsp->fsp_name->st.st_ex_size;
684 /* Only do this on non-stream file handles. */
685 if (fsp->base_fsp == NULL) {
686 /* for allocation try fallocate first. This can fail on some
687 * platforms e.g. when the filesystem doesn't support it and no
688 * emulation is being done by the libc (like on AIX with JFS1). In that
689 * case we do our own emulation. fallocate implementations can
690 * return ENOTSUP or EINVAL in cases like that. */
691 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
692 if (ret == -1 && errno == ENOSPC) {
698 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
699 "error %d. Falling back to slow manual allocation\n", ret));
702 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
707 set_filelen_write_cache(fsp, len);
710 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
714 /****************************************************************************
715 Transfer some data (n bytes) between two file_struct's.
716 ****************************************************************************/
718 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
720 struct files_struct *fsp = (struct files_struct *)file;
722 return SMB_VFS_PREAD(fsp, buf, len, offset);
725 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
727 struct files_struct *fsp = (struct files_struct *)file;
729 return SMB_VFS_PWRITE(fsp, buf, len, offset);
732 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
734 return transfer_file_internal((void *)in, (void *)out, n,
735 vfs_pread_fn, vfs_pwrite_fn);
738 /*******************************************************************
739 A vfs_readdir wrapper which just returns the file name.
740 ********************************************************************/
742 const char *vfs_readdirname(connection_struct *conn, void *p,
743 SMB_STRUCT_STAT *sbuf, char **talloced)
745 struct dirent *ptr= NULL;
753 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
765 #ifdef HAVE_BROKEN_READDIR_NAME
766 /* using /usr/ucb/cc is BAD */
770 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
771 talloc_tos(), &translated);
772 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
776 *talloced = translated;
777 if (!NT_STATUS_IS_OK(status)) {
783 /*******************************************************************
784 A wrapper for vfs_chdir().
785 ********************************************************************/
787 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
790 struct smb_filename *cwd = NULL;
793 LastDir = SMB_STRDUP("");
796 if (ISDOT(smb_fname->base_name)) {
800 if (*smb_fname->base_name == '/' &&
801 strcsequal(LastDir,smb_fname->base_name)) {
805 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
807 ret = SMB_VFS_CHDIR(conn, smb_fname);
813 * Always replace conn->cwd_fsp. We
814 * don't know if it's been modified by
815 * VFS modules in the stack.
819 cwd = vfs_GetWd(conn, conn);
822 * vfs_GetWd() failed.
823 * We must be able to read cwd.
824 * Return to original directory
827 int saved_errno = errno;
829 if (conn->cwd_fsp->fsp_name == NULL) {
831 * Failed on the very first chdir()+getwd()
832 * for this connection. We can't
835 smb_panic("conn->cwd getwd failed\n");
840 /* Return to the previous $cwd. */
841 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
843 smb_panic("conn->cwd getwd failed\n");
848 /* And fail the chdir(). */
852 /* vfs_GetWd() succeeded. */
853 /* Replace global cache. */
855 LastDir = SMB_STRDUP(smb_fname->base_name);
858 * (Indirect) Callers of vfs_ChDir() may still hold references to the
859 * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
860 * callers can use it for the lifetime of the SMB request.
862 talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
864 conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
865 conn->cwd_fsp->fh->fd = AT_FDCWD;
867 DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
872 /*******************************************************************
873 Return the absolute current directory path - given a UNIX pathname.
874 Note that this path is returned in DOS format, not UNIX
875 format. Note this can be called with conn == NULL.
876 ********************************************************************/
878 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
880 struct smb_filename *current_dir_fname = NULL;
882 struct smb_filename *smb_fname_dot = NULL;
883 struct smb_filename *smb_fname_full = NULL;
884 struct smb_filename *result = NULL;
886 if (!lp_getwd_cache()) {
890 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
891 if (smb_fname_dot == NULL) {
896 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
898 * Known to fail for root: the directory may be NFS-mounted
899 * and exported with root_squash (so has no root access).
901 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
902 "(NFS problem ?)\n", strerror(errno) ));
906 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
908 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
911 data_blob_const(&key, sizeof(key)));
913 if (smb_fname_full == NULL) {
917 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
918 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
919 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
920 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
923 * Note: smb_fname_full is owned by smbd_memcache()
924 * so we must make a copy to return.
926 result = cp_smb_filename(ctx, smb_fname_full);
927 if (result == NULL) {
936 * We don't have the information to hand so rely on traditional
937 * methods. The very slow getcwd, which spawns a process on some
938 * systems, or the not quite so bad getwd.
941 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
942 if (current_dir_fname == NULL) {
943 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
948 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
949 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
952 * smbd_memcache() will own current_dir_fname after the
953 * memcache_add_talloc call, so we must make
954 * a copy on ctx to return.
956 result = cp_smb_filename(ctx, current_dir_fname);
957 if (result == NULL) {
962 * Ensure the memory going into the cache
963 * doesn't have a destructor so it can be
966 talloc_set_destructor(current_dir_fname, NULL);
968 memcache_add_talloc(smbd_memcache(),
970 data_blob_const(&key, sizeof(key)),
972 /* current_dir_fname is now == NULL here. */
974 /* current_dir_fname is already allocated on ctx. */
975 result = current_dir_fname;
979 TALLOC_FREE(smb_fname_dot);
981 * Don't free current_dir_fname here. It's either been moved
982 * to the memcache or is being returned in result.
987 /*******************************************************************
988 Reduce a file name, removing .. elements and checking that
989 it is below dir in the hierarchy. This uses realpath.
990 This function must run as root, and will return names
991 and valid stat structs that can be checked on open.
992 ********************************************************************/
994 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
995 const struct smb_filename *smb_fname,
996 struct smb_request *smbreq)
999 TALLOC_CTX *ctx = talloc_tos();
1000 const char *conn_rootdir;
1002 char *dir_name = NULL;
1003 char *resolved_name = NULL;
1004 const char *last_component = NULL;
1005 struct smb_filename *resolved_fname = NULL;
1006 struct smb_filename *saved_dir_fname = NULL;
1007 struct smb_filename *smb_fname_cwd = NULL;
1008 struct privilege_paths *priv_paths = NULL;
1011 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1012 smb_fname->base_name,
1013 conn->connectpath));
1016 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1018 status = NT_STATUS_NO_MEMORY;
1022 if (!parent_dirname(ctx, smb_fname->base_name,
1023 &dir_name, &last_component)) {
1024 status = NT_STATUS_NO_MEMORY;
1028 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1029 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1031 if (priv_paths->parent_name.base_name == NULL ||
1032 priv_paths->file_name.base_name == NULL) {
1033 status = NT_STATUS_NO_MEMORY;
1037 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1038 status = map_nt_error_from_unix(errno);
1041 /* Remember where we were. */
1042 saved_dir_fname = vfs_GetWd(ctx, conn);
1043 if (!saved_dir_fname) {
1044 status = map_nt_error_from_unix(errno);
1048 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1049 status = map_nt_error_from_unix(errno);
1053 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1054 if (smb_fname_cwd == NULL) {
1055 status = NT_STATUS_NO_MEMORY;
1059 /* Get the absolute path of the parent directory. */
1060 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1061 if (resolved_fname == NULL) {
1062 status = map_nt_error_from_unix(errno);
1065 resolved_name = resolved_fname->base_name;
1067 if (*resolved_name != '/') {
1068 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1069 "doesn't return absolute paths !\n"));
1070 status = NT_STATUS_OBJECT_NAME_INVALID;
1074 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1075 priv_paths->parent_name.base_name,
1078 /* Now check the stat value is the same. */
1079 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1080 status = map_nt_error_from_unix(errno);
1084 /* Ensure we're pointing at the same place. */
1085 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1086 DEBUG(0,("check_reduced_name_with_privilege: "
1087 "device/inode/uid/gid on directory %s changed. "
1088 "Denying access !\n",
1089 priv_paths->parent_name.base_name));
1090 status = NT_STATUS_ACCESS_DENIED;
1094 /* Ensure we're below the connect path. */
1096 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1097 if (conn_rootdir == NULL) {
1098 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1100 status = NT_STATUS_ACCESS_DENIED;
1104 rootdir_len = strlen(conn_rootdir);
1107 * In the case of rootdir_len == 1, we know that conn_rootdir is
1108 * "/", and we also know that resolved_name starts with a slash.
1109 * So, in this corner case, resolved_name is automatically a
1110 * sub-directory of the conn_rootdir. Thus we can skip the string
1111 * comparison and the next character checks (which are even
1112 * wrong in this case).
1114 if (rootdir_len != 1) {
1117 matched = (strncmp(conn_rootdir, resolved_name,
1120 if (!matched || (resolved_name[rootdir_len] != '/' &&
1121 resolved_name[rootdir_len] != '\0')) {
1122 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1123 "access attempt: %s is a symlink outside the "
1126 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1127 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1128 status = NT_STATUS_ACCESS_DENIED;
1133 /* Now ensure that the last component either doesn't
1134 exist, or is *NOT* a symlink. */
1136 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1138 /* Errno must be ENOENT for this be ok. */
1139 if (errno != ENOENT) {
1140 status = map_nt_error_from_unix(errno);
1141 DEBUG(2, ("check_reduced_name_with_privilege: "
1142 "LSTAT on %s failed with %s\n",
1143 priv_paths->file_name.base_name,
1144 nt_errstr(status)));
1149 if (VALID_STAT(priv_paths->file_name.st) &&
1150 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1151 DEBUG(2, ("check_reduced_name_with_privilege: "
1152 "Last component %s is a symlink. Denying"
1154 priv_paths->file_name.base_name));
1155 status = NT_STATUS_ACCESS_DENIED;
1159 smbreq->priv_paths = priv_paths;
1160 status = NT_STATUS_OK;
1164 if (saved_dir_fname != NULL) {
1165 vfs_ChDir(conn, saved_dir_fname);
1166 TALLOC_FREE(saved_dir_fname);
1168 TALLOC_FREE(resolved_fname);
1169 if (!NT_STATUS_IS_OK(status)) {
1170 TALLOC_FREE(priv_paths);
1172 TALLOC_FREE(dir_name);
1176 /*******************************************************************
1177 Reduce a file name, removing .. elements and checking that
1178 it is below dir in the hierarchy. This uses realpath.
1180 If cwd_name == NULL then fname is a client given path relative
1181 to the root path of the share.
1183 If cwd_name != NULL then fname is a client given path relative
1184 to cwd_name. cwd_name is relative to the root path of the share.
1185 ********************************************************************/
1187 NTSTATUS check_reduced_name(connection_struct *conn,
1188 const struct smb_filename *cwd_fname,
1189 const struct smb_filename *smb_fname)
1191 TALLOC_CTX *ctx = talloc_tos();
1192 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1193 const char *fname = smb_fname->base_name;
1194 struct smb_filename *resolved_fname;
1195 char *resolved_name = NULL;
1196 char *new_fname = NULL;
1197 bool allow_symlinks = true;
1198 bool allow_widelinks = false;
1200 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1202 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1204 if (resolved_fname == NULL) {
1207 DEBUG(3,("check_reduced_name: Component not a "
1208 "directory in getting realpath for "
1210 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1213 char *dir_name = NULL;
1214 struct smb_filename dir_fname = {0};
1215 const char *last_component = NULL;
1217 /* Last component didn't exist.
1218 Remove it and try and canonicalise
1219 the directory name. */
1220 if (!parent_dirname(ctx, fname,
1223 return NT_STATUS_NO_MEMORY;
1226 dir_fname = (struct smb_filename)
1227 { .base_name = dir_name };
1228 resolved_fname = SMB_VFS_REALPATH(conn,
1231 if (resolved_fname == NULL) {
1232 NTSTATUS status = map_nt_error_from_unix(errno);
1234 if (errno == ENOENT || errno == ENOTDIR) {
1235 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1238 DEBUG(3,("check_reduce_name: "
1239 "couldn't get realpath for "
1242 nt_errstr(status)));
1245 resolved_name = talloc_asprintf(ctx,
1247 resolved_fname->base_name,
1249 if (resolved_name == NULL) {
1250 return NT_STATUS_NO_MEMORY;
1255 DEBUG(3,("check_reduced_name: couldn't get "
1256 "realpath for %s\n", fname));
1257 return map_nt_error_from_unix(errno);
1260 resolved_name = resolved_fname->base_name;
1263 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1266 if (*resolved_name != '/') {
1267 DEBUG(0,("check_reduced_name: realpath doesn't return "
1268 "absolute paths !\n"));
1269 TALLOC_FREE(resolved_fname);
1270 return NT_STATUS_OBJECT_NAME_INVALID;
1273 allow_widelinks = lp_widelinks(SNUM(conn));
1274 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1276 /* Common widelinks and symlinks checks. */
1277 if (!allow_widelinks || !allow_symlinks) {
1278 const char *conn_rootdir;
1281 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1282 if (conn_rootdir == NULL) {
1283 DEBUG(2, ("check_reduced_name: Could not get "
1285 TALLOC_FREE(resolved_fname);
1286 return NT_STATUS_ACCESS_DENIED;
1289 rootdir_len = strlen(conn_rootdir);
1292 * In the case of rootdir_len == 1, we know that
1293 * conn_rootdir is "/", and we also know that
1294 * resolved_name starts with a slash. So, in this
1295 * corner case, resolved_name is automatically a
1296 * sub-directory of the conn_rootdir. Thus we can skip
1297 * the string comparison and the next character checks
1298 * (which are even wrong in this case).
1300 if (rootdir_len != 1) {
1303 matched = (strncmp(conn_rootdir, resolved_name,
1305 if (!matched || (resolved_name[rootdir_len] != '/' &&
1306 resolved_name[rootdir_len] != '\0')) {
1307 DEBUG(2, ("check_reduced_name: Bad access "
1308 "attempt: %s is a symlink outside the "
1309 "share path\n", fname));
1310 DEBUGADD(2, ("conn_rootdir =%s\n",
1312 DEBUGADD(2, ("resolved_name=%s\n",
1314 TALLOC_FREE(resolved_fname);
1315 return NT_STATUS_ACCESS_DENIED;
1319 /* Extra checks if all symlinks are disallowed. */
1320 if (!allow_symlinks) {
1321 /* fname can't have changed in resolved_path. */
1322 const char *p = &resolved_name[rootdir_len];
1325 * UNIX filesystem semantics, names consisting
1326 * only of "." or ".." CANNOT be symlinks.
1328 if (ISDOT(fname) || ISDOTDOT(fname)) {
1333 DEBUG(2, ("check_reduced_name: logic error (%c) "
1334 "in resolved_name: %s\n",
1337 TALLOC_FREE(resolved_fname);
1338 return NT_STATUS_ACCESS_DENIED;
1344 * If cwd_name is present and not ".",
1345 * then fname is relative to that, not
1346 * the root of the share. Make sure the
1347 * path we check is the one the client
1348 * sent (cwd_name+fname).
1350 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1351 new_fname = talloc_asprintf(ctx,
1355 if (new_fname == NULL) {
1356 TALLOC_FREE(resolved_fname);
1357 return NT_STATUS_NO_MEMORY;
1362 if (strcmp(fname, p)!=0) {
1363 DEBUG(2, ("check_reduced_name: Bad access "
1364 "attempt: %s is a symlink to %s\n",
1366 TALLOC_FREE(resolved_fname);
1367 TALLOC_FREE(new_fname);
1368 return NT_STATUS_ACCESS_DENIED;
1375 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1376 TALLOC_FREE(resolved_fname);
1377 TALLOC_FREE(new_fname);
1378 return NT_STATUS_OK;
1382 * XXX: This is temporary and there should be no callers of this once
1383 * smb_filename is plumbed through all path based operations.
1385 * Called when we know stream name parsing has already been done.
1387 int vfs_stat_smb_basename(struct connection_struct *conn,
1388 const struct smb_filename *smb_fname_in,
1389 SMB_STRUCT_STAT *psbuf)
1391 struct smb_filename smb_fname = {
1392 .base_name = discard_const_p(char, smb_fname_in->base_name),
1393 .flags = smb_fname_in->flags
1397 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1398 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1400 ret = SMB_VFS_STAT(conn, &smb_fname);
1404 *psbuf = smb_fname.st;
1410 * Ensure LSTAT is called for POSIX paths.
1413 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1417 if(fsp->fh->fd == -1) {
1418 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1419 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1421 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1424 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1427 return map_nt_error_from_unix(errno);
1429 return NT_STATUS_OK;
1433 * Initialize num_streams and streams, then call VFS op streaminfo
1435 NTSTATUS vfs_streaminfo(connection_struct *conn,
1436 struct files_struct *fsp,
1437 const struct smb_filename *smb_fname,
1438 TALLOC_CTX *mem_ctx,
1439 unsigned int *num_streams,
1440 struct stream_struct **streams)
1444 return SMB_VFS_STREAMINFO(conn,
1453 generate a file_id from a stat structure
1455 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1457 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1460 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1461 const char *service, const char *user)
1464 return handle->fns->connect_fn(handle, service, user);
1467 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1469 VFS_FIND(disconnect);
1470 handle->fns->disconnect_fn(handle);
1473 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1474 const struct smb_filename *smb_fname,
1479 VFS_FIND(disk_free);
1480 return handle->fns->disk_free_fn(handle, smb_fname,
1481 bsize, dfree, dsize);
1484 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1485 const struct smb_filename *smb_fname,
1486 enum SMB_QUOTA_TYPE qtype,
1490 VFS_FIND(get_quota);
1491 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1494 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1495 enum SMB_QUOTA_TYPE qtype, unid_t id,
1498 VFS_FIND(set_quota);
1499 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1502 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1503 struct files_struct *fsp,
1504 struct shadow_copy_data *shadow_copy_data,
1507 VFS_FIND(get_shadow_copy_data);
1508 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1512 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1513 const struct smb_filename *smb_fname,
1514 struct vfs_statvfs_struct *statbuf)
1517 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1520 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1521 enum timestamp_set_resolution *p_ts_res)
1523 VFS_FIND(fs_capabilities);
1524 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1527 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1528 struct dfs_GetDFSReferral *r)
1530 VFS_FIND(get_dfs_referrals);
1531 return handle->fns->get_dfs_referrals_fn(handle, r);
1534 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1535 const struct smb_filename *smb_fname,
1537 uint32_t attributes)
1540 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1543 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1544 struct files_struct *fsp,
1546 uint32_t attributes)
1548 VFS_FIND(fdopendir);
1549 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1552 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1554 SMB_STRUCT_STAT *sbuf)
1557 return handle->fns->readdir_fn(handle, dirp, sbuf);
1560 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1561 DIR *dirp, long offset)
1564 handle->fns->seekdir_fn(handle, dirp, offset);
1567 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1571 return handle->fns->telldir_fn(handle, dirp);
1574 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1577 VFS_FIND(rewind_dir);
1578 handle->fns->rewind_dir_fn(handle, dirp);
1581 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1582 const struct smb_filename *smb_fname,
1586 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1589 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1590 const struct smb_filename *smb_fname)
1593 return handle->fns->rmdir_fn(handle, smb_fname);
1596 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1600 return handle->fns->closedir_fn(handle, dir);
1603 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1604 struct smb_filename *smb_fname, struct files_struct *fsp,
1605 int flags, mode_t mode)
1608 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1611 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1612 struct smb_request *req,
1613 uint16_t root_dir_fid,
1614 struct smb_filename *smb_fname,
1615 uint32_t access_mask,
1616 uint32_t share_access,
1617 uint32_t create_disposition,
1618 uint32_t create_options,
1619 uint32_t file_attributes,
1620 uint32_t oplock_request,
1621 const struct smb2_lease *lease,
1622 uint64_t allocation_size,
1623 uint32_t private_flags,
1624 struct security_descriptor *sd,
1625 struct ea_list *ea_list,
1626 files_struct **result,
1628 const struct smb2_create_blobs *in_context_blobs,
1629 struct smb2_create_blobs *out_context_blobs)
1631 VFS_FIND(create_file);
1632 return handle->fns->create_file_fn(
1633 handle, req, root_dir_fid, smb_fname, access_mask,
1634 share_access, create_disposition, create_options,
1635 file_attributes, oplock_request, lease, allocation_size,
1636 private_flags, sd, ea_list,
1637 result, pinfo, in_context_blobs, out_context_blobs);
1640 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1641 struct files_struct *fsp)
1644 return handle->fns->close_fn(handle, fsp);
1647 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1648 struct files_struct *fsp, void *data, size_t n,
1652 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1655 struct smb_vfs_call_pread_state {
1656 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1658 struct vfs_aio_state vfs_aio_state;
1661 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1663 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1664 TALLOC_CTX *mem_ctx,
1665 struct tevent_context *ev,
1666 struct files_struct *fsp,
1668 size_t n, off_t offset)
1670 struct tevent_req *req, *subreq;
1671 struct smb_vfs_call_pread_state *state;
1673 req = tevent_req_create(mem_ctx, &state,
1674 struct smb_vfs_call_pread_state);
1678 VFS_FIND(pread_send);
1679 state->recv_fn = handle->fns->pread_recv_fn;
1681 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1683 if (tevent_req_nomem(subreq, req)) {
1684 return tevent_req_post(req, ev);
1686 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1690 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1692 struct tevent_req *req = tevent_req_callback_data(
1693 subreq, struct tevent_req);
1694 struct smb_vfs_call_pread_state *state = tevent_req_data(
1695 req, struct smb_vfs_call_pread_state);
1697 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1698 TALLOC_FREE(subreq);
1699 if (state->retval == -1) {
1700 tevent_req_error(req, state->vfs_aio_state.error);
1703 tevent_req_done(req);
1706 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1707 struct vfs_aio_state *vfs_aio_state)
1709 struct smb_vfs_call_pread_state *state = tevent_req_data(
1710 req, struct smb_vfs_call_pread_state);
1713 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1714 tevent_req_received(req);
1717 *vfs_aio_state = state->vfs_aio_state;
1718 retval = state->retval;
1719 tevent_req_received(req);
1723 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1724 struct files_struct *fsp, const void *data,
1725 size_t n, off_t offset)
1728 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1731 struct smb_vfs_call_pwrite_state {
1732 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1734 struct vfs_aio_state vfs_aio_state;
1737 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1739 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1740 TALLOC_CTX *mem_ctx,
1741 struct tevent_context *ev,
1742 struct files_struct *fsp,
1744 size_t n, off_t offset)
1746 struct tevent_req *req, *subreq;
1747 struct smb_vfs_call_pwrite_state *state;
1749 req = tevent_req_create(mem_ctx, &state,
1750 struct smb_vfs_call_pwrite_state);
1754 VFS_FIND(pwrite_send);
1755 state->recv_fn = handle->fns->pwrite_recv_fn;
1757 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1759 if (tevent_req_nomem(subreq, req)) {
1760 return tevent_req_post(req, ev);
1762 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1766 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1768 struct tevent_req *req = tevent_req_callback_data(
1769 subreq, struct tevent_req);
1770 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1771 req, struct smb_vfs_call_pwrite_state);
1773 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1774 TALLOC_FREE(subreq);
1775 if (state->retval == -1) {
1776 tevent_req_error(req, state->vfs_aio_state.error);
1779 tevent_req_done(req);
1782 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1783 struct vfs_aio_state *vfs_aio_state)
1785 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1786 req, struct smb_vfs_call_pwrite_state);
1789 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1790 tevent_req_received(req);
1793 *vfs_aio_state = state->vfs_aio_state;
1794 retval = state->retval;
1795 tevent_req_received(req);
1799 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1800 struct files_struct *fsp, off_t offset,
1804 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1807 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1808 files_struct *fromfsp, const DATA_BLOB *header,
1809 off_t offset, size_t count)
1812 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1816 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1817 files_struct *tofsp, off_t offset,
1821 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1824 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
1825 files_struct *srcfsp,
1826 const struct smb_filename *smb_fname_src,
1827 files_struct *dstfsp,
1828 const struct smb_filename *smb_fname_dst)
1831 return handle->fns->renameat_fn(handle,
1838 struct smb_vfs_call_fsync_state {
1839 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1841 struct vfs_aio_state vfs_aio_state;
1844 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1846 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1847 TALLOC_CTX *mem_ctx,
1848 struct tevent_context *ev,
1849 struct files_struct *fsp)
1851 struct tevent_req *req, *subreq;
1852 struct smb_vfs_call_fsync_state *state;
1854 req = tevent_req_create(mem_ctx, &state,
1855 struct smb_vfs_call_fsync_state);
1859 VFS_FIND(fsync_send);
1860 state->recv_fn = handle->fns->fsync_recv_fn;
1862 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1863 if (tevent_req_nomem(subreq, req)) {
1864 return tevent_req_post(req, ev);
1866 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1870 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1872 struct tevent_req *req = tevent_req_callback_data(
1873 subreq, struct tevent_req);
1874 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1875 req, struct smb_vfs_call_fsync_state);
1877 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1878 TALLOC_FREE(subreq);
1879 if (state->retval == -1) {
1880 tevent_req_error(req, state->vfs_aio_state.error);
1883 tevent_req_done(req);
1886 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1888 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1889 req, struct smb_vfs_call_fsync_state);
1892 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1893 tevent_req_received(req);
1896 *vfs_aio_state = state->vfs_aio_state;
1897 retval = state->retval;
1898 tevent_req_received(req);
1903 * Synchronous version of fsync, built from backend
1904 * async VFS primitives. Uses a temporary sub-event
1905 * context (NOT NESTED).
1908 int smb_vfs_fsync_sync(files_struct *fsp)
1910 TALLOC_CTX *frame = talloc_stackframe();
1911 struct tevent_req *req = NULL;
1912 struct vfs_aio_state aio_state = { 0 };
1915 struct tevent_context *ev = samba_tevent_context_init(frame);
1921 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
1926 ok = tevent_req_poll(req, ev);
1931 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
1936 if (aio_state.error != 0) {
1937 errno = aio_state.error;
1942 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1943 struct smb_filename *smb_fname)
1946 return handle->fns->stat_fn(handle, smb_fname);
1949 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1950 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1953 return handle->fns->fstat_fn(handle, fsp, sbuf);
1956 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1957 struct smb_filename *smb_filename)
1960 return handle->fns->lstat_fn(handle, smb_filename);
1963 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1964 struct files_struct *fsp,
1965 const SMB_STRUCT_STAT *sbuf)
1967 VFS_FIND(get_alloc_size);
1968 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1971 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1972 const struct smb_filename *smb_fname)
1975 return handle->fns->unlink_fn(handle, smb_fname);
1978 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1979 const struct smb_filename *smb_fname,
1983 return handle->fns->chmod_fn(handle, smb_fname, mode);
1986 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1987 struct files_struct *fsp, mode_t mode)
1990 return handle->fns->fchmod_fn(handle, fsp, mode);
1993 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1994 const struct smb_filename *smb_fname,
1999 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
2002 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2003 struct files_struct *fsp, uid_t uid, gid_t gid)
2006 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2009 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2010 const struct smb_filename *smb_fname,
2015 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2018 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2021 bool as_root = false;
2024 if (fsp->fh->fd != -1) {
2026 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2028 return NT_STATUS_OK;
2030 if (ret == -1 && errno != ENOSYS) {
2031 return map_nt_error_from_unix(errno);
2035 as_root = (geteuid() == 0);
2039 * We are being asked to chown as root. Make
2040 * sure we chdir() into the path to pin it,
2041 * and always act using lchown to ensure we
2042 * don't deref any symbolic links.
2044 char *parent_dir = NULL;
2045 const char *final_component = NULL;
2046 struct smb_filename *local_smb_fname = NULL;
2047 struct smb_filename parent_dir_fname = {0};
2048 struct smb_filename *saved_dir_fname = NULL;
2050 saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
2051 if (!saved_dir_fname) {
2052 status = map_nt_error_from_unix(errno);
2053 DEBUG(0,("vfs_chown_fsp: failed to get "
2054 "current working directory. Error was %s\n",
2059 if (!parent_dirname(talloc_tos(),
2060 fsp->fsp_name->base_name,
2062 &final_component)) {
2063 return NT_STATUS_NO_MEMORY;
2066 parent_dir_fname = (struct smb_filename) {
2067 .base_name = parent_dir,
2068 .flags = fsp->fsp_name->flags
2071 /* cd into the parent dir to pin it. */
2072 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2074 return map_nt_error_from_unix(errno);
2077 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2081 fsp->fsp_name->flags);
2082 if (local_smb_fname == NULL) {
2083 status = NT_STATUS_NO_MEMORY;
2087 /* Must use lstat here. */
2088 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2090 status = map_nt_error_from_unix(errno);
2094 /* Ensure it matches the fsp stat. */
2095 if (!check_same_stat(&local_smb_fname->st,
2096 &fsp->fsp_name->st)) {
2097 status = NT_STATUS_ACCESS_DENIED;
2101 ret = SMB_VFS_LCHOWN(fsp->conn,
2106 status = NT_STATUS_OK;
2108 status = map_nt_error_from_unix(errno);
2113 vfs_ChDir(fsp->conn, saved_dir_fname);
2114 TALLOC_FREE(local_smb_fname);
2115 TALLOC_FREE(saved_dir_fname);
2116 TALLOC_FREE(parent_dir);
2121 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2122 ret = SMB_VFS_LCHOWN(fsp->conn,
2126 ret = SMB_VFS_CHOWN(fsp->conn,
2132 status = NT_STATUS_OK;
2134 status = map_nt_error_from_unix(errno);
2139 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2140 const struct smb_filename *smb_fname)
2143 return handle->fns->chdir_fn(handle, smb_fname);
2146 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2150 return handle->fns->getwd_fn(handle, ctx);
2153 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2154 const struct smb_filename *smb_fname,
2155 struct smb_file_time *ft)
2158 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2161 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2162 struct files_struct *fsp, off_t offset)
2164 VFS_FIND(ftruncate);
2165 return handle->fns->ftruncate_fn(handle, fsp, offset);
2168 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2169 struct files_struct *fsp,
2174 VFS_FIND(fallocate);
2175 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2178 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2179 struct files_struct *fsp, uint32_t share_mode,
2180 uint32_t access_mask)
2182 VFS_FIND(kernel_flock);
2183 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2187 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2188 struct files_struct *fsp, int leasetype)
2190 VFS_FIND(linux_setlease);
2191 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2194 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2195 const char *link_target,
2196 struct files_struct *dirfsp,
2197 const struct smb_filename *new_smb_fname)
2199 VFS_FIND(symlinkat);
2200 return handle->fns->symlinkat_fn(handle,
2206 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2207 files_struct *dirfsp,
2208 const struct smb_filename *smb_fname,
2212 VFS_FIND(readlinkat);
2213 return handle->fns->readlinkat_fn(handle,
2220 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2221 struct files_struct *srcfsp,
2222 const struct smb_filename *old_smb_fname,
2223 struct files_struct *dstfsp,
2224 const struct smb_filename *new_smb_fname,
2228 return handle->fns->linkat_fn(handle,
2236 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2237 struct files_struct *dirfsp,
2238 const struct smb_filename *smb_fname,
2243 return handle->fns->mknodat_fn(handle,
2250 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2252 const struct smb_filename *smb_fname)
2255 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2258 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2259 const struct smb_filename *smb_fname,
2263 return handle->fns->chflags_fn(handle, smb_fname, flags);
2266 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2267 const SMB_STRUCT_STAT *sbuf)
2269 VFS_FIND(file_id_create);
2270 return handle->fns->file_id_create_fn(handle, sbuf);
2273 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2274 const SMB_STRUCT_STAT *sbuf)
2276 VFS_FIND(fs_file_id);
2277 return handle->fns->fs_file_id_fn(handle, sbuf);
2280 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2281 struct files_struct *fsp,
2282 const struct smb_filename *smb_fname,
2283 TALLOC_CTX *mem_ctx,
2284 unsigned int *num_streams,
2285 struct stream_struct **streams)
2287 VFS_FIND(streaminfo);
2288 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2289 num_streams, streams);
2292 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2293 const char *path, const char *name,
2294 TALLOC_CTX *mem_ctx, char **found_name)
2296 VFS_FIND(get_real_filename);
2297 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2301 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2302 const struct smb_filename *smb_fname)
2304 VFS_FIND(connectpath);
2305 return handle->fns->connectpath_fn(handle, smb_fname);
2308 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2309 struct files_struct *fsp,
2310 struct lock_struct *plock)
2312 VFS_FIND(strict_lock_check);
2313 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2316 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2318 enum vfs_translate_direction direction,
2319 TALLOC_CTX *mem_ctx,
2322 VFS_FIND(translate_name);
2323 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2327 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2328 struct files_struct *fsp,
2332 const uint8_t *in_data,
2335 uint32_t max_out_len,
2339 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2340 in_data, in_len, out_data, max_out_len,
2344 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2345 struct smb_filename *smb_fname,
2348 VFS_FIND(get_dos_attributes);
2349 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2352 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2353 struct files_struct *fsp,
2356 VFS_FIND(fget_dos_attributes);
2357 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2360 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2361 const struct smb_filename *smb_fname,
2364 VFS_FIND(set_dos_attributes);
2365 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2368 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2369 struct files_struct *fsp,
2372 VFS_FIND(set_dos_attributes);
2373 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2376 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2377 struct tevent_context *ev,
2378 struct vfs_handle_struct *handle,
2379 struct files_struct *fsp,
2385 VFS_FIND(offload_read_send);
2386 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2388 ttl, offset, to_copy);
2391 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2392 struct vfs_handle_struct *handle,
2393 TALLOC_CTX *mem_ctx,
2394 DATA_BLOB *token_blob)
2396 VFS_FIND(offload_read_recv);
2397 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2400 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2401 TALLOC_CTX *mem_ctx,
2402 struct tevent_context *ev,
2405 off_t transfer_offset,
2406 struct files_struct *dest_fsp,
2410 VFS_FIND(offload_write_send);
2411 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2412 token, transfer_offset,
2413 dest_fsp, dest_off, num);
2416 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2417 struct tevent_req *req,
2420 VFS_FIND(offload_write_recv);
2421 return handle->fns->offload_write_recv_fn(handle, req, copied);
2424 struct smb_vfs_call_get_dos_attributes_state {
2425 files_struct *dir_fsp;
2426 NTSTATUS (*recv_fn)(struct tevent_req *req,
2427 struct vfs_aio_state *aio_state,
2429 struct vfs_aio_state aio_state;
2430 uint32_t dos_attributes;
2433 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2435 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2436 TALLOC_CTX *mem_ctx,
2437 struct tevent_context *ev,
2438 struct vfs_handle_struct *handle,
2439 files_struct *dir_fsp,
2440 struct smb_filename *smb_fname)
2442 struct tevent_req *req = NULL;
2443 struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2444 struct tevent_req *subreq = NULL;
2446 req = tevent_req_create(mem_ctx, &state,
2447 struct smb_vfs_call_get_dos_attributes_state);
2452 VFS_FIND(get_dos_attributes_send);
2454 *state = (struct smb_vfs_call_get_dos_attributes_state) {
2456 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2459 subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2464 if (tevent_req_nomem(subreq, req)) {
2465 return tevent_req_post(req, ev);
2467 tevent_req_defer_callback(req, ev);
2469 tevent_req_set_callback(subreq,
2470 smb_vfs_call_get_dos_attributes_done,
2476 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2478 struct tevent_req *req =
2479 tevent_req_callback_data(subreq,
2481 struct smb_vfs_call_get_dos_attributes_state *state =
2482 tevent_req_data(req,
2483 struct smb_vfs_call_get_dos_attributes_state);
2488 * Make sure we run as the user again
2490 ok = change_to_user_by_fsp(state->dir_fsp);
2493 status = state->recv_fn(subreq,
2495 &state->dos_attributes);
2496 TALLOC_FREE(subreq);
2497 if (tevent_req_nterror(req, status)) {
2501 tevent_req_done(req);
2504 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2505 struct tevent_req *req,
2506 struct vfs_aio_state *aio_state,
2507 uint32_t *dos_attributes)
2509 struct smb_vfs_call_get_dos_attributes_state *state =
2510 tevent_req_data(req,
2511 struct smb_vfs_call_get_dos_attributes_state);
2514 if (tevent_req_is_nterror(req, &status)) {
2515 tevent_req_received(req);
2519 *aio_state = state->aio_state;
2520 *dos_attributes = state->dos_attributes;
2521 tevent_req_received(req);
2522 return NT_STATUS_OK;
2525 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2526 TALLOC_CTX *mem_ctx,
2527 struct files_struct *fsp,
2528 struct smb_filename *smb_fname,
2529 uint16_t *_compression_fmt)
2531 VFS_FIND(get_compression);
2532 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2536 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2537 TALLOC_CTX *mem_ctx,
2538 struct files_struct *fsp,
2539 uint16_t compression_fmt)
2541 VFS_FIND(set_compression);
2542 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2546 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2547 TALLOC_CTX *mem_ctx,
2548 const char *service_path,
2551 VFS_FIND(snap_check_path);
2552 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2556 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2557 TALLOC_CTX *mem_ctx,
2558 const char *base_volume,
2564 VFS_FIND(snap_create);
2565 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2566 rw, base_path, snap_path);
2569 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2570 TALLOC_CTX *mem_ctx,
2574 VFS_FIND(snap_delete);
2575 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2579 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2580 struct files_struct *fsp,
2581 uint32_t security_info,
2582 TALLOC_CTX *mem_ctx,
2583 struct security_descriptor **ppdesc)
2585 VFS_FIND(fget_nt_acl);
2586 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2590 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2591 const struct smb_filename *smb_fname,
2592 uint32_t security_info,
2593 TALLOC_CTX *mem_ctx,
2594 struct security_descriptor **ppdesc)
2596 VFS_FIND(get_nt_acl);
2597 return handle->fns->get_nt_acl_fn(handle,
2604 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2605 struct files_struct *fsp,
2606 uint32_t security_info_sent,
2607 const struct security_descriptor *psd)
2609 VFS_FIND(fset_nt_acl);
2610 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2614 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2615 struct smb_filename *file,
2616 struct security_acl *sacl,
2617 uint32_t access_requested,
2618 uint32_t access_denied)
2620 VFS_FIND(audit_file);
2621 return handle->fns->audit_file_fn(handle,
2628 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2629 const struct smb_filename *smb_fname,
2630 SMB_ACL_TYPE_T type,
2631 TALLOC_CTX *mem_ctx)
2633 VFS_FIND(sys_acl_get_file);
2634 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2637 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2638 struct files_struct *fsp,
2639 TALLOC_CTX *mem_ctx)
2641 VFS_FIND(sys_acl_get_fd);
2642 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2645 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2646 const struct smb_filename *smb_fname,
2647 TALLOC_CTX *mem_ctx,
2648 char **blob_description,
2651 VFS_FIND(sys_acl_blob_get_file);
2652 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2653 mem_ctx, blob_description, blob);
2656 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2657 struct files_struct *fsp,
2658 TALLOC_CTX *mem_ctx,
2659 char **blob_description,
2662 VFS_FIND(sys_acl_blob_get_fd);
2663 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2666 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2667 const struct smb_filename *smb_fname,
2668 SMB_ACL_TYPE_T acltype,
2671 VFS_FIND(sys_acl_set_file);
2672 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2676 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2677 struct files_struct *fsp, SMB_ACL_T theacl)
2679 VFS_FIND(sys_acl_set_fd);
2680 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2683 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2684 const struct smb_filename *smb_fname)
2686 VFS_FIND(sys_acl_delete_def_file);
2687 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2690 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2691 const struct smb_filename *smb_fname,
2697 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2701 struct smb_vfs_call_getxattrat_state {
2702 files_struct *dir_fsp;
2703 ssize_t (*recv_fn)(struct tevent_req *req,
2704 struct vfs_aio_state *aio_state,
2705 TALLOC_CTX *mem_ctx,
2706 uint8_t **xattr_value);
2708 uint8_t *xattr_value;
2709 struct vfs_aio_state aio_state;
2712 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2714 struct tevent_req *smb_vfs_call_getxattrat_send(
2715 TALLOC_CTX *mem_ctx,
2716 struct tevent_context *ev,
2717 struct vfs_handle_struct *handle,
2718 files_struct *dir_fsp,
2719 const struct smb_filename *smb_fname,
2720 const char *xattr_name,
2723 struct tevent_req *req = NULL;
2724 struct smb_vfs_call_getxattrat_state *state = NULL;
2725 struct tevent_req *subreq = NULL;
2727 req = tevent_req_create(mem_ctx, &state,
2728 struct smb_vfs_call_getxattrat_state);
2733 VFS_FIND(getxattrat_send);
2735 *state = (struct smb_vfs_call_getxattrat_state) {
2737 .recv_fn = handle->fns->getxattrat_recv_fn,
2740 subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2747 if (tevent_req_nomem(subreq, req)) {
2748 return tevent_req_post(req, ev);
2750 tevent_req_defer_callback(req, ev);
2752 tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2756 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2758 struct tevent_req *req = tevent_req_callback_data(
2759 subreq, struct tevent_req);
2760 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2761 req, struct smb_vfs_call_getxattrat_state);
2765 * Make sure we run as the user again
2767 ok = change_to_user_by_fsp(state->dir_fsp);
2770 state->retval = state->recv_fn(subreq,
2773 &state->xattr_value);
2774 TALLOC_FREE(subreq);
2775 if (state->retval == -1) {
2776 tevent_req_error(req, state->aio_state.error);
2780 tevent_req_done(req);
2783 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2784 struct vfs_aio_state *aio_state,
2785 TALLOC_CTX *mem_ctx,
2786 uint8_t **xattr_value)
2788 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2789 req, struct smb_vfs_call_getxattrat_state);
2792 if (tevent_req_is_unix_error(req, &aio_state->error)) {
2793 tevent_req_received(req);
2797 *aio_state = state->aio_state;
2798 xattr_size = state->retval;
2799 if (xattr_value != NULL) {
2800 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2803 tevent_req_received(req);
2807 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2808 struct files_struct *fsp, const char *name,
2809 void *value, size_t size)
2811 VFS_FIND(fgetxattr);
2812 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2815 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2816 const struct smb_filename *smb_fname,
2820 VFS_FIND(listxattr);
2821 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2824 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2825 struct files_struct *fsp, char *list,
2828 VFS_FIND(flistxattr);
2829 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2832 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2833 const struct smb_filename *smb_fname,
2836 VFS_FIND(removexattr);
2837 return handle->fns->removexattr_fn(handle, smb_fname, name);
2840 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2841 struct files_struct *fsp, const char *name)
2843 VFS_FIND(fremovexattr);
2844 return handle->fns->fremovexattr_fn(handle, fsp, name);
2847 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2848 const struct smb_filename *smb_fname,
2855 return handle->fns->setxattr_fn(handle, smb_fname,
2856 name, value, size, flags);
2859 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2860 struct files_struct *fsp, const char *name,
2861 const void *value, size_t size, int flags)
2863 VFS_FIND(fsetxattr);
2864 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2867 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2868 struct files_struct *fsp)
2870 VFS_FIND(aio_force);
2871 return handle->fns->aio_force_fn(handle, fsp);
2874 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2875 struct files_struct *fsp,
2876 TALLOC_CTX *mem_ctx,
2879 VFS_FIND(durable_cookie);
2880 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2883 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2884 struct files_struct *fsp,
2885 const DATA_BLOB old_cookie,
2886 TALLOC_CTX *mem_ctx,
2887 DATA_BLOB *new_cookie)
2889 VFS_FIND(durable_disconnect);
2890 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2891 mem_ctx, new_cookie);
2894 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2895 struct smb_request *smb1req,
2896 struct smbXsrv_open *op,
2897 const DATA_BLOB old_cookie,
2898 TALLOC_CTX *mem_ctx,
2899 struct files_struct **fsp,
2900 DATA_BLOB *new_cookie)
2902 VFS_FIND(durable_reconnect);
2903 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2904 old_cookie, mem_ctx, fsp,
2908 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2909 const struct smb_filename *fname,
2910 TALLOC_CTX *mem_ctx,
2911 struct readdir_attr_data **attr_data)
2913 VFS_FIND(readdir_attr);
2914 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);