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 ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
520 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
525 /* Grow - we need to test if we have enough space. */
527 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
529 if (lp_strict_allocate(SNUM(fsp->conn))) {
530 /* See if we have a syscall that will allocate beyond
531 end-of-file without changing EOF. */
532 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
538 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
541 /* We changed the allocation size on disk, but not
542 EOF - exactly as required. We're done ! */
546 if (ret == -1 && errno == ENOSPC) {
550 len -= fsp->fsp_name->st.st_ex_size;
551 len /= 1024; /* Len is now number of 1k blocks needed. */
553 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
554 if (space_avail == (uint64_t)-1) {
558 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
559 "needed blocks = %.0f, space avail = %.0f\n",
560 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
561 (double)space_avail));
563 if (len > space_avail) {
571 /****************************************************************************
572 A vfs set_filelen call.
573 set the length of a file from a filedescriptor.
574 Returns 0 on success, -1 on failure.
575 ****************************************************************************/
577 int vfs_set_filelen(files_struct *fsp, off_t len)
581 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
583 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
584 fsp_str_dbg(fsp), (double)len));
585 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
586 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
587 FILE_NOTIFY_CHANGE_SIZE
588 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
589 fsp->fsp_name->base_name);
592 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
597 /****************************************************************************
598 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
599 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
600 as this is also called from the default SMB_VFS_FTRUNCATE code.
601 Always extends the file size.
602 Returns 0 on success, -1 on failure.
603 ****************************************************************************/
605 #define SPARSE_BUF_WRITE_SIZE (32*1024)
607 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
613 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
620 while (total < len) {
621 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
623 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
624 if (pwrite_ret == -1) {
625 int saved_errno = errno;
626 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
627 "%s failed with error %s\n",
628 fsp_str_dbg(fsp), strerror(saved_errno)));
638 /****************************************************************************
639 A vfs fill sparse call.
640 Writes zeros from the end of file to len, if len is greater than EOF.
641 Used only by strict_sync.
642 Returns 0 on success, -1 on failure.
643 ****************************************************************************/
645 int vfs_fill_sparse(files_struct *fsp, off_t len)
652 status = vfs_stat_fsp(fsp);
653 if (!NT_STATUS_IS_OK(status)) {
657 if (len <= fsp->fsp_name->st.st_ex_size) {
662 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
667 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
668 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
669 (double)fsp->fsp_name->st.st_ex_size, (double)len,
670 (double)(len - fsp->fsp_name->st.st_ex_size)));
672 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
674 offset = fsp->fsp_name->st.st_ex_size;
675 num_to_write = len - fsp->fsp_name->st.st_ex_size;
677 /* Only do this on non-stream file handles. */
678 if (fsp->base_fsp == NULL) {
679 /* for allocation try fallocate first. This can fail on some
680 * platforms e.g. when the filesystem doesn't support it and no
681 * emulation is being done by the libc (like on AIX with JFS1). In that
682 * case we do our own emulation. fallocate implementations can
683 * return ENOTSUP or EINVAL in cases like that. */
684 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
685 if (ret == -1 && errno == ENOSPC) {
691 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
692 "error %d. Falling back to slow manual allocation\n", ret));
695 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
699 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
703 /*******************************************************************************
704 Set a fd into blocking/nonblocking mode through VFS
705 *******************************************************************************/
707 int vfs_set_blocking(files_struct *fsp, bool set)
711 #define FLAG_TO_SET O_NONBLOCK
714 #define FLAG_TO_SET O_NDELAY
716 #define FLAG_TO_SET FNDELAY
719 val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
730 return SMB_VFS_FCNTL(fsp, F_SETFL, val);
734 /****************************************************************************
735 Transfer some data (n bytes) between two file_struct's.
736 ****************************************************************************/
738 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
740 struct files_struct *fsp = (struct files_struct *)file;
742 return SMB_VFS_PREAD(fsp, buf, len, offset);
745 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
747 struct files_struct *fsp = (struct files_struct *)file;
749 return SMB_VFS_PWRITE(fsp, buf, len, offset);
752 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
754 return transfer_file_internal((void *)in, (void *)out, n,
755 vfs_pread_fn, vfs_pwrite_fn);
758 /*******************************************************************
759 A vfs_readdir wrapper which just returns the file name.
760 ********************************************************************/
762 const char *vfs_readdirname(connection_struct *conn, void *p,
763 SMB_STRUCT_STAT *sbuf, char **talloced)
765 struct dirent *ptr= NULL;
773 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
785 #ifdef HAVE_BROKEN_READDIR_NAME
786 /* using /usr/ucb/cc is BAD */
790 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
791 talloc_tos(), &translated);
792 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
796 *talloced = translated;
797 if (!NT_STATUS_IS_OK(status)) {
803 /*******************************************************************
804 A wrapper for vfs_chdir().
805 ********************************************************************/
807 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
810 struct smb_filename *cwd = NULL;
813 LastDir = SMB_STRDUP("");
816 if (ISDOT(smb_fname->base_name)) {
820 if (*smb_fname->base_name == '/' &&
821 strcsequal(LastDir,smb_fname->base_name)) {
825 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
827 ret = SMB_VFS_CHDIR(conn, smb_fname);
833 * Always replace conn->cwd_fsp. We
834 * don't know if it's been modified by
835 * VFS modules in the stack.
839 cwd = vfs_GetWd(conn, conn);
842 * vfs_GetWd() failed.
843 * We must be able to read cwd.
844 * Return to original directory
847 int saved_errno = errno;
849 if (conn->cwd_fsp->fsp_name == NULL) {
851 * Failed on the very first chdir()+getwd()
852 * for this connection. We can't
855 smb_panic("conn->cwd getwd failed\n");
860 /* Return to the previous $cwd. */
861 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
863 smb_panic("conn->cwd getwd failed\n");
868 /* And fail the chdir(). */
872 /* vfs_GetWd() succeeded. */
873 /* Replace global cache. */
875 LastDir = SMB_STRDUP(smb_fname->base_name);
878 * (Indirect) Callers of vfs_ChDir() may still hold references to the
879 * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
880 * callers can use it for the lifetime of the SMB request.
882 talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
884 conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
885 conn->cwd_fsp->fh->fd = AT_FDCWD;
887 DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
892 /*******************************************************************
893 Return the absolute current directory path - given a UNIX pathname.
894 Note that this path is returned in DOS format, not UNIX
895 format. Note this can be called with conn == NULL.
896 ********************************************************************/
898 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
900 struct smb_filename *current_dir_fname = NULL;
902 struct smb_filename *smb_fname_dot = NULL;
903 struct smb_filename *smb_fname_full = NULL;
904 struct smb_filename *result = NULL;
906 if (!lp_getwd_cache()) {
910 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
911 if (smb_fname_dot == NULL) {
916 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
918 * Known to fail for root: the directory may be NFS-mounted
919 * and exported with root_squash (so has no root access).
921 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
922 "(NFS problem ?)\n", strerror(errno) ));
926 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
928 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
931 data_blob_const(&key, sizeof(key)));
933 if (smb_fname_full == NULL) {
937 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
938 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
939 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
940 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
943 * Note: smb_fname_full is owned by smbd_memcache()
944 * so we must make a copy to return.
946 result = cp_smb_filename(ctx, smb_fname_full);
947 if (result == NULL) {
956 * We don't have the information to hand so rely on traditional
957 * methods. The very slow getcwd, which spawns a process on some
958 * systems, or the not quite so bad getwd.
961 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
962 if (current_dir_fname == NULL) {
963 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
968 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
969 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
972 * smbd_memcache() will own current_dir_fname after the
973 * memcache_add_talloc call, so we must make
974 * a copy on ctx to return.
976 result = cp_smb_filename(ctx, current_dir_fname);
977 if (result == NULL) {
982 * Ensure the memory going into the cache
983 * doesn't have a destructor so it can be
986 talloc_set_destructor(current_dir_fname, NULL);
988 memcache_add_talloc(smbd_memcache(),
990 data_blob_const(&key, sizeof(key)),
992 /* current_dir_fname is now == NULL here. */
994 /* current_dir_fname is already allocated on ctx. */
995 result = current_dir_fname;
999 TALLOC_FREE(smb_fname_dot);
1001 * Don't free current_dir_fname here. It's either been moved
1002 * to the memcache or is being returned in result.
1007 /*******************************************************************
1008 Reduce a file name, removing .. elements and checking that
1009 it is below dir in the hierarchy. This uses realpath.
1010 This function must run as root, and will return names
1011 and valid stat structs that can be checked on open.
1012 ********************************************************************/
1014 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1015 const struct smb_filename *smb_fname,
1016 struct smb_request *smbreq)
1019 TALLOC_CTX *ctx = talloc_tos();
1020 const char *conn_rootdir;
1022 char *dir_name = NULL;
1023 char *resolved_name = NULL;
1024 const char *last_component = NULL;
1025 struct smb_filename *resolved_fname = NULL;
1026 struct smb_filename *saved_dir_fname = NULL;
1027 struct smb_filename *smb_fname_cwd = NULL;
1028 struct privilege_paths *priv_paths = NULL;
1031 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1032 smb_fname->base_name,
1033 conn->connectpath));
1036 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1038 status = NT_STATUS_NO_MEMORY;
1042 if (!parent_dirname(ctx, smb_fname->base_name,
1043 &dir_name, &last_component)) {
1044 status = NT_STATUS_NO_MEMORY;
1048 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1049 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1051 if (priv_paths->parent_name.base_name == NULL ||
1052 priv_paths->file_name.base_name == NULL) {
1053 status = NT_STATUS_NO_MEMORY;
1057 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1058 status = map_nt_error_from_unix(errno);
1061 /* Remember where we were. */
1062 saved_dir_fname = vfs_GetWd(ctx, conn);
1063 if (!saved_dir_fname) {
1064 status = map_nt_error_from_unix(errno);
1068 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1069 status = map_nt_error_from_unix(errno);
1073 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1074 if (smb_fname_cwd == NULL) {
1075 status = NT_STATUS_NO_MEMORY;
1079 /* Get the absolute path of the parent directory. */
1080 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1081 if (resolved_fname == NULL) {
1082 status = map_nt_error_from_unix(errno);
1085 resolved_name = resolved_fname->base_name;
1087 if (*resolved_name != '/') {
1088 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1089 "doesn't return absolute paths !\n"));
1090 status = NT_STATUS_OBJECT_NAME_INVALID;
1094 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1095 priv_paths->parent_name.base_name,
1098 /* Now check the stat value is the same. */
1099 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1100 status = map_nt_error_from_unix(errno);
1104 /* Ensure we're pointing at the same place. */
1105 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1106 DEBUG(0,("check_reduced_name_with_privilege: "
1107 "device/inode/uid/gid on directory %s changed. "
1108 "Denying access !\n",
1109 priv_paths->parent_name.base_name));
1110 status = NT_STATUS_ACCESS_DENIED;
1114 /* Ensure we're below the connect path. */
1116 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1117 if (conn_rootdir == NULL) {
1118 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1120 status = NT_STATUS_ACCESS_DENIED;
1124 rootdir_len = strlen(conn_rootdir);
1127 * In the case of rootdir_len == 1, we know that conn_rootdir is
1128 * "/", and we also know that resolved_name starts with a slash.
1129 * So, in this corner case, resolved_name is automatically a
1130 * sub-directory of the conn_rootdir. Thus we can skip the string
1131 * comparison and the next character checks (which are even
1132 * wrong in this case).
1134 if (rootdir_len != 1) {
1137 matched = (strncmp(conn_rootdir, resolved_name,
1140 if (!matched || (resolved_name[rootdir_len] != '/' &&
1141 resolved_name[rootdir_len] != '\0')) {
1142 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1143 "access attempt: %s is a symlink outside the "
1146 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1147 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1148 status = NT_STATUS_ACCESS_DENIED;
1153 /* Now ensure that the last component either doesn't
1154 exist, or is *NOT* a symlink. */
1156 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1158 /* Errno must be ENOENT for this be ok. */
1159 if (errno != ENOENT) {
1160 status = map_nt_error_from_unix(errno);
1161 DEBUG(2, ("check_reduced_name_with_privilege: "
1162 "LSTAT on %s failed with %s\n",
1163 priv_paths->file_name.base_name,
1164 nt_errstr(status)));
1169 if (VALID_STAT(priv_paths->file_name.st) &&
1170 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1171 DEBUG(2, ("check_reduced_name_with_privilege: "
1172 "Last component %s is a symlink. Denying"
1174 priv_paths->file_name.base_name));
1175 status = NT_STATUS_ACCESS_DENIED;
1179 smbreq->priv_paths = priv_paths;
1180 status = NT_STATUS_OK;
1184 if (saved_dir_fname != NULL) {
1185 vfs_ChDir(conn, saved_dir_fname);
1186 TALLOC_FREE(saved_dir_fname);
1188 TALLOC_FREE(resolved_fname);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 TALLOC_FREE(priv_paths);
1192 TALLOC_FREE(dir_name);
1196 /*******************************************************************
1197 Reduce a file name, removing .. elements and checking that
1198 it is below dir in the hierarchy. This uses realpath.
1200 If cwd_name == NULL then fname is a client given path relative
1201 to the root path of the share.
1203 If cwd_name != NULL then fname is a client given path relative
1204 to cwd_name. cwd_name is relative to the root path of the share.
1205 ********************************************************************/
1207 NTSTATUS check_reduced_name(connection_struct *conn,
1208 const struct smb_filename *cwd_fname,
1209 const struct smb_filename *smb_fname)
1211 TALLOC_CTX *ctx = talloc_tos();
1212 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1213 const char *fname = smb_fname->base_name;
1214 struct smb_filename *resolved_fname;
1215 char *resolved_name = NULL;
1216 char *new_fname = NULL;
1217 bool allow_symlinks = true;
1218 bool allow_widelinks = false;
1220 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1222 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1224 if (resolved_fname == NULL) {
1227 DEBUG(3,("check_reduced_name: Component not a "
1228 "directory in getting realpath for "
1230 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1233 char *dir_name = NULL;
1234 struct smb_filename dir_fname = {0};
1235 const char *last_component = NULL;
1237 /* Last component didn't exist.
1238 Remove it and try and canonicalise
1239 the directory name. */
1240 if (!parent_dirname(ctx, fname,
1243 return NT_STATUS_NO_MEMORY;
1246 dir_fname = (struct smb_filename)
1247 { .base_name = dir_name };
1248 resolved_fname = SMB_VFS_REALPATH(conn,
1251 if (resolved_fname == NULL) {
1252 NTSTATUS status = map_nt_error_from_unix(errno);
1254 if (errno == ENOENT || errno == ENOTDIR) {
1255 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1258 DEBUG(3,("check_reduce_name: "
1259 "couldn't get realpath for "
1262 nt_errstr(status)));
1265 resolved_name = talloc_asprintf(ctx,
1267 resolved_fname->base_name,
1269 if (resolved_name == NULL) {
1270 return NT_STATUS_NO_MEMORY;
1275 DEBUG(3,("check_reduced_name: couldn't get "
1276 "realpath for %s\n", fname));
1277 return map_nt_error_from_unix(errno);
1280 resolved_name = resolved_fname->base_name;
1283 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1286 if (*resolved_name != '/') {
1287 DEBUG(0,("check_reduced_name: realpath doesn't return "
1288 "absolute paths !\n"));
1289 TALLOC_FREE(resolved_fname);
1290 return NT_STATUS_OBJECT_NAME_INVALID;
1293 allow_widelinks = lp_widelinks(SNUM(conn));
1294 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1296 /* Common widelinks and symlinks checks. */
1297 if (!allow_widelinks || !allow_symlinks) {
1298 const char *conn_rootdir;
1301 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1302 if (conn_rootdir == NULL) {
1303 DEBUG(2, ("check_reduced_name: Could not get "
1305 TALLOC_FREE(resolved_fname);
1306 return NT_STATUS_ACCESS_DENIED;
1309 rootdir_len = strlen(conn_rootdir);
1312 * In the case of rootdir_len == 1, we know that
1313 * conn_rootdir is "/", and we also know that
1314 * resolved_name starts with a slash. So, in this
1315 * corner case, resolved_name is automatically a
1316 * sub-directory of the conn_rootdir. Thus we can skip
1317 * the string comparison and the next character checks
1318 * (which are even wrong in this case).
1320 if (rootdir_len != 1) {
1323 matched = (strncmp(conn_rootdir, resolved_name,
1325 if (!matched || (resolved_name[rootdir_len] != '/' &&
1326 resolved_name[rootdir_len] != '\0')) {
1327 DEBUG(2, ("check_reduced_name: Bad access "
1328 "attempt: %s is a symlink outside the "
1329 "share path\n", fname));
1330 DEBUGADD(2, ("conn_rootdir =%s\n",
1332 DEBUGADD(2, ("resolved_name=%s\n",
1334 TALLOC_FREE(resolved_fname);
1335 return NT_STATUS_ACCESS_DENIED;
1339 /* Extra checks if all symlinks are disallowed. */
1340 if (!allow_symlinks) {
1341 /* fname can't have changed in resolved_path. */
1342 const char *p = &resolved_name[rootdir_len];
1345 * UNIX filesystem semantics, names consisting
1346 * only of "." or ".." CANNOT be symlinks.
1348 if (ISDOT(fname) || ISDOTDOT(fname)) {
1353 DEBUG(2, ("check_reduced_name: logic error (%c) "
1354 "in resolved_name: %s\n",
1357 TALLOC_FREE(resolved_fname);
1358 return NT_STATUS_ACCESS_DENIED;
1364 * If cwd_name is present and not ".",
1365 * then fname is relative to that, not
1366 * the root of the share. Make sure the
1367 * path we check is the one the client
1368 * sent (cwd_name+fname).
1370 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1371 new_fname = talloc_asprintf(ctx,
1375 if (new_fname == NULL) {
1376 TALLOC_FREE(resolved_fname);
1377 return NT_STATUS_NO_MEMORY;
1382 if (strcmp(fname, p)!=0) {
1383 DEBUG(2, ("check_reduced_name: Bad access "
1384 "attempt: %s is a symlink to %s\n",
1386 TALLOC_FREE(resolved_fname);
1387 TALLOC_FREE(new_fname);
1388 return NT_STATUS_ACCESS_DENIED;
1395 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1396 TALLOC_FREE(resolved_fname);
1397 TALLOC_FREE(new_fname);
1398 return NT_STATUS_OK;
1402 * XXX: This is temporary and there should be no callers of this once
1403 * smb_filename is plumbed through all path based operations.
1405 * Called when we know stream name parsing has already been done.
1407 int vfs_stat_smb_basename(struct connection_struct *conn,
1408 const struct smb_filename *smb_fname_in,
1409 SMB_STRUCT_STAT *psbuf)
1411 struct smb_filename smb_fname = {
1412 .base_name = discard_const_p(char, smb_fname_in->base_name),
1413 .flags = smb_fname_in->flags
1417 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1418 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1420 ret = SMB_VFS_STAT(conn, &smb_fname);
1424 *psbuf = smb_fname.st;
1430 * Ensure LSTAT is called for POSIX paths.
1433 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1436 struct stat_ex saved_stat = fsp->fsp_name->st;
1438 if(fsp->fh->fd == -1) {
1439 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1440 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1442 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1445 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1448 return map_nt_error_from_unix(errno);
1450 update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat);
1451 return NT_STATUS_OK;
1455 * Initialize num_streams and streams, then call VFS op streaminfo
1457 NTSTATUS vfs_streaminfo(connection_struct *conn,
1458 struct files_struct *fsp,
1459 const struct smb_filename *smb_fname,
1460 TALLOC_CTX *mem_ctx,
1461 unsigned int *num_streams,
1462 struct stream_struct **streams)
1466 return SMB_VFS_STREAMINFO(conn,
1475 generate a file_id from a stat structure
1477 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1479 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1482 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1483 const char *service, const char *user)
1486 return handle->fns->connect_fn(handle, service, user);
1489 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1491 VFS_FIND(disconnect);
1492 handle->fns->disconnect_fn(handle);
1495 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1496 const struct smb_filename *smb_fname,
1501 VFS_FIND(disk_free);
1502 return handle->fns->disk_free_fn(handle, smb_fname,
1503 bsize, dfree, dsize);
1506 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1507 const struct smb_filename *smb_fname,
1508 enum SMB_QUOTA_TYPE qtype,
1512 VFS_FIND(get_quota);
1513 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1516 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1517 enum SMB_QUOTA_TYPE qtype, unid_t id,
1520 VFS_FIND(set_quota);
1521 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1524 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1525 struct files_struct *fsp,
1526 struct shadow_copy_data *shadow_copy_data,
1529 VFS_FIND(get_shadow_copy_data);
1530 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1534 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1535 const struct smb_filename *smb_fname,
1536 struct vfs_statvfs_struct *statbuf)
1539 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1542 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1543 enum timestamp_set_resolution *p_ts_res)
1545 VFS_FIND(fs_capabilities);
1546 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1549 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1550 struct dfs_GetDFSReferral *r)
1552 VFS_FIND(get_dfs_referrals);
1553 return handle->fns->get_dfs_referrals_fn(handle, r);
1556 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1557 const struct smb_filename *smb_fname,
1559 uint32_t attributes)
1562 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1565 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1566 struct files_struct *fsp,
1568 uint32_t attributes)
1570 VFS_FIND(fdopendir);
1571 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1574 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1576 SMB_STRUCT_STAT *sbuf)
1579 return handle->fns->readdir_fn(handle, dirp, sbuf);
1582 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1583 DIR *dirp, long offset)
1586 handle->fns->seekdir_fn(handle, dirp, offset);
1589 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1593 return handle->fns->telldir_fn(handle, dirp);
1596 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1599 VFS_FIND(rewind_dir);
1600 handle->fns->rewind_dir_fn(handle, dirp);
1603 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1604 struct files_struct *dirfsp,
1605 const struct smb_filename *smb_fname,
1609 return handle->fns->mkdirat_fn(handle,
1615 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1619 return handle->fns->closedir_fn(handle, dir);
1622 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1623 struct smb_filename *smb_fname, struct files_struct *fsp,
1624 int flags, mode_t mode)
1627 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1630 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1631 struct smb_request *req,
1632 uint16_t root_dir_fid,
1633 struct smb_filename *smb_fname,
1634 uint32_t access_mask,
1635 uint32_t share_access,
1636 uint32_t create_disposition,
1637 uint32_t create_options,
1638 uint32_t file_attributes,
1639 uint32_t oplock_request,
1640 const struct smb2_lease *lease,
1641 uint64_t allocation_size,
1642 uint32_t private_flags,
1643 struct security_descriptor *sd,
1644 struct ea_list *ea_list,
1645 files_struct **result,
1647 const struct smb2_create_blobs *in_context_blobs,
1648 struct smb2_create_blobs *out_context_blobs)
1650 VFS_FIND(create_file);
1651 return handle->fns->create_file_fn(
1652 handle, req, root_dir_fid, smb_fname, access_mask,
1653 share_access, create_disposition, create_options,
1654 file_attributes, oplock_request, lease, allocation_size,
1655 private_flags, sd, ea_list,
1656 result, pinfo, in_context_blobs, out_context_blobs);
1659 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1660 struct files_struct *fsp)
1663 return handle->fns->close_fn(handle, fsp);
1666 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1667 struct files_struct *fsp, void *data, size_t n,
1671 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1674 struct smb_vfs_call_pread_state {
1675 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1677 struct vfs_aio_state vfs_aio_state;
1680 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1682 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1683 TALLOC_CTX *mem_ctx,
1684 struct tevent_context *ev,
1685 struct files_struct *fsp,
1687 size_t n, off_t offset)
1689 struct tevent_req *req, *subreq;
1690 struct smb_vfs_call_pread_state *state;
1692 req = tevent_req_create(mem_ctx, &state,
1693 struct smb_vfs_call_pread_state);
1697 VFS_FIND(pread_send);
1698 state->recv_fn = handle->fns->pread_recv_fn;
1700 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1702 if (tevent_req_nomem(subreq, req)) {
1703 return tevent_req_post(req, ev);
1705 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1709 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1711 struct tevent_req *req = tevent_req_callback_data(
1712 subreq, struct tevent_req);
1713 struct smb_vfs_call_pread_state *state = tevent_req_data(
1714 req, struct smb_vfs_call_pread_state);
1716 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1717 TALLOC_FREE(subreq);
1718 if (state->retval == -1) {
1719 tevent_req_error(req, state->vfs_aio_state.error);
1722 tevent_req_done(req);
1725 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1726 struct vfs_aio_state *vfs_aio_state)
1728 struct smb_vfs_call_pread_state *state = tevent_req_data(
1729 req, struct smb_vfs_call_pread_state);
1732 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1733 tevent_req_received(req);
1736 *vfs_aio_state = state->vfs_aio_state;
1737 retval = state->retval;
1738 tevent_req_received(req);
1742 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1743 struct files_struct *fsp, const void *data,
1744 size_t n, off_t offset)
1747 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1750 struct smb_vfs_call_pwrite_state {
1751 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1753 struct vfs_aio_state vfs_aio_state;
1756 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1758 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1759 TALLOC_CTX *mem_ctx,
1760 struct tevent_context *ev,
1761 struct files_struct *fsp,
1763 size_t n, off_t offset)
1765 struct tevent_req *req, *subreq;
1766 struct smb_vfs_call_pwrite_state *state;
1768 req = tevent_req_create(mem_ctx, &state,
1769 struct smb_vfs_call_pwrite_state);
1773 VFS_FIND(pwrite_send);
1774 state->recv_fn = handle->fns->pwrite_recv_fn;
1776 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1778 if (tevent_req_nomem(subreq, req)) {
1779 return tevent_req_post(req, ev);
1781 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1785 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1787 struct tevent_req *req = tevent_req_callback_data(
1788 subreq, struct tevent_req);
1789 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1790 req, struct smb_vfs_call_pwrite_state);
1792 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1793 TALLOC_FREE(subreq);
1794 if (state->retval == -1) {
1795 tevent_req_error(req, state->vfs_aio_state.error);
1798 tevent_req_done(req);
1801 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1802 struct vfs_aio_state *vfs_aio_state)
1804 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1805 req, struct smb_vfs_call_pwrite_state);
1808 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1809 tevent_req_received(req);
1812 *vfs_aio_state = state->vfs_aio_state;
1813 retval = state->retval;
1814 tevent_req_received(req);
1818 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1819 struct files_struct *fsp, off_t offset,
1823 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1826 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1827 files_struct *fromfsp, const DATA_BLOB *header,
1828 off_t offset, size_t count)
1831 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1835 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1836 files_struct *tofsp, off_t offset,
1840 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1843 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
1844 files_struct *srcfsp,
1845 const struct smb_filename *smb_fname_src,
1846 files_struct *dstfsp,
1847 const struct smb_filename *smb_fname_dst)
1850 return handle->fns->renameat_fn(handle,
1857 struct smb_vfs_call_fsync_state {
1858 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1860 struct vfs_aio_state vfs_aio_state;
1863 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1865 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1866 TALLOC_CTX *mem_ctx,
1867 struct tevent_context *ev,
1868 struct files_struct *fsp)
1870 struct tevent_req *req, *subreq;
1871 struct smb_vfs_call_fsync_state *state;
1873 req = tevent_req_create(mem_ctx, &state,
1874 struct smb_vfs_call_fsync_state);
1878 VFS_FIND(fsync_send);
1879 state->recv_fn = handle->fns->fsync_recv_fn;
1881 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1882 if (tevent_req_nomem(subreq, req)) {
1883 return tevent_req_post(req, ev);
1885 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1889 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1891 struct tevent_req *req = tevent_req_callback_data(
1892 subreq, struct tevent_req);
1893 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1894 req, struct smb_vfs_call_fsync_state);
1896 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1897 TALLOC_FREE(subreq);
1898 if (state->retval == -1) {
1899 tevent_req_error(req, state->vfs_aio_state.error);
1902 tevent_req_done(req);
1905 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1907 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1908 req, struct smb_vfs_call_fsync_state);
1911 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1912 tevent_req_received(req);
1915 *vfs_aio_state = state->vfs_aio_state;
1916 retval = state->retval;
1917 tevent_req_received(req);
1922 * Synchronous version of fsync, built from backend
1923 * async VFS primitives. Uses a temporary sub-event
1924 * context (NOT NESTED).
1927 int smb_vfs_fsync_sync(files_struct *fsp)
1929 TALLOC_CTX *frame = talloc_stackframe();
1930 struct tevent_req *req = NULL;
1931 struct vfs_aio_state aio_state = { 0 };
1934 struct tevent_context *ev = samba_tevent_context_init(frame);
1940 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
1945 ok = tevent_req_poll(req, ev);
1950 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
1955 if (aio_state.error != 0) {
1956 errno = aio_state.error;
1961 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1962 struct smb_filename *smb_fname)
1965 return handle->fns->stat_fn(handle, smb_fname);
1968 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1969 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1972 return handle->fns->fstat_fn(handle, fsp, sbuf);
1975 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1976 struct smb_filename *smb_filename)
1979 return handle->fns->lstat_fn(handle, smb_filename);
1982 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1983 struct files_struct *fsp,
1984 const SMB_STRUCT_STAT *sbuf)
1986 VFS_FIND(get_alloc_size);
1987 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1990 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
1991 struct files_struct *dirfsp,
1992 const struct smb_filename *smb_fname,
1996 return handle->fns->unlinkat_fn(handle,
2002 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
2003 const struct smb_filename *smb_fname,
2007 return handle->fns->chmod_fn(handle, smb_fname, mode);
2010 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2011 struct files_struct *fsp, mode_t mode)
2014 return handle->fns->fchmod_fn(handle, fsp, mode);
2017 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2018 struct files_struct *fsp, uid_t uid, gid_t gid)
2021 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2024 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2025 const struct smb_filename *smb_fname,
2030 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2033 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2034 const struct smb_filename *smb_fname)
2037 return handle->fns->chdir_fn(handle, smb_fname);
2040 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2044 return handle->fns->getwd_fn(handle, ctx);
2047 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2048 const struct smb_filename *smb_fname,
2049 struct smb_file_time *ft)
2052 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2055 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2056 struct files_struct *fsp, off_t offset)
2058 VFS_FIND(ftruncate);
2059 return handle->fns->ftruncate_fn(handle, fsp, offset);
2062 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2063 struct files_struct *fsp,
2068 VFS_FIND(fallocate);
2069 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2072 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2073 struct files_struct *fsp, uint32_t share_mode,
2074 uint32_t access_mask)
2076 VFS_FIND(kernel_flock);
2077 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2081 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2082 struct files_struct *fsp, int cmd, ...)
2089 va_start(cmd_arg, cmd);
2090 result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2096 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2097 struct files_struct *fsp, int leasetype)
2099 VFS_FIND(linux_setlease);
2100 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2103 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2104 const char *link_target,
2105 struct files_struct *dirfsp,
2106 const struct smb_filename *new_smb_fname)
2108 VFS_FIND(symlinkat);
2109 return handle->fns->symlinkat_fn(handle,
2115 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2116 files_struct *dirfsp,
2117 const struct smb_filename *smb_fname,
2121 VFS_FIND(readlinkat);
2122 return handle->fns->readlinkat_fn(handle,
2129 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2130 struct files_struct *srcfsp,
2131 const struct smb_filename *old_smb_fname,
2132 struct files_struct *dstfsp,
2133 const struct smb_filename *new_smb_fname,
2137 return handle->fns->linkat_fn(handle,
2145 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2146 struct files_struct *dirfsp,
2147 const struct smb_filename *smb_fname,
2152 return handle->fns->mknodat_fn(handle,
2159 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2161 const struct smb_filename *smb_fname)
2164 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2167 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2168 const struct smb_filename *smb_fname,
2172 return handle->fns->chflags_fn(handle, smb_fname, flags);
2175 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2176 const SMB_STRUCT_STAT *sbuf)
2178 VFS_FIND(file_id_create);
2179 return handle->fns->file_id_create_fn(handle, sbuf);
2182 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2183 const SMB_STRUCT_STAT *sbuf)
2185 VFS_FIND(fs_file_id);
2186 return handle->fns->fs_file_id_fn(handle, sbuf);
2189 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2190 struct files_struct *fsp,
2191 const struct smb_filename *smb_fname,
2192 TALLOC_CTX *mem_ctx,
2193 unsigned int *num_streams,
2194 struct stream_struct **streams)
2196 VFS_FIND(streaminfo);
2197 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2198 num_streams, streams);
2201 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2202 const char *path, const char *name,
2203 TALLOC_CTX *mem_ctx, char **found_name)
2205 VFS_FIND(get_real_filename);
2206 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2210 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2211 const struct smb_filename *smb_fname)
2213 VFS_FIND(connectpath);
2214 return handle->fns->connectpath_fn(handle, smb_fname);
2217 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2218 struct files_struct *fsp,
2219 struct lock_struct *plock)
2221 VFS_FIND(strict_lock_check);
2222 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2225 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2227 enum vfs_translate_direction direction,
2228 TALLOC_CTX *mem_ctx,
2231 VFS_FIND(translate_name);
2232 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2236 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2237 struct files_struct *fsp,
2241 const uint8_t *in_data,
2244 uint32_t max_out_len,
2248 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2249 in_data, in_len, out_data, max_out_len,
2253 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2254 struct smb_filename *smb_fname,
2257 VFS_FIND(get_dos_attributes);
2258 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2261 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2262 struct files_struct *fsp,
2265 VFS_FIND(fget_dos_attributes);
2266 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2269 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2270 const struct smb_filename *smb_fname,
2273 VFS_FIND(set_dos_attributes);
2274 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2277 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2278 struct files_struct *fsp,
2281 VFS_FIND(set_dos_attributes);
2282 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2285 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2286 struct tevent_context *ev,
2287 struct vfs_handle_struct *handle,
2288 struct files_struct *fsp,
2294 VFS_FIND(offload_read_send);
2295 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2297 ttl, offset, to_copy);
2300 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2301 struct vfs_handle_struct *handle,
2302 TALLOC_CTX *mem_ctx,
2303 DATA_BLOB *token_blob)
2305 VFS_FIND(offload_read_recv);
2306 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2309 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2310 TALLOC_CTX *mem_ctx,
2311 struct tevent_context *ev,
2314 off_t transfer_offset,
2315 struct files_struct *dest_fsp,
2319 VFS_FIND(offload_write_send);
2320 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2321 token, transfer_offset,
2322 dest_fsp, dest_off, num);
2325 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2326 struct tevent_req *req,
2329 VFS_FIND(offload_write_recv);
2330 return handle->fns->offload_write_recv_fn(handle, req, copied);
2333 struct smb_vfs_call_get_dos_attributes_state {
2334 files_struct *dir_fsp;
2335 NTSTATUS (*recv_fn)(struct tevent_req *req,
2336 struct vfs_aio_state *aio_state,
2338 struct vfs_aio_state aio_state;
2339 uint32_t dos_attributes;
2342 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2344 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2345 TALLOC_CTX *mem_ctx,
2346 struct tevent_context *ev,
2347 struct vfs_handle_struct *handle,
2348 files_struct *dir_fsp,
2349 struct smb_filename *smb_fname)
2351 struct tevent_req *req = NULL;
2352 struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2353 struct tevent_req *subreq = NULL;
2355 req = tevent_req_create(mem_ctx, &state,
2356 struct smb_vfs_call_get_dos_attributes_state);
2361 VFS_FIND(get_dos_attributes_send);
2363 *state = (struct smb_vfs_call_get_dos_attributes_state) {
2365 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2368 subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2373 if (tevent_req_nomem(subreq, req)) {
2374 return tevent_req_post(req, ev);
2376 tevent_req_defer_callback(req, ev);
2378 tevent_req_set_callback(subreq,
2379 smb_vfs_call_get_dos_attributes_done,
2385 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2387 struct tevent_req *req =
2388 tevent_req_callback_data(subreq,
2390 struct smb_vfs_call_get_dos_attributes_state *state =
2391 tevent_req_data(req,
2392 struct smb_vfs_call_get_dos_attributes_state);
2397 * Make sure we run as the user again
2399 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2402 status = state->recv_fn(subreq,
2404 &state->dos_attributes);
2405 TALLOC_FREE(subreq);
2406 if (tevent_req_nterror(req, status)) {
2410 tevent_req_done(req);
2413 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2414 struct tevent_req *req,
2415 struct vfs_aio_state *aio_state,
2416 uint32_t *dos_attributes)
2418 struct smb_vfs_call_get_dos_attributes_state *state =
2419 tevent_req_data(req,
2420 struct smb_vfs_call_get_dos_attributes_state);
2423 if (tevent_req_is_nterror(req, &status)) {
2424 tevent_req_received(req);
2428 *aio_state = state->aio_state;
2429 *dos_attributes = state->dos_attributes;
2430 tevent_req_received(req);
2431 return NT_STATUS_OK;
2434 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2435 TALLOC_CTX *mem_ctx,
2436 struct files_struct *fsp,
2437 struct smb_filename *smb_fname,
2438 uint16_t *_compression_fmt)
2440 VFS_FIND(get_compression);
2441 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2445 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2446 TALLOC_CTX *mem_ctx,
2447 struct files_struct *fsp,
2448 uint16_t compression_fmt)
2450 VFS_FIND(set_compression);
2451 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2455 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2456 TALLOC_CTX *mem_ctx,
2457 const char *service_path,
2460 VFS_FIND(snap_check_path);
2461 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2465 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2466 TALLOC_CTX *mem_ctx,
2467 const char *base_volume,
2473 VFS_FIND(snap_create);
2474 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2475 rw, base_path, snap_path);
2478 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2479 TALLOC_CTX *mem_ctx,
2483 VFS_FIND(snap_delete);
2484 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2488 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2489 struct files_struct *fsp,
2490 uint32_t security_info,
2491 TALLOC_CTX *mem_ctx,
2492 struct security_descriptor **ppdesc)
2494 VFS_FIND(fget_nt_acl);
2495 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2499 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2500 const struct smb_filename *smb_fname,
2501 uint32_t security_info,
2502 TALLOC_CTX *mem_ctx,
2503 struct security_descriptor **ppdesc)
2505 VFS_FIND(get_nt_acl);
2506 return handle->fns->get_nt_acl_fn(handle,
2513 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2514 struct files_struct *fsp,
2515 uint32_t security_info_sent,
2516 const struct security_descriptor *psd)
2518 VFS_FIND(fset_nt_acl);
2519 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2523 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2524 struct smb_filename *file,
2525 struct security_acl *sacl,
2526 uint32_t access_requested,
2527 uint32_t access_denied)
2529 VFS_FIND(audit_file);
2530 return handle->fns->audit_file_fn(handle,
2537 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2538 const struct smb_filename *smb_fname,
2539 SMB_ACL_TYPE_T type,
2540 TALLOC_CTX *mem_ctx)
2542 VFS_FIND(sys_acl_get_file);
2543 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2546 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2547 struct files_struct *fsp,
2548 TALLOC_CTX *mem_ctx)
2550 VFS_FIND(sys_acl_get_fd);
2551 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2554 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2555 const struct smb_filename *smb_fname,
2556 TALLOC_CTX *mem_ctx,
2557 char **blob_description,
2560 VFS_FIND(sys_acl_blob_get_file);
2561 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2562 mem_ctx, blob_description, blob);
2565 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2566 struct files_struct *fsp,
2567 TALLOC_CTX *mem_ctx,
2568 char **blob_description,
2571 VFS_FIND(sys_acl_blob_get_fd);
2572 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2575 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2576 const struct smb_filename *smb_fname,
2577 SMB_ACL_TYPE_T acltype,
2580 VFS_FIND(sys_acl_set_file);
2581 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2585 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2586 struct files_struct *fsp, SMB_ACL_T theacl)
2588 VFS_FIND(sys_acl_set_fd);
2589 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2592 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2593 const struct smb_filename *smb_fname)
2595 VFS_FIND(sys_acl_delete_def_file);
2596 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2599 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2600 const struct smb_filename *smb_fname,
2606 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2610 struct smb_vfs_call_getxattrat_state {
2611 files_struct *dir_fsp;
2612 ssize_t (*recv_fn)(struct tevent_req *req,
2613 struct vfs_aio_state *aio_state,
2614 TALLOC_CTX *mem_ctx,
2615 uint8_t **xattr_value);
2617 uint8_t *xattr_value;
2618 struct vfs_aio_state aio_state;
2621 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2623 struct tevent_req *smb_vfs_call_getxattrat_send(
2624 TALLOC_CTX *mem_ctx,
2625 struct tevent_context *ev,
2626 struct vfs_handle_struct *handle,
2627 files_struct *dir_fsp,
2628 const struct smb_filename *smb_fname,
2629 const char *xattr_name,
2632 struct tevent_req *req = NULL;
2633 struct smb_vfs_call_getxattrat_state *state = NULL;
2634 struct tevent_req *subreq = NULL;
2636 req = tevent_req_create(mem_ctx, &state,
2637 struct smb_vfs_call_getxattrat_state);
2642 VFS_FIND(getxattrat_send);
2644 *state = (struct smb_vfs_call_getxattrat_state) {
2646 .recv_fn = handle->fns->getxattrat_recv_fn,
2649 subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2656 if (tevent_req_nomem(subreq, req)) {
2657 return tevent_req_post(req, ev);
2659 tevent_req_defer_callback(req, ev);
2661 tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2665 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2667 struct tevent_req *req = tevent_req_callback_data(
2668 subreq, struct tevent_req);
2669 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2670 req, struct smb_vfs_call_getxattrat_state);
2674 * Make sure we run as the user again
2676 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2679 state->retval = state->recv_fn(subreq,
2682 &state->xattr_value);
2683 TALLOC_FREE(subreq);
2684 if (state->retval == -1) {
2685 tevent_req_error(req, state->aio_state.error);
2689 tevent_req_done(req);
2692 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2693 struct vfs_aio_state *aio_state,
2694 TALLOC_CTX *mem_ctx,
2695 uint8_t **xattr_value)
2697 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2698 req, struct smb_vfs_call_getxattrat_state);
2701 if (tevent_req_is_unix_error(req, &aio_state->error)) {
2702 tevent_req_received(req);
2706 *aio_state = state->aio_state;
2707 xattr_size = state->retval;
2708 if (xattr_value != NULL) {
2709 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2712 tevent_req_received(req);
2716 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2717 struct files_struct *fsp, const char *name,
2718 void *value, size_t size)
2720 VFS_FIND(fgetxattr);
2721 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2724 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2725 const struct smb_filename *smb_fname,
2729 VFS_FIND(listxattr);
2730 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2733 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2734 struct files_struct *fsp, char *list,
2737 VFS_FIND(flistxattr);
2738 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2741 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2742 const struct smb_filename *smb_fname,
2745 VFS_FIND(removexattr);
2746 return handle->fns->removexattr_fn(handle, smb_fname, name);
2749 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2750 struct files_struct *fsp, const char *name)
2752 VFS_FIND(fremovexattr);
2753 return handle->fns->fremovexattr_fn(handle, fsp, name);
2756 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2757 const struct smb_filename *smb_fname,
2764 return handle->fns->setxattr_fn(handle, smb_fname,
2765 name, value, size, flags);
2768 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2769 struct files_struct *fsp, const char *name,
2770 const void *value, size_t size, int flags)
2772 VFS_FIND(fsetxattr);
2773 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2776 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2777 struct files_struct *fsp)
2779 VFS_FIND(aio_force);
2780 return handle->fns->aio_force_fn(handle, fsp);
2783 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2784 struct files_struct *fsp,
2785 TALLOC_CTX *mem_ctx,
2788 VFS_FIND(durable_cookie);
2789 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2792 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2793 struct files_struct *fsp,
2794 const DATA_BLOB old_cookie,
2795 TALLOC_CTX *mem_ctx,
2796 DATA_BLOB *new_cookie)
2798 VFS_FIND(durable_disconnect);
2799 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2800 mem_ctx, new_cookie);
2803 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2804 struct smb_request *smb1req,
2805 struct smbXsrv_open *op,
2806 const DATA_BLOB old_cookie,
2807 TALLOC_CTX *mem_ctx,
2808 struct files_struct **fsp,
2809 DATA_BLOB *new_cookie)
2811 VFS_FIND(durable_reconnect);
2812 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2813 old_cookie, mem_ctx, fsp,
2817 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2818 const struct smb_filename *fname,
2819 TALLOC_CTX *mem_ctx,
2820 struct readdir_attr_data **attr_data)
2822 VFS_FIND(readdir_attr);
2823 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);