s3: VFS: Add SMB_VFS_READ_DFS_PATHAT().
[Samba.git] / source3 / smbd / vfs.c
blob7dc15158ccb614b1a206c0061bf78ff35c41dab9
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"
34 #include "lib/util/tevent_ntstatus.h"
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_VFS
39 static_decl_vfs;
41 struct vfs_fsp_data {
42 struct vfs_fsp_data *next;
43 struct vfs_handle_struct *owner;
44 void (*destroy)(void *p_data);
45 void *_dummy_;
46 /* NOTE: This structure contains four pointers so that we can guarantee
47 * that the end of the structure is always both 4-byte and 8-byte aligned.
51 struct vfs_init_function_entry {
52 char *name;
53 struct vfs_init_function_entry *prev, *next;
54 const struct vfs_fn_pointers *fns;
57 /****************************************************************************
58 maintain the list of available backends
59 ****************************************************************************/
61 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
63 struct vfs_init_function_entry *entry = backends;
65 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
67 while(entry) {
68 if (strcmp(entry->name, name)==0) return entry;
69 entry = entry->next;
72 return NULL;
75 NTSTATUS smb_register_vfs(int version, const char *name,
76 const struct vfs_fn_pointers *fns)
78 struct vfs_init_function_entry *entry = backends;
80 if ((version != SMB_VFS_INTERFACE_VERSION)) {
81 DEBUG(0, ("Failed to register vfs module.\n"
82 "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
83 "current SMB_VFS_INTERFACE_VERSION is %d.\n"
84 "Please recompile against the current Samba Version!\n",
85 version, SMB_VFS_INTERFACE_VERSION));
86 return NT_STATUS_OBJECT_TYPE_MISMATCH;
89 if (!name || !name[0]) {
90 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
91 return NT_STATUS_INVALID_PARAMETER;
94 if (vfs_find_backend_entry(name)) {
95 DEBUG(0,("VFS module %s already loaded!\n", name));
96 return NT_STATUS_OBJECT_NAME_COLLISION;
99 entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
100 entry->name = smb_xstrdup(name);
101 entry->fns = fns;
103 DLIST_ADD(backends, entry);
104 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
105 return NT_STATUS_OK;
108 /****************************************************************************
109 initialise default vfs hooks
110 ****************************************************************************/
112 static void vfs_init_default(connection_struct *conn)
114 DEBUG(3, ("Initialising default vfs hooks\n"));
115 vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
118 /****************************************************************************
119 initialise custom vfs hooks
120 ****************************************************************************/
122 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
124 char *module_path = NULL;
125 char *module_name = NULL;
126 char *module_param = NULL, *p;
127 vfs_handle_struct *handle;
128 const struct vfs_init_function_entry *entry;
130 if (!conn||!vfs_object||!vfs_object[0]) {
131 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
132 "empty vfs_object!\n"));
133 return False;
136 if(!backends) {
137 static_init_vfs(NULL);
140 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
142 module_path = smb_xstrdup(vfs_object);
144 p = strchr_m(module_path, ':');
146 if (p) {
147 *p = 0;
148 module_param = p+1;
149 trim_char(module_param, ' ', ' ');
152 trim_char(module_path, ' ', ' ');
154 module_name = smb_xstrdup(module_path);
156 if ((module_name[0] == '/') &&
157 (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
160 * Extract the module name from the path. Just use the base
161 * name of the last path component.
164 SAFE_FREE(module_name);
165 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
167 p = strchr_m(module_name, '.');
169 if (p != NULL) {
170 *p = '\0';
174 /* First, try to load the module with the new module system */
175 entry = vfs_find_backend_entry(module_name);
176 if (!entry) {
177 NTSTATUS status;
179 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
180 vfs_object));
182 status = smb_load_module("vfs", module_path);
183 if (!NT_STATUS_IS_OK(status)) {
184 DEBUG(0, ("error probing vfs module '%s': %s\n",
185 module_path, nt_errstr(status)));
186 goto fail;
189 entry = vfs_find_backend_entry(module_name);
190 if (!entry) {
191 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
192 goto fail;
196 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
198 handle = talloc_zero(conn, vfs_handle_struct);
199 if (!handle) {
200 DEBUG(0,("TALLOC_ZERO() failed!\n"));
201 goto fail;
203 handle->conn = conn;
204 handle->fns = entry->fns;
205 if (module_param) {
206 handle->param = talloc_strdup(conn, module_param);
208 DLIST_ADD(conn->vfs_handles, handle);
210 SAFE_FREE(module_path);
211 SAFE_FREE(module_name);
212 return True;
214 fail:
215 SAFE_FREE(module_path);
216 SAFE_FREE(module_name);
217 return False;
220 /*****************************************************************
221 Allow VFS modules to extend files_struct with VFS-specific state.
222 This will be ok for small numbers of extensions, but might need to
223 be refactored if it becomes more widely used.
224 ******************************************************************/
226 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
228 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
229 files_struct *fsp, size_t ext_size,
230 void (*destroy_fn)(void *p_data))
232 struct vfs_fsp_data *ext;
233 void * ext_data;
235 /* Prevent VFS modules adding multiple extensions. */
236 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
237 return ext_data;
240 ext = (struct vfs_fsp_data *)TALLOC_ZERO(
241 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
242 if (ext == NULL) {
243 return NULL;
246 ext->owner = handle;
247 ext->next = fsp->vfs_extension;
248 ext->destroy = destroy_fn;
249 fsp->vfs_extension = ext;
250 return EXT_DATA_AREA(ext);
253 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
255 struct vfs_fsp_data *curr;
256 struct vfs_fsp_data *prev;
258 for (curr = fsp->vfs_extension, prev = NULL;
259 curr;
260 prev = curr, curr = curr->next) {
261 if (curr->owner == handle) {
262 if (prev) {
263 prev->next = curr->next;
264 } else {
265 fsp->vfs_extension = curr->next;
267 if (curr->destroy) {
268 curr->destroy(EXT_DATA_AREA(curr));
270 TALLOC_FREE(curr);
271 return;
276 void vfs_remove_all_fsp_extensions(files_struct *fsp)
278 struct vfs_fsp_data *curr;
279 struct vfs_fsp_data *next;
281 for (curr = fsp->vfs_extension; curr; curr = next) {
283 next = curr->next;
284 fsp->vfs_extension = next;
286 if (curr->destroy) {
287 curr->destroy(EXT_DATA_AREA(curr));
289 TALLOC_FREE(curr);
293 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
295 struct vfs_fsp_data *head;
297 for (head = fsp->vfs_extension; head; head = head->next) {
298 if (head->owner == handle) {
299 return head;
303 return NULL;
306 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
308 struct vfs_fsp_data *head;
310 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
311 if (head != NULL) {
312 return EXT_DATA_AREA(head);
315 return NULL;
318 #undef EXT_DATA_AREA
321 * Ensure this module catches all VFS functions.
323 #ifdef DEVELOPER
324 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
325 const char *module)
327 bool missing_fn = false;
328 unsigned int idx;
329 const uintptr_t *end = (const uintptr_t *)(fns + 1);
331 for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
332 if (*((const uintptr_t *)fns + idx) == 0) {
333 DBG_ERR("VFS function at index %d not implemented "
334 "in module %s\n", idx, module);
335 missing_fn = true;
339 if (missing_fn) {
340 smb_panic("Required VFS function not implemented in module.\n");
343 #else
344 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
345 const char *module)
348 #endif
350 /*****************************************************************
351 Generic VFS init.
352 ******************************************************************/
354 bool smbd_vfs_init(connection_struct *conn)
356 const char **vfs_objects;
357 unsigned int i = 0;
358 int j = 0;
360 /* Normal share - initialise with disk access functions */
361 vfs_init_default(conn);
363 /* No need to load vfs modules for printer connections */
364 if (conn->printer) {
365 return True;
368 vfs_objects = lp_vfs_objects(SNUM(conn));
370 /* Override VFS functions if 'vfs object' was not specified*/
371 if (!vfs_objects || !vfs_objects[0])
372 return True;
374 for (i=0; vfs_objects[i] ;) {
375 i++;
378 for (j=i-1; j >= 0; j--) {
379 if (!vfs_init_custom(conn, vfs_objects[j])) {
380 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
381 return False;
384 return True;
387 /*******************************************************************
388 Check if a file exists in the vfs.
389 ********************************************************************/
391 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
393 /* Only return OK if stat was successful and S_ISREG */
394 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
395 S_ISREG(smb_fname->st.st_ex_mode)) {
396 return NT_STATUS_OK;
399 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
402 ssize_t vfs_pwrite_data(struct smb_request *req,
403 files_struct *fsp,
404 const char *buffer,
405 size_t N,
406 off_t offset)
408 size_t total=0;
409 ssize_t ret;
411 if (req && req->unread_bytes) {
412 int sockfd = req->xconn->transport.sock;
413 SMB_ASSERT(req->unread_bytes == N);
414 /* VFS_RECVFILE must drain the socket
415 * before returning. */
416 req->unread_bytes = 0;
418 * Leave the socket non-blocking and
419 * use SMB_VFS_RECVFILE. If it returns
420 * EAGAIN || EWOULDBLOCK temporarily set
421 * the socket blocking and retry
422 * the RECVFILE.
424 while (total < N) {
425 ret = SMB_VFS_RECVFILE(sockfd,
426 fsp,
427 offset + total,
428 N - total);
429 if (ret == 0 || (ret == -1 &&
430 (errno == EAGAIN ||
431 errno == EWOULDBLOCK))) {
432 int old_flags;
433 /* Ensure the socket is blocking. */
434 old_flags = fcntl(sockfd, F_GETFL, 0);
435 if (set_blocking(sockfd, true) == -1) {
436 return (ssize_t)-1;
438 ret = SMB_VFS_RECVFILE(sockfd,
439 fsp,
440 offset + total,
441 N - total);
442 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
443 return (ssize_t)-1;
445 if (ret == -1) {
446 return (ssize_t)-1;
448 total += ret;
449 return (ssize_t)total;
451 /* Any other error case. */
452 if (ret == -1) {
453 return ret;
455 total += ret;
457 return (ssize_t)total;
460 while (total < N) {
461 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
462 offset + total);
464 if (ret == -1)
465 return -1;
466 if (ret == 0)
467 return total;
469 total += ret;
471 return (ssize_t)total;
473 /****************************************************************************
474 An allocate file space call using the vfs interface.
475 Allocates space for a file from a filedescriptor.
476 Returns 0 on success, -1 on failure.
477 ****************************************************************************/
479 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
481 int ret;
482 connection_struct *conn = fsp->conn;
483 uint64_t space_avail;
484 uint64_t bsize,dfree,dsize;
485 NTSTATUS status;
488 * Actually try and commit the space on disk....
491 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
492 fsp_str_dbg(fsp), (double)len));
494 if (((off_t)len) < 0) {
495 DEBUG(0,("vfs_allocate_file_space: %s negative len "
496 "requested.\n", fsp_str_dbg(fsp)));
497 errno = EINVAL;
498 return -1;
501 status = vfs_stat_fsp(fsp);
502 if (!NT_STATUS_IS_OK(status)) {
503 return -1;
506 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
507 return 0;
509 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
510 /* Shrink - use ftruncate. */
512 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
513 "size %.0f\n", fsp_str_dbg(fsp),
514 (double)fsp->fsp_name->st.st_ex_size));
516 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
518 ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
520 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
522 return ret;
525 /* Grow - we need to test if we have enough space. */
527 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
529 if (lp_strict_allocate(SNUM(fsp->conn))) {
530 /* See if we have a syscall that will allocate beyond
531 end-of-file without changing EOF. */
532 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
533 0, len);
534 } else {
535 ret = 0;
538 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
540 if (ret == 0) {
541 /* We changed the allocation size on disk, but not
542 EOF - exactly as required. We're done ! */
543 return 0;
546 if (ret == -1 && errno == ENOSPC) {
547 return -1;
550 len -= fsp->fsp_name->st.st_ex_size;
551 len /= 1024; /* Len is now number of 1k blocks needed. */
552 space_avail =
553 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
554 if (space_avail == (uint64_t)-1) {
555 return -1;
558 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
559 "needed blocks = %.0f, space avail = %.0f\n",
560 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
561 (double)space_avail));
563 if (len > space_avail) {
564 errno = ENOSPC;
565 return -1;
568 return 0;
571 /****************************************************************************
572 A vfs set_filelen call.
573 set the length of a file from a filedescriptor.
574 Returns 0 on success, -1 on failure.
575 ****************************************************************************/
577 int vfs_set_filelen(files_struct *fsp, off_t len)
579 int ret;
581 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
583 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
584 fsp_str_dbg(fsp), (double)len));
585 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
586 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
587 FILE_NOTIFY_CHANGE_SIZE
588 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
589 fsp->fsp_name->base_name);
592 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
594 return ret;
597 /****************************************************************************
598 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
599 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
600 as this is also called from the default SMB_VFS_FTRUNCATE code.
601 Always extends the file size.
602 Returns 0 on success, -1 on failure.
603 ****************************************************************************/
605 #define SPARSE_BUF_WRITE_SIZE (32*1024)
607 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
609 ssize_t pwrite_ret;
610 size_t total = 0;
612 if (!sparse_buf) {
613 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
614 if (!sparse_buf) {
615 errno = ENOMEM;
616 return -1;
620 while (total < len) {
621 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
623 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
624 if (pwrite_ret == -1) {
625 int saved_errno = errno;
626 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
627 "%s failed with error %s\n",
628 fsp_str_dbg(fsp), strerror(saved_errno)));
629 errno = saved_errno;
630 return -1;
632 total += pwrite_ret;
635 return 0;
638 /****************************************************************************
639 A vfs fill sparse call.
640 Writes zeros from the end of file to len, if len is greater than EOF.
641 Used only by strict_sync.
642 Returns 0 on success, -1 on failure.
643 ****************************************************************************/
645 int vfs_fill_sparse(files_struct *fsp, off_t len)
647 int ret;
648 NTSTATUS status;
649 off_t offset;
650 size_t num_to_write;
652 status = vfs_stat_fsp(fsp);
653 if (!NT_STATUS_IS_OK(status)) {
654 return -1;
657 if (len <= fsp->fsp_name->st.st_ex_size) {
658 return 0;
661 #ifdef S_ISFIFO
662 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
663 return 0;
665 #endif
667 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
668 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
669 (double)fsp->fsp_name->st.st_ex_size, (double)len,
670 (double)(len - fsp->fsp_name->st.st_ex_size)));
672 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
674 offset = fsp->fsp_name->st.st_ex_size;
675 num_to_write = len - fsp->fsp_name->st.st_ex_size;
677 /* Only do this on non-stream file handles. */
678 if (fsp->base_fsp == NULL) {
679 /* for allocation try fallocate first. This can fail on some
680 * platforms e.g. when the filesystem doesn't support it and no
681 * emulation is being done by the libc (like on AIX with JFS1). In that
682 * case we do our own emulation. fallocate implementations can
683 * return ENOTSUP or EINVAL in cases like that. */
684 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
685 if (ret == -1 && errno == ENOSPC) {
686 goto out;
688 if (ret == 0) {
689 goto out;
691 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
692 "error %d. Falling back to slow manual allocation\n", ret));
695 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
697 out:
699 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
700 return ret;
703 /*******************************************************************************
704 Set a fd into blocking/nonblocking mode through VFS
705 *******************************************************************************/
707 int vfs_set_blocking(files_struct *fsp, bool set)
709 int val;
710 #ifdef O_NONBLOCK
711 #define FLAG_TO_SET O_NONBLOCK
712 #else
713 #ifdef SYSV
714 #define FLAG_TO_SET O_NDELAY
715 #else /* BSD */
716 #define FLAG_TO_SET FNDELAY
717 #endif
718 #endif
719 val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
720 if (val == -1) {
721 return -1;
724 if (set) {
725 val &= ~FLAG_TO_SET;
726 } else {
727 val |= FLAG_TO_SET;
730 return SMB_VFS_FCNTL(fsp, F_SETFL, val);
731 #undef FLAG_TO_SET
734 /****************************************************************************
735 Transfer some data (n bytes) between two file_struct's.
736 ****************************************************************************/
738 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
740 struct files_struct *fsp = (struct files_struct *)file;
742 return SMB_VFS_PREAD(fsp, buf, len, offset);
745 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
747 struct files_struct *fsp = (struct files_struct *)file;
749 return SMB_VFS_PWRITE(fsp, buf, len, offset);
752 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
754 return transfer_file_internal((void *)in, (void *)out, n,
755 vfs_pread_fn, vfs_pwrite_fn);
758 /*******************************************************************
759 A vfs_readdir wrapper which just returns the file name.
760 ********************************************************************/
762 const char *vfs_readdirname(connection_struct *conn, void *p,
763 SMB_STRUCT_STAT *sbuf, char **talloced)
765 struct dirent *ptr= NULL;
766 const char *dname;
767 char *translated;
768 NTSTATUS status;
770 if (!p)
771 return(NULL);
773 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
774 if (!ptr)
775 return(NULL);
777 dname = ptr->d_name;
780 #ifdef NEXT2
781 if (telldir(p) < 0)
782 return(NULL);
783 #endif
785 #ifdef HAVE_BROKEN_READDIR_NAME
786 /* using /usr/ucb/cc is BAD */
787 dname = dname - 2;
788 #endif
790 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
791 talloc_tos(), &translated);
792 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
793 *talloced = NULL;
794 return dname;
796 *talloced = translated;
797 if (!NT_STATUS_IS_OK(status)) {
798 return NULL;
800 return translated;
803 /*******************************************************************
804 A wrapper for vfs_chdir().
805 ********************************************************************/
807 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
809 int ret;
810 struct smb_filename *cwd = NULL;
812 if (!LastDir) {
813 LastDir = SMB_STRDUP("");
816 if (ISDOT(smb_fname->base_name)) {
817 return 0;
820 if (*smb_fname->base_name == '/' &&
821 strcsequal(LastDir,smb_fname->base_name)) {
822 return 0;
825 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
827 ret = SMB_VFS_CHDIR(conn, smb_fname);
828 if (ret != 0) {
829 return -1;
833 * Always replace conn->cwd_fsp. We
834 * don't know if it's been modified by
835 * VFS modules in the stack.
838 /* conn cache. */
839 cwd = vfs_GetWd(conn, conn);
840 if (cwd == NULL) {
842 * vfs_GetWd() failed.
843 * We must be able to read cwd.
844 * Return to original directory
845 * and return -1.
847 int saved_errno = errno;
849 if (conn->cwd_fsp->fsp_name == NULL) {
851 * Failed on the very first chdir()+getwd()
852 * for this connection. We can't
853 * continue.
855 smb_panic("conn->cwd getwd failed\n");
856 /* NOTREACHED */
857 return -1;
860 /* Return to the previous $cwd. */
861 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
862 if (ret != 0) {
863 smb_panic("conn->cwd getwd failed\n");
864 /* NOTREACHED */
865 return -1;
867 errno = saved_errno;
868 /* And fail the chdir(). */
869 return -1;
872 /* vfs_GetWd() succeeded. */
873 /* Replace global cache. */
874 SAFE_FREE(LastDir);
875 LastDir = SMB_STRDUP(smb_fname->base_name);
878 * (Indirect) Callers of vfs_ChDir() may still hold references to the
879 * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
880 * callers can use it for the lifetime of the SMB request.
882 talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
884 conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
885 conn->cwd_fsp->fh->fd = AT_FDCWD;
887 DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
889 return ret;
892 /*******************************************************************
893 Return the absolute current directory path - given a UNIX pathname.
894 Note that this path is returned in DOS format, not UNIX
895 format. Note this can be called with conn == NULL.
896 ********************************************************************/
898 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
900 struct smb_filename *current_dir_fname = NULL;
901 struct file_id key;
902 struct smb_filename *smb_fname_dot = NULL;
903 struct smb_filename *smb_fname_full = NULL;
904 struct smb_filename *result = NULL;
906 if (!lp_getwd_cache()) {
907 goto nocache;
910 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
911 if (smb_fname_dot == NULL) {
912 errno = ENOMEM;
913 goto out;
916 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
918 * Known to fail for root: the directory may be NFS-mounted
919 * and exported with root_squash (so has no root access).
921 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
922 "(NFS problem ?)\n", strerror(errno) ));
923 goto nocache;
926 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
928 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
929 smbd_memcache(),
930 GETWD_CACHE,
931 data_blob_const(&key, sizeof(key)));
933 if (smb_fname_full == NULL) {
934 goto nocache;
937 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
938 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
939 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
940 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
942 * Ok, we're done
943 * Note: smb_fname_full is owned by smbd_memcache()
944 * so we must make a copy to return.
946 result = cp_smb_filename(ctx, smb_fname_full);
947 if (result == NULL) {
948 errno = ENOMEM;
950 goto out;
953 nocache:
956 * We don't have the information to hand so rely on traditional
957 * methods. The very slow getcwd, which spawns a process on some
958 * systems, or the not quite so bad getwd.
961 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
962 if (current_dir_fname == NULL) {
963 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
964 strerror(errno)));
965 goto out;
968 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
969 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
972 * smbd_memcache() will own current_dir_fname after the
973 * memcache_add_talloc call, so we must make
974 * a copy on ctx to return.
976 result = cp_smb_filename(ctx, current_dir_fname);
977 if (result == NULL) {
978 errno = ENOMEM;
982 * Ensure the memory going into the cache
983 * doesn't have a destructor so it can be
984 * cleanly freed.
986 talloc_set_destructor(current_dir_fname, NULL);
988 memcache_add_talloc(smbd_memcache(),
989 GETWD_CACHE,
990 data_blob_const(&key, sizeof(key)),
991 &current_dir_fname);
992 /* current_dir_fname is now == NULL here. */
993 } else {
994 /* current_dir_fname is already allocated on ctx. */
995 result = current_dir_fname;
998 out:
999 TALLOC_FREE(smb_fname_dot);
1001 * Don't free current_dir_fname here. It's either been moved
1002 * to the memcache or is being returned in result.
1004 return result;
1007 /*******************************************************************
1008 Reduce a file name, removing .. elements and checking that
1009 it is below dir in the hierarchy. This uses realpath.
1010 This function must run as root, and will return names
1011 and valid stat structs that can be checked on open.
1012 ********************************************************************/
1014 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1015 const struct smb_filename *smb_fname,
1016 struct smb_request *smbreq)
1018 NTSTATUS status;
1019 TALLOC_CTX *ctx = talloc_tos();
1020 const char *conn_rootdir;
1021 size_t rootdir_len;
1022 char *dir_name = NULL;
1023 char *resolved_name = NULL;
1024 const char *last_component = NULL;
1025 struct smb_filename *resolved_fname = NULL;
1026 struct smb_filename *saved_dir_fname = NULL;
1027 struct smb_filename *smb_fname_cwd = NULL;
1028 struct privilege_paths *priv_paths = NULL;
1029 int ret;
1031 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1032 smb_fname->base_name,
1033 conn->connectpath));
1036 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1037 if (!priv_paths) {
1038 status = NT_STATUS_NO_MEMORY;
1039 goto err;
1042 if (!parent_dirname(ctx, smb_fname->base_name,
1043 &dir_name, &last_component)) {
1044 status = NT_STATUS_NO_MEMORY;
1045 goto err;
1048 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1049 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1051 if (priv_paths->parent_name.base_name == NULL ||
1052 priv_paths->file_name.base_name == NULL) {
1053 status = NT_STATUS_NO_MEMORY;
1054 goto err;
1057 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1058 status = map_nt_error_from_unix(errno);
1059 goto err;
1061 /* Remember where we were. */
1062 saved_dir_fname = vfs_GetWd(ctx, conn);
1063 if (!saved_dir_fname) {
1064 status = map_nt_error_from_unix(errno);
1065 goto err;
1068 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1069 status = map_nt_error_from_unix(errno);
1070 goto err;
1073 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1074 if (smb_fname_cwd == NULL) {
1075 status = NT_STATUS_NO_MEMORY;
1076 goto err;
1079 /* Get the absolute path of the parent directory. */
1080 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1081 if (resolved_fname == NULL) {
1082 status = map_nt_error_from_unix(errno);
1083 goto err;
1085 resolved_name = resolved_fname->base_name;
1087 if (*resolved_name != '/') {
1088 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1089 "doesn't return absolute paths !\n"));
1090 status = NT_STATUS_OBJECT_NAME_INVALID;
1091 goto err;
1094 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1095 priv_paths->parent_name.base_name,
1096 resolved_name));
1098 /* Now check the stat value is the same. */
1099 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1100 status = map_nt_error_from_unix(errno);
1101 goto err;
1104 /* Ensure we're pointing at the same place. */
1105 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1106 DEBUG(0,("check_reduced_name_with_privilege: "
1107 "device/inode/uid/gid on directory %s changed. "
1108 "Denying access !\n",
1109 priv_paths->parent_name.base_name));
1110 status = NT_STATUS_ACCESS_DENIED;
1111 goto err;
1114 /* Ensure we're below the connect path. */
1116 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1117 if (conn_rootdir == NULL) {
1118 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1119 "conn_rootdir\n"));
1120 status = NT_STATUS_ACCESS_DENIED;
1121 goto err;
1124 rootdir_len = strlen(conn_rootdir);
1127 * In the case of rootdir_len == 1, we know that conn_rootdir is
1128 * "/", and we also know that resolved_name starts with a slash.
1129 * So, in this corner case, resolved_name is automatically a
1130 * sub-directory of the conn_rootdir. Thus we can skip the string
1131 * comparison and the next character checks (which are even
1132 * wrong in this case).
1134 if (rootdir_len != 1) {
1135 bool matched;
1137 matched = (strncmp(conn_rootdir, resolved_name,
1138 rootdir_len) == 0);
1140 if (!matched || (resolved_name[rootdir_len] != '/' &&
1141 resolved_name[rootdir_len] != '\0')) {
1142 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1143 "access attempt: %s is a symlink outside the "
1144 "share path\n",
1145 dir_name));
1146 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1147 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1148 status = NT_STATUS_ACCESS_DENIED;
1149 goto err;
1153 /* Now ensure that the last component either doesn't
1154 exist, or is *NOT* a symlink. */
1156 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1157 if (ret == -1) {
1158 /* Errno must be ENOENT for this be ok. */
1159 if (errno != ENOENT) {
1160 status = map_nt_error_from_unix(errno);
1161 DEBUG(2, ("check_reduced_name_with_privilege: "
1162 "LSTAT on %s failed with %s\n",
1163 priv_paths->file_name.base_name,
1164 nt_errstr(status)));
1165 goto err;
1169 if (VALID_STAT(priv_paths->file_name.st) &&
1170 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1171 DEBUG(2, ("check_reduced_name_with_privilege: "
1172 "Last component %s is a symlink. Denying"
1173 "access.\n",
1174 priv_paths->file_name.base_name));
1175 status = NT_STATUS_ACCESS_DENIED;
1176 goto err;
1179 smbreq->priv_paths = priv_paths;
1180 status = NT_STATUS_OK;
1182 err:
1184 if (saved_dir_fname != NULL) {
1185 vfs_ChDir(conn, saved_dir_fname);
1186 TALLOC_FREE(saved_dir_fname);
1188 TALLOC_FREE(resolved_fname);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 TALLOC_FREE(priv_paths);
1192 TALLOC_FREE(dir_name);
1193 return status;
1196 /*******************************************************************
1197 Reduce a file name, removing .. elements and checking that
1198 it is below dir in the hierarchy. This uses realpath.
1200 If cwd_name == NULL then fname is a client given path relative
1201 to the root path of the share.
1203 If cwd_name != NULL then fname is a client given path relative
1204 to cwd_name. cwd_name is relative to the root path of the share.
1205 ********************************************************************/
1207 NTSTATUS check_reduced_name(connection_struct *conn,
1208 const struct smb_filename *cwd_fname,
1209 const struct smb_filename *smb_fname)
1211 TALLOC_CTX *ctx = talloc_tos();
1212 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1213 const char *fname = smb_fname->base_name;
1214 struct smb_filename *resolved_fname;
1215 char *resolved_name = NULL;
1216 char *new_fname = NULL;
1217 bool allow_symlinks = true;
1218 bool allow_widelinks = false;
1220 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1222 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1224 if (resolved_fname == NULL) {
1225 switch (errno) {
1226 case ENOTDIR:
1227 DEBUG(3,("check_reduced_name: Component not a "
1228 "directory in getting realpath for "
1229 "%s\n", fname));
1230 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1231 case ENOENT:
1233 char *dir_name = NULL;
1234 struct smb_filename dir_fname = {0};
1235 const char *last_component = NULL;
1237 /* Last component didn't exist.
1238 Remove it and try and canonicalise
1239 the directory name. */
1240 if (!parent_dirname(ctx, fname,
1241 &dir_name,
1242 &last_component)) {
1243 return NT_STATUS_NO_MEMORY;
1246 dir_fname = (struct smb_filename)
1247 { .base_name = dir_name };
1248 resolved_fname = SMB_VFS_REALPATH(conn,
1249 ctx,
1250 &dir_fname);
1251 if (resolved_fname == NULL) {
1252 NTSTATUS status = map_nt_error_from_unix(errno);
1254 if (errno == ENOENT || errno == ENOTDIR) {
1255 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1258 DEBUG(3,("check_reduce_name: "
1259 "couldn't get realpath for "
1260 "%s (%s)\n",
1261 fname,
1262 nt_errstr(status)));
1263 return status;
1265 resolved_name = talloc_asprintf(ctx,
1266 "%s/%s",
1267 resolved_fname->base_name,
1268 last_component);
1269 if (resolved_name == NULL) {
1270 return NT_STATUS_NO_MEMORY;
1272 break;
1274 default:
1275 DEBUG(3,("check_reduced_name: couldn't get "
1276 "realpath for %s\n", fname));
1277 return map_nt_error_from_unix(errno);
1279 } else {
1280 resolved_name = resolved_fname->base_name;
1283 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1284 resolved_name));
1286 if (*resolved_name != '/') {
1287 DEBUG(0,("check_reduced_name: realpath doesn't return "
1288 "absolute paths !\n"));
1289 TALLOC_FREE(resolved_fname);
1290 return NT_STATUS_OBJECT_NAME_INVALID;
1293 allow_widelinks = lp_widelinks(SNUM(conn));
1294 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1296 /* Common widelinks and symlinks checks. */
1297 if (!allow_widelinks || !allow_symlinks) {
1298 const char *conn_rootdir;
1299 size_t rootdir_len;
1301 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1302 if (conn_rootdir == NULL) {
1303 DEBUG(2, ("check_reduced_name: Could not get "
1304 "conn_rootdir\n"));
1305 TALLOC_FREE(resolved_fname);
1306 return NT_STATUS_ACCESS_DENIED;
1309 rootdir_len = strlen(conn_rootdir);
1312 * In the case of rootdir_len == 1, we know that
1313 * conn_rootdir is "/", and we also know that
1314 * resolved_name starts with a slash. So, in this
1315 * corner case, resolved_name is automatically a
1316 * sub-directory of the conn_rootdir. Thus we can skip
1317 * the string comparison and the next character checks
1318 * (which are even wrong in this case).
1320 if (rootdir_len != 1) {
1321 bool matched;
1323 matched = (strncmp(conn_rootdir, resolved_name,
1324 rootdir_len) == 0);
1325 if (!matched || (resolved_name[rootdir_len] != '/' &&
1326 resolved_name[rootdir_len] != '\0')) {
1327 DEBUG(2, ("check_reduced_name: Bad access "
1328 "attempt: %s is a symlink outside the "
1329 "share path\n", fname));
1330 DEBUGADD(2, ("conn_rootdir =%s\n",
1331 conn_rootdir));
1332 DEBUGADD(2, ("resolved_name=%s\n",
1333 resolved_name));
1334 TALLOC_FREE(resolved_fname);
1335 return NT_STATUS_ACCESS_DENIED;
1339 /* Extra checks if all symlinks are disallowed. */
1340 if (!allow_symlinks) {
1341 /* fname can't have changed in resolved_path. */
1342 const char *p = &resolved_name[rootdir_len];
1345 * UNIX filesystem semantics, names consisting
1346 * only of "." or ".." CANNOT be symlinks.
1348 if (ISDOT(fname) || ISDOTDOT(fname)) {
1349 goto out;
1352 if (*p != '/') {
1353 DEBUG(2, ("check_reduced_name: logic error (%c) "
1354 "in resolved_name: %s\n",
1356 fname));
1357 TALLOC_FREE(resolved_fname);
1358 return NT_STATUS_ACCESS_DENIED;
1361 p++;
1364 * If cwd_name is present and not ".",
1365 * then fname is relative to that, not
1366 * the root of the share. Make sure the
1367 * path we check is the one the client
1368 * sent (cwd_name+fname).
1370 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1371 new_fname = talloc_asprintf(ctx,
1372 "%s/%s",
1373 cwd_name,
1374 fname);
1375 if (new_fname == NULL) {
1376 TALLOC_FREE(resolved_fname);
1377 return NT_STATUS_NO_MEMORY;
1379 fname = new_fname;
1382 if (strcmp(fname, p)!=0) {
1383 DEBUG(2, ("check_reduced_name: Bad access "
1384 "attempt: %s is a symlink to %s\n",
1385 fname, p));
1386 TALLOC_FREE(resolved_fname);
1387 TALLOC_FREE(new_fname);
1388 return NT_STATUS_ACCESS_DENIED;
1393 out:
1395 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1396 TALLOC_FREE(resolved_fname);
1397 TALLOC_FREE(new_fname);
1398 return NT_STATUS_OK;
1402 * XXX: This is temporary and there should be no callers of this once
1403 * smb_filename is plumbed through all path based operations.
1405 * Called when we know stream name parsing has already been done.
1407 int vfs_stat_smb_basename(struct connection_struct *conn,
1408 const struct smb_filename *smb_fname_in,
1409 SMB_STRUCT_STAT *psbuf)
1411 struct smb_filename smb_fname = {
1412 .base_name = discard_const_p(char, smb_fname_in->base_name),
1413 .flags = smb_fname_in->flags
1415 int ret;
1417 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1418 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1419 } else {
1420 ret = SMB_VFS_STAT(conn, &smb_fname);
1423 if (ret != -1) {
1424 *psbuf = smb_fname.st;
1426 return ret;
1430 * Ensure LSTAT is called for POSIX paths.
1433 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1435 int ret;
1436 struct stat_ex saved_stat = fsp->fsp_name->st;
1438 if(fsp->fh->fd == -1) {
1439 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1440 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1441 } else {
1442 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1444 } else {
1445 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1447 if (ret == -1) {
1448 return map_nt_error_from_unix(errno);
1450 update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat);
1451 return NT_STATUS_OK;
1454 void init_smb_file_time(struct smb_file_time *ft)
1456 *ft = (struct smb_file_time) {
1457 .atime = make_omit_timespec(),
1458 .ctime = make_omit_timespec(),
1459 .mtime = make_omit_timespec(),
1460 .create_time = make_omit_timespec()
1465 * Initialize num_streams and streams, then call VFS op streaminfo
1467 NTSTATUS vfs_streaminfo(connection_struct *conn,
1468 struct files_struct *fsp,
1469 const struct smb_filename *smb_fname,
1470 TALLOC_CTX *mem_ctx,
1471 unsigned int *num_streams,
1472 struct stream_struct **streams)
1474 *num_streams = 0;
1475 *streams = NULL;
1476 return SMB_VFS_STREAMINFO(conn,
1477 fsp,
1478 smb_fname,
1479 mem_ctx,
1480 num_streams,
1481 streams);
1485 generate a file_id from a stat structure
1487 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1489 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1492 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1493 const char *service, const char *user)
1495 VFS_FIND(connect);
1496 return handle->fns->connect_fn(handle, service, user);
1499 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1501 VFS_FIND(disconnect);
1502 handle->fns->disconnect_fn(handle);
1505 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1506 const struct smb_filename *smb_fname,
1507 uint64_t *bsize,
1508 uint64_t *dfree,
1509 uint64_t *dsize)
1511 VFS_FIND(disk_free);
1512 return handle->fns->disk_free_fn(handle, smb_fname,
1513 bsize, dfree, dsize);
1516 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1517 const struct smb_filename *smb_fname,
1518 enum SMB_QUOTA_TYPE qtype,
1519 unid_t id,
1520 SMB_DISK_QUOTA *qt)
1522 VFS_FIND(get_quota);
1523 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1526 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1527 enum SMB_QUOTA_TYPE qtype, unid_t id,
1528 SMB_DISK_QUOTA *qt)
1530 VFS_FIND(set_quota);
1531 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1534 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1535 struct files_struct *fsp,
1536 struct shadow_copy_data *shadow_copy_data,
1537 bool labels)
1539 VFS_FIND(get_shadow_copy_data);
1540 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1541 shadow_copy_data,
1542 labels);
1544 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1545 const struct smb_filename *smb_fname,
1546 struct vfs_statvfs_struct *statbuf)
1548 VFS_FIND(statvfs);
1549 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1552 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1553 enum timestamp_set_resolution *p_ts_res)
1555 VFS_FIND(fs_capabilities);
1556 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1559 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1560 struct dfs_GetDFSReferral *r)
1562 VFS_FIND(get_dfs_referrals);
1563 return handle->fns->get_dfs_referrals_fn(handle, r);
1566 NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
1567 struct files_struct *dirfsp,
1568 const struct smb_filename *smb_fname,
1569 const struct referral *reflist,
1570 size_t referral_count)
1572 VFS_FIND(create_dfs_pathat);
1573 return handle->fns->create_dfs_pathat_fn(handle,
1574 dirfsp,
1575 smb_fname,
1576 reflist,
1577 referral_count);
1580 NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
1581 TALLOC_CTX *mem_ctx,
1582 struct files_struct *dirfsp,
1583 const struct smb_filename *smb_fname,
1584 struct referral **ppreflist,
1585 size_t *preferral_count)
1587 VFS_FIND(read_dfs_pathat);
1588 return handle->fns->read_dfs_pathat_fn(handle,
1589 mem_ctx,
1590 dirfsp,
1591 smb_fname,
1592 ppreflist,
1593 preferral_count);
1596 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1597 const struct smb_filename *smb_fname,
1598 const char *mask,
1599 uint32_t attributes)
1601 VFS_FIND(opendir);
1602 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1605 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1606 struct files_struct *fsp,
1607 const char *mask,
1608 uint32_t attributes)
1610 VFS_FIND(fdopendir);
1611 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1614 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1615 DIR *dirp,
1616 SMB_STRUCT_STAT *sbuf)
1618 VFS_FIND(readdir);
1619 return handle->fns->readdir_fn(handle, dirp, sbuf);
1622 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1623 DIR *dirp, long offset)
1625 VFS_FIND(seekdir);
1626 handle->fns->seekdir_fn(handle, dirp, offset);
1629 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1630 DIR *dirp)
1632 VFS_FIND(telldir);
1633 return handle->fns->telldir_fn(handle, dirp);
1636 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1637 DIR *dirp)
1639 VFS_FIND(rewind_dir);
1640 handle->fns->rewind_dir_fn(handle, dirp);
1643 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1644 struct files_struct *dirfsp,
1645 const struct smb_filename *smb_fname,
1646 mode_t mode)
1648 VFS_FIND(mkdirat);
1649 return handle->fns->mkdirat_fn(handle,
1650 dirfsp,
1651 smb_fname,
1652 mode);
1655 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1656 DIR *dir)
1658 VFS_FIND(closedir);
1659 return handle->fns->closedir_fn(handle, dir);
1662 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1663 struct smb_filename *smb_fname, struct files_struct *fsp,
1664 int flags, mode_t mode)
1666 VFS_FIND(open);
1667 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1670 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1671 struct smb_request *req,
1672 uint16_t root_dir_fid,
1673 struct smb_filename *smb_fname,
1674 uint32_t access_mask,
1675 uint32_t share_access,
1676 uint32_t create_disposition,
1677 uint32_t create_options,
1678 uint32_t file_attributes,
1679 uint32_t oplock_request,
1680 const struct smb2_lease *lease,
1681 uint64_t allocation_size,
1682 uint32_t private_flags,
1683 struct security_descriptor *sd,
1684 struct ea_list *ea_list,
1685 files_struct **result,
1686 int *pinfo,
1687 const struct smb2_create_blobs *in_context_blobs,
1688 struct smb2_create_blobs *out_context_blobs)
1690 VFS_FIND(create_file);
1691 return handle->fns->create_file_fn(
1692 handle, req, root_dir_fid, smb_fname, access_mask,
1693 share_access, create_disposition, create_options,
1694 file_attributes, oplock_request, lease, allocation_size,
1695 private_flags, sd, ea_list,
1696 result, pinfo, in_context_blobs, out_context_blobs);
1699 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1700 struct files_struct *fsp)
1702 VFS_FIND(close);
1703 return handle->fns->close_fn(handle, fsp);
1706 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1707 struct files_struct *fsp, void *data, size_t n,
1708 off_t offset)
1710 VFS_FIND(pread);
1711 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1714 struct smb_vfs_call_pread_state {
1715 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1716 ssize_t retval;
1717 struct vfs_aio_state vfs_aio_state;
1720 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1722 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1723 TALLOC_CTX *mem_ctx,
1724 struct tevent_context *ev,
1725 struct files_struct *fsp,
1726 void *data,
1727 size_t n, off_t offset)
1729 struct tevent_req *req, *subreq;
1730 struct smb_vfs_call_pread_state *state;
1732 req = tevent_req_create(mem_ctx, &state,
1733 struct smb_vfs_call_pread_state);
1734 if (req == NULL) {
1735 return NULL;
1737 VFS_FIND(pread_send);
1738 state->recv_fn = handle->fns->pread_recv_fn;
1740 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1741 offset);
1742 if (tevent_req_nomem(subreq, req)) {
1743 return tevent_req_post(req, ev);
1745 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1746 return req;
1749 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1751 struct tevent_req *req = tevent_req_callback_data(
1752 subreq, struct tevent_req);
1753 struct smb_vfs_call_pread_state *state = tevent_req_data(
1754 req, struct smb_vfs_call_pread_state);
1756 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1757 TALLOC_FREE(subreq);
1758 if (state->retval == -1) {
1759 tevent_req_error(req, state->vfs_aio_state.error);
1760 return;
1762 tevent_req_done(req);
1765 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1766 struct vfs_aio_state *vfs_aio_state)
1768 struct smb_vfs_call_pread_state *state = tevent_req_data(
1769 req, struct smb_vfs_call_pread_state);
1770 ssize_t retval;
1772 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1773 tevent_req_received(req);
1774 return -1;
1776 *vfs_aio_state = state->vfs_aio_state;
1777 retval = state->retval;
1778 tevent_req_received(req);
1779 return retval;
1782 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1783 struct files_struct *fsp, const void *data,
1784 size_t n, off_t offset)
1786 VFS_FIND(pwrite);
1787 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1790 struct smb_vfs_call_pwrite_state {
1791 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1792 ssize_t retval;
1793 struct vfs_aio_state vfs_aio_state;
1796 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1798 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1799 TALLOC_CTX *mem_ctx,
1800 struct tevent_context *ev,
1801 struct files_struct *fsp,
1802 const void *data,
1803 size_t n, off_t offset)
1805 struct tevent_req *req, *subreq;
1806 struct smb_vfs_call_pwrite_state *state;
1808 req = tevent_req_create(mem_ctx, &state,
1809 struct smb_vfs_call_pwrite_state);
1810 if (req == NULL) {
1811 return NULL;
1813 VFS_FIND(pwrite_send);
1814 state->recv_fn = handle->fns->pwrite_recv_fn;
1816 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1817 offset);
1818 if (tevent_req_nomem(subreq, req)) {
1819 return tevent_req_post(req, ev);
1821 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1822 return req;
1825 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1827 struct tevent_req *req = tevent_req_callback_data(
1828 subreq, struct tevent_req);
1829 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1830 req, struct smb_vfs_call_pwrite_state);
1832 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1833 TALLOC_FREE(subreq);
1834 if (state->retval == -1) {
1835 tevent_req_error(req, state->vfs_aio_state.error);
1836 return;
1838 tevent_req_done(req);
1841 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1842 struct vfs_aio_state *vfs_aio_state)
1844 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1845 req, struct smb_vfs_call_pwrite_state);
1846 ssize_t retval;
1848 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1849 tevent_req_received(req);
1850 return -1;
1852 *vfs_aio_state = state->vfs_aio_state;
1853 retval = state->retval;
1854 tevent_req_received(req);
1855 return retval;
1858 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1859 struct files_struct *fsp, off_t offset,
1860 int whence)
1862 VFS_FIND(lseek);
1863 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1866 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1867 files_struct *fromfsp, const DATA_BLOB *header,
1868 off_t offset, size_t count)
1870 VFS_FIND(sendfile);
1871 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1872 count);
1875 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1876 files_struct *tofsp, off_t offset,
1877 size_t count)
1879 VFS_FIND(recvfile);
1880 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1883 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
1884 files_struct *srcfsp,
1885 const struct smb_filename *smb_fname_src,
1886 files_struct *dstfsp,
1887 const struct smb_filename *smb_fname_dst)
1889 VFS_FIND(renameat);
1890 return handle->fns->renameat_fn(handle,
1891 srcfsp,
1892 smb_fname_src,
1893 dstfsp,
1894 smb_fname_dst);
1897 struct smb_vfs_call_fsync_state {
1898 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1899 int retval;
1900 struct vfs_aio_state vfs_aio_state;
1903 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1905 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1906 TALLOC_CTX *mem_ctx,
1907 struct tevent_context *ev,
1908 struct files_struct *fsp)
1910 struct tevent_req *req, *subreq;
1911 struct smb_vfs_call_fsync_state *state;
1913 req = tevent_req_create(mem_ctx, &state,
1914 struct smb_vfs_call_fsync_state);
1915 if (req == NULL) {
1916 return NULL;
1918 VFS_FIND(fsync_send);
1919 state->recv_fn = handle->fns->fsync_recv_fn;
1921 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1922 if (tevent_req_nomem(subreq, req)) {
1923 return tevent_req_post(req, ev);
1925 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1926 return req;
1929 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1931 struct tevent_req *req = tevent_req_callback_data(
1932 subreq, struct tevent_req);
1933 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1934 req, struct smb_vfs_call_fsync_state);
1936 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1937 TALLOC_FREE(subreq);
1938 if (state->retval == -1) {
1939 tevent_req_error(req, state->vfs_aio_state.error);
1940 return;
1942 tevent_req_done(req);
1945 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1947 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1948 req, struct smb_vfs_call_fsync_state);
1949 ssize_t retval;
1951 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1952 tevent_req_received(req);
1953 return -1;
1955 *vfs_aio_state = state->vfs_aio_state;
1956 retval = state->retval;
1957 tevent_req_received(req);
1958 return retval;
1962 * Synchronous version of fsync, built from backend
1963 * async VFS primitives. Uses a temporary sub-event
1964 * context (NOT NESTED).
1967 int smb_vfs_fsync_sync(files_struct *fsp)
1969 TALLOC_CTX *frame = talloc_stackframe();
1970 struct tevent_req *req = NULL;
1971 struct vfs_aio_state aio_state = { 0 };
1972 int ret = -1;
1973 bool ok;
1974 struct tevent_context *ev = samba_tevent_context_init(frame);
1976 if (ev == NULL) {
1977 goto out;
1980 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
1981 if (req == NULL) {
1982 goto out;
1985 ok = tevent_req_poll(req, ev);
1986 if (!ok) {
1987 goto out;
1990 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
1992 out:
1994 TALLOC_FREE(frame);
1995 if (aio_state.error != 0) {
1996 errno = aio_state.error;
1998 return ret;
2001 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
2002 struct smb_filename *smb_fname)
2004 VFS_FIND(stat);
2005 return handle->fns->stat_fn(handle, smb_fname);
2008 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2009 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2011 VFS_FIND(fstat);
2012 return handle->fns->fstat_fn(handle, fsp, sbuf);
2015 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2016 struct smb_filename *smb_filename)
2018 VFS_FIND(lstat);
2019 return handle->fns->lstat_fn(handle, smb_filename);
2022 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2023 struct files_struct *fsp,
2024 const SMB_STRUCT_STAT *sbuf)
2026 VFS_FIND(get_alloc_size);
2027 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2030 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
2031 struct files_struct *dirfsp,
2032 const struct smb_filename *smb_fname,
2033 int flags)
2035 VFS_FIND(unlinkat);
2036 return handle->fns->unlinkat_fn(handle,
2037 dirfsp,
2038 smb_fname,
2039 flags);
2042 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
2043 const struct smb_filename *smb_fname,
2044 mode_t mode)
2046 VFS_FIND(chmod);
2047 return handle->fns->chmod_fn(handle, smb_fname, mode);
2050 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2051 struct files_struct *fsp, mode_t mode)
2053 VFS_FIND(fchmod);
2054 return handle->fns->fchmod_fn(handle, fsp, mode);
2057 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2058 struct files_struct *fsp, uid_t uid, gid_t gid)
2060 VFS_FIND(fchown);
2061 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2064 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2065 const struct smb_filename *smb_fname,
2066 uid_t uid,
2067 gid_t gid)
2069 VFS_FIND(lchown);
2070 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2073 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2074 const struct smb_filename *smb_fname)
2076 VFS_FIND(chdir);
2077 return handle->fns->chdir_fn(handle, smb_fname);
2080 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2081 TALLOC_CTX *ctx)
2083 VFS_FIND(getwd);
2084 return handle->fns->getwd_fn(handle, ctx);
2087 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2088 const struct smb_filename *smb_fname,
2089 struct smb_file_time *ft)
2091 VFS_FIND(ntimes);
2092 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2095 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2096 struct files_struct *fsp, off_t offset)
2098 VFS_FIND(ftruncate);
2099 return handle->fns->ftruncate_fn(handle, fsp, offset);
2102 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2103 struct files_struct *fsp,
2104 uint32_t mode,
2105 off_t offset,
2106 off_t len)
2108 VFS_FIND(fallocate);
2109 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2112 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2113 struct files_struct *fsp, uint32_t share_mode,
2114 uint32_t access_mask)
2116 VFS_FIND(kernel_flock);
2117 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2118 access_mask);
2121 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2122 struct files_struct *fsp, int cmd, ...)
2124 int result;
2125 va_list cmd_arg;
2127 VFS_FIND(fcntl);
2129 va_start(cmd_arg, cmd);
2130 result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2131 va_end(cmd_arg);
2133 return result;
2136 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2137 struct files_struct *fsp, int leasetype)
2139 VFS_FIND(linux_setlease);
2140 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2143 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2144 const char *link_target,
2145 struct files_struct *dirfsp,
2146 const struct smb_filename *new_smb_fname)
2148 VFS_FIND(symlinkat);
2149 return handle->fns->symlinkat_fn(handle,
2150 link_target,
2151 dirfsp,
2152 new_smb_fname);
2155 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2156 files_struct *dirfsp,
2157 const struct smb_filename *smb_fname,
2158 char *buf,
2159 size_t bufsiz)
2161 VFS_FIND(readlinkat);
2162 return handle->fns->readlinkat_fn(handle,
2163 dirfsp,
2164 smb_fname,
2165 buf,
2166 bufsiz);
2169 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2170 struct files_struct *srcfsp,
2171 const struct smb_filename *old_smb_fname,
2172 struct files_struct *dstfsp,
2173 const struct smb_filename *new_smb_fname,
2174 int flags)
2176 VFS_FIND(linkat);
2177 return handle->fns->linkat_fn(handle,
2178 srcfsp,
2179 old_smb_fname,
2180 dstfsp,
2181 new_smb_fname,
2182 flags);
2185 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2186 struct files_struct *dirfsp,
2187 const struct smb_filename *smb_fname,
2188 mode_t mode,
2189 SMB_DEV_T dev)
2191 VFS_FIND(mknodat);
2192 return handle->fns->mknodat_fn(handle,
2193 dirfsp,
2194 smb_fname,
2195 mode,
2196 dev);
2199 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2200 TALLOC_CTX *ctx,
2201 const struct smb_filename *smb_fname)
2203 VFS_FIND(realpath);
2204 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2207 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2208 const struct smb_filename *smb_fname,
2209 unsigned int flags)
2211 VFS_FIND(chflags);
2212 return handle->fns->chflags_fn(handle, smb_fname, flags);
2215 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2216 const SMB_STRUCT_STAT *sbuf)
2218 VFS_FIND(file_id_create);
2219 return handle->fns->file_id_create_fn(handle, sbuf);
2222 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2223 const SMB_STRUCT_STAT *sbuf)
2225 VFS_FIND(fs_file_id);
2226 return handle->fns->fs_file_id_fn(handle, sbuf);
2229 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2230 struct files_struct *fsp,
2231 const struct smb_filename *smb_fname,
2232 TALLOC_CTX *mem_ctx,
2233 unsigned int *num_streams,
2234 struct stream_struct **streams)
2236 VFS_FIND(streaminfo);
2237 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2238 num_streams, streams);
2241 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2242 const char *path, const char *name,
2243 TALLOC_CTX *mem_ctx, char **found_name)
2245 VFS_FIND(get_real_filename);
2246 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2247 found_name);
2250 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2251 const struct smb_filename *smb_fname)
2253 VFS_FIND(connectpath);
2254 return handle->fns->connectpath_fn(handle, smb_fname);
2257 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2258 struct files_struct *fsp,
2259 struct lock_struct *plock)
2261 VFS_FIND(strict_lock_check);
2262 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2265 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2266 const char *name,
2267 enum vfs_translate_direction direction,
2268 TALLOC_CTX *mem_ctx,
2269 char **mapped_name)
2271 VFS_FIND(translate_name);
2272 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2273 mapped_name);
2276 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2277 struct files_struct *fsp,
2278 TALLOC_CTX *ctx,
2279 uint32_t function,
2280 uint16_t req_flags,
2281 const uint8_t *in_data,
2282 uint32_t in_len,
2283 uint8_t **out_data,
2284 uint32_t max_out_len,
2285 uint32_t *out_len)
2287 VFS_FIND(fsctl);
2288 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2289 in_data, in_len, out_data, max_out_len,
2290 out_len);
2293 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2294 struct smb_filename *smb_fname,
2295 uint32_t *dosmode)
2297 VFS_FIND(get_dos_attributes);
2298 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2301 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2302 struct files_struct *fsp,
2303 uint32_t *dosmode)
2305 VFS_FIND(fget_dos_attributes);
2306 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2309 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2310 const struct smb_filename *smb_fname,
2311 uint32_t dosmode)
2313 VFS_FIND(set_dos_attributes);
2314 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2317 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2318 struct files_struct *fsp,
2319 uint32_t dosmode)
2321 VFS_FIND(set_dos_attributes);
2322 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2325 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2326 struct tevent_context *ev,
2327 struct vfs_handle_struct *handle,
2328 struct files_struct *fsp,
2329 uint32_t fsctl,
2330 uint32_t ttl,
2331 off_t offset,
2332 size_t to_copy)
2334 VFS_FIND(offload_read_send);
2335 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2336 fsp, fsctl,
2337 ttl, offset, to_copy);
2340 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2341 struct vfs_handle_struct *handle,
2342 TALLOC_CTX *mem_ctx,
2343 DATA_BLOB *token_blob)
2345 VFS_FIND(offload_read_recv);
2346 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2349 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2350 TALLOC_CTX *mem_ctx,
2351 struct tevent_context *ev,
2352 uint32_t fsctl,
2353 DATA_BLOB *token,
2354 off_t transfer_offset,
2355 struct files_struct *dest_fsp,
2356 off_t dest_off,
2357 off_t num)
2359 VFS_FIND(offload_write_send);
2360 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2361 token, transfer_offset,
2362 dest_fsp, dest_off, num);
2365 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2366 struct tevent_req *req,
2367 off_t *copied)
2369 VFS_FIND(offload_write_recv);
2370 return handle->fns->offload_write_recv_fn(handle, req, copied);
2373 struct smb_vfs_call_get_dos_attributes_state {
2374 files_struct *dir_fsp;
2375 NTSTATUS (*recv_fn)(struct tevent_req *req,
2376 struct vfs_aio_state *aio_state,
2377 uint32_t *dosmode);
2378 struct vfs_aio_state aio_state;
2379 uint32_t dos_attributes;
2382 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2384 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2385 TALLOC_CTX *mem_ctx,
2386 struct tevent_context *ev,
2387 struct vfs_handle_struct *handle,
2388 files_struct *dir_fsp,
2389 struct smb_filename *smb_fname)
2391 struct tevent_req *req = NULL;
2392 struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2393 struct tevent_req *subreq = NULL;
2395 req = tevent_req_create(mem_ctx, &state,
2396 struct smb_vfs_call_get_dos_attributes_state);
2397 if (req == NULL) {
2398 return NULL;
2401 VFS_FIND(get_dos_attributes_send);
2403 *state = (struct smb_vfs_call_get_dos_attributes_state) {
2404 .dir_fsp = dir_fsp,
2405 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2408 subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2410 handle,
2411 dir_fsp,
2412 smb_fname);
2413 if (tevent_req_nomem(subreq, req)) {
2414 return tevent_req_post(req, ev);
2416 tevent_req_defer_callback(req, ev);
2418 tevent_req_set_callback(subreq,
2419 smb_vfs_call_get_dos_attributes_done,
2420 req);
2422 return req;
2425 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2427 struct tevent_req *req =
2428 tevent_req_callback_data(subreq,
2429 struct tevent_req);
2430 struct smb_vfs_call_get_dos_attributes_state *state =
2431 tevent_req_data(req,
2432 struct smb_vfs_call_get_dos_attributes_state);
2433 NTSTATUS status;
2434 bool ok;
2437 * Make sure we run as the user again
2439 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2440 SMB_ASSERT(ok);
2442 status = state->recv_fn(subreq,
2443 &state->aio_state,
2444 &state->dos_attributes);
2445 TALLOC_FREE(subreq);
2446 if (tevent_req_nterror(req, status)) {
2447 return;
2450 tevent_req_done(req);
2453 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2454 struct tevent_req *req,
2455 struct vfs_aio_state *aio_state,
2456 uint32_t *dos_attributes)
2458 struct smb_vfs_call_get_dos_attributes_state *state =
2459 tevent_req_data(req,
2460 struct smb_vfs_call_get_dos_attributes_state);
2461 NTSTATUS status;
2463 if (tevent_req_is_nterror(req, &status)) {
2464 tevent_req_received(req);
2465 return status;
2468 *aio_state = state->aio_state;
2469 *dos_attributes = state->dos_attributes;
2470 tevent_req_received(req);
2471 return NT_STATUS_OK;
2474 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2475 TALLOC_CTX *mem_ctx,
2476 struct files_struct *fsp,
2477 struct smb_filename *smb_fname,
2478 uint16_t *_compression_fmt)
2480 VFS_FIND(get_compression);
2481 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2482 _compression_fmt);
2485 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2486 TALLOC_CTX *mem_ctx,
2487 struct files_struct *fsp,
2488 uint16_t compression_fmt)
2490 VFS_FIND(set_compression);
2491 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2492 compression_fmt);
2495 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2496 TALLOC_CTX *mem_ctx,
2497 const char *service_path,
2498 char **base_volume)
2500 VFS_FIND(snap_check_path);
2501 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2502 base_volume);
2505 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2506 TALLOC_CTX *mem_ctx,
2507 const char *base_volume,
2508 time_t *tstamp,
2509 bool rw,
2510 char **base_path,
2511 char **snap_path)
2513 VFS_FIND(snap_create);
2514 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2515 rw, base_path, snap_path);
2518 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2519 TALLOC_CTX *mem_ctx,
2520 char *base_path,
2521 char *snap_path)
2523 VFS_FIND(snap_delete);
2524 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2525 snap_path);
2528 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2529 struct files_struct *fsp,
2530 uint32_t security_info,
2531 TALLOC_CTX *mem_ctx,
2532 struct security_descriptor **ppdesc)
2534 VFS_FIND(fget_nt_acl);
2535 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2536 mem_ctx, ppdesc);
2539 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2540 const struct smb_filename *smb_fname,
2541 uint32_t security_info,
2542 TALLOC_CTX *mem_ctx,
2543 struct security_descriptor **ppdesc)
2545 VFS_FIND(get_nt_acl);
2546 return handle->fns->get_nt_acl_fn(handle,
2547 smb_fname,
2548 security_info,
2549 mem_ctx,
2550 ppdesc);
2553 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2554 struct files_struct *fsp,
2555 uint32_t security_info_sent,
2556 const struct security_descriptor *psd)
2558 VFS_FIND(fset_nt_acl);
2559 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2560 psd);
2563 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2564 struct smb_filename *file,
2565 struct security_acl *sacl,
2566 uint32_t access_requested,
2567 uint32_t access_denied)
2569 VFS_FIND(audit_file);
2570 return handle->fns->audit_file_fn(handle,
2571 file,
2572 sacl,
2573 access_requested,
2574 access_denied);
2577 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2578 const struct smb_filename *smb_fname,
2579 SMB_ACL_TYPE_T type,
2580 TALLOC_CTX *mem_ctx)
2582 VFS_FIND(sys_acl_get_file);
2583 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2586 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2587 struct files_struct *fsp,
2588 TALLOC_CTX *mem_ctx)
2590 VFS_FIND(sys_acl_get_fd);
2591 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2594 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2595 const struct smb_filename *smb_fname,
2596 TALLOC_CTX *mem_ctx,
2597 char **blob_description,
2598 DATA_BLOB *blob)
2600 VFS_FIND(sys_acl_blob_get_file);
2601 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2602 mem_ctx, blob_description, blob);
2605 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2606 struct files_struct *fsp,
2607 TALLOC_CTX *mem_ctx,
2608 char **blob_description,
2609 DATA_BLOB *blob)
2611 VFS_FIND(sys_acl_blob_get_fd);
2612 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2615 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2616 const struct smb_filename *smb_fname,
2617 SMB_ACL_TYPE_T acltype,
2618 SMB_ACL_T theacl)
2620 VFS_FIND(sys_acl_set_file);
2621 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2622 acltype, theacl);
2625 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2626 struct files_struct *fsp, SMB_ACL_T theacl)
2628 VFS_FIND(sys_acl_set_fd);
2629 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2632 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2633 const struct smb_filename *smb_fname)
2635 VFS_FIND(sys_acl_delete_def_file);
2636 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2639 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2640 const struct smb_filename *smb_fname,
2641 const char *name,
2642 void *value,
2643 size_t size)
2645 VFS_FIND(getxattr);
2646 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2650 struct smb_vfs_call_getxattrat_state {
2651 files_struct *dir_fsp;
2652 ssize_t (*recv_fn)(struct tevent_req *req,
2653 struct vfs_aio_state *aio_state,
2654 TALLOC_CTX *mem_ctx,
2655 uint8_t **xattr_value);
2656 ssize_t retval;
2657 uint8_t *xattr_value;
2658 struct vfs_aio_state aio_state;
2661 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2663 struct tevent_req *smb_vfs_call_getxattrat_send(
2664 TALLOC_CTX *mem_ctx,
2665 struct tevent_context *ev,
2666 struct vfs_handle_struct *handle,
2667 files_struct *dir_fsp,
2668 const struct smb_filename *smb_fname,
2669 const char *xattr_name,
2670 size_t alloc_hint)
2672 struct tevent_req *req = NULL;
2673 struct smb_vfs_call_getxattrat_state *state = NULL;
2674 struct tevent_req *subreq = NULL;
2676 req = tevent_req_create(mem_ctx, &state,
2677 struct smb_vfs_call_getxattrat_state);
2678 if (req == NULL) {
2679 return NULL;
2682 VFS_FIND(getxattrat_send);
2684 *state = (struct smb_vfs_call_getxattrat_state) {
2685 .dir_fsp = dir_fsp,
2686 .recv_fn = handle->fns->getxattrat_recv_fn,
2689 subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2691 handle,
2692 dir_fsp,
2693 smb_fname,
2694 xattr_name,
2695 alloc_hint);
2696 if (tevent_req_nomem(subreq, req)) {
2697 return tevent_req_post(req, ev);
2699 tevent_req_defer_callback(req, ev);
2701 tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2702 return req;
2705 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2707 struct tevent_req *req = tevent_req_callback_data(
2708 subreq, struct tevent_req);
2709 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2710 req, struct smb_vfs_call_getxattrat_state);
2711 bool ok;
2714 * Make sure we run as the user again
2716 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2717 SMB_ASSERT(ok);
2719 state->retval = state->recv_fn(subreq,
2720 &state->aio_state,
2721 state,
2722 &state->xattr_value);
2723 TALLOC_FREE(subreq);
2724 if (state->retval == -1) {
2725 tevent_req_error(req, state->aio_state.error);
2726 return;
2729 tevent_req_done(req);
2732 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2733 struct vfs_aio_state *aio_state,
2734 TALLOC_CTX *mem_ctx,
2735 uint8_t **xattr_value)
2737 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2738 req, struct smb_vfs_call_getxattrat_state);
2739 size_t xattr_size;
2741 if (tevent_req_is_unix_error(req, &aio_state->error)) {
2742 tevent_req_received(req);
2743 return -1;
2746 *aio_state = state->aio_state;
2747 xattr_size = state->retval;
2748 if (xattr_value != NULL) {
2749 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2752 tevent_req_received(req);
2753 return xattr_size;
2756 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2757 struct files_struct *fsp, const char *name,
2758 void *value, size_t size)
2760 VFS_FIND(fgetxattr);
2761 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2764 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2765 const struct smb_filename *smb_fname,
2766 char *list,
2767 size_t size)
2769 VFS_FIND(listxattr);
2770 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2773 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2774 struct files_struct *fsp, char *list,
2775 size_t size)
2777 VFS_FIND(flistxattr);
2778 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2781 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2782 const struct smb_filename *smb_fname,
2783 const char *name)
2785 VFS_FIND(removexattr);
2786 return handle->fns->removexattr_fn(handle, smb_fname, name);
2789 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2790 struct files_struct *fsp, const char *name)
2792 VFS_FIND(fremovexattr);
2793 return handle->fns->fremovexattr_fn(handle, fsp, name);
2796 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2797 const struct smb_filename *smb_fname,
2798 const char *name,
2799 const void *value,
2800 size_t size,
2801 int flags)
2803 VFS_FIND(setxattr);
2804 return handle->fns->setxattr_fn(handle, smb_fname,
2805 name, value, size, flags);
2808 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2809 struct files_struct *fsp, const char *name,
2810 const void *value, size_t size, int flags)
2812 VFS_FIND(fsetxattr);
2813 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2816 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2817 struct files_struct *fsp)
2819 VFS_FIND(aio_force);
2820 return handle->fns->aio_force_fn(handle, fsp);
2823 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2824 struct files_struct *fsp,
2825 TALLOC_CTX *mem_ctx,
2826 DATA_BLOB *cookie)
2828 VFS_FIND(durable_cookie);
2829 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2832 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2833 struct files_struct *fsp,
2834 const DATA_BLOB old_cookie,
2835 TALLOC_CTX *mem_ctx,
2836 DATA_BLOB *new_cookie)
2838 VFS_FIND(durable_disconnect);
2839 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2840 mem_ctx, new_cookie);
2843 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2844 struct smb_request *smb1req,
2845 struct smbXsrv_open *op,
2846 const DATA_BLOB old_cookie,
2847 TALLOC_CTX *mem_ctx,
2848 struct files_struct **fsp,
2849 DATA_BLOB *new_cookie)
2851 VFS_FIND(durable_reconnect);
2852 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2853 old_cookie, mem_ctx, fsp,
2854 new_cookie);
2857 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2858 const struct smb_filename *fname,
2859 TALLOC_CTX *mem_ctx,
2860 struct readdir_attr_data **attr_data)
2862 VFS_FIND(readdir_attr);
2863 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);