s3: VFS: Remove SMB_VFS_WRITE() function and all implementations.
[Samba.git] / source3 / smbd / vfs.c
blob386e955243f57bc41ab1dc997f429d019f6633f7
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
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.
26 #include "includes.h"
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"
32 #include "ntioctl.h"
33 #include "lib/util/tevent_unix.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_VFS
38 static_decl_vfs;
40 struct vfs_fsp_data {
41 struct vfs_fsp_data *next;
42 struct vfs_handle_struct *owner;
43 void (*destroy)(void *p_data);
44 void *_dummy_;
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 {
51 char *name;
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));
66 while(entry) {
67 if (strcmp(entry->name, name)==0) return entry;
68 entry = entry->next;
71 return NULL;
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);
100 entry->fns = fns;
102 DLIST_ADD(backends, entry);
103 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
104 return NT_STATUS_OK;
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"));
132 return False;
135 if(!backends) {
136 static_init_vfs(NULL);
139 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
141 module_path = smb_xstrdup(vfs_object);
143 p = strchr_m(module_path, ':');
145 if (p) {
146 *p = 0;
147 module_param = p+1;
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, '.');
168 if (p != NULL) {
169 *p = '\0';
173 /* First, try to load the module with the new module system */
174 entry = vfs_find_backend_entry(module_name);
175 if (!entry) {
176 NTSTATUS status;
178 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
179 vfs_object));
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)));
185 goto fail;
188 entry = vfs_find_backend_entry(module_name);
189 if (!entry) {
190 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
191 goto fail;
195 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
197 handle = talloc_zero(conn, vfs_handle_struct);
198 if (!handle) {
199 DEBUG(0,("TALLOC_ZERO() failed!\n"));
200 goto fail;
202 handle->conn = conn;
203 handle->fns = entry->fns;
204 if (module_param) {
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);
211 return True;
213 fail:
214 SAFE_FREE(module_path);
215 SAFE_FREE(module_name);
216 return False;
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;
232 void * ext_data;
234 /* Prevent VFS modules adding multiple extensions. */
235 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
236 return ext_data;
239 ext = (struct vfs_fsp_data *)TALLOC_ZERO(
240 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
241 if (ext == NULL) {
242 return NULL;
245 ext->owner = handle;
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;
258 curr;
259 prev = curr, curr = curr->next) {
260 if (curr->owner == handle) {
261 if (prev) {
262 prev->next = curr->next;
263 } else {
264 fsp->vfs_extension = curr->next;
266 if (curr->destroy) {
267 curr->destroy(EXT_DATA_AREA(curr));
269 TALLOC_FREE(curr);
270 return;
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) {
282 next = curr->next;
283 fsp->vfs_extension = next;
285 if (curr->destroy) {
286 curr->destroy(EXT_DATA_AREA(curr));
288 TALLOC_FREE(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) {
298 return head;
302 return NULL;
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);
310 if (head != NULL) {
311 return EXT_DATA_AREA(head);
314 return NULL;
317 #undef EXT_DATA_AREA
320 * Ensure this module catches all VFS functions.
322 #ifdef DEVELOPER
323 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
324 const char *module)
326 bool missing_fn = false;
327 unsigned int idx;
328 const uintptr_t *end = (const uintptr_t *)(fns + 1);
330 for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
331 if (*((const uintptr_t *)fns + idx) == 0) {
332 DBG_ERR("VFS function at index %d not implemented "
333 "in module %s\n", idx, module);
334 missing_fn = true;
338 if (missing_fn) {
339 smb_panic("Required VFS function not implemented in module.\n");
342 #else
343 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
344 const char *module)
347 #endif
349 /*****************************************************************
350 Generic VFS init.
351 ******************************************************************/
353 bool smbd_vfs_init(connection_struct *conn)
355 const char **vfs_objects;
356 unsigned int i = 0;
357 int j = 0;
359 /* Normal share - initialise with disk access functions */
360 vfs_init_default(conn);
362 /* No need to load vfs modules for printer connections */
363 if (conn->printer) {
364 return True;
367 vfs_objects = lp_vfs_objects(SNUM(conn));
369 /* Override VFS functions if 'vfs object' was not specified*/
370 if (!vfs_objects || !vfs_objects[0])
371 return True;
373 for (i=0; vfs_objects[i] ;) {
374 i++;
377 for (j=i-1; j >= 0; j--) {
378 if (!vfs_init_custom(conn, vfs_objects[j])) {
379 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
380 return False;
383 return True;
386 /*******************************************************************
387 Check if a file exists in the vfs.
388 ********************************************************************/
390 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
392 /* Only return OK if stat was successful and S_ISREG */
393 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
394 S_ISREG(smb_fname->st.st_ex_mode)) {
395 return NT_STATUS_OK;
398 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
401 ssize_t vfs_pwrite_data(struct smb_request *req,
402 files_struct *fsp,
403 const char *buffer,
404 size_t N,
405 off_t offset)
407 size_t total=0;
408 ssize_t ret;
410 if (req && req->unread_bytes) {
411 int sockfd = req->xconn->transport.sock;
412 SMB_ASSERT(req->unread_bytes == N);
413 /* VFS_RECVFILE must drain the socket
414 * before returning. */
415 req->unread_bytes = 0;
417 * Leave the socket non-blocking and
418 * use SMB_VFS_RECVFILE. If it returns
419 * EAGAIN || EWOULDBLOCK temporarily set
420 * the socket blocking and retry
421 * the RECVFILE.
423 while (total < N) {
424 ret = SMB_VFS_RECVFILE(sockfd,
425 fsp,
426 offset + total,
427 N - total);
428 if (ret == 0 || (ret == -1 &&
429 (errno == EAGAIN ||
430 errno == EWOULDBLOCK))) {
431 int old_flags;
432 /* Ensure the socket is blocking. */
433 old_flags = fcntl(sockfd, F_GETFL, 0);
434 if (set_blocking(sockfd, true) == -1) {
435 return (ssize_t)-1;
437 ret = SMB_VFS_RECVFILE(sockfd,
438 fsp,
439 offset + total,
440 N - total);
441 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
442 return (ssize_t)-1;
444 if (ret == -1) {
445 return (ssize_t)-1;
447 total += ret;
448 return (ssize_t)total;
450 /* Any other error case. */
451 if (ret == -1) {
452 return ret;
454 total += ret;
456 return (ssize_t)total;
459 while (total < N) {
460 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
461 offset + total);
463 if (ret == -1)
464 return -1;
465 if (ret == 0)
466 return total;
468 total += ret;
470 return (ssize_t)total;
472 /****************************************************************************
473 An allocate file space call using the vfs interface.
474 Allocates space for a file from a filedescriptor.
475 Returns 0 on success, -1 on failure.
476 ****************************************************************************/
478 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
480 int ret;
481 connection_struct *conn = fsp->conn;
482 uint64_t space_avail;
483 uint64_t bsize,dfree,dsize;
484 NTSTATUS status;
487 * Actually try and commit the space on disk....
490 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
491 fsp_str_dbg(fsp), (double)len));
493 if (((off_t)len) < 0) {
494 DEBUG(0,("vfs_allocate_file_space: %s negative len "
495 "requested.\n", fsp_str_dbg(fsp)));
496 errno = EINVAL;
497 return -1;
500 status = vfs_stat_fsp(fsp);
501 if (!NT_STATUS_IS_OK(status)) {
502 return -1;
505 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
506 return 0;
508 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
509 /* Shrink - use ftruncate. */
511 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
512 "size %.0f\n", fsp_str_dbg(fsp),
513 (double)fsp->fsp_name->st.st_ex_size));
515 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
517 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
518 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
519 set_filelen_write_cache(fsp, len);
522 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
524 return ret;
527 /* Grow - we need to test if we have enough space. */
529 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
531 if (lp_strict_allocate(SNUM(fsp->conn))) {
532 /* See if we have a syscall that will allocate beyond
533 end-of-file without changing EOF. */
534 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
535 0, len);
536 } else {
537 ret = 0;
540 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
542 if (ret == 0) {
543 /* We changed the allocation size on disk, but not
544 EOF - exactly as required. We're done ! */
545 return 0;
548 if (ret == -1 && errno == ENOSPC) {
549 return -1;
552 len -= fsp->fsp_name->st.st_ex_size;
553 len /= 1024; /* Len is now number of 1k blocks needed. */
554 space_avail =
555 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
556 if (space_avail == (uint64_t)-1) {
557 return -1;
560 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
561 "needed blocks = %.0f, space avail = %.0f\n",
562 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
563 (double)space_avail));
565 if (len > space_avail) {
566 errno = ENOSPC;
567 return -1;
570 return 0;
573 /****************************************************************************
574 A vfs set_filelen call.
575 set the length of a file from a filedescriptor.
576 Returns 0 on success, -1 on failure.
577 ****************************************************************************/
579 int vfs_set_filelen(files_struct *fsp, off_t len)
581 int ret;
583 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
585 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
586 fsp_str_dbg(fsp), (double)len));
587 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
588 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
589 set_filelen_write_cache(fsp, len);
590 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
591 FILE_NOTIFY_CHANGE_SIZE
592 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
593 fsp->fsp_name->base_name);
596 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
598 return ret;
601 /****************************************************************************
602 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
603 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
604 as this is also called from the default SMB_VFS_FTRUNCATE code.
605 Always extends the file size.
606 Returns 0 on success, -1 on failure.
607 ****************************************************************************/
609 #define SPARSE_BUF_WRITE_SIZE (32*1024)
611 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
613 ssize_t pwrite_ret;
614 size_t total = 0;
616 if (!sparse_buf) {
617 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
618 if (!sparse_buf) {
619 errno = ENOMEM;
620 return -1;
624 while (total < len) {
625 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
627 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
628 if (pwrite_ret == -1) {
629 int saved_errno = errno;
630 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
631 "%s failed with error %s\n",
632 fsp_str_dbg(fsp), strerror(saved_errno)));
633 errno = saved_errno;
634 return -1;
636 total += pwrite_ret;
639 return 0;
642 /****************************************************************************
643 A vfs fill sparse call.
644 Writes zeros from the end of file to len, if len is greater than EOF.
645 Used only by strict_sync.
646 Returns 0 on success, -1 on failure.
647 ****************************************************************************/
649 int vfs_fill_sparse(files_struct *fsp, off_t len)
651 int ret;
652 NTSTATUS status;
653 off_t offset;
654 size_t num_to_write;
656 status = vfs_stat_fsp(fsp);
657 if (!NT_STATUS_IS_OK(status)) {
658 return -1;
661 if (len <= fsp->fsp_name->st.st_ex_size) {
662 return 0;
665 #ifdef S_ISFIFO
666 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
667 return 0;
669 #endif
671 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
672 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
673 (double)fsp->fsp_name->st.st_ex_size, (double)len,
674 (double)(len - fsp->fsp_name->st.st_ex_size)));
676 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
678 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
680 offset = fsp->fsp_name->st.st_ex_size;
681 num_to_write = len - fsp->fsp_name->st.st_ex_size;
683 /* Only do this on non-stream file handles. */
684 if (fsp->base_fsp == NULL) {
685 /* for allocation try fallocate first. This can fail on some
686 * platforms e.g. when the filesystem doesn't support it and no
687 * emulation is being done by the libc (like on AIX with JFS1). In that
688 * case we do our own emulation. fallocate implementations can
689 * return ENOTSUP or EINVAL in cases like that. */
690 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
691 if (ret == -1 && errno == ENOSPC) {
692 goto out;
694 if (ret == 0) {
695 goto out;
697 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
698 "error %d. Falling back to slow manual allocation\n", ret));
701 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
703 out:
705 if (ret == 0) {
706 set_filelen_write_cache(fsp, len);
709 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
710 return ret;
713 /****************************************************************************
714 Transfer some data (n bytes) between two file_struct's.
715 ****************************************************************************/
717 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
719 struct files_struct *fsp = (struct files_struct *)file;
721 return SMB_VFS_PREAD(fsp, buf, len, offset);
724 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
726 struct files_struct *fsp = (struct files_struct *)file;
728 return SMB_VFS_PWRITE(fsp, buf, len, offset);
731 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
733 return transfer_file_internal((void *)in, (void *)out, n,
734 vfs_pread_fn, vfs_pwrite_fn);
737 /*******************************************************************
738 A vfs_readdir wrapper which just returns the file name.
739 ********************************************************************/
741 const char *vfs_readdirname(connection_struct *conn, void *p,
742 SMB_STRUCT_STAT *sbuf, char **talloced)
744 struct dirent *ptr= NULL;
745 const char *dname;
746 char *translated;
747 NTSTATUS status;
749 if (!p)
750 return(NULL);
752 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
753 if (!ptr)
754 return(NULL);
756 dname = ptr->d_name;
759 #ifdef NEXT2
760 if (telldir(p) < 0)
761 return(NULL);
762 #endif
764 #ifdef HAVE_BROKEN_READDIR_NAME
765 /* using /usr/ucb/cc is BAD */
766 dname = dname - 2;
767 #endif
769 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
770 talloc_tos(), &translated);
771 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
772 *talloced = NULL;
773 return dname;
775 *talloced = translated;
776 if (!NT_STATUS_IS_OK(status)) {
777 return NULL;
779 return translated;
782 /*******************************************************************
783 A wrapper for vfs_chdir().
784 ********************************************************************/
786 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
788 int ret;
789 int saved_errno = 0;
790 struct smb_filename *saved_cwd = NULL;
792 if (!LastDir) {
793 LastDir = SMB_STRDUP("");
796 if (ISDOT(smb_fname->base_name)) {
797 return 0;
800 if (*smb_fname->base_name == '/' &&
801 strcsequal(LastDir,smb_fname->base_name)) {
802 return 0;
805 if (conn->cwd_fname != NULL) {
807 * Save off where we are in case we need to return
808 * on vfs_GetWd() failure after successful SMB_VFS_CHDIR().
810 saved_cwd = cp_smb_filename(conn, conn->cwd_fname);
811 if (saved_cwd == NULL) {
812 return -1;
816 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
818 ret = SMB_VFS_CHDIR(conn, smb_fname);
819 if (ret != 0) {
820 saved_errno = errno;
821 TALLOC_FREE(saved_cwd);
822 errno = saved_errno;
823 return -1;
827 * Always replace conn->cwd_fname. We
828 * don't know if it's been modified by
829 * VFS modules in the stack.
832 /* conn cache. */
833 TALLOC_FREE(conn->cwd_fname);
834 conn->cwd_fname = vfs_GetWd(conn, conn);
835 if (conn->cwd_fname == NULL) {
837 * vfs_GetWd() failed.
838 * We must be able to read cwd.
839 * Return to original directory
840 * and return -1.
842 saved_errno = errno;
844 if (saved_cwd == NULL) {
846 * Failed on the very first chdir()+getwd()
847 * for this connection. We can't
848 * continue.
850 smb_panic("conn->cwd getwd failed\n");
851 /* NOTREACHED */
852 return -1;
855 /* Return to the previous $cwd. */
856 ret = SMB_VFS_CHDIR(conn, saved_cwd);
857 if (ret != 0) {
858 smb_panic("conn->cwd getwd failed\n");
859 /* NOTREACHED */
860 return -1;
862 /* Restore original conn->cwd_fname. */
863 conn->cwd_fname = saved_cwd;
864 errno = saved_errno;
865 /* And fail the chdir(). */
866 return -1;
869 /* vfs_GetWd() succeeded. */
870 /* Replace global cache. */
871 SAFE_FREE(LastDir);
872 LastDir = SMB_STRDUP(smb_fname->base_name);
874 DEBUG(4,("vfs_ChDir got %s\n", conn->cwd_fname->base_name));
876 TALLOC_FREE(saved_cwd);
877 if (saved_errno != 0) {
878 errno = saved_errno;
880 return ret;
883 /*******************************************************************
884 Return the absolute current directory path - given a UNIX pathname.
885 Note that this path is returned in DOS format, not UNIX
886 format. Note this can be called with conn == NULL.
887 ********************************************************************/
889 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
891 struct smb_filename *current_dir_fname = NULL;
892 struct file_id key;
893 struct smb_filename *smb_fname_dot = NULL;
894 struct smb_filename *smb_fname_full = NULL;
895 struct smb_filename *result = NULL;
897 if (!lp_getwd_cache()) {
898 goto nocache;
901 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
902 if (smb_fname_dot == NULL) {
903 errno = ENOMEM;
904 goto out;
907 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
909 * Known to fail for root: the directory may be NFS-mounted
910 * and exported with root_squash (so has no root access).
912 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
913 "(NFS problem ?)\n", strerror(errno) ));
914 goto nocache;
917 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
919 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
920 smbd_memcache(),
921 GETWD_CACHE,
922 data_blob_const(&key, sizeof(key)));
924 if (smb_fname_full == NULL) {
925 goto nocache;
928 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
929 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
930 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
931 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
933 * Ok, we're done
934 * Note: smb_fname_full is owned by smbd_memcache()
935 * so we must make a copy to return.
937 result = cp_smb_filename(ctx, smb_fname_full);
938 if (result == NULL) {
939 errno = ENOMEM;
941 goto out;
944 nocache:
947 * We don't have the information to hand so rely on traditional
948 * methods. The very slow getcwd, which spawns a process on some
949 * systems, or the not quite so bad getwd.
952 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
953 if (current_dir_fname == NULL) {
954 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
955 strerror(errno)));
956 goto out;
959 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
960 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
963 * smbd_memcache() will own current_dir_fname after the
964 * memcache_add_talloc call, so we must make
965 * a copy on ctx to return.
967 result = cp_smb_filename(ctx, current_dir_fname);
968 if (result == NULL) {
969 errno = ENOMEM;
973 * Ensure the memory going into the cache
974 * doesn't have a destructor so it can be
975 * cleanly freed.
977 talloc_set_destructor(current_dir_fname, NULL);
979 memcache_add_talloc(smbd_memcache(),
980 GETWD_CACHE,
981 data_blob_const(&key, sizeof(key)),
982 &current_dir_fname);
983 /* current_dir_fname is now == NULL here. */
984 } else {
985 /* current_dir_fname is already allocated on ctx. */
986 result = current_dir_fname;
989 out:
990 TALLOC_FREE(smb_fname_dot);
992 * Don't free current_dir_fname here. It's either been moved
993 * to the memcache or is being returned in result.
995 return result;
998 /*******************************************************************
999 Reduce a file name, removing .. elements and checking that
1000 it is below dir in the heirachy. This uses realpath.
1001 This function must run as root, and will return names
1002 and valid stat structs that can be checked on open.
1003 ********************************************************************/
1005 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1006 const struct smb_filename *smb_fname,
1007 struct smb_request *smbreq)
1009 NTSTATUS status;
1010 TALLOC_CTX *ctx = talloc_tos();
1011 const char *conn_rootdir;
1012 size_t rootdir_len;
1013 char *dir_name = NULL;
1014 char *resolved_name = NULL;
1015 const char *last_component = NULL;
1016 struct smb_filename *resolved_fname = NULL;
1017 struct smb_filename *saved_dir_fname = NULL;
1018 struct smb_filename *smb_fname_cwd = NULL;
1019 struct privilege_paths *priv_paths = NULL;
1020 int ret;
1022 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1023 smb_fname->base_name,
1024 conn->connectpath));
1027 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1028 if (!priv_paths) {
1029 status = NT_STATUS_NO_MEMORY;
1030 goto err;
1033 if (!parent_dirname(ctx, smb_fname->base_name,
1034 &dir_name, &last_component)) {
1035 status = NT_STATUS_NO_MEMORY;
1036 goto err;
1039 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1040 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1042 if (priv_paths->parent_name.base_name == NULL ||
1043 priv_paths->file_name.base_name == NULL) {
1044 status = NT_STATUS_NO_MEMORY;
1045 goto err;
1048 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1049 status = map_nt_error_from_unix(errno);
1050 goto err;
1052 /* Remember where we were. */
1053 saved_dir_fname = vfs_GetWd(ctx, conn);
1054 if (!saved_dir_fname) {
1055 status = map_nt_error_from_unix(errno);
1056 goto err;
1059 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1060 status = map_nt_error_from_unix(errno);
1061 goto err;
1064 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1065 if (smb_fname_cwd == NULL) {
1066 status = NT_STATUS_NO_MEMORY;
1067 goto err;
1070 /* Get the absolute path of the parent directory. */
1071 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1072 if (resolved_fname == NULL) {
1073 status = map_nt_error_from_unix(errno);
1074 goto err;
1076 resolved_name = resolved_fname->base_name;
1078 if (*resolved_name != '/') {
1079 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1080 "doesn't return absolute paths !\n"));
1081 status = NT_STATUS_OBJECT_NAME_INVALID;
1082 goto err;
1085 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1086 priv_paths->parent_name.base_name,
1087 resolved_name));
1089 /* Now check the stat value is the same. */
1090 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1091 status = map_nt_error_from_unix(errno);
1092 goto err;
1095 /* Ensure we're pointing at the same place. */
1096 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1097 DEBUG(0,("check_reduced_name_with_privilege: "
1098 "device/inode/uid/gid on directory %s changed. "
1099 "Denying access !\n",
1100 priv_paths->parent_name.base_name));
1101 status = NT_STATUS_ACCESS_DENIED;
1102 goto err;
1105 /* Ensure we're below the connect path. */
1107 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1108 if (conn_rootdir == NULL) {
1109 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1110 "conn_rootdir\n"));
1111 status = NT_STATUS_ACCESS_DENIED;
1112 goto err;
1115 rootdir_len = strlen(conn_rootdir);
1118 * In the case of rootdir_len == 1, we know that conn_rootdir is
1119 * "/", and we also know that resolved_name starts with a slash.
1120 * So, in this corner case, resolved_name is automatically a
1121 * sub-directory of the conn_rootdir. Thus we can skip the string
1122 * comparison and the next character checks (which are even
1123 * wrong in this case).
1125 if (rootdir_len != 1) {
1126 bool matched;
1128 matched = (strncmp(conn_rootdir, resolved_name,
1129 rootdir_len) == 0);
1131 if (!matched || (resolved_name[rootdir_len] != '/' &&
1132 resolved_name[rootdir_len] != '\0')) {
1133 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1134 "access attempt: %s is a symlink outside the "
1135 "share path\n",
1136 dir_name));
1137 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1138 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1139 status = NT_STATUS_ACCESS_DENIED;
1140 goto err;
1144 /* Now ensure that the last component either doesn't
1145 exist, or is *NOT* a symlink. */
1147 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1148 if (ret == -1) {
1149 /* Errno must be ENOENT for this be ok. */
1150 if (errno != ENOENT) {
1151 status = map_nt_error_from_unix(errno);
1152 DEBUG(2, ("check_reduced_name_with_privilege: "
1153 "LSTAT on %s failed with %s\n",
1154 priv_paths->file_name.base_name,
1155 nt_errstr(status)));
1156 goto err;
1160 if (VALID_STAT(priv_paths->file_name.st) &&
1161 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1162 DEBUG(2, ("check_reduced_name_with_privilege: "
1163 "Last component %s is a symlink. Denying"
1164 "access.\n",
1165 priv_paths->file_name.base_name));
1166 status = NT_STATUS_ACCESS_DENIED;
1167 goto err;
1170 smbreq->priv_paths = priv_paths;
1171 status = NT_STATUS_OK;
1173 err:
1175 if (saved_dir_fname != NULL) {
1176 vfs_ChDir(conn, saved_dir_fname);
1177 TALLOC_FREE(saved_dir_fname);
1179 TALLOC_FREE(resolved_fname);
1180 if (!NT_STATUS_IS_OK(status)) {
1181 TALLOC_FREE(priv_paths);
1183 TALLOC_FREE(dir_name);
1184 return status;
1187 /*******************************************************************
1188 Reduce a file name, removing .. elements and checking that
1189 it is below dir in the heirachy. This uses realpath.
1191 If cwd_name == NULL then fname is a client given path relative
1192 to the root path of the share.
1194 If cwd_name != NULL then fname is a client given path relative
1195 to cwd_name. cwd_name is relative to the root path of the share.
1196 ********************************************************************/
1198 NTSTATUS check_reduced_name(connection_struct *conn,
1199 const struct smb_filename *cwd_fname,
1200 const struct smb_filename *smb_fname)
1202 TALLOC_CTX *ctx = talloc_tos();
1203 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1204 const char *fname = smb_fname->base_name;
1205 struct smb_filename *resolved_fname;
1206 char *resolved_name = NULL;
1207 char *new_fname = NULL;
1208 bool allow_symlinks = true;
1209 bool allow_widelinks = false;
1211 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1213 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1215 if (resolved_fname == NULL) {
1216 switch (errno) {
1217 case ENOTDIR:
1218 DEBUG(3,("check_reduced_name: Component not a "
1219 "directory in getting realpath for "
1220 "%s\n", fname));
1221 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1222 case ENOENT:
1224 char *dir_name = NULL;
1225 struct smb_filename dir_fname = {0};
1226 const char *last_component = NULL;
1228 /* Last component didn't exist.
1229 Remove it and try and canonicalise
1230 the directory name. */
1231 if (!parent_dirname(ctx, fname,
1232 &dir_name,
1233 &last_component)) {
1234 return NT_STATUS_NO_MEMORY;
1237 dir_fname = (struct smb_filename)
1238 { .base_name = dir_name };
1239 resolved_fname = SMB_VFS_REALPATH(conn,
1240 ctx,
1241 &dir_fname);
1242 if (resolved_fname == NULL) {
1243 NTSTATUS status = map_nt_error_from_unix(errno);
1245 if (errno == ENOENT || errno == ENOTDIR) {
1246 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1249 DEBUG(3,("check_reduce_name: "
1250 "couldn't get realpath for "
1251 "%s (%s)\n",
1252 fname,
1253 nt_errstr(status)));
1254 return status;
1256 resolved_name = talloc_asprintf(ctx,
1257 "%s/%s",
1258 resolved_fname->base_name,
1259 last_component);
1260 if (resolved_name == NULL) {
1261 return NT_STATUS_NO_MEMORY;
1263 break;
1265 default:
1266 DEBUG(3,("check_reduced_name: couldn't get "
1267 "realpath for %s\n", fname));
1268 return map_nt_error_from_unix(errno);
1270 } else {
1271 resolved_name = resolved_fname->base_name;
1274 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1275 resolved_name));
1277 if (*resolved_name != '/') {
1278 DEBUG(0,("check_reduced_name: realpath doesn't return "
1279 "absolute paths !\n"));
1280 TALLOC_FREE(resolved_fname);
1281 return NT_STATUS_OBJECT_NAME_INVALID;
1284 allow_widelinks = lp_widelinks(SNUM(conn));
1285 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1287 /* Common widelinks and symlinks checks. */
1288 if (!allow_widelinks || !allow_symlinks) {
1289 const char *conn_rootdir;
1290 size_t rootdir_len;
1292 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1293 if (conn_rootdir == NULL) {
1294 DEBUG(2, ("check_reduced_name: Could not get "
1295 "conn_rootdir\n"));
1296 TALLOC_FREE(resolved_fname);
1297 return NT_STATUS_ACCESS_DENIED;
1300 rootdir_len = strlen(conn_rootdir);
1303 * In the case of rootdir_len == 1, we know that
1304 * conn_rootdir is "/", and we also know that
1305 * resolved_name starts with a slash. So, in this
1306 * corner case, resolved_name is automatically a
1307 * sub-directory of the conn_rootdir. Thus we can skip
1308 * the string comparison and the next character checks
1309 * (which are even wrong in this case).
1311 if (rootdir_len != 1) {
1312 bool matched;
1314 matched = (strncmp(conn_rootdir, resolved_name,
1315 rootdir_len) == 0);
1316 if (!matched || (resolved_name[rootdir_len] != '/' &&
1317 resolved_name[rootdir_len] != '\0')) {
1318 DEBUG(2, ("check_reduced_name: Bad access "
1319 "attempt: %s is a symlink outside the "
1320 "share path\n", fname));
1321 DEBUGADD(2, ("conn_rootdir =%s\n",
1322 conn_rootdir));
1323 DEBUGADD(2, ("resolved_name=%s\n",
1324 resolved_name));
1325 TALLOC_FREE(resolved_fname);
1326 return NT_STATUS_ACCESS_DENIED;
1330 /* Extra checks if all symlinks are disallowed. */
1331 if (!allow_symlinks) {
1332 /* fname can't have changed in resolved_path. */
1333 const char *p = &resolved_name[rootdir_len];
1336 * UNIX filesystem semantics, names consisting
1337 * only of "." or ".." CANNOT be symlinks.
1339 if (ISDOT(fname) || ISDOTDOT(fname)) {
1340 goto out;
1343 if (*p != '/') {
1344 DEBUG(2, ("check_reduced_name: logic error (%c) "
1345 "in resolved_name: %s\n",
1347 fname));
1348 TALLOC_FREE(resolved_fname);
1349 return NT_STATUS_ACCESS_DENIED;
1352 p++;
1355 * If cwd_name is present and not ".",
1356 * then fname is relative to that, not
1357 * the root of the share. Make sure the
1358 * path we check is the one the client
1359 * sent (cwd_name+fname).
1361 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1362 new_fname = talloc_asprintf(ctx,
1363 "%s/%s",
1364 cwd_name,
1365 fname);
1366 if (new_fname == NULL) {
1367 TALLOC_FREE(resolved_fname);
1368 return NT_STATUS_NO_MEMORY;
1370 fname = new_fname;
1373 if (strcmp(fname, p)!=0) {
1374 DEBUG(2, ("check_reduced_name: Bad access "
1375 "attempt: %s is a symlink to %s\n",
1376 fname, p));
1377 TALLOC_FREE(resolved_fname);
1378 TALLOC_FREE(new_fname);
1379 return NT_STATUS_ACCESS_DENIED;
1384 out:
1386 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1387 TALLOC_FREE(resolved_fname);
1388 TALLOC_FREE(new_fname);
1389 return NT_STATUS_OK;
1393 * XXX: This is temporary and there should be no callers of this once
1394 * smb_filename is plumbed through all path based operations.
1396 * Called when we know stream name parsing has already been done.
1398 int vfs_stat_smb_basename(struct connection_struct *conn,
1399 const struct smb_filename *smb_fname_in,
1400 SMB_STRUCT_STAT *psbuf)
1402 struct smb_filename smb_fname = {
1403 .base_name = discard_const_p(char, smb_fname_in->base_name),
1404 .flags = smb_fname_in->flags
1406 int ret;
1408 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1409 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1410 } else {
1411 ret = SMB_VFS_STAT(conn, &smb_fname);
1414 if (ret != -1) {
1415 *psbuf = smb_fname.st;
1417 return ret;
1421 * Ensure LSTAT is called for POSIX paths.
1424 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1426 int ret;
1428 if(fsp->fh->fd == -1) {
1429 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1430 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1431 } else {
1432 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1434 if (ret == -1) {
1435 return map_nt_error_from_unix(errno);
1437 } else {
1438 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1439 return map_nt_error_from_unix(errno);
1442 return NT_STATUS_OK;
1446 * Initialize num_streams and streams, then call VFS op streaminfo
1448 NTSTATUS vfs_streaminfo(connection_struct *conn,
1449 struct files_struct *fsp,
1450 const struct smb_filename *smb_fname,
1451 TALLOC_CTX *mem_ctx,
1452 unsigned int *num_streams,
1453 struct stream_struct **streams)
1455 *num_streams = 0;
1456 *streams = NULL;
1457 return SMB_VFS_STREAMINFO(conn,
1458 fsp,
1459 smb_fname,
1460 mem_ctx,
1461 num_streams,
1462 streams);
1466 generate a file_id from a stat structure
1468 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1470 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1473 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1474 const char *service, const char *user)
1476 VFS_FIND(connect);
1477 return handle->fns->connect_fn(handle, service, user);
1480 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1482 VFS_FIND(disconnect);
1483 handle->fns->disconnect_fn(handle);
1486 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1487 const struct smb_filename *smb_fname,
1488 uint64_t *bsize,
1489 uint64_t *dfree,
1490 uint64_t *dsize)
1492 VFS_FIND(disk_free);
1493 return handle->fns->disk_free_fn(handle, smb_fname,
1494 bsize, dfree, dsize);
1497 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1498 const struct smb_filename *smb_fname,
1499 enum SMB_QUOTA_TYPE qtype,
1500 unid_t id,
1501 SMB_DISK_QUOTA *qt)
1503 VFS_FIND(get_quota);
1504 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1507 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1508 enum SMB_QUOTA_TYPE qtype, unid_t id,
1509 SMB_DISK_QUOTA *qt)
1511 VFS_FIND(set_quota);
1512 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1515 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1516 struct files_struct *fsp,
1517 struct shadow_copy_data *shadow_copy_data,
1518 bool labels)
1520 VFS_FIND(get_shadow_copy_data);
1521 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1522 shadow_copy_data,
1523 labels);
1525 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1526 const struct smb_filename *smb_fname,
1527 struct vfs_statvfs_struct *statbuf)
1529 VFS_FIND(statvfs);
1530 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1533 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1534 enum timestamp_set_resolution *p_ts_res)
1536 VFS_FIND(fs_capabilities);
1537 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1540 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1541 struct dfs_GetDFSReferral *r)
1543 VFS_FIND(get_dfs_referrals);
1544 return handle->fns->get_dfs_referrals_fn(handle, r);
1547 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1548 const struct smb_filename *smb_fname,
1549 const char *mask,
1550 uint32_t attributes)
1552 VFS_FIND(opendir);
1553 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1556 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1557 struct files_struct *fsp,
1558 const char *mask,
1559 uint32_t attributes)
1561 VFS_FIND(fdopendir);
1562 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1565 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1566 DIR *dirp,
1567 SMB_STRUCT_STAT *sbuf)
1569 VFS_FIND(readdir);
1570 return handle->fns->readdir_fn(handle, dirp, sbuf);
1573 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1574 DIR *dirp, long offset)
1576 VFS_FIND(seekdir);
1577 handle->fns->seekdir_fn(handle, dirp, offset);
1580 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1581 DIR *dirp)
1583 VFS_FIND(telldir);
1584 return handle->fns->telldir_fn(handle, dirp);
1587 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1588 DIR *dirp)
1590 VFS_FIND(rewind_dir);
1591 handle->fns->rewind_dir_fn(handle, dirp);
1594 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1595 const struct smb_filename *smb_fname,
1596 mode_t mode)
1598 VFS_FIND(mkdir);
1599 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1602 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1603 const struct smb_filename *smb_fname)
1605 VFS_FIND(rmdir);
1606 return handle->fns->rmdir_fn(handle, smb_fname);
1609 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1610 DIR *dir)
1612 VFS_FIND(closedir);
1613 return handle->fns->closedir_fn(handle, dir);
1616 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1617 struct smb_filename *smb_fname, struct files_struct *fsp,
1618 int flags, mode_t mode)
1620 VFS_FIND(open);
1621 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1624 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1625 struct smb_request *req,
1626 uint16_t root_dir_fid,
1627 struct smb_filename *smb_fname,
1628 uint32_t access_mask,
1629 uint32_t share_access,
1630 uint32_t create_disposition,
1631 uint32_t create_options,
1632 uint32_t file_attributes,
1633 uint32_t oplock_request,
1634 struct smb2_lease *lease,
1635 uint64_t allocation_size,
1636 uint32_t private_flags,
1637 struct security_descriptor *sd,
1638 struct ea_list *ea_list,
1639 files_struct **result,
1640 int *pinfo,
1641 const struct smb2_create_blobs *in_context_blobs,
1642 struct smb2_create_blobs *out_context_blobs)
1644 VFS_FIND(create_file);
1645 return handle->fns->create_file_fn(
1646 handle, req, root_dir_fid, smb_fname, access_mask,
1647 share_access, create_disposition, create_options,
1648 file_attributes, oplock_request, lease, allocation_size,
1649 private_flags, sd, ea_list,
1650 result, pinfo, in_context_blobs, out_context_blobs);
1653 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1654 struct files_struct *fsp)
1656 VFS_FIND(close);
1657 return handle->fns->close_fn(handle, fsp);
1660 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1661 struct files_struct *fsp, void *data, size_t n,
1662 off_t offset)
1664 VFS_FIND(pread);
1665 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1668 struct smb_vfs_call_pread_state {
1669 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1670 ssize_t retval;
1671 struct vfs_aio_state vfs_aio_state;
1674 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1676 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1677 TALLOC_CTX *mem_ctx,
1678 struct tevent_context *ev,
1679 struct files_struct *fsp,
1680 void *data,
1681 size_t n, off_t offset)
1683 struct tevent_req *req, *subreq;
1684 struct smb_vfs_call_pread_state *state;
1686 req = tevent_req_create(mem_ctx, &state,
1687 struct smb_vfs_call_pread_state);
1688 if (req == NULL) {
1689 return NULL;
1691 VFS_FIND(pread_send);
1692 state->recv_fn = handle->fns->pread_recv_fn;
1694 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1695 offset);
1696 if (tevent_req_nomem(subreq, req)) {
1697 return tevent_req_post(req, ev);
1699 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1700 return req;
1703 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1705 struct tevent_req *req = tevent_req_callback_data(
1706 subreq, struct tevent_req);
1707 struct smb_vfs_call_pread_state *state = tevent_req_data(
1708 req, struct smb_vfs_call_pread_state);
1710 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1711 TALLOC_FREE(subreq);
1712 if (state->retval == -1) {
1713 tevent_req_error(req, state->vfs_aio_state.error);
1714 return;
1716 tevent_req_done(req);
1719 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1720 struct vfs_aio_state *vfs_aio_state)
1722 struct smb_vfs_call_pread_state *state = tevent_req_data(
1723 req, struct smb_vfs_call_pread_state);
1725 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1726 return -1;
1728 *vfs_aio_state = state->vfs_aio_state;
1729 return state->retval;
1732 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1733 struct files_struct *fsp, const void *data,
1734 size_t n, off_t offset)
1736 VFS_FIND(pwrite);
1737 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1740 struct smb_vfs_call_pwrite_state {
1741 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1742 ssize_t retval;
1743 struct vfs_aio_state vfs_aio_state;
1746 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1748 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1749 TALLOC_CTX *mem_ctx,
1750 struct tevent_context *ev,
1751 struct files_struct *fsp,
1752 const void *data,
1753 size_t n, off_t offset)
1755 struct tevent_req *req, *subreq;
1756 struct smb_vfs_call_pwrite_state *state;
1758 req = tevent_req_create(mem_ctx, &state,
1759 struct smb_vfs_call_pwrite_state);
1760 if (req == NULL) {
1761 return NULL;
1763 VFS_FIND(pwrite_send);
1764 state->recv_fn = handle->fns->pwrite_recv_fn;
1766 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1767 offset);
1768 if (tevent_req_nomem(subreq, req)) {
1769 return tevent_req_post(req, ev);
1771 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1772 return req;
1775 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1777 struct tevent_req *req = tevent_req_callback_data(
1778 subreq, struct tevent_req);
1779 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1780 req, struct smb_vfs_call_pwrite_state);
1782 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1783 TALLOC_FREE(subreq);
1784 if (state->retval == -1) {
1785 tevent_req_error(req, state->vfs_aio_state.error);
1786 return;
1788 tevent_req_done(req);
1791 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1792 struct vfs_aio_state *vfs_aio_state)
1794 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1795 req, struct smb_vfs_call_pwrite_state);
1797 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1798 return -1;
1800 *vfs_aio_state = state->vfs_aio_state;
1801 return state->retval;
1804 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1805 struct files_struct *fsp, off_t offset,
1806 int whence)
1808 VFS_FIND(lseek);
1809 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1812 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1813 files_struct *fromfsp, const DATA_BLOB *header,
1814 off_t offset, size_t count)
1816 VFS_FIND(sendfile);
1817 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1818 count);
1821 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1822 files_struct *tofsp, off_t offset,
1823 size_t count)
1825 VFS_FIND(recvfile);
1826 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1829 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1830 const struct smb_filename *smb_fname_src,
1831 const struct smb_filename *smb_fname_dst)
1833 VFS_FIND(rename);
1834 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1837 struct smb_vfs_call_fsync_state {
1838 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1839 int retval;
1840 struct vfs_aio_state vfs_aio_state;
1843 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1845 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1846 TALLOC_CTX *mem_ctx,
1847 struct tevent_context *ev,
1848 struct files_struct *fsp)
1850 struct tevent_req *req, *subreq;
1851 struct smb_vfs_call_fsync_state *state;
1853 req = tevent_req_create(mem_ctx, &state,
1854 struct smb_vfs_call_fsync_state);
1855 if (req == NULL) {
1856 return NULL;
1858 VFS_FIND(fsync_send);
1859 state->recv_fn = handle->fns->fsync_recv_fn;
1861 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1862 if (tevent_req_nomem(subreq, req)) {
1863 return tevent_req_post(req, ev);
1865 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1866 return req;
1869 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1871 struct tevent_req *req = tevent_req_callback_data(
1872 subreq, struct tevent_req);
1873 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1874 req, struct smb_vfs_call_fsync_state);
1876 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1877 TALLOC_FREE(subreq);
1878 if (state->retval == -1) {
1879 tevent_req_error(req, state->vfs_aio_state.error);
1880 return;
1882 tevent_req_done(req);
1885 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1887 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1888 req, struct smb_vfs_call_fsync_state);
1890 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1891 return -1;
1893 *vfs_aio_state = state->vfs_aio_state;
1894 return state->retval;
1898 * Synchronous version of fsync, built from backend
1899 * async VFS primitives. Uses a temporary sub-event
1900 * context (NOT NESTED).
1903 int smb_vfs_fsync_sync(files_struct *fsp)
1905 TALLOC_CTX *frame = talloc_stackframe();
1906 struct tevent_req *req = NULL;
1907 struct vfs_aio_state aio_state = { 0 };
1908 int ret = -1;
1909 bool ok;
1910 struct tevent_context *ev = samba_tevent_context_init(frame);
1912 if (ev == NULL) {
1913 goto out;
1916 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
1917 if (req == NULL) {
1918 goto out;
1921 ok = tevent_req_poll(req, ev);
1922 if (!ok) {
1923 goto out;
1926 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
1928 out:
1930 TALLOC_FREE(frame);
1931 if (aio_state.error != 0) {
1932 errno = aio_state.error;
1934 return ret;
1937 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1938 struct smb_filename *smb_fname)
1940 VFS_FIND(stat);
1941 return handle->fns->stat_fn(handle, smb_fname);
1944 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1945 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1947 VFS_FIND(fstat);
1948 return handle->fns->fstat_fn(handle, fsp, sbuf);
1951 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1952 struct smb_filename *smb_filename)
1954 VFS_FIND(lstat);
1955 return handle->fns->lstat_fn(handle, smb_filename);
1958 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1959 struct files_struct *fsp,
1960 const SMB_STRUCT_STAT *sbuf)
1962 VFS_FIND(get_alloc_size);
1963 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1966 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1967 const struct smb_filename *smb_fname)
1969 VFS_FIND(unlink);
1970 return handle->fns->unlink_fn(handle, smb_fname);
1973 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1974 const struct smb_filename *smb_fname,
1975 mode_t mode)
1977 VFS_FIND(chmod);
1978 return handle->fns->chmod_fn(handle, smb_fname, mode);
1981 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1982 struct files_struct *fsp, mode_t mode)
1984 VFS_FIND(fchmod);
1985 return handle->fns->fchmod_fn(handle, fsp, mode);
1988 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1989 const struct smb_filename *smb_fname,
1990 uid_t uid,
1991 gid_t gid)
1993 VFS_FIND(chown);
1994 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1997 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1998 struct files_struct *fsp, uid_t uid, gid_t gid)
2000 VFS_FIND(fchown);
2001 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2004 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2005 const struct smb_filename *smb_fname,
2006 uid_t uid,
2007 gid_t gid)
2009 VFS_FIND(lchown);
2010 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2013 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2015 int ret;
2016 bool as_root = false;
2017 NTSTATUS status;
2019 if (fsp->fh->fd != -1) {
2020 /* Try fchown. */
2021 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2022 if (ret == 0) {
2023 return NT_STATUS_OK;
2025 if (ret == -1 && errno != ENOSYS) {
2026 return map_nt_error_from_unix(errno);
2030 as_root = (geteuid() == 0);
2032 if (as_root) {
2034 * We are being asked to chown as root. Make
2035 * sure we chdir() into the path to pin it,
2036 * and always act using lchown to ensure we
2037 * don't deref any symbolic links.
2039 char *parent_dir = NULL;
2040 const char *final_component = NULL;
2041 struct smb_filename *local_smb_fname = NULL;
2042 struct smb_filename parent_dir_fname = {0};
2043 struct smb_filename *saved_dir_fname = NULL;
2045 saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
2046 if (!saved_dir_fname) {
2047 status = map_nt_error_from_unix(errno);
2048 DEBUG(0,("vfs_chown_fsp: failed to get "
2049 "current working directory. Error was %s\n",
2050 strerror(errno)));
2051 return status;
2054 if (!parent_dirname(talloc_tos(),
2055 fsp->fsp_name->base_name,
2056 &parent_dir,
2057 &final_component)) {
2058 return NT_STATUS_NO_MEMORY;
2061 parent_dir_fname = (struct smb_filename) {
2062 .base_name = parent_dir,
2063 .flags = fsp->fsp_name->flags
2066 /* cd into the parent dir to pin it. */
2067 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2068 if (ret == -1) {
2069 return map_nt_error_from_unix(errno);
2072 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2073 final_component,
2074 NULL,
2075 NULL,
2076 fsp->fsp_name->flags);
2077 if (local_smb_fname == NULL) {
2078 status = NT_STATUS_NO_MEMORY;
2079 goto out;
2082 /* Must use lstat here. */
2083 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2084 if (ret == -1) {
2085 status = map_nt_error_from_unix(errno);
2086 goto out;
2089 /* Ensure it matches the fsp stat. */
2090 if (!check_same_stat(&local_smb_fname->st,
2091 &fsp->fsp_name->st)) {
2092 status = NT_STATUS_ACCESS_DENIED;
2093 goto out;
2096 ret = SMB_VFS_LCHOWN(fsp->conn,
2097 local_smb_fname,
2098 uid, gid);
2100 if (ret == 0) {
2101 status = NT_STATUS_OK;
2102 } else {
2103 status = map_nt_error_from_unix(errno);
2106 out:
2108 vfs_ChDir(fsp->conn, saved_dir_fname);
2109 TALLOC_FREE(local_smb_fname);
2110 TALLOC_FREE(saved_dir_fname);
2111 TALLOC_FREE(parent_dir);
2113 return status;
2116 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2117 ret = SMB_VFS_LCHOWN(fsp->conn,
2118 fsp->fsp_name,
2119 uid, gid);
2120 } else {
2121 ret = SMB_VFS_CHOWN(fsp->conn,
2122 fsp->fsp_name,
2123 uid, gid);
2126 if (ret == 0) {
2127 status = NT_STATUS_OK;
2128 } else {
2129 status = map_nt_error_from_unix(errno);
2131 return status;
2134 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2135 const struct smb_filename *smb_fname)
2137 VFS_FIND(chdir);
2138 return handle->fns->chdir_fn(handle, smb_fname);
2141 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2142 TALLOC_CTX *ctx)
2144 VFS_FIND(getwd);
2145 return handle->fns->getwd_fn(handle, ctx);
2148 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2149 const struct smb_filename *smb_fname,
2150 struct smb_file_time *ft)
2152 VFS_FIND(ntimes);
2153 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2156 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2157 struct files_struct *fsp, off_t offset)
2159 VFS_FIND(ftruncate);
2160 return handle->fns->ftruncate_fn(handle, fsp, offset);
2163 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2164 struct files_struct *fsp,
2165 uint32_t mode,
2166 off_t offset,
2167 off_t len)
2169 VFS_FIND(fallocate);
2170 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2173 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2174 struct files_struct *fsp, uint32_t share_mode,
2175 uint32_t access_mask)
2177 VFS_FIND(kernel_flock);
2178 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2179 access_mask);
2182 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2183 struct files_struct *fsp, int leasetype)
2185 VFS_FIND(linux_setlease);
2186 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2189 int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
2190 const char *link_target,
2191 const struct smb_filename *new_smb_fname)
2193 VFS_FIND(symlink);
2194 return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
2197 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2198 const struct smb_filename *smb_fname,
2199 char *buf,
2200 size_t bufsiz)
2202 VFS_FIND(readlink);
2203 return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
2206 int smb_vfs_call_link(struct vfs_handle_struct *handle,
2207 const struct smb_filename *old_smb_fname,
2208 const struct smb_filename *new_smb_fname)
2210 VFS_FIND(link);
2211 return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2214 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2215 const struct smb_filename *smb_fname,
2216 mode_t mode,
2217 SMB_DEV_T dev)
2219 VFS_FIND(mknod);
2220 return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2223 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2224 TALLOC_CTX *ctx,
2225 const struct smb_filename *smb_fname)
2227 VFS_FIND(realpath);
2228 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2231 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2232 const struct smb_filename *smb_fname,
2233 unsigned int flags)
2235 VFS_FIND(chflags);
2236 return handle->fns->chflags_fn(handle, smb_fname, flags);
2239 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2240 const SMB_STRUCT_STAT *sbuf)
2242 VFS_FIND(file_id_create);
2243 return handle->fns->file_id_create_fn(handle, sbuf);
2246 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2247 struct files_struct *fsp,
2248 const struct smb_filename *smb_fname,
2249 TALLOC_CTX *mem_ctx,
2250 unsigned int *num_streams,
2251 struct stream_struct **streams)
2253 VFS_FIND(streaminfo);
2254 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2255 num_streams, streams);
2258 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2259 const char *path, const char *name,
2260 TALLOC_CTX *mem_ctx, char **found_name)
2262 VFS_FIND(get_real_filename);
2263 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2264 found_name);
2267 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2268 const struct smb_filename *smb_fname)
2270 VFS_FIND(connectpath);
2271 return handle->fns->connectpath_fn(handle, smb_fname);
2274 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2275 struct files_struct *fsp,
2276 struct lock_struct *plock)
2278 VFS_FIND(strict_lock_check);
2279 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2282 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2283 const char *name,
2284 enum vfs_translate_direction direction,
2285 TALLOC_CTX *mem_ctx,
2286 char **mapped_name)
2288 VFS_FIND(translate_name);
2289 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2290 mapped_name);
2293 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2294 struct files_struct *fsp,
2295 TALLOC_CTX *ctx,
2296 uint32_t function,
2297 uint16_t req_flags,
2298 const uint8_t *in_data,
2299 uint32_t in_len,
2300 uint8_t **out_data,
2301 uint32_t max_out_len,
2302 uint32_t *out_len)
2304 VFS_FIND(fsctl);
2305 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2306 in_data, in_len, out_data, max_out_len,
2307 out_len);
2310 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2311 struct smb_filename *smb_fname,
2312 uint32_t *dosmode)
2314 VFS_FIND(get_dos_attributes);
2315 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2318 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2319 struct files_struct *fsp,
2320 uint32_t *dosmode)
2322 VFS_FIND(fget_dos_attributes);
2323 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2326 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2327 const struct smb_filename *smb_fname,
2328 uint32_t dosmode)
2330 VFS_FIND(set_dos_attributes);
2331 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2334 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2335 struct files_struct *fsp,
2336 uint32_t dosmode)
2338 VFS_FIND(set_dos_attributes);
2339 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2342 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2343 struct tevent_context *ev,
2344 struct vfs_handle_struct *handle,
2345 struct files_struct *fsp,
2346 uint32_t fsctl,
2347 uint32_t ttl,
2348 off_t offset,
2349 size_t to_copy)
2351 VFS_FIND(offload_read_send);
2352 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2353 fsp, fsctl,
2354 ttl, offset, to_copy);
2357 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2358 struct vfs_handle_struct *handle,
2359 TALLOC_CTX *mem_ctx,
2360 DATA_BLOB *token_blob)
2362 VFS_FIND(offload_read_recv);
2363 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2366 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2367 TALLOC_CTX *mem_ctx,
2368 struct tevent_context *ev,
2369 uint32_t fsctl,
2370 DATA_BLOB *token,
2371 off_t transfer_offset,
2372 struct files_struct *dest_fsp,
2373 off_t dest_off,
2374 off_t num)
2376 VFS_FIND(offload_write_send);
2377 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2378 token, transfer_offset,
2379 dest_fsp, dest_off, num);
2382 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2383 struct tevent_req *req,
2384 off_t *copied)
2386 VFS_FIND(offload_write_recv);
2387 return handle->fns->offload_write_recv_fn(handle, req, copied);
2390 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2391 TALLOC_CTX *mem_ctx,
2392 struct files_struct *fsp,
2393 struct smb_filename *smb_fname,
2394 uint16_t *_compression_fmt)
2396 VFS_FIND(get_compression);
2397 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2398 _compression_fmt);
2401 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2402 TALLOC_CTX *mem_ctx,
2403 struct files_struct *fsp,
2404 uint16_t compression_fmt)
2406 VFS_FIND(set_compression);
2407 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2408 compression_fmt);
2411 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2412 TALLOC_CTX *mem_ctx,
2413 const char *service_path,
2414 char **base_volume)
2416 VFS_FIND(snap_check_path);
2417 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2418 base_volume);
2421 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2422 TALLOC_CTX *mem_ctx,
2423 const char *base_volume,
2424 time_t *tstamp,
2425 bool rw,
2426 char **base_path,
2427 char **snap_path)
2429 VFS_FIND(snap_create);
2430 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2431 rw, base_path, snap_path);
2434 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2435 TALLOC_CTX *mem_ctx,
2436 char *base_path,
2437 char *snap_path)
2439 VFS_FIND(snap_delete);
2440 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2441 snap_path);
2444 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2445 struct files_struct *fsp,
2446 uint32_t security_info,
2447 TALLOC_CTX *mem_ctx,
2448 struct security_descriptor **ppdesc)
2450 VFS_FIND(fget_nt_acl);
2451 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2452 mem_ctx, ppdesc);
2455 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2456 const struct smb_filename *smb_fname,
2457 uint32_t security_info,
2458 TALLOC_CTX *mem_ctx,
2459 struct security_descriptor **ppdesc)
2461 VFS_FIND(get_nt_acl);
2462 return handle->fns->get_nt_acl_fn(handle,
2463 smb_fname,
2464 security_info,
2465 mem_ctx,
2466 ppdesc);
2469 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2470 struct files_struct *fsp,
2471 uint32_t security_info_sent,
2472 const struct security_descriptor *psd)
2474 VFS_FIND(fset_nt_acl);
2475 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2476 psd);
2479 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2480 struct smb_filename *file,
2481 struct security_acl *sacl,
2482 uint32_t access_requested,
2483 uint32_t access_denied)
2485 VFS_FIND(audit_file);
2486 return handle->fns->audit_file_fn(handle,
2487 file,
2488 sacl,
2489 access_requested,
2490 access_denied);
2493 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle,
2494 const struct smb_filename *smb_fname,
2495 mode_t mode)
2497 VFS_FIND(chmod_acl);
2498 return handle->fns->chmod_acl_fn(handle, smb_fname, mode);
2501 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2502 struct files_struct *fsp, mode_t mode)
2504 VFS_FIND(fchmod_acl);
2505 return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2508 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2509 const struct smb_filename *smb_fname,
2510 SMB_ACL_TYPE_T type,
2511 TALLOC_CTX *mem_ctx)
2513 VFS_FIND(sys_acl_get_file);
2514 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2517 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2518 struct files_struct *fsp,
2519 TALLOC_CTX *mem_ctx)
2521 VFS_FIND(sys_acl_get_fd);
2522 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2525 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2526 const struct smb_filename *smb_fname,
2527 TALLOC_CTX *mem_ctx,
2528 char **blob_description,
2529 DATA_BLOB *blob)
2531 VFS_FIND(sys_acl_blob_get_file);
2532 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2533 mem_ctx, blob_description, blob);
2536 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2537 struct files_struct *fsp,
2538 TALLOC_CTX *mem_ctx,
2539 char **blob_description,
2540 DATA_BLOB *blob)
2542 VFS_FIND(sys_acl_blob_get_fd);
2543 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2546 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2547 const struct smb_filename *smb_fname,
2548 SMB_ACL_TYPE_T acltype,
2549 SMB_ACL_T theacl)
2551 VFS_FIND(sys_acl_set_file);
2552 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2553 acltype, theacl);
2556 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2557 struct files_struct *fsp, SMB_ACL_T theacl)
2559 VFS_FIND(sys_acl_set_fd);
2560 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2563 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2564 const struct smb_filename *smb_fname)
2566 VFS_FIND(sys_acl_delete_def_file);
2567 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2570 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2571 const struct smb_filename *smb_fname,
2572 const char *name,
2573 void *value,
2574 size_t size)
2576 VFS_FIND(getxattr);
2577 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2580 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2581 struct files_struct *fsp, const char *name,
2582 void *value, size_t size)
2584 VFS_FIND(fgetxattr);
2585 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2588 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2589 const struct smb_filename *smb_fname,
2590 char *list,
2591 size_t size)
2593 VFS_FIND(listxattr);
2594 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2597 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2598 struct files_struct *fsp, char *list,
2599 size_t size)
2601 VFS_FIND(flistxattr);
2602 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2605 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2606 const struct smb_filename *smb_fname,
2607 const char *name)
2609 VFS_FIND(removexattr);
2610 return handle->fns->removexattr_fn(handle, smb_fname, name);
2613 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2614 struct files_struct *fsp, const char *name)
2616 VFS_FIND(fremovexattr);
2617 return handle->fns->fremovexattr_fn(handle, fsp, name);
2620 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2621 const struct smb_filename *smb_fname,
2622 const char *name,
2623 const void *value,
2624 size_t size,
2625 int flags)
2627 VFS_FIND(setxattr);
2628 return handle->fns->setxattr_fn(handle, smb_fname,
2629 name, value, size, flags);
2632 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2633 struct files_struct *fsp, const char *name,
2634 const void *value, size_t size, int flags)
2636 VFS_FIND(fsetxattr);
2637 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2640 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2641 struct files_struct *fsp)
2643 VFS_FIND(aio_force);
2644 return handle->fns->aio_force_fn(handle, fsp);
2647 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2648 struct files_struct *fsp,
2649 TALLOC_CTX *mem_ctx,
2650 DATA_BLOB *cookie)
2652 VFS_FIND(durable_cookie);
2653 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2656 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2657 struct files_struct *fsp,
2658 const DATA_BLOB old_cookie,
2659 TALLOC_CTX *mem_ctx,
2660 DATA_BLOB *new_cookie)
2662 VFS_FIND(durable_disconnect);
2663 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2664 mem_ctx, new_cookie);
2667 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2668 struct smb_request *smb1req,
2669 struct smbXsrv_open *op,
2670 const DATA_BLOB old_cookie,
2671 TALLOC_CTX *mem_ctx,
2672 struct files_struct **fsp,
2673 DATA_BLOB *new_cookie)
2675 VFS_FIND(durable_reconnect);
2676 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2677 old_cookie, mem_ctx, fsp,
2678 new_cookie);
2681 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2682 const struct smb_filename *fname,
2683 TALLOC_CTX *mem_ctx,
2684 struct readdir_attr_data **attr_data)
2686 VFS_FIND(readdir_attr);
2687 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);