2 Unix SMB/Netbios implementation.
4 VFS initialisation and support functions
5 Copyright (C) Tim Potter 1999
6 Copyright (C) Alexander Bokovoy 2002
7 Copyright (C) James Peach 2006
8 Copyright (C) Volker Lendecke 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This work was sponsored by Optifacio Software Services, Inc.
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "../lib/util/memcache.h"
31 #include "transfer_file.h"
33 #include "lib/util/tevent_unix.h"
36 #define DBGC_CLASS DBGC_VFS
41 struct vfs_fsp_data *next;
42 struct vfs_handle_struct *owner;
43 void (*destroy)(void *p_data);
45 /* NOTE: This structure contains four pointers so that we can guarantee
46 * that the end of the structure is always both 4-byte and 8-byte aligned.
50 struct vfs_init_function_entry {
52 struct vfs_init_function_entry *prev, *next;
53 const struct vfs_fn_pointers *fns;
56 /****************************************************************************
57 maintain the list of available backends
58 ****************************************************************************/
60 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
62 struct vfs_init_function_entry *entry = backends;
64 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
67 if (strcmp(entry->name, name)==0) return entry;
74 NTSTATUS smb_register_vfs(int version, const char *name,
75 const struct vfs_fn_pointers *fns)
77 struct vfs_init_function_entry *entry = backends;
79 if ((version != SMB_VFS_INTERFACE_VERSION)) {
80 DEBUG(0, ("Failed to register vfs module.\n"
81 "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
82 "current SMB_VFS_INTERFACE_VERSION is %d.\n"
83 "Please recompile against the current Samba Version!\n",
84 version, SMB_VFS_INTERFACE_VERSION));
85 return NT_STATUS_OBJECT_TYPE_MISMATCH;
88 if (!name || !name[0]) {
89 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
90 return NT_STATUS_INVALID_PARAMETER;
93 if (vfs_find_backend_entry(name)) {
94 DEBUG(0,("VFS module %s already loaded!\n", name));
95 return NT_STATUS_OBJECT_NAME_COLLISION;
98 entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
99 entry->name = smb_xstrdup(name);
102 DLIST_ADD(backends, entry);
103 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
107 /****************************************************************************
108 initialise default vfs hooks
109 ****************************************************************************/
111 static void vfs_init_default(connection_struct *conn)
113 DEBUG(3, ("Initialising default vfs hooks\n"));
114 vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
117 /****************************************************************************
118 initialise custom vfs hooks
119 ****************************************************************************/
121 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
123 char *module_path = NULL;
124 char *module_name = NULL;
125 char *module_param = NULL, *p;
126 vfs_handle_struct *handle;
127 const struct vfs_init_function_entry *entry;
129 if (!conn||!vfs_object||!vfs_object[0]) {
130 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
131 "empty vfs_object!\n"));
139 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
141 module_path = smb_xstrdup(vfs_object);
143 p = strchr_m(module_path, ':');
148 trim_char(module_param, ' ', ' ');
151 trim_char(module_path, ' ', ' ');
153 module_name = smb_xstrdup(module_path);
155 if ((module_name[0] == '/') &&
156 (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
159 * Extract the module name from the path. Just use the base
160 * name of the last path component.
163 SAFE_FREE(module_name);
164 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
166 p = strchr_m(module_name, '.');
173 /* First, try to load the module with the new module system */
174 entry = vfs_find_backend_entry(module_name);
178 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
181 status = smb_load_module("vfs", module_path);
182 if (!NT_STATUS_IS_OK(status)) {
183 DEBUG(0, ("error probing vfs module '%s': %s\n",
184 module_path, nt_errstr(status)));
188 entry = vfs_find_backend_entry(module_name);
190 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
195 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
197 handle = talloc_zero(conn, vfs_handle_struct);
199 DEBUG(0,("TALLOC_ZERO() failed!\n"));
203 handle->fns = entry->fns;
205 handle->param = talloc_strdup(conn, module_param);
207 DLIST_ADD(conn->vfs_handles, handle);
209 SAFE_FREE(module_path);
210 SAFE_FREE(module_name);
214 SAFE_FREE(module_path);
215 SAFE_FREE(module_name);
219 /*****************************************************************
220 Allow VFS modules to extend files_struct with VFS-specific state.
221 This will be ok for small numbers of extensions, but might need to
222 be refactored if it becomes more widely used.
223 ******************************************************************/
225 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
227 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
228 files_struct *fsp, size_t ext_size,
229 void (*destroy_fn)(void *p_data))
231 struct vfs_fsp_data *ext;
234 /* Prevent VFS modules adding multiple extensions. */
235 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
239 ext = (struct vfs_fsp_data *)TALLOC_ZERO(
240 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
246 ext->next = fsp->vfs_extension;
247 ext->destroy = destroy_fn;
248 fsp->vfs_extension = ext;
249 return EXT_DATA_AREA(ext);
252 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
254 struct vfs_fsp_data *curr;
255 struct vfs_fsp_data *prev;
257 for (curr = fsp->vfs_extension, prev = NULL;
259 prev = curr, curr = curr->next) {
260 if (curr->owner == handle) {
262 prev->next = curr->next;
264 fsp->vfs_extension = curr->next;
267 curr->destroy(EXT_DATA_AREA(curr));
275 void vfs_remove_all_fsp_extensions(files_struct *fsp)
277 struct vfs_fsp_data *curr;
278 struct vfs_fsp_data *next;
280 for (curr = fsp->vfs_extension; curr; curr = next) {
283 fsp->vfs_extension = next;
286 curr->destroy(EXT_DATA_AREA(curr));
292 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
294 struct vfs_fsp_data *head;
296 for (head = fsp->vfs_extension; head; head = head->next) {
297 if (head->owner == handle) {
305 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
307 struct vfs_fsp_data *head;
309 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
311 return EXT_DATA_AREA(head);
319 /*****************************************************************
321 ******************************************************************/
323 bool smbd_vfs_init(connection_struct *conn)
325 const char **vfs_objects;
329 /* Normal share - initialise with disk access functions */
330 vfs_init_default(conn);
332 /* No need to load vfs modules for printer connections */
337 vfs_objects = lp_vfs_objects(SNUM(conn));
339 /* Override VFS functions if 'vfs object' was not specified*/
340 if (!vfs_objects || !vfs_objects[0])
343 for (i=0; vfs_objects[i] ;) {
347 for (j=i-1; j >= 0; j--) {
348 if (!vfs_init_custom(conn, vfs_objects[j])) {
349 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
356 /*******************************************************************
357 Check if a file exists in the vfs.
358 ********************************************************************/
360 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
362 /* Only return OK if stat was successful and S_ISREG */
363 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
364 S_ISREG(smb_fname->st.st_ex_mode)) {
368 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
371 /****************************************************************************
372 Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
373 ****************************************************************************/
375 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
379 while (total < byte_count)
381 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
384 if (ret == 0) return total;
393 return (ssize_t)total;
396 /****************************************************************************
397 Write data to a fd on the vfs.
398 ****************************************************************************/
400 ssize_t vfs_write_data(struct smb_request *req,
408 if (req && req->unread_bytes) {
409 int sockfd = req->xconn->transport.sock;
411 SMB_ASSERT(req->unread_bytes == N);
412 /* VFS_RECVFILE must drain the socket
413 * before returning. */
414 req->unread_bytes = 0;
415 /* Ensure the socket is blocking. */
416 old_flags = fcntl(sockfd, F_GETFL, 0);
417 if (set_blocking(sockfd, true) == -1) {
420 ret = SMB_VFS_RECVFILE(sockfd,
424 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
431 ret = SMB_VFS_WRITE(fsp, buffer + total, N - total);
440 return (ssize_t)total;
443 ssize_t vfs_pwrite_data(struct smb_request *req,
452 if (req && req->unread_bytes) {
453 int sockfd = req->xconn->transport.sock;
454 SMB_ASSERT(req->unread_bytes == N);
455 /* VFS_RECVFILE must drain the socket
456 * before returning. */
457 req->unread_bytes = 0;
459 * Leave the socket non-blocking and
460 * use SMB_VFS_RECVFILE. If it returns
461 * EAGAIN || EWOULDBLOCK temporarily set
462 * the socket blocking and retry
466 ret = SMB_VFS_RECVFILE(sockfd,
470 if (ret == 0 || (ret == -1 &&
472 errno == EWOULDBLOCK))) {
474 /* Ensure the socket is blocking. */
475 old_flags = fcntl(sockfd, F_GETFL, 0);
476 if (set_blocking(sockfd, true) == -1) {
479 ret = SMB_VFS_RECVFILE(sockfd,
483 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
490 return (ssize_t)total;
492 /* Any other error case. */
498 return (ssize_t)total;
502 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
512 return (ssize_t)total;
514 /****************************************************************************
515 An allocate file space call using the vfs interface.
516 Allocates space for a file from a filedescriptor.
517 Returns 0 on success, -1 on failure.
518 ****************************************************************************/
520 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
523 connection_struct *conn = fsp->conn;
524 uint64_t space_avail;
525 uint64_t bsize,dfree,dsize;
529 * Actually try and commit the space on disk....
532 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
533 fsp_str_dbg(fsp), (double)len));
535 if (((off_t)len) < 0) {
536 DEBUG(0,("vfs_allocate_file_space: %s negative len "
537 "requested.\n", fsp_str_dbg(fsp)));
542 status = vfs_stat_fsp(fsp);
543 if (!NT_STATUS_IS_OK(status)) {
547 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
550 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
551 /* Shrink - use ftruncate. */
553 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
554 "size %.0f\n", fsp_str_dbg(fsp),
555 (double)fsp->fsp_name->st.st_ex_size));
557 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
559 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
560 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
561 set_filelen_write_cache(fsp, len);
564 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
569 /* Grow - we need to test if we have enough space. */
571 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
573 if (lp_strict_allocate(SNUM(fsp->conn))) {
574 /* See if we have a syscall that will allocate beyond
575 end-of-file without changing EOF. */
576 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
582 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
585 /* We changed the allocation size on disk, but not
586 EOF - exactly as required. We're done ! */
590 if (ret == -1 && errno == ENOSPC) {
594 len -= fsp->fsp_name->st.st_ex_size;
595 len /= 1024; /* Len is now number of 1k blocks needed. */
596 space_avail = get_dfree_info(conn, fsp->fsp_name->base_name,
597 &bsize, &dfree, &dsize);
598 if (space_avail == (uint64_t)-1) {
602 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
603 "needed blocks = %.0f, space avail = %.0f\n",
604 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
605 (double)space_avail));
607 if (len > space_avail) {
615 /****************************************************************************
616 A vfs set_filelen call.
617 set the length of a file from a filedescriptor.
618 Returns 0 on success, -1 on failure.
619 ****************************************************************************/
621 int vfs_set_filelen(files_struct *fsp, off_t len)
625 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
627 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
628 fsp_str_dbg(fsp), (double)len));
629 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
630 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
631 set_filelen_write_cache(fsp, len);
632 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
633 FILE_NOTIFY_CHANGE_SIZE
634 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
635 fsp->fsp_name->base_name);
638 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
643 /****************************************************************************
644 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
645 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
646 as this is also called from the default SMB_VFS_FTRUNCATE code.
647 Always extends the file size.
648 Returns 0 on success, -1 on failure.
649 ****************************************************************************/
651 #define SPARSE_BUF_WRITE_SIZE (32*1024)
653 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
659 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
666 while (total < len) {
667 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
669 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
670 if (pwrite_ret == -1) {
671 int saved_errno = errno;
672 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
673 "%s failed with error %s\n",
674 fsp_str_dbg(fsp), strerror(saved_errno)));
684 /****************************************************************************
685 A vfs fill sparse call.
686 Writes zeros from the end of file to len, if len is greater than EOF.
687 Used only by strict_sync.
688 Returns 0 on success, -1 on failure.
689 ****************************************************************************/
691 int vfs_fill_sparse(files_struct *fsp, off_t len)
698 status = vfs_stat_fsp(fsp);
699 if (!NT_STATUS_IS_OK(status)) {
703 if (len <= fsp->fsp_name->st.st_ex_size) {
708 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
713 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
714 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
715 (double)fsp->fsp_name->st.st_ex_size, (double)len,
716 (double)(len - fsp->fsp_name->st.st_ex_size)));
718 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
720 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
722 offset = fsp->fsp_name->st.st_ex_size;
723 num_to_write = len - fsp->fsp_name->st.st_ex_size;
725 /* Only do this on non-stream file handles. */
726 if (fsp->base_fsp == NULL) {
727 /* for allocation try fallocate first. This can fail on some
728 * platforms e.g. when the filesystem doesn't support it and no
729 * emulation is being done by the libc (like on AIX with JFS1). In that
730 * case we do our own emulation. fallocate implementations can
731 * return ENOTSUP or EINVAL in cases like that. */
732 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
733 if (ret == -1 && errno == ENOSPC) {
739 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
740 "error %d. Falling back to slow manual allocation\n", ret));
743 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
748 set_filelen_write_cache(fsp, len);
751 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
755 /****************************************************************************
756 Transfer some data (n bytes) between two file_struct's.
757 ****************************************************************************/
759 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
761 struct files_struct *fsp = (struct files_struct *)file;
763 return SMB_VFS_PREAD(fsp, buf, len, offset);
766 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
768 struct files_struct *fsp = (struct files_struct *)file;
770 return SMB_VFS_PWRITE(fsp, buf, len, offset);
773 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
775 return transfer_file_internal((void *)in, (void *)out, n,
776 vfs_pread_fn, vfs_pwrite_fn);
779 /*******************************************************************
780 A vfs_readdir wrapper which just returns the file name.
781 ********************************************************************/
783 const char *vfs_readdirname(connection_struct *conn, void *p,
784 SMB_STRUCT_STAT *sbuf, char **talloced)
786 struct dirent *ptr= NULL;
794 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
806 #ifdef HAVE_BROKEN_READDIR_NAME
807 /* using /usr/ucb/cc is BAD */
811 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
812 talloc_tos(), &translated);
813 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
817 *talloced = translated;
818 if (!NT_STATUS_IS_OK(status)) {
824 /*******************************************************************
825 A wrapper for vfs_chdir().
826 ********************************************************************/
828 int vfs_ChDir(connection_struct *conn, const char *path)
833 LastDir = SMB_STRDUP("");
840 if (*path == '/' && strcsequal(LastDir,path)) {
844 DEBUG(4,("vfs_ChDir to %s\n",path));
846 ret = SMB_VFS_CHDIR(conn,path);
850 LastDir = SMB_STRDUP(path);
853 TALLOC_FREE(conn->cwd);
854 conn->cwd = vfs_GetWd(conn, conn);
855 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
860 /*******************************************************************
861 Return the absolute current directory path - given a UNIX pathname.
862 Note that this path is returned in DOS format, not UNIX
863 format. Note this can be called with conn == NULL.
864 ********************************************************************/
866 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
868 char *current_dir = NULL;
870 DATA_BLOB cache_value;
872 struct smb_filename *smb_fname_dot = NULL;
873 struct smb_filename *smb_fname_full = NULL;
875 if (!lp_getwd_cache()) {
879 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
880 if (smb_fname_dot == NULL) {
885 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
887 * Known to fail for root: the directory may be NFS-mounted
888 * and exported with root_squash (so has no root access).
890 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
891 "(NFS problem ?)\n", strerror(errno) ));
895 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
897 if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
898 data_blob_const(&key, sizeof(key)),
903 SMB_ASSERT((cache_value.length > 0)
904 && (cache_value.data[cache_value.length-1] == '\0'));
906 smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
908 if (smb_fname_full == NULL) {
913 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
914 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
915 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
916 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
920 result = talloc_strdup(ctx, smb_fname_full->base_name);
921 if (result == NULL) {
930 * We don't have the information to hand so rely on traditional
931 * methods. The very slow getcwd, which spawns a process on some
932 * systems, or the not quite so bad getwd.
935 current_dir = SMB_VFS_GETWD(conn);
936 if (current_dir == NULL) {
937 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
942 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
943 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
945 memcache_add(smbd_memcache(), GETWD_CACHE,
946 data_blob_const(&key, sizeof(key)),
947 data_blob_const(current_dir,
948 strlen(current_dir)+1));
951 result = talloc_strdup(ctx, current_dir);
952 if (result == NULL) {
957 TALLOC_FREE(smb_fname_dot);
958 TALLOC_FREE(smb_fname_full);
959 SAFE_FREE(current_dir);
963 /*******************************************************************
964 Reduce a file name, removing .. elements and checking that
965 it is below dir in the heirachy. This uses realpath.
966 This function must run as root, and will return names
967 and valid stat structs that can be checked on open.
968 ********************************************************************/
970 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
972 struct smb_request *smbreq)
975 TALLOC_CTX *ctx = talloc_tos();
976 const char *conn_rootdir;
978 char *dir_name = NULL;
979 const char *last_component = NULL;
980 char *resolved_name = NULL;
981 char *saved_dir = NULL;
982 struct smb_filename *smb_fname_cwd = NULL;
983 struct privilege_paths *priv_paths = NULL;
986 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
991 priv_paths = talloc_zero(smbreq, struct privilege_paths);
993 status = NT_STATUS_NO_MEMORY;
997 if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
998 status = NT_STATUS_NO_MEMORY;
1002 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1003 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1005 if (priv_paths->parent_name.base_name == NULL ||
1006 priv_paths->file_name.base_name == NULL) {
1007 status = NT_STATUS_NO_MEMORY;
1011 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1012 status = map_nt_error_from_unix(errno);
1015 /* Remember where we were. */
1016 saved_dir = vfs_GetWd(ctx, conn);
1018 status = map_nt_error_from_unix(errno);
1022 /* Go to the parent directory to lock in memory. */
1023 if (vfs_ChDir(conn, priv_paths->parent_name.base_name) == -1) {
1024 status = map_nt_error_from_unix(errno);
1028 /* Get the absolute path of the parent directory. */
1029 resolved_name = SMB_VFS_REALPATH(conn,".");
1030 if (!resolved_name) {
1031 status = map_nt_error_from_unix(errno);
1035 if (*resolved_name != '/') {
1036 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1037 "doesn't return absolute paths !\n"));
1038 status = NT_STATUS_OBJECT_NAME_INVALID;
1042 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1043 priv_paths->parent_name.base_name,
1046 /* Now check the stat value is the same. */
1047 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1048 if (smb_fname_cwd == NULL) {
1049 status = NT_STATUS_NO_MEMORY;
1053 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1054 status = map_nt_error_from_unix(errno);
1058 /* Ensure we're pointing at the same place. */
1059 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1060 DEBUG(0,("check_reduced_name_with_privilege: "
1061 "device/inode/uid/gid on directory %s changed. "
1062 "Denying access !\n",
1063 priv_paths->parent_name.base_name));
1064 status = NT_STATUS_ACCESS_DENIED;
1068 /* Ensure we're below the connect path. */
1070 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1071 if (conn_rootdir == NULL) {
1072 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1074 status = NT_STATUS_ACCESS_DENIED;
1078 rootdir_len = strlen(conn_rootdir);
1081 * In the case of rootdir_len == 1, we know that conn_rootdir is
1082 * "/", and we also know that resolved_name starts with a slash.
1083 * So, in this corner case, resolved_name is automatically a
1084 * sub-directory of the conn_rootdir. Thus we can skip the string
1085 * comparison and the next character checks (which are even
1086 * wrong in this case).
1088 if (rootdir_len != 1) {
1091 matched = (strncmp(conn_rootdir, resolved_name,
1094 if (!matched || (resolved_name[rootdir_len] != '/' &&
1095 resolved_name[rootdir_len] != '\0')) {
1096 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1097 "access attempt: %s is a symlink outside the "
1100 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1101 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1102 status = NT_STATUS_ACCESS_DENIED;
1107 /* Now ensure that the last component either doesn't
1108 exist, or is *NOT* a symlink. */
1110 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1112 /* Errno must be ENOENT for this be ok. */
1113 if (errno != ENOENT) {
1114 status = map_nt_error_from_unix(errno);
1115 DEBUG(2, ("check_reduced_name_with_privilege: "
1116 "LSTAT on %s failed with %s\n",
1117 priv_paths->file_name.base_name,
1118 nt_errstr(status)));
1123 if (VALID_STAT(priv_paths->file_name.st) &&
1124 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1125 DEBUG(2, ("check_reduced_name_with_privilege: "
1126 "Last component %s is a symlink. Denying"
1128 priv_paths->file_name.base_name));
1129 status = NT_STATUS_ACCESS_DENIED;
1133 smbreq->priv_paths = priv_paths;
1134 status = NT_STATUS_OK;
1139 vfs_ChDir(conn, saved_dir);
1141 SAFE_FREE(resolved_name);
1142 if (!NT_STATUS_IS_OK(status)) {
1143 TALLOC_FREE(priv_paths);
1145 TALLOC_FREE(dir_name);
1149 /*******************************************************************
1150 Reduce a file name, removing .. elements and checking that
1151 it is below dir in the heirachy. This uses realpath.
1152 ********************************************************************/
1154 NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
1156 char *resolved_name = NULL;
1157 bool allow_symlinks = true;
1158 bool allow_widelinks = false;
1160 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1162 resolved_name = SMB_VFS_REALPATH(conn,fname);
1164 if (!resolved_name) {
1167 DEBUG(3,("check_reduced_name: Component not a "
1168 "directory in getting realpath for "
1170 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1173 TALLOC_CTX *ctx = talloc_tos();
1174 char *dir_name = NULL;
1175 const char *last_component = NULL;
1176 char *new_name = NULL;
1179 /* Last component didn't exist.
1180 Remove it and try and canonicalise
1181 the directory name. */
1182 if (!parent_dirname(ctx, fname,
1185 return NT_STATUS_NO_MEMORY;
1188 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1189 if (!resolved_name) {
1190 NTSTATUS status = map_nt_error_from_unix(errno);
1192 if (errno == ENOENT || errno == ENOTDIR) {
1193 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1196 DEBUG(3,("check_reduce_name: "
1197 "couldn't get realpath for "
1200 nt_errstr(status)));
1203 ret = asprintf(&new_name, "%s/%s",
1204 resolved_name, last_component);
1205 SAFE_FREE(resolved_name);
1207 return NT_STATUS_NO_MEMORY;
1209 resolved_name = new_name;
1213 DEBUG(3,("check_reduced_name: couldn't get "
1214 "realpath for %s\n", fname));
1215 return map_nt_error_from_unix(errno);
1219 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1222 if (*resolved_name != '/') {
1223 DEBUG(0,("check_reduced_name: realpath doesn't return "
1224 "absolute paths !\n"));
1225 SAFE_FREE(resolved_name);
1226 return NT_STATUS_OBJECT_NAME_INVALID;
1229 allow_widelinks = lp_widelinks(SNUM(conn));
1230 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1232 /* Common widelinks and symlinks checks. */
1233 if (!allow_widelinks || !allow_symlinks) {
1234 const char *conn_rootdir;
1237 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1238 if (conn_rootdir == NULL) {
1239 DEBUG(2, ("check_reduced_name: Could not get "
1241 SAFE_FREE(resolved_name);
1242 return NT_STATUS_ACCESS_DENIED;
1245 rootdir_len = strlen(conn_rootdir);
1248 * In the case of rootdir_len == 1, we know that
1249 * conn_rootdir is "/", and we also know that
1250 * resolved_name starts with a slash. So, in this
1251 * corner case, resolved_name is automatically a
1252 * sub-directory of the conn_rootdir. Thus we can skip
1253 * the string comparison and the next character checks
1254 * (which are even wrong in this case).
1256 if (rootdir_len != 1) {
1259 matched = (strncmp(conn_rootdir, resolved_name,
1261 if (!matched || (resolved_name[rootdir_len] != '/' &&
1262 resolved_name[rootdir_len] != '\0')) {
1263 DEBUG(2, ("check_reduced_name: Bad access "
1264 "attempt: %s is a symlink outside the "
1265 "share path\n", fname));
1266 DEBUGADD(2, ("conn_rootdir =%s\n",
1268 DEBUGADD(2, ("resolved_name=%s\n",
1270 SAFE_FREE(resolved_name);
1271 return NT_STATUS_ACCESS_DENIED;
1275 /* Extra checks if all symlinks are disallowed. */
1276 if (!allow_symlinks) {
1277 /* fname can't have changed in resolved_path. */
1278 const char *p = &resolved_name[rootdir_len];
1280 /* *p can be '\0' if fname was "." */
1281 if (*p == '\0' && ISDOT(fname)) {
1286 DEBUG(2, ("check_reduced_name: logic error (%c) "
1287 "in resolved_name: %s\n",
1290 SAFE_FREE(resolved_name);
1291 return NT_STATUS_ACCESS_DENIED;
1295 if (strcmp(fname, p)!=0) {
1296 DEBUG(2, ("check_reduced_name: Bad access "
1297 "attempt: %s is a symlink to %s\n",
1299 SAFE_FREE(resolved_name);
1300 return NT_STATUS_ACCESS_DENIED;
1307 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1308 SAFE_FREE(resolved_name);
1309 return NT_STATUS_OK;
1313 * XXX: This is temporary and there should be no callers of this once
1314 * smb_filename is plumbed through all path based operations.
1316 * Called when we know stream name parsing has already been done.
1318 int vfs_stat_smb_basename(struct connection_struct *conn,
1319 const struct smb_filename *smb_fname_in,
1320 SMB_STRUCT_STAT *psbuf)
1322 struct smb_filename smb_fname = {
1323 .base_name = discard_const_p(char, smb_fname_in->base_name),
1324 .flags = smb_fname_in->flags
1328 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1329 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1331 ret = SMB_VFS_STAT(conn, &smb_fname);
1335 *psbuf = smb_fname.st;
1341 * Ensure LSTAT is called for POSIX paths.
1344 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1348 if(fsp->fh->fd == -1) {
1349 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1350 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1352 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1355 return map_nt_error_from_unix(errno);
1358 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1359 return map_nt_error_from_unix(errno);
1362 return NT_STATUS_OK;
1366 * Initialize num_streams and streams, then call VFS op streaminfo
1368 NTSTATUS vfs_streaminfo(connection_struct *conn,
1369 struct files_struct *fsp,
1370 const struct smb_filename *smb_fname,
1371 TALLOC_CTX *mem_ctx,
1372 unsigned int *num_streams,
1373 struct stream_struct **streams)
1377 return SMB_VFS_STREAMINFO(conn,
1386 generate a file_id from a stat structure
1388 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1390 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1393 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1394 const char *service, const char *user)
1397 return handle->fns->connect_fn(handle, service, user);
1400 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1402 VFS_FIND(disconnect);
1403 handle->fns->disconnect_fn(handle);
1406 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1407 const char *path, uint64_t *bsize,
1408 uint64_t *dfree, uint64_t *dsize)
1410 VFS_FIND(disk_free);
1411 return handle->fns->disk_free_fn(handle, path, bsize, dfree, dsize);
1414 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle, const char *path,
1415 enum SMB_QUOTA_TYPE qtype, unid_t id,
1418 VFS_FIND(get_quota);
1419 return handle->fns->get_quota_fn(handle, path, qtype, id, qt);
1422 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1423 enum SMB_QUOTA_TYPE qtype, unid_t id,
1426 VFS_FIND(set_quota);
1427 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1430 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1431 struct files_struct *fsp,
1432 struct shadow_copy_data *shadow_copy_data,
1435 VFS_FIND(get_shadow_copy_data);
1436 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1440 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
1441 struct vfs_statvfs_struct *statbuf)
1444 return handle->fns->statvfs_fn(handle, path, statbuf);
1447 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1448 enum timestamp_set_resolution *p_ts_res)
1450 VFS_FIND(fs_capabilities);
1451 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1454 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1455 struct dfs_GetDFSReferral *r)
1457 VFS_FIND(get_dfs_referrals);
1458 return handle->fns->get_dfs_referrals_fn(handle, r);
1461 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1462 const struct smb_filename *smb_fname,
1464 uint32_t attributes)
1467 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1470 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1471 struct files_struct *fsp,
1473 uint32_t attributes)
1475 VFS_FIND(fdopendir);
1476 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1479 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1481 SMB_STRUCT_STAT *sbuf)
1484 return handle->fns->readdir_fn(handle, dirp, sbuf);
1487 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1488 DIR *dirp, long offset)
1491 handle->fns->seekdir_fn(handle, dirp, offset);
1494 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1498 return handle->fns->telldir_fn(handle, dirp);
1501 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1504 VFS_FIND(rewind_dir);
1505 handle->fns->rewind_dir_fn(handle, dirp);
1508 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1509 const struct smb_filename *smb_fname,
1513 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1516 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1517 const struct smb_filename *smb_fname)
1520 return handle->fns->rmdir_fn(handle, smb_fname);
1523 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1527 return handle->fns->closedir_fn(handle, dir);
1530 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1533 VFS_FIND(init_search_op);
1534 handle->fns->init_search_op_fn(handle, dirp);
1537 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1538 struct smb_filename *smb_fname, struct files_struct *fsp,
1539 int flags, mode_t mode)
1542 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1545 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1546 struct smb_request *req,
1547 uint16_t root_dir_fid,
1548 struct smb_filename *smb_fname,
1549 uint32_t access_mask,
1550 uint32_t share_access,
1551 uint32_t create_disposition,
1552 uint32_t create_options,
1553 uint32_t file_attributes,
1554 uint32_t oplock_request,
1555 struct smb2_lease *lease,
1556 uint64_t allocation_size,
1557 uint32_t private_flags,
1558 struct security_descriptor *sd,
1559 struct ea_list *ea_list,
1560 files_struct **result,
1562 const struct smb2_create_blobs *in_context_blobs,
1563 struct smb2_create_blobs *out_context_blobs)
1565 VFS_FIND(create_file);
1566 return handle->fns->create_file_fn(
1567 handle, req, root_dir_fid, smb_fname, access_mask,
1568 share_access, create_disposition, create_options,
1569 file_attributes, oplock_request, lease, allocation_size,
1570 private_flags, sd, ea_list,
1571 result, pinfo, in_context_blobs, out_context_blobs);
1574 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1575 struct files_struct *fsp)
1578 return handle->fns->close_fn(handle, fsp);
1581 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1582 struct files_struct *fsp, void *data, size_t n)
1585 return handle->fns->read_fn(handle, fsp, data, n);
1588 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1589 struct files_struct *fsp, void *data, size_t n,
1593 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1596 struct smb_vfs_call_pread_state {
1597 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1599 struct vfs_aio_state vfs_aio_state;
1602 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1604 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1605 TALLOC_CTX *mem_ctx,
1606 struct tevent_context *ev,
1607 struct files_struct *fsp,
1609 size_t n, off_t offset)
1611 struct tevent_req *req, *subreq;
1612 struct smb_vfs_call_pread_state *state;
1614 req = tevent_req_create(mem_ctx, &state,
1615 struct smb_vfs_call_pread_state);
1619 VFS_FIND(pread_send);
1620 state->recv_fn = handle->fns->pread_recv_fn;
1622 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1624 if (tevent_req_nomem(subreq, req)) {
1625 return tevent_req_post(req, ev);
1627 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1631 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1633 struct tevent_req *req = tevent_req_callback_data(
1634 subreq, struct tevent_req);
1635 struct smb_vfs_call_pread_state *state = tevent_req_data(
1636 req, struct smb_vfs_call_pread_state);
1638 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1639 TALLOC_FREE(subreq);
1640 if (state->retval == -1) {
1641 tevent_req_error(req, state->vfs_aio_state.error);
1644 tevent_req_done(req);
1647 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1648 struct vfs_aio_state *vfs_aio_state)
1650 struct smb_vfs_call_pread_state *state = tevent_req_data(
1651 req, struct smb_vfs_call_pread_state);
1653 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1656 *vfs_aio_state = state->vfs_aio_state;
1657 return state->retval;
1660 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1661 struct files_struct *fsp, const void *data,
1665 return handle->fns->write_fn(handle, fsp, data, n);
1668 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1669 struct files_struct *fsp, const void *data,
1670 size_t n, off_t offset)
1673 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1676 struct smb_vfs_call_pwrite_state {
1677 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1679 struct vfs_aio_state vfs_aio_state;
1682 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1684 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1685 TALLOC_CTX *mem_ctx,
1686 struct tevent_context *ev,
1687 struct files_struct *fsp,
1689 size_t n, off_t offset)
1691 struct tevent_req *req, *subreq;
1692 struct smb_vfs_call_pwrite_state *state;
1694 req = tevent_req_create(mem_ctx, &state,
1695 struct smb_vfs_call_pwrite_state);
1699 VFS_FIND(pwrite_send);
1700 state->recv_fn = handle->fns->pwrite_recv_fn;
1702 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1704 if (tevent_req_nomem(subreq, req)) {
1705 return tevent_req_post(req, ev);
1707 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1711 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1713 struct tevent_req *req = tevent_req_callback_data(
1714 subreq, struct tevent_req);
1715 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1716 req, struct smb_vfs_call_pwrite_state);
1718 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1719 TALLOC_FREE(subreq);
1720 if (state->retval == -1) {
1721 tevent_req_error(req, state->vfs_aio_state.error);
1724 tevent_req_done(req);
1727 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1728 struct vfs_aio_state *vfs_aio_state)
1730 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1731 req, struct smb_vfs_call_pwrite_state);
1733 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1736 *vfs_aio_state = state->vfs_aio_state;
1737 return state->retval;
1740 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1741 struct files_struct *fsp, off_t offset,
1745 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1748 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1749 files_struct *fromfsp, const DATA_BLOB *header,
1750 off_t offset, size_t count)
1753 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1757 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1758 files_struct *tofsp, off_t offset,
1762 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1765 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1766 const struct smb_filename *smb_fname_src,
1767 const struct smb_filename *smb_fname_dst)
1770 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1773 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1774 struct files_struct *fsp)
1777 return handle->fns->fsync_fn(handle, fsp);
1780 struct smb_vfs_call_fsync_state {
1781 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1783 struct vfs_aio_state vfs_aio_state;
1786 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1788 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1789 TALLOC_CTX *mem_ctx,
1790 struct tevent_context *ev,
1791 struct files_struct *fsp)
1793 struct tevent_req *req, *subreq;
1794 struct smb_vfs_call_fsync_state *state;
1796 req = tevent_req_create(mem_ctx, &state,
1797 struct smb_vfs_call_fsync_state);
1801 VFS_FIND(fsync_send);
1802 state->recv_fn = handle->fns->fsync_recv_fn;
1804 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1805 if (tevent_req_nomem(subreq, req)) {
1806 return tevent_req_post(req, ev);
1808 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1812 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1814 struct tevent_req *req = tevent_req_callback_data(
1815 subreq, struct tevent_req);
1816 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1817 req, struct smb_vfs_call_fsync_state);
1819 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1820 TALLOC_FREE(subreq);
1821 if (state->retval == -1) {
1822 tevent_req_error(req, state->vfs_aio_state.error);
1825 tevent_req_done(req);
1828 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1830 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1831 req, struct smb_vfs_call_fsync_state);
1833 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1836 *vfs_aio_state = state->vfs_aio_state;
1837 return state->retval;
1841 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1842 struct smb_filename *smb_fname)
1845 return handle->fns->stat_fn(handle, smb_fname);
1848 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1849 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1852 return handle->fns->fstat_fn(handle, fsp, sbuf);
1855 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1856 struct smb_filename *smb_filename)
1859 return handle->fns->lstat_fn(handle, smb_filename);
1862 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1863 struct files_struct *fsp,
1864 const SMB_STRUCT_STAT *sbuf)
1866 VFS_FIND(get_alloc_size);
1867 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1870 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1871 const struct smb_filename *smb_fname)
1874 return handle->fns->unlink_fn(handle, smb_fname);
1877 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1878 const struct smb_filename *smb_fname,
1882 return handle->fns->chmod_fn(handle, smb_fname, mode);
1885 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1886 struct files_struct *fsp, mode_t mode)
1889 return handle->fns->fchmod_fn(handle, fsp, mode);
1892 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1893 const struct smb_filename *smb_fname,
1898 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1901 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1902 struct files_struct *fsp, uid_t uid, gid_t gid)
1905 return handle->fns->fchown_fn(handle, fsp, uid, gid);
1908 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
1909 const struct smb_filename *smb_fname,
1914 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
1917 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
1920 bool as_root = false;
1923 if (fsp->fh->fd != -1) {
1925 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
1927 return NT_STATUS_OK;
1929 if (ret == -1 && errno != ENOSYS) {
1930 return map_nt_error_from_unix(errno);
1934 as_root = (geteuid() == 0);
1938 * We are being asked to chown as root. Make
1939 * sure we chdir() into the path to pin it,
1940 * and always act using lchown to ensure we
1941 * don't deref any symbolic links.
1943 char *saved_dir = NULL;
1944 char *parent_dir = NULL;
1945 const char *final_component = NULL;
1946 struct smb_filename *local_smb_fname = NULL;
1948 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
1950 status = map_nt_error_from_unix(errno);
1951 DEBUG(0,("vfs_chown_fsp: failed to get "
1952 "current working directory. Error was %s\n",
1957 if (!parent_dirname(talloc_tos(),
1958 fsp->fsp_name->base_name,
1960 &final_component)) {
1961 return NT_STATUS_NO_MEMORY;
1964 /* cd into the parent dir to pin it. */
1965 ret = vfs_ChDir(fsp->conn, parent_dir);
1967 return map_nt_error_from_unix(errno);
1970 local_smb_fname = synthetic_smb_fname(talloc_tos(),
1974 fsp->fsp_name->flags);
1975 if (local_smb_fname == NULL) {
1976 status = NT_STATUS_NO_MEMORY;
1980 /* Must use lstat here. */
1981 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
1983 status = map_nt_error_from_unix(errno);
1987 /* Ensure it matches the fsp stat. */
1988 if (!check_same_stat(&local_smb_fname->st,
1989 &fsp->fsp_name->st)) {
1990 status = NT_STATUS_ACCESS_DENIED;
1994 ret = SMB_VFS_LCHOWN(fsp->conn,
1999 status = NT_STATUS_OK;
2001 status = map_nt_error_from_unix(errno);
2006 vfs_ChDir(fsp->conn,saved_dir);
2007 TALLOC_FREE(local_smb_fname);
2008 TALLOC_FREE(saved_dir);
2009 TALLOC_FREE(parent_dir);
2014 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2015 ret = SMB_VFS_LCHOWN(fsp->conn,
2019 ret = SMB_VFS_CHOWN(fsp->conn,
2025 status = NT_STATUS_OK;
2027 status = map_nt_error_from_unix(errno);
2032 int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
2035 return handle->fns->chdir_fn(handle, path);
2038 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
2041 return handle->fns->getwd_fn(handle);
2044 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2045 const struct smb_filename *smb_fname,
2046 struct smb_file_time *ft)
2049 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2052 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2053 struct files_struct *fsp, off_t offset)
2055 VFS_FIND(ftruncate);
2056 return handle->fns->ftruncate_fn(handle, fsp, offset);
2059 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2060 struct files_struct *fsp,
2065 VFS_FIND(fallocate);
2066 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2069 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2070 struct files_struct *fsp, uint32_t share_mode,
2071 uint32_t access_mask)
2073 VFS_FIND(kernel_flock);
2074 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2078 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2079 struct files_struct *fsp, int leasetype)
2081 VFS_FIND(linux_setlease);
2082 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2085 int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
2086 const char *newpath)
2089 return handle->fns->symlink_fn(handle, oldpath, newpath);
2092 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2093 const char *path, char *buf, size_t bufsiz)
2096 return handle->fns->readlink_fn(handle, path, buf, bufsiz);
2099 int smb_vfs_call_link(struct vfs_handle_struct *handle, const char *oldpath,
2100 const char *newpath)
2103 return handle->fns->link_fn(handle, oldpath, newpath);
2106 int smb_vfs_call_mknod(struct vfs_handle_struct *handle, const char *path,
2107 mode_t mode, SMB_DEV_T dev)
2110 return handle->fns->mknod_fn(handle, path, mode, dev);
2113 char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
2116 return handle->fns->realpath_fn(handle, path);
2119 int smb_vfs_call_chflags(struct vfs_handle_struct *handle, const char *path,
2123 return handle->fns->chflags_fn(handle, path, flags);
2126 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2127 const SMB_STRUCT_STAT *sbuf)
2129 VFS_FIND(file_id_create);
2130 return handle->fns->file_id_create_fn(handle, sbuf);
2133 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2134 struct files_struct *fsp,
2135 const struct smb_filename *smb_fname,
2136 TALLOC_CTX *mem_ctx,
2137 unsigned int *num_streams,
2138 struct stream_struct **streams)
2140 VFS_FIND(streaminfo);
2141 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2142 num_streams, streams);
2145 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2146 const char *path, const char *name,
2147 TALLOC_CTX *mem_ctx, char **found_name)
2149 VFS_FIND(get_real_filename);
2150 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2154 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2155 const char *filename)
2157 VFS_FIND(connectpath);
2158 return handle->fns->connectpath_fn(handle, filename);
2161 bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
2162 struct files_struct *fsp,
2163 struct lock_struct *plock)
2165 VFS_FIND(strict_lock);
2166 return handle->fns->strict_lock_fn(handle, fsp, plock);
2169 void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
2170 struct files_struct *fsp,
2171 struct lock_struct *plock)
2173 VFS_FIND(strict_unlock);
2174 handle->fns->strict_unlock_fn(handle, fsp, plock);
2177 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2179 enum vfs_translate_direction direction,
2180 TALLOC_CTX *mem_ctx,
2183 VFS_FIND(translate_name);
2184 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2188 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2189 struct files_struct *fsp,
2193 const uint8_t *in_data,
2196 uint32_t max_out_len,
2200 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2201 in_data, in_len, out_data, max_out_len,
2205 struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
2206 TALLOC_CTX *mem_ctx,
2207 struct tevent_context *ev,
2208 struct files_struct *src_fsp,
2210 struct files_struct *dest_fsp,
2214 VFS_FIND(copy_chunk_send);
2215 return handle->fns->copy_chunk_send_fn(handle, mem_ctx, ev, src_fsp,
2216 src_off, dest_fsp, dest_off, num);
2219 NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
2220 struct tevent_req *req,
2223 VFS_FIND(copy_chunk_recv);
2224 return handle->fns->copy_chunk_recv_fn(handle, req, copied);
2227 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2228 TALLOC_CTX *mem_ctx,
2229 struct files_struct *fsp,
2230 struct smb_filename *smb_fname,
2231 uint16_t *_compression_fmt)
2233 VFS_FIND(get_compression);
2234 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2238 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2239 TALLOC_CTX *mem_ctx,
2240 struct files_struct *fsp,
2241 uint16_t compression_fmt)
2243 VFS_FIND(set_compression);
2244 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2248 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2249 TALLOC_CTX *mem_ctx,
2250 const char *service_path,
2253 VFS_FIND(snap_check_path);
2254 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2258 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2259 TALLOC_CTX *mem_ctx,
2260 const char *base_volume,
2266 VFS_FIND(snap_create);
2267 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2268 rw, base_path, snap_path);
2271 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2272 TALLOC_CTX *mem_ctx,
2276 VFS_FIND(snap_delete);
2277 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2281 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2282 struct files_struct *fsp,
2283 uint32_t security_info,
2284 TALLOC_CTX *mem_ctx,
2285 struct security_descriptor **ppdesc)
2287 VFS_FIND(fget_nt_acl);
2288 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2292 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2293 const struct smb_filename *smb_fname,
2294 uint32_t security_info,
2295 TALLOC_CTX *mem_ctx,
2296 struct security_descriptor **ppdesc)
2298 VFS_FIND(get_nt_acl);
2299 return handle->fns->get_nt_acl_fn(handle,
2306 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2307 struct files_struct *fsp,
2308 uint32_t security_info_sent,
2309 const struct security_descriptor *psd)
2311 VFS_FIND(fset_nt_acl);
2312 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2316 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2317 struct smb_filename *file,
2318 struct security_acl *sacl,
2319 uint32_t access_requested,
2320 uint32_t access_denied)
2322 VFS_FIND(audit_file);
2323 return handle->fns->audit_file_fn(handle,
2330 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle,
2331 const struct smb_filename *smb_fname,
2334 VFS_FIND(chmod_acl);
2335 return handle->fns->chmod_acl_fn(handle, smb_fname, mode);
2338 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2339 struct files_struct *fsp, mode_t mode)
2341 VFS_FIND(fchmod_acl);
2342 return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2345 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2347 SMB_ACL_TYPE_T type,
2348 TALLOC_CTX *mem_ctx)
2350 VFS_FIND(sys_acl_get_file);
2351 return handle->fns->sys_acl_get_file_fn(handle, path_p, type, mem_ctx);
2354 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2355 struct files_struct *fsp,
2356 TALLOC_CTX *mem_ctx)
2358 VFS_FIND(sys_acl_get_fd);
2359 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2362 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2364 TALLOC_CTX *mem_ctx,
2365 char **blob_description,
2368 VFS_FIND(sys_acl_blob_get_file);
2369 return handle->fns->sys_acl_blob_get_file_fn(handle, path_p, mem_ctx, blob_description, blob);
2372 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2373 struct files_struct *fsp,
2374 TALLOC_CTX *mem_ctx,
2375 char **blob_description,
2378 VFS_FIND(sys_acl_blob_get_fd);
2379 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2382 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2383 const char *name, SMB_ACL_TYPE_T acltype,
2386 VFS_FIND(sys_acl_set_file);
2387 return handle->fns->sys_acl_set_file_fn(handle, name, acltype, theacl);
2390 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2391 struct files_struct *fsp, SMB_ACL_T theacl)
2393 VFS_FIND(sys_acl_set_fd);
2394 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2397 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2400 VFS_FIND(sys_acl_delete_def_file);
2401 return handle->fns->sys_acl_delete_def_file_fn(handle, path);
2404 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2405 const char *path, const char *name, void *value,
2409 return handle->fns->getxattr_fn(handle, path, name, value, size);
2412 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2413 struct files_struct *fsp, const char *name,
2414 void *value, size_t size)
2416 VFS_FIND(fgetxattr);
2417 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2420 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2421 const char *path, char *list, size_t size)
2423 VFS_FIND(listxattr);
2424 return handle->fns->listxattr_fn(handle, path, list, size);
2427 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2428 struct files_struct *fsp, char *list,
2431 VFS_FIND(flistxattr);
2432 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2435 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2436 const char *path, const char *name)
2438 VFS_FIND(removexattr);
2439 return handle->fns->removexattr_fn(handle, path, name);
2442 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2443 struct files_struct *fsp, const char *name)
2445 VFS_FIND(fremovexattr);
2446 return handle->fns->fremovexattr_fn(handle, fsp, name);
2449 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle, const char *path,
2450 const char *name, const void *value, size_t size,
2454 return handle->fns->setxattr_fn(handle, path, name, value, size, flags);
2457 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2458 struct files_struct *fsp, const char *name,
2459 const void *value, size_t size, int flags)
2461 VFS_FIND(fsetxattr);
2462 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2465 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2466 struct files_struct *fsp)
2468 VFS_FIND(aio_force);
2469 return handle->fns->aio_force_fn(handle, fsp);
2472 bool smb_vfs_call_is_offline(struct vfs_handle_struct *handle,
2473 const struct smb_filename *fname,
2474 SMB_STRUCT_STAT *sbuf)
2476 VFS_FIND(is_offline);
2477 return handle->fns->is_offline_fn(handle, fname, sbuf);
2480 int smb_vfs_call_set_offline(struct vfs_handle_struct *handle,
2481 const struct smb_filename *fname)
2483 VFS_FIND(set_offline);
2484 return handle->fns->set_offline_fn(handle, fname);
2487 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2488 struct files_struct *fsp,
2489 TALLOC_CTX *mem_ctx,
2492 VFS_FIND(durable_cookie);
2493 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2496 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2497 struct files_struct *fsp,
2498 const DATA_BLOB old_cookie,
2499 TALLOC_CTX *mem_ctx,
2500 DATA_BLOB *new_cookie)
2502 VFS_FIND(durable_disconnect);
2503 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2504 mem_ctx, new_cookie);
2507 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2508 struct smb_request *smb1req,
2509 struct smbXsrv_open *op,
2510 const DATA_BLOB old_cookie,
2511 TALLOC_CTX *mem_ctx,
2512 struct files_struct **fsp,
2513 DATA_BLOB *new_cookie)
2515 VFS_FIND(durable_reconnect);
2516 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2517 old_cookie, mem_ctx, fsp,
2521 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2522 const struct smb_filename *fname,
2523 TALLOC_CTX *mem_ctx,
2524 struct readdir_attr_data **attr_data)
2526 VFS_FIND(readdir_attr);
2527 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);