prefork tests: re-enable restart tests for MIT Kerberos
[Samba.git] / source3 / smbd / vfs.c
blob51a4aeb0f2253fbd76cb0950439f86f1f75ec691
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 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
519 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
520 set_filelen_write_cache(fsp, len);
523 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
525 return ret;
528 /* Grow - we need to test if we have enough space. */
530 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
532 if (lp_strict_allocate(SNUM(fsp->conn))) {
533 /* See if we have a syscall that will allocate beyond
534 end-of-file without changing EOF. */
535 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
536 0, len);
537 } else {
538 ret = 0;
541 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
543 if (ret == 0) {
544 /* We changed the allocation size on disk, but not
545 EOF - exactly as required. We're done ! */
546 return 0;
549 if (ret == -1 && errno == ENOSPC) {
550 return -1;
553 len -= fsp->fsp_name->st.st_ex_size;
554 len /= 1024; /* Len is now number of 1k blocks needed. */
555 space_avail =
556 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
557 if (space_avail == (uint64_t)-1) {
558 return -1;
561 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
562 "needed blocks = %.0f, space avail = %.0f\n",
563 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
564 (double)space_avail));
566 if (len > space_avail) {
567 errno = ENOSPC;
568 return -1;
571 return 0;
574 /****************************************************************************
575 A vfs set_filelen call.
576 set the length of a file from a filedescriptor.
577 Returns 0 on success, -1 on failure.
578 ****************************************************************************/
580 int vfs_set_filelen(files_struct *fsp, off_t len)
582 int ret;
584 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
586 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
587 fsp_str_dbg(fsp), (double)len));
588 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
589 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
590 set_filelen_write_cache(fsp, len);
591 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
592 FILE_NOTIFY_CHANGE_SIZE
593 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
594 fsp->fsp_name->base_name);
597 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
599 return ret;
602 /****************************************************************************
603 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
604 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
605 as this is also called from the default SMB_VFS_FTRUNCATE code.
606 Always extends the file size.
607 Returns 0 on success, -1 on failure.
608 ****************************************************************************/
610 #define SPARSE_BUF_WRITE_SIZE (32*1024)
612 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
614 ssize_t pwrite_ret;
615 size_t total = 0;
617 if (!sparse_buf) {
618 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
619 if (!sparse_buf) {
620 errno = ENOMEM;
621 return -1;
625 while (total < len) {
626 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
628 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
629 if (pwrite_ret == -1) {
630 int saved_errno = errno;
631 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
632 "%s failed with error %s\n",
633 fsp_str_dbg(fsp), strerror(saved_errno)));
634 errno = saved_errno;
635 return -1;
637 total += pwrite_ret;
640 return 0;
643 /****************************************************************************
644 A vfs fill sparse call.
645 Writes zeros from the end of file to len, if len is greater than EOF.
646 Used only by strict_sync.
647 Returns 0 on success, -1 on failure.
648 ****************************************************************************/
650 int vfs_fill_sparse(files_struct *fsp, off_t len)
652 int ret;
653 NTSTATUS status;
654 off_t offset;
655 size_t num_to_write;
657 status = vfs_stat_fsp(fsp);
658 if (!NT_STATUS_IS_OK(status)) {
659 return -1;
662 if (len <= fsp->fsp_name->st.st_ex_size) {
663 return 0;
666 #ifdef S_ISFIFO
667 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
668 return 0;
670 #endif
672 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
673 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
674 (double)fsp->fsp_name->st.st_ex_size, (double)len,
675 (double)(len - fsp->fsp_name->st.st_ex_size)));
677 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
679 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
681 offset = fsp->fsp_name->st.st_ex_size;
682 num_to_write = len - fsp->fsp_name->st.st_ex_size;
684 /* Only do this on non-stream file handles. */
685 if (fsp->base_fsp == NULL) {
686 /* for allocation try fallocate first. This can fail on some
687 * platforms e.g. when the filesystem doesn't support it and no
688 * emulation is being done by the libc (like on AIX with JFS1). In that
689 * case we do our own emulation. fallocate implementations can
690 * return ENOTSUP or EINVAL in cases like that. */
691 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
692 if (ret == -1 && errno == ENOSPC) {
693 goto out;
695 if (ret == 0) {
696 goto out;
698 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
699 "error %d. Falling back to slow manual allocation\n", ret));
702 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
704 out:
706 if (ret == 0) {
707 set_filelen_write_cache(fsp, len);
710 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
711 return ret;
714 /****************************************************************************
715 Transfer some data (n bytes) between two file_struct's.
716 ****************************************************************************/
718 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
720 struct files_struct *fsp = (struct files_struct *)file;
722 return SMB_VFS_PREAD(fsp, buf, len, offset);
725 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
727 struct files_struct *fsp = (struct files_struct *)file;
729 return SMB_VFS_PWRITE(fsp, buf, len, offset);
732 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
734 return transfer_file_internal((void *)in, (void *)out, n,
735 vfs_pread_fn, vfs_pwrite_fn);
738 /*******************************************************************
739 A vfs_readdir wrapper which just returns the file name.
740 ********************************************************************/
742 const char *vfs_readdirname(connection_struct *conn, void *p,
743 SMB_STRUCT_STAT *sbuf, char **talloced)
745 struct dirent *ptr= NULL;
746 const char *dname;
747 char *translated;
748 NTSTATUS status;
750 if (!p)
751 return(NULL);
753 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
754 if (!ptr)
755 return(NULL);
757 dname = ptr->d_name;
760 #ifdef NEXT2
761 if (telldir(p) < 0)
762 return(NULL);
763 #endif
765 #ifdef HAVE_BROKEN_READDIR_NAME
766 /* using /usr/ucb/cc is BAD */
767 dname = dname - 2;
768 #endif
770 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
771 talloc_tos(), &translated);
772 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
773 *talloced = NULL;
774 return dname;
776 *talloced = translated;
777 if (!NT_STATUS_IS_OK(status)) {
778 return NULL;
780 return translated;
783 /*******************************************************************
784 A wrapper for vfs_chdir().
785 ********************************************************************/
787 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
789 int ret;
790 struct smb_filename *old_cwd = conn->cwd_fname;
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 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
807 ret = SMB_VFS_CHDIR(conn, smb_fname);
808 if (ret != 0) {
809 return -1;
813 * Always replace conn->cwd_fname. We
814 * don't know if it's been modified by
815 * VFS modules in the stack.
818 /* conn cache. */
819 conn->cwd_fname = vfs_GetWd(conn, conn);
820 if (conn->cwd_fname == NULL) {
822 * vfs_GetWd() failed.
823 * We must be able to read cwd.
824 * Return to original directory
825 * and return -1.
827 int saved_errno = errno;
829 if (old_cwd == NULL) {
831 * Failed on the very first chdir()+getwd()
832 * for this connection. We can't
833 * continue.
835 smb_panic("conn->cwd getwd failed\n");
836 /* NOTREACHED */
837 return -1;
839 /* Restore original conn->cwd_fname. */
840 conn->cwd_fname = old_cwd;
842 /* Return to the previous $cwd. */
843 ret = SMB_VFS_CHDIR(conn, conn->cwd_fname);
844 if (ret != 0) {
845 smb_panic("conn->cwd getwd failed\n");
846 /* NOTREACHED */
847 return -1;
849 errno = saved_errno;
850 /* And fail the chdir(). */
851 return -1;
854 /* vfs_GetWd() succeeded. */
855 /* Replace global cache. */
856 SAFE_FREE(LastDir);
857 LastDir = SMB_STRDUP(smb_fname->base_name);
859 DEBUG(4,("vfs_ChDir got %s\n", conn->cwd_fname->base_name));
861 TALLOC_FREE(old_cwd);
862 return ret;
865 /*******************************************************************
866 Return the absolute current directory path - given a UNIX pathname.
867 Note that this path is returned in DOS format, not UNIX
868 format. Note this can be called with conn == NULL.
869 ********************************************************************/
871 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
873 struct smb_filename *current_dir_fname = NULL;
874 struct file_id key;
875 struct smb_filename *smb_fname_dot = NULL;
876 struct smb_filename *smb_fname_full = NULL;
877 struct smb_filename *result = NULL;
879 if (!lp_getwd_cache()) {
880 goto nocache;
883 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
884 if (smb_fname_dot == NULL) {
885 errno = ENOMEM;
886 goto out;
889 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
891 * Known to fail for root: the directory may be NFS-mounted
892 * and exported with root_squash (so has no root access).
894 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
895 "(NFS problem ?)\n", strerror(errno) ));
896 goto nocache;
899 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
901 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
902 smbd_memcache(),
903 GETWD_CACHE,
904 data_blob_const(&key, sizeof(key)));
906 if (smb_fname_full == NULL) {
907 goto nocache;
910 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
911 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
912 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
913 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
915 * Ok, we're done
916 * Note: smb_fname_full is owned by smbd_memcache()
917 * so we must make a copy to return.
919 result = cp_smb_filename(ctx, smb_fname_full);
920 if (result == NULL) {
921 errno = ENOMEM;
923 goto out;
926 nocache:
929 * We don't have the information to hand so rely on traditional
930 * methods. The very slow getcwd, which spawns a process on some
931 * systems, or the not quite so bad getwd.
934 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
935 if (current_dir_fname == NULL) {
936 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
937 strerror(errno)));
938 goto out;
941 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
942 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
945 * smbd_memcache() will own current_dir_fname after the
946 * memcache_add_talloc call, so we must make
947 * a copy on ctx to return.
949 result = cp_smb_filename(ctx, current_dir_fname);
950 if (result == NULL) {
951 errno = ENOMEM;
955 * Ensure the memory going into the cache
956 * doesn't have a destructor so it can be
957 * cleanly freed.
959 talloc_set_destructor(current_dir_fname, NULL);
961 memcache_add_talloc(smbd_memcache(),
962 GETWD_CACHE,
963 data_blob_const(&key, sizeof(key)),
964 &current_dir_fname);
965 /* current_dir_fname is now == NULL here. */
966 } else {
967 /* current_dir_fname is already allocated on ctx. */
968 result = current_dir_fname;
971 out:
972 TALLOC_FREE(smb_fname_dot);
974 * Don't free current_dir_fname here. It's either been moved
975 * to the memcache or is being returned in result.
977 return result;
980 /*******************************************************************
981 Reduce a file name, removing .. elements and checking that
982 it is below dir in the hierarchy. This uses realpath.
983 This function must run as root, and will return names
984 and valid stat structs that can be checked on open.
985 ********************************************************************/
987 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
988 const struct smb_filename *smb_fname,
989 struct smb_request *smbreq)
991 NTSTATUS status;
992 TALLOC_CTX *ctx = talloc_tos();
993 const char *conn_rootdir;
994 size_t rootdir_len;
995 char *dir_name = NULL;
996 char *resolved_name = NULL;
997 const char *last_component = NULL;
998 struct smb_filename *resolved_fname = NULL;
999 struct smb_filename *saved_dir_fname = NULL;
1000 struct smb_filename *smb_fname_cwd = NULL;
1001 struct privilege_paths *priv_paths = NULL;
1002 int ret;
1004 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1005 smb_fname->base_name,
1006 conn->connectpath));
1009 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1010 if (!priv_paths) {
1011 status = NT_STATUS_NO_MEMORY;
1012 goto err;
1015 if (!parent_dirname(ctx, smb_fname->base_name,
1016 &dir_name, &last_component)) {
1017 status = NT_STATUS_NO_MEMORY;
1018 goto err;
1021 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1022 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1024 if (priv_paths->parent_name.base_name == NULL ||
1025 priv_paths->file_name.base_name == NULL) {
1026 status = NT_STATUS_NO_MEMORY;
1027 goto err;
1030 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1031 status = map_nt_error_from_unix(errno);
1032 goto err;
1034 /* Remember where we were. */
1035 saved_dir_fname = vfs_GetWd(ctx, conn);
1036 if (!saved_dir_fname) {
1037 status = map_nt_error_from_unix(errno);
1038 goto err;
1041 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1042 status = map_nt_error_from_unix(errno);
1043 goto err;
1046 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1047 if (smb_fname_cwd == NULL) {
1048 status = NT_STATUS_NO_MEMORY;
1049 goto err;
1052 /* Get the absolute path of the parent directory. */
1053 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1054 if (resolved_fname == NULL) {
1055 status = map_nt_error_from_unix(errno);
1056 goto err;
1058 resolved_name = resolved_fname->base_name;
1060 if (*resolved_name != '/') {
1061 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1062 "doesn't return absolute paths !\n"));
1063 status = NT_STATUS_OBJECT_NAME_INVALID;
1064 goto err;
1067 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1068 priv_paths->parent_name.base_name,
1069 resolved_name));
1071 /* Now check the stat value is the same. */
1072 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1073 status = map_nt_error_from_unix(errno);
1074 goto err;
1077 /* Ensure we're pointing at the same place. */
1078 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1079 DEBUG(0,("check_reduced_name_with_privilege: "
1080 "device/inode/uid/gid on directory %s changed. "
1081 "Denying access !\n",
1082 priv_paths->parent_name.base_name));
1083 status = NT_STATUS_ACCESS_DENIED;
1084 goto err;
1087 /* Ensure we're below the connect path. */
1089 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1090 if (conn_rootdir == NULL) {
1091 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1092 "conn_rootdir\n"));
1093 status = NT_STATUS_ACCESS_DENIED;
1094 goto err;
1097 rootdir_len = strlen(conn_rootdir);
1100 * In the case of rootdir_len == 1, we know that conn_rootdir is
1101 * "/", and we also know that resolved_name starts with a slash.
1102 * So, in this corner case, resolved_name is automatically a
1103 * sub-directory of the conn_rootdir. Thus we can skip the string
1104 * comparison and the next character checks (which are even
1105 * wrong in this case).
1107 if (rootdir_len != 1) {
1108 bool matched;
1110 matched = (strncmp(conn_rootdir, resolved_name,
1111 rootdir_len) == 0);
1113 if (!matched || (resolved_name[rootdir_len] != '/' &&
1114 resolved_name[rootdir_len] != '\0')) {
1115 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1116 "access attempt: %s is a symlink outside the "
1117 "share path\n",
1118 dir_name));
1119 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1120 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1121 status = NT_STATUS_ACCESS_DENIED;
1122 goto err;
1126 /* Now ensure that the last component either doesn't
1127 exist, or is *NOT* a symlink. */
1129 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1130 if (ret == -1) {
1131 /* Errno must be ENOENT for this be ok. */
1132 if (errno != ENOENT) {
1133 status = map_nt_error_from_unix(errno);
1134 DEBUG(2, ("check_reduced_name_with_privilege: "
1135 "LSTAT on %s failed with %s\n",
1136 priv_paths->file_name.base_name,
1137 nt_errstr(status)));
1138 goto err;
1142 if (VALID_STAT(priv_paths->file_name.st) &&
1143 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1144 DEBUG(2, ("check_reduced_name_with_privilege: "
1145 "Last component %s is a symlink. Denying"
1146 "access.\n",
1147 priv_paths->file_name.base_name));
1148 status = NT_STATUS_ACCESS_DENIED;
1149 goto err;
1152 smbreq->priv_paths = priv_paths;
1153 status = NT_STATUS_OK;
1155 err:
1157 if (saved_dir_fname != NULL) {
1158 vfs_ChDir(conn, saved_dir_fname);
1159 TALLOC_FREE(saved_dir_fname);
1161 TALLOC_FREE(resolved_fname);
1162 if (!NT_STATUS_IS_OK(status)) {
1163 TALLOC_FREE(priv_paths);
1165 TALLOC_FREE(dir_name);
1166 return status;
1169 /*******************************************************************
1170 Reduce a file name, removing .. elements and checking that
1171 it is below dir in the hierarchy. This uses realpath.
1173 If cwd_name == NULL then fname is a client given path relative
1174 to the root path of the share.
1176 If cwd_name != NULL then fname is a client given path relative
1177 to cwd_name. cwd_name is relative to the root path of the share.
1178 ********************************************************************/
1180 NTSTATUS check_reduced_name(connection_struct *conn,
1181 const struct smb_filename *cwd_fname,
1182 const struct smb_filename *smb_fname)
1184 TALLOC_CTX *ctx = talloc_tos();
1185 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1186 const char *fname = smb_fname->base_name;
1187 struct smb_filename *resolved_fname;
1188 char *resolved_name = NULL;
1189 char *new_fname = NULL;
1190 bool allow_symlinks = true;
1191 bool allow_widelinks = false;
1193 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1195 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1197 if (resolved_fname == NULL) {
1198 switch (errno) {
1199 case ENOTDIR:
1200 DEBUG(3,("check_reduced_name: Component not a "
1201 "directory in getting realpath for "
1202 "%s\n", fname));
1203 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1204 case ENOENT:
1206 char *dir_name = NULL;
1207 struct smb_filename dir_fname = {0};
1208 const char *last_component = NULL;
1210 /* Last component didn't exist.
1211 Remove it and try and canonicalise
1212 the directory name. */
1213 if (!parent_dirname(ctx, fname,
1214 &dir_name,
1215 &last_component)) {
1216 return NT_STATUS_NO_MEMORY;
1219 dir_fname = (struct smb_filename)
1220 { .base_name = dir_name };
1221 resolved_fname = SMB_VFS_REALPATH(conn,
1222 ctx,
1223 &dir_fname);
1224 if (resolved_fname == NULL) {
1225 NTSTATUS status = map_nt_error_from_unix(errno);
1227 if (errno == ENOENT || errno == ENOTDIR) {
1228 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1231 DEBUG(3,("check_reduce_name: "
1232 "couldn't get realpath for "
1233 "%s (%s)\n",
1234 fname,
1235 nt_errstr(status)));
1236 return status;
1238 resolved_name = talloc_asprintf(ctx,
1239 "%s/%s",
1240 resolved_fname->base_name,
1241 last_component);
1242 if (resolved_name == NULL) {
1243 return NT_STATUS_NO_MEMORY;
1245 break;
1247 default:
1248 DEBUG(3,("check_reduced_name: couldn't get "
1249 "realpath for %s\n", fname));
1250 return map_nt_error_from_unix(errno);
1252 } else {
1253 resolved_name = resolved_fname->base_name;
1256 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1257 resolved_name));
1259 if (*resolved_name != '/') {
1260 DEBUG(0,("check_reduced_name: realpath doesn't return "
1261 "absolute paths !\n"));
1262 TALLOC_FREE(resolved_fname);
1263 return NT_STATUS_OBJECT_NAME_INVALID;
1266 allow_widelinks = lp_widelinks(SNUM(conn));
1267 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1269 /* Common widelinks and symlinks checks. */
1270 if (!allow_widelinks || !allow_symlinks) {
1271 const char *conn_rootdir;
1272 size_t rootdir_len;
1274 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1275 if (conn_rootdir == NULL) {
1276 DEBUG(2, ("check_reduced_name: Could not get "
1277 "conn_rootdir\n"));
1278 TALLOC_FREE(resolved_fname);
1279 return NT_STATUS_ACCESS_DENIED;
1282 rootdir_len = strlen(conn_rootdir);
1285 * In the case of rootdir_len == 1, we know that
1286 * conn_rootdir is "/", and we also know that
1287 * resolved_name starts with a slash. So, in this
1288 * corner case, resolved_name is automatically a
1289 * sub-directory of the conn_rootdir. Thus we can skip
1290 * the string comparison and the next character checks
1291 * (which are even wrong in this case).
1293 if (rootdir_len != 1) {
1294 bool matched;
1296 matched = (strncmp(conn_rootdir, resolved_name,
1297 rootdir_len) == 0);
1298 if (!matched || (resolved_name[rootdir_len] != '/' &&
1299 resolved_name[rootdir_len] != '\0')) {
1300 DEBUG(2, ("check_reduced_name: Bad access "
1301 "attempt: %s is a symlink outside the "
1302 "share path\n", fname));
1303 DEBUGADD(2, ("conn_rootdir =%s\n",
1304 conn_rootdir));
1305 DEBUGADD(2, ("resolved_name=%s\n",
1306 resolved_name));
1307 TALLOC_FREE(resolved_fname);
1308 return NT_STATUS_ACCESS_DENIED;
1312 /* Extra checks if all symlinks are disallowed. */
1313 if (!allow_symlinks) {
1314 /* fname can't have changed in resolved_path. */
1315 const char *p = &resolved_name[rootdir_len];
1318 * UNIX filesystem semantics, names consisting
1319 * only of "." or ".." CANNOT be symlinks.
1321 if (ISDOT(fname) || ISDOTDOT(fname)) {
1322 goto out;
1325 if (*p != '/') {
1326 DEBUG(2, ("check_reduced_name: logic error (%c) "
1327 "in resolved_name: %s\n",
1329 fname));
1330 TALLOC_FREE(resolved_fname);
1331 return NT_STATUS_ACCESS_DENIED;
1334 p++;
1337 * If cwd_name is present and not ".",
1338 * then fname is relative to that, not
1339 * the root of the share. Make sure the
1340 * path we check is the one the client
1341 * sent (cwd_name+fname).
1343 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1344 new_fname = talloc_asprintf(ctx,
1345 "%s/%s",
1346 cwd_name,
1347 fname);
1348 if (new_fname == NULL) {
1349 TALLOC_FREE(resolved_fname);
1350 return NT_STATUS_NO_MEMORY;
1352 fname = new_fname;
1355 if (strcmp(fname, p)!=0) {
1356 DEBUG(2, ("check_reduced_name: Bad access "
1357 "attempt: %s is a symlink to %s\n",
1358 fname, p));
1359 TALLOC_FREE(resolved_fname);
1360 TALLOC_FREE(new_fname);
1361 return NT_STATUS_ACCESS_DENIED;
1366 out:
1368 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1369 TALLOC_FREE(resolved_fname);
1370 TALLOC_FREE(new_fname);
1371 return NT_STATUS_OK;
1375 * XXX: This is temporary and there should be no callers of this once
1376 * smb_filename is plumbed through all path based operations.
1378 * Called when we know stream name parsing has already been done.
1380 int vfs_stat_smb_basename(struct connection_struct *conn,
1381 const struct smb_filename *smb_fname_in,
1382 SMB_STRUCT_STAT *psbuf)
1384 struct smb_filename smb_fname = {
1385 .base_name = discard_const_p(char, smb_fname_in->base_name),
1386 .flags = smb_fname_in->flags
1388 int ret;
1390 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1391 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1392 } else {
1393 ret = SMB_VFS_STAT(conn, &smb_fname);
1396 if (ret != -1) {
1397 *psbuf = smb_fname.st;
1399 return ret;
1403 * Ensure LSTAT is called for POSIX paths.
1406 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1408 int ret;
1410 if(fsp->fh->fd == -1) {
1411 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1412 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1413 } else {
1414 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1416 if (ret == -1) {
1417 return map_nt_error_from_unix(errno);
1419 } else {
1420 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1421 return map_nt_error_from_unix(errno);
1424 return NT_STATUS_OK;
1428 * Initialize num_streams and streams, then call VFS op streaminfo
1430 NTSTATUS vfs_streaminfo(connection_struct *conn,
1431 struct files_struct *fsp,
1432 const struct smb_filename *smb_fname,
1433 TALLOC_CTX *mem_ctx,
1434 unsigned int *num_streams,
1435 struct stream_struct **streams)
1437 *num_streams = 0;
1438 *streams = NULL;
1439 return SMB_VFS_STREAMINFO(conn,
1440 fsp,
1441 smb_fname,
1442 mem_ctx,
1443 num_streams,
1444 streams);
1448 generate a file_id from a stat structure
1450 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1452 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1455 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1456 const char *service, const char *user)
1458 VFS_FIND(connect);
1459 return handle->fns->connect_fn(handle, service, user);
1462 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1464 VFS_FIND(disconnect);
1465 handle->fns->disconnect_fn(handle);
1468 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1469 const struct smb_filename *smb_fname,
1470 uint64_t *bsize,
1471 uint64_t *dfree,
1472 uint64_t *dsize)
1474 VFS_FIND(disk_free);
1475 return handle->fns->disk_free_fn(handle, smb_fname,
1476 bsize, dfree, dsize);
1479 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1480 const struct smb_filename *smb_fname,
1481 enum SMB_QUOTA_TYPE qtype,
1482 unid_t id,
1483 SMB_DISK_QUOTA *qt)
1485 VFS_FIND(get_quota);
1486 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1489 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1490 enum SMB_QUOTA_TYPE qtype, unid_t id,
1491 SMB_DISK_QUOTA *qt)
1493 VFS_FIND(set_quota);
1494 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1497 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1498 struct files_struct *fsp,
1499 struct shadow_copy_data *shadow_copy_data,
1500 bool labels)
1502 VFS_FIND(get_shadow_copy_data);
1503 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1504 shadow_copy_data,
1505 labels);
1507 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1508 const struct smb_filename *smb_fname,
1509 struct vfs_statvfs_struct *statbuf)
1511 VFS_FIND(statvfs);
1512 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1515 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1516 enum timestamp_set_resolution *p_ts_res)
1518 VFS_FIND(fs_capabilities);
1519 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1522 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1523 struct dfs_GetDFSReferral *r)
1525 VFS_FIND(get_dfs_referrals);
1526 return handle->fns->get_dfs_referrals_fn(handle, r);
1529 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1530 const struct smb_filename *smb_fname,
1531 const char *mask,
1532 uint32_t attributes)
1534 VFS_FIND(opendir);
1535 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1538 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1539 struct files_struct *fsp,
1540 const char *mask,
1541 uint32_t attributes)
1543 VFS_FIND(fdopendir);
1544 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1547 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1548 DIR *dirp,
1549 SMB_STRUCT_STAT *sbuf)
1551 VFS_FIND(readdir);
1552 return handle->fns->readdir_fn(handle, dirp, sbuf);
1555 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1556 DIR *dirp, long offset)
1558 VFS_FIND(seekdir);
1559 handle->fns->seekdir_fn(handle, dirp, offset);
1562 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1563 DIR *dirp)
1565 VFS_FIND(telldir);
1566 return handle->fns->telldir_fn(handle, dirp);
1569 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1570 DIR *dirp)
1572 VFS_FIND(rewind_dir);
1573 handle->fns->rewind_dir_fn(handle, dirp);
1576 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1577 const struct smb_filename *smb_fname,
1578 mode_t mode)
1580 VFS_FIND(mkdir);
1581 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1584 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1585 const struct smb_filename *smb_fname)
1587 VFS_FIND(rmdir);
1588 return handle->fns->rmdir_fn(handle, smb_fname);
1591 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1592 DIR *dir)
1594 VFS_FIND(closedir);
1595 return handle->fns->closedir_fn(handle, dir);
1598 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1599 struct smb_filename *smb_fname, struct files_struct *fsp,
1600 int flags, mode_t mode)
1602 VFS_FIND(open);
1603 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1606 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1607 struct smb_request *req,
1608 uint16_t root_dir_fid,
1609 struct smb_filename *smb_fname,
1610 uint32_t access_mask,
1611 uint32_t share_access,
1612 uint32_t create_disposition,
1613 uint32_t create_options,
1614 uint32_t file_attributes,
1615 uint32_t oplock_request,
1616 struct smb2_lease *lease,
1617 uint64_t allocation_size,
1618 uint32_t private_flags,
1619 struct security_descriptor *sd,
1620 struct ea_list *ea_list,
1621 files_struct **result,
1622 int *pinfo,
1623 const struct smb2_create_blobs *in_context_blobs,
1624 struct smb2_create_blobs *out_context_blobs)
1626 VFS_FIND(create_file);
1627 return handle->fns->create_file_fn(
1628 handle, req, root_dir_fid, smb_fname, access_mask,
1629 share_access, create_disposition, create_options,
1630 file_attributes, oplock_request, lease, allocation_size,
1631 private_flags, sd, ea_list,
1632 result, pinfo, in_context_blobs, out_context_blobs);
1635 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1636 struct files_struct *fsp)
1638 VFS_FIND(close);
1639 return handle->fns->close_fn(handle, fsp);
1642 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1643 struct files_struct *fsp, void *data, size_t n,
1644 off_t offset)
1646 VFS_FIND(pread);
1647 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1650 struct smb_vfs_call_pread_state {
1651 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1652 ssize_t retval;
1653 struct vfs_aio_state vfs_aio_state;
1656 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1658 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1659 TALLOC_CTX *mem_ctx,
1660 struct tevent_context *ev,
1661 struct files_struct *fsp,
1662 void *data,
1663 size_t n, off_t offset)
1665 struct tevent_req *req, *subreq;
1666 struct smb_vfs_call_pread_state *state;
1668 req = tevent_req_create(mem_ctx, &state,
1669 struct smb_vfs_call_pread_state);
1670 if (req == NULL) {
1671 return NULL;
1673 VFS_FIND(pread_send);
1674 state->recv_fn = handle->fns->pread_recv_fn;
1676 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1677 offset);
1678 if (tevent_req_nomem(subreq, req)) {
1679 return tevent_req_post(req, ev);
1681 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1682 return req;
1685 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1687 struct tevent_req *req = tevent_req_callback_data(
1688 subreq, struct tevent_req);
1689 struct smb_vfs_call_pread_state *state = tevent_req_data(
1690 req, struct smb_vfs_call_pread_state);
1692 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1693 TALLOC_FREE(subreq);
1694 if (state->retval == -1) {
1695 tevent_req_error(req, state->vfs_aio_state.error);
1696 return;
1698 tevent_req_done(req);
1701 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1702 struct vfs_aio_state *vfs_aio_state)
1704 struct smb_vfs_call_pread_state *state = tevent_req_data(
1705 req, struct smb_vfs_call_pread_state);
1706 ssize_t retval;
1708 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1709 tevent_req_received(req);
1710 return -1;
1712 *vfs_aio_state = state->vfs_aio_state;
1713 retval = state->retval;
1714 tevent_req_received(req);
1715 return retval;
1718 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1719 struct files_struct *fsp, const void *data,
1720 size_t n, off_t offset)
1722 VFS_FIND(pwrite);
1723 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1726 struct smb_vfs_call_pwrite_state {
1727 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1728 ssize_t retval;
1729 struct vfs_aio_state vfs_aio_state;
1732 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1734 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1735 TALLOC_CTX *mem_ctx,
1736 struct tevent_context *ev,
1737 struct files_struct *fsp,
1738 const void *data,
1739 size_t n, off_t offset)
1741 struct tevent_req *req, *subreq;
1742 struct smb_vfs_call_pwrite_state *state;
1744 req = tevent_req_create(mem_ctx, &state,
1745 struct smb_vfs_call_pwrite_state);
1746 if (req == NULL) {
1747 return NULL;
1749 VFS_FIND(pwrite_send);
1750 state->recv_fn = handle->fns->pwrite_recv_fn;
1752 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1753 offset);
1754 if (tevent_req_nomem(subreq, req)) {
1755 return tevent_req_post(req, ev);
1757 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1758 return req;
1761 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1763 struct tevent_req *req = tevent_req_callback_data(
1764 subreq, struct tevent_req);
1765 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1766 req, struct smb_vfs_call_pwrite_state);
1768 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1769 TALLOC_FREE(subreq);
1770 if (state->retval == -1) {
1771 tevent_req_error(req, state->vfs_aio_state.error);
1772 return;
1774 tevent_req_done(req);
1777 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1778 struct vfs_aio_state *vfs_aio_state)
1780 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1781 req, struct smb_vfs_call_pwrite_state);
1782 ssize_t retval;
1784 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1785 tevent_req_received(req);
1786 return -1;
1788 *vfs_aio_state = state->vfs_aio_state;
1789 retval = state->retval;
1790 tevent_req_received(req);
1791 return retval;
1794 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1795 struct files_struct *fsp, off_t offset,
1796 int whence)
1798 VFS_FIND(lseek);
1799 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1802 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1803 files_struct *fromfsp, const DATA_BLOB *header,
1804 off_t offset, size_t count)
1806 VFS_FIND(sendfile);
1807 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1808 count);
1811 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1812 files_struct *tofsp, off_t offset,
1813 size_t count)
1815 VFS_FIND(recvfile);
1816 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1819 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1820 const struct smb_filename *smb_fname_src,
1821 const struct smb_filename *smb_fname_dst)
1823 VFS_FIND(rename);
1824 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1827 struct smb_vfs_call_fsync_state {
1828 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1829 int retval;
1830 struct vfs_aio_state vfs_aio_state;
1833 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1835 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1836 TALLOC_CTX *mem_ctx,
1837 struct tevent_context *ev,
1838 struct files_struct *fsp)
1840 struct tevent_req *req, *subreq;
1841 struct smb_vfs_call_fsync_state *state;
1843 req = tevent_req_create(mem_ctx, &state,
1844 struct smb_vfs_call_fsync_state);
1845 if (req == NULL) {
1846 return NULL;
1848 VFS_FIND(fsync_send);
1849 state->recv_fn = handle->fns->fsync_recv_fn;
1851 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1852 if (tevent_req_nomem(subreq, req)) {
1853 return tevent_req_post(req, ev);
1855 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1856 return req;
1859 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1861 struct tevent_req *req = tevent_req_callback_data(
1862 subreq, struct tevent_req);
1863 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1864 req, struct smb_vfs_call_fsync_state);
1866 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1867 TALLOC_FREE(subreq);
1868 if (state->retval == -1) {
1869 tevent_req_error(req, state->vfs_aio_state.error);
1870 return;
1872 tevent_req_done(req);
1875 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1877 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1878 req, struct smb_vfs_call_fsync_state);
1879 ssize_t retval;
1881 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1882 tevent_req_received(req);
1883 return -1;
1885 *vfs_aio_state = state->vfs_aio_state;
1886 retval = state->retval;
1887 tevent_req_received(req);
1888 return retval;
1892 * Synchronous version of fsync, built from backend
1893 * async VFS primitives. Uses a temporary sub-event
1894 * context (NOT NESTED).
1897 int smb_vfs_fsync_sync(files_struct *fsp)
1899 TALLOC_CTX *frame = talloc_stackframe();
1900 struct tevent_req *req = NULL;
1901 struct vfs_aio_state aio_state = { 0 };
1902 int ret = -1;
1903 bool ok;
1904 struct tevent_context *ev = samba_tevent_context_init(frame);
1906 if (ev == NULL) {
1907 goto out;
1910 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
1911 if (req == NULL) {
1912 goto out;
1915 ok = tevent_req_poll(req, ev);
1916 if (!ok) {
1917 goto out;
1920 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
1922 out:
1924 TALLOC_FREE(frame);
1925 if (aio_state.error != 0) {
1926 errno = aio_state.error;
1928 return ret;
1931 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1932 struct smb_filename *smb_fname)
1934 VFS_FIND(stat);
1935 return handle->fns->stat_fn(handle, smb_fname);
1938 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1939 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1941 VFS_FIND(fstat);
1942 return handle->fns->fstat_fn(handle, fsp, sbuf);
1945 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1946 struct smb_filename *smb_filename)
1948 VFS_FIND(lstat);
1949 return handle->fns->lstat_fn(handle, smb_filename);
1952 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1953 struct files_struct *fsp,
1954 const SMB_STRUCT_STAT *sbuf)
1956 VFS_FIND(get_alloc_size);
1957 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1960 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1961 const struct smb_filename *smb_fname)
1963 VFS_FIND(unlink);
1964 return handle->fns->unlink_fn(handle, smb_fname);
1967 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1968 const struct smb_filename *smb_fname,
1969 mode_t mode)
1971 VFS_FIND(chmod);
1972 return handle->fns->chmod_fn(handle, smb_fname, mode);
1975 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1976 struct files_struct *fsp, mode_t mode)
1978 VFS_FIND(fchmod);
1979 return handle->fns->fchmod_fn(handle, fsp, mode);
1982 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1983 const struct smb_filename *smb_fname,
1984 uid_t uid,
1985 gid_t gid)
1987 VFS_FIND(chown);
1988 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1991 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1992 struct files_struct *fsp, uid_t uid, gid_t gid)
1994 VFS_FIND(fchown);
1995 return handle->fns->fchown_fn(handle, fsp, uid, gid);
1998 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
1999 const struct smb_filename *smb_fname,
2000 uid_t uid,
2001 gid_t gid)
2003 VFS_FIND(lchown);
2004 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2007 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2009 int ret;
2010 bool as_root = false;
2011 NTSTATUS status;
2013 if (fsp->fh->fd != -1) {
2014 /* Try fchown. */
2015 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2016 if (ret == 0) {
2017 return NT_STATUS_OK;
2019 if (ret == -1 && errno != ENOSYS) {
2020 return map_nt_error_from_unix(errno);
2024 as_root = (geteuid() == 0);
2026 if (as_root) {
2028 * We are being asked to chown as root. Make
2029 * sure we chdir() into the path to pin it,
2030 * and always act using lchown to ensure we
2031 * don't deref any symbolic links.
2033 char *parent_dir = NULL;
2034 const char *final_component = NULL;
2035 struct smb_filename *local_smb_fname = NULL;
2036 struct smb_filename parent_dir_fname = {0};
2037 struct smb_filename *saved_dir_fname = NULL;
2039 saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
2040 if (!saved_dir_fname) {
2041 status = map_nt_error_from_unix(errno);
2042 DEBUG(0,("vfs_chown_fsp: failed to get "
2043 "current working directory. Error was %s\n",
2044 strerror(errno)));
2045 return status;
2048 if (!parent_dirname(talloc_tos(),
2049 fsp->fsp_name->base_name,
2050 &parent_dir,
2051 &final_component)) {
2052 return NT_STATUS_NO_MEMORY;
2055 parent_dir_fname = (struct smb_filename) {
2056 .base_name = parent_dir,
2057 .flags = fsp->fsp_name->flags
2060 /* cd into the parent dir to pin it. */
2061 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2062 if (ret == -1) {
2063 return map_nt_error_from_unix(errno);
2066 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2067 final_component,
2068 NULL,
2069 NULL,
2070 fsp->fsp_name->flags);
2071 if (local_smb_fname == NULL) {
2072 status = NT_STATUS_NO_MEMORY;
2073 goto out;
2076 /* Must use lstat here. */
2077 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2078 if (ret == -1) {
2079 status = map_nt_error_from_unix(errno);
2080 goto out;
2083 /* Ensure it matches the fsp stat. */
2084 if (!check_same_stat(&local_smb_fname->st,
2085 &fsp->fsp_name->st)) {
2086 status = NT_STATUS_ACCESS_DENIED;
2087 goto out;
2090 ret = SMB_VFS_LCHOWN(fsp->conn,
2091 local_smb_fname,
2092 uid, gid);
2094 if (ret == 0) {
2095 status = NT_STATUS_OK;
2096 } else {
2097 status = map_nt_error_from_unix(errno);
2100 out:
2102 vfs_ChDir(fsp->conn, saved_dir_fname);
2103 TALLOC_FREE(local_smb_fname);
2104 TALLOC_FREE(saved_dir_fname);
2105 TALLOC_FREE(parent_dir);
2107 return status;
2110 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2111 ret = SMB_VFS_LCHOWN(fsp->conn,
2112 fsp->fsp_name,
2113 uid, gid);
2114 } else {
2115 ret = SMB_VFS_CHOWN(fsp->conn,
2116 fsp->fsp_name,
2117 uid, gid);
2120 if (ret == 0) {
2121 status = NT_STATUS_OK;
2122 } else {
2123 status = map_nt_error_from_unix(errno);
2125 return status;
2128 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2129 const struct smb_filename *smb_fname)
2131 VFS_FIND(chdir);
2132 return handle->fns->chdir_fn(handle, smb_fname);
2135 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2136 TALLOC_CTX *ctx)
2138 VFS_FIND(getwd);
2139 return handle->fns->getwd_fn(handle, ctx);
2142 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2143 const struct smb_filename *smb_fname,
2144 struct smb_file_time *ft)
2146 VFS_FIND(ntimes);
2147 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2150 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2151 struct files_struct *fsp, off_t offset)
2153 VFS_FIND(ftruncate);
2154 return handle->fns->ftruncate_fn(handle, fsp, offset);
2157 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2158 struct files_struct *fsp,
2159 uint32_t mode,
2160 off_t offset,
2161 off_t len)
2163 VFS_FIND(fallocate);
2164 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2167 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2168 struct files_struct *fsp, uint32_t share_mode,
2169 uint32_t access_mask)
2171 VFS_FIND(kernel_flock);
2172 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2173 access_mask);
2176 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2177 struct files_struct *fsp, int leasetype)
2179 VFS_FIND(linux_setlease);
2180 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2183 int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
2184 const char *link_target,
2185 const struct smb_filename *new_smb_fname)
2187 VFS_FIND(symlink);
2188 return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
2191 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2192 const struct smb_filename *smb_fname,
2193 char *buf,
2194 size_t bufsiz)
2196 VFS_FIND(readlink);
2197 return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
2200 int smb_vfs_call_link(struct vfs_handle_struct *handle,
2201 const struct smb_filename *old_smb_fname,
2202 const struct smb_filename *new_smb_fname)
2204 VFS_FIND(link);
2205 return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2208 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2209 const struct smb_filename *smb_fname,
2210 mode_t mode,
2211 SMB_DEV_T dev)
2213 VFS_FIND(mknod);
2214 return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2217 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2218 TALLOC_CTX *ctx,
2219 const struct smb_filename *smb_fname)
2221 VFS_FIND(realpath);
2222 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2225 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2226 const struct smb_filename *smb_fname,
2227 unsigned int flags)
2229 VFS_FIND(chflags);
2230 return handle->fns->chflags_fn(handle, smb_fname, flags);
2233 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2234 const SMB_STRUCT_STAT *sbuf)
2236 VFS_FIND(file_id_create);
2237 return handle->fns->file_id_create_fn(handle, sbuf);
2240 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2241 const SMB_STRUCT_STAT *sbuf)
2243 VFS_FIND(fs_file_id);
2244 return handle->fns->fs_file_id_fn(handle, sbuf);
2247 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2248 struct files_struct *fsp,
2249 const struct smb_filename *smb_fname,
2250 TALLOC_CTX *mem_ctx,
2251 unsigned int *num_streams,
2252 struct stream_struct **streams)
2254 VFS_FIND(streaminfo);
2255 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2256 num_streams, streams);
2259 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2260 const char *path, const char *name,
2261 TALLOC_CTX *mem_ctx, char **found_name)
2263 VFS_FIND(get_real_filename);
2264 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2265 found_name);
2268 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2269 const struct smb_filename *smb_fname)
2271 VFS_FIND(connectpath);
2272 return handle->fns->connectpath_fn(handle, smb_fname);
2275 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2276 struct files_struct *fsp,
2277 struct lock_struct *plock)
2279 VFS_FIND(strict_lock_check);
2280 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2283 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2284 const char *name,
2285 enum vfs_translate_direction direction,
2286 TALLOC_CTX *mem_ctx,
2287 char **mapped_name)
2289 VFS_FIND(translate_name);
2290 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2291 mapped_name);
2294 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2295 struct files_struct *fsp,
2296 TALLOC_CTX *ctx,
2297 uint32_t function,
2298 uint16_t req_flags,
2299 const uint8_t *in_data,
2300 uint32_t in_len,
2301 uint8_t **out_data,
2302 uint32_t max_out_len,
2303 uint32_t *out_len)
2305 VFS_FIND(fsctl);
2306 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2307 in_data, in_len, out_data, max_out_len,
2308 out_len);
2311 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2312 struct smb_filename *smb_fname,
2313 uint32_t *dosmode)
2315 VFS_FIND(get_dos_attributes);
2316 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2319 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2320 struct files_struct *fsp,
2321 uint32_t *dosmode)
2323 VFS_FIND(fget_dos_attributes);
2324 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2327 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2328 const struct smb_filename *smb_fname,
2329 uint32_t dosmode)
2331 VFS_FIND(set_dos_attributes);
2332 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2335 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2336 struct files_struct *fsp,
2337 uint32_t dosmode)
2339 VFS_FIND(set_dos_attributes);
2340 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2343 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2344 struct tevent_context *ev,
2345 struct vfs_handle_struct *handle,
2346 struct files_struct *fsp,
2347 uint32_t fsctl,
2348 uint32_t ttl,
2349 off_t offset,
2350 size_t to_copy)
2352 VFS_FIND(offload_read_send);
2353 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2354 fsp, fsctl,
2355 ttl, offset, to_copy);
2358 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2359 struct vfs_handle_struct *handle,
2360 TALLOC_CTX *mem_ctx,
2361 DATA_BLOB *token_blob)
2363 VFS_FIND(offload_read_recv);
2364 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2367 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2368 TALLOC_CTX *mem_ctx,
2369 struct tevent_context *ev,
2370 uint32_t fsctl,
2371 DATA_BLOB *token,
2372 off_t transfer_offset,
2373 struct files_struct *dest_fsp,
2374 off_t dest_off,
2375 off_t num)
2377 VFS_FIND(offload_write_send);
2378 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2379 token, transfer_offset,
2380 dest_fsp, dest_off, num);
2383 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2384 struct tevent_req *req,
2385 off_t *copied)
2387 VFS_FIND(offload_write_recv);
2388 return handle->fns->offload_write_recv_fn(handle, req, copied);
2391 struct smb_vfs_call_get_dos_attributes_state {
2392 files_struct *dir_fsp;
2393 NTSTATUS (*recv_fn)(struct tevent_req *req,
2394 struct vfs_aio_state *aio_state,
2395 uint32_t *dosmode);
2396 struct vfs_aio_state aio_state;
2397 uint32_t dos_attributes;
2400 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2402 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2403 TALLOC_CTX *mem_ctx,
2404 struct tevent_context *ev,
2405 struct vfs_handle_struct *handle,
2406 files_struct *dir_fsp,
2407 struct smb_filename *smb_fname)
2409 struct tevent_req *req = NULL;
2410 struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2411 struct tevent_req *subreq = NULL;
2413 req = tevent_req_create(mem_ctx, &state,
2414 struct smb_vfs_call_get_dos_attributes_state);
2415 if (req == NULL) {
2416 return NULL;
2419 VFS_FIND(get_dos_attributes_send);
2421 *state = (struct smb_vfs_call_get_dos_attributes_state) {
2422 .dir_fsp = dir_fsp,
2423 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2426 subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2428 handle,
2429 dir_fsp,
2430 smb_fname);
2431 if (tevent_req_nomem(subreq, req)) {
2432 return tevent_req_post(req, ev);
2434 tevent_req_defer_callback(req, ev);
2436 tevent_req_set_callback(subreq,
2437 smb_vfs_call_get_dos_attributes_done,
2438 req);
2440 return req;
2443 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2445 struct tevent_req *req =
2446 tevent_req_callback_data(subreq,
2447 struct tevent_req);
2448 struct smb_vfs_call_get_dos_attributes_state *state =
2449 tevent_req_data(req,
2450 struct smb_vfs_call_get_dos_attributes_state);
2451 NTSTATUS status;
2452 bool ok;
2455 * Make sure we run as the user again
2457 ok = change_to_user_by_fsp(state->dir_fsp);
2458 SMB_ASSERT(ok);
2460 status = state->recv_fn(subreq,
2461 &state->aio_state,
2462 &state->dos_attributes);
2463 TALLOC_FREE(subreq);
2464 if (tevent_req_nterror(req, status)) {
2465 return;
2468 tevent_req_done(req);
2471 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2472 struct tevent_req *req,
2473 struct vfs_aio_state *aio_state,
2474 uint32_t *dos_attributes)
2476 struct smb_vfs_call_get_dos_attributes_state *state =
2477 tevent_req_data(req,
2478 struct smb_vfs_call_get_dos_attributes_state);
2479 NTSTATUS status;
2481 if (tevent_req_is_nterror(req, &status)) {
2482 tevent_req_received(req);
2483 return status;
2486 *aio_state = state->aio_state;
2487 *dos_attributes = state->dos_attributes;
2488 tevent_req_received(req);
2489 return NT_STATUS_OK;
2492 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2493 TALLOC_CTX *mem_ctx,
2494 struct files_struct *fsp,
2495 struct smb_filename *smb_fname,
2496 uint16_t *_compression_fmt)
2498 VFS_FIND(get_compression);
2499 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2500 _compression_fmt);
2503 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2504 TALLOC_CTX *mem_ctx,
2505 struct files_struct *fsp,
2506 uint16_t compression_fmt)
2508 VFS_FIND(set_compression);
2509 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2510 compression_fmt);
2513 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2514 TALLOC_CTX *mem_ctx,
2515 const char *service_path,
2516 char **base_volume)
2518 VFS_FIND(snap_check_path);
2519 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2520 base_volume);
2523 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2524 TALLOC_CTX *mem_ctx,
2525 const char *base_volume,
2526 time_t *tstamp,
2527 bool rw,
2528 char **base_path,
2529 char **snap_path)
2531 VFS_FIND(snap_create);
2532 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2533 rw, base_path, snap_path);
2536 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2537 TALLOC_CTX *mem_ctx,
2538 char *base_path,
2539 char *snap_path)
2541 VFS_FIND(snap_delete);
2542 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2543 snap_path);
2546 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2547 struct files_struct *fsp,
2548 uint32_t security_info,
2549 TALLOC_CTX *mem_ctx,
2550 struct security_descriptor **ppdesc)
2552 VFS_FIND(fget_nt_acl);
2553 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2554 mem_ctx, ppdesc);
2557 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2558 const struct smb_filename *smb_fname,
2559 uint32_t security_info,
2560 TALLOC_CTX *mem_ctx,
2561 struct security_descriptor **ppdesc)
2563 VFS_FIND(get_nt_acl);
2564 return handle->fns->get_nt_acl_fn(handle,
2565 smb_fname,
2566 security_info,
2567 mem_ctx,
2568 ppdesc);
2571 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2572 struct files_struct *fsp,
2573 uint32_t security_info_sent,
2574 const struct security_descriptor *psd)
2576 VFS_FIND(fset_nt_acl);
2577 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2578 psd);
2581 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2582 struct smb_filename *file,
2583 struct security_acl *sacl,
2584 uint32_t access_requested,
2585 uint32_t access_denied)
2587 VFS_FIND(audit_file);
2588 return handle->fns->audit_file_fn(handle,
2589 file,
2590 sacl,
2591 access_requested,
2592 access_denied);
2595 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2596 const struct smb_filename *smb_fname,
2597 SMB_ACL_TYPE_T type,
2598 TALLOC_CTX *mem_ctx)
2600 VFS_FIND(sys_acl_get_file);
2601 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2604 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2605 struct files_struct *fsp,
2606 TALLOC_CTX *mem_ctx)
2608 VFS_FIND(sys_acl_get_fd);
2609 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2612 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2613 const struct smb_filename *smb_fname,
2614 TALLOC_CTX *mem_ctx,
2615 char **blob_description,
2616 DATA_BLOB *blob)
2618 VFS_FIND(sys_acl_blob_get_file);
2619 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2620 mem_ctx, blob_description, blob);
2623 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2624 struct files_struct *fsp,
2625 TALLOC_CTX *mem_ctx,
2626 char **blob_description,
2627 DATA_BLOB *blob)
2629 VFS_FIND(sys_acl_blob_get_fd);
2630 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2633 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2634 const struct smb_filename *smb_fname,
2635 SMB_ACL_TYPE_T acltype,
2636 SMB_ACL_T theacl)
2638 VFS_FIND(sys_acl_set_file);
2639 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2640 acltype, theacl);
2643 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2644 struct files_struct *fsp, SMB_ACL_T theacl)
2646 VFS_FIND(sys_acl_set_fd);
2647 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2650 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2651 const struct smb_filename *smb_fname)
2653 VFS_FIND(sys_acl_delete_def_file);
2654 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2657 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2658 const struct smb_filename *smb_fname,
2659 const char *name,
2660 void *value,
2661 size_t size)
2663 VFS_FIND(getxattr);
2664 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2668 struct smb_vfs_call_getxattrat_state {
2669 files_struct *dir_fsp;
2670 ssize_t (*recv_fn)(struct tevent_req *req,
2671 struct vfs_aio_state *aio_state,
2672 TALLOC_CTX *mem_ctx,
2673 uint8_t **xattr_value);
2674 ssize_t retval;
2675 uint8_t *xattr_value;
2676 struct vfs_aio_state aio_state;
2679 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2681 struct tevent_req *smb_vfs_call_getxattrat_send(
2682 TALLOC_CTX *mem_ctx,
2683 struct tevent_context *ev,
2684 struct vfs_handle_struct *handle,
2685 files_struct *dir_fsp,
2686 const struct smb_filename *smb_fname,
2687 const char *xattr_name,
2688 size_t alloc_hint)
2690 struct tevent_req *req = NULL;
2691 struct smb_vfs_call_getxattrat_state *state = NULL;
2692 struct tevent_req *subreq = NULL;
2694 req = tevent_req_create(mem_ctx, &state,
2695 struct smb_vfs_call_getxattrat_state);
2696 if (req == NULL) {
2697 return NULL;
2700 VFS_FIND(getxattrat_send);
2702 *state = (struct smb_vfs_call_getxattrat_state) {
2703 .dir_fsp = dir_fsp,
2704 .recv_fn = handle->fns->getxattrat_recv_fn,
2707 subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2709 handle,
2710 dir_fsp,
2711 smb_fname,
2712 xattr_name,
2713 alloc_hint);
2714 if (tevent_req_nomem(subreq, req)) {
2715 return tevent_req_post(req, ev);
2717 tevent_req_defer_callback(req, ev);
2719 tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2720 return req;
2723 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2725 struct tevent_req *req = tevent_req_callback_data(
2726 subreq, struct tevent_req);
2727 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2728 req, struct smb_vfs_call_getxattrat_state);
2729 bool ok;
2732 * Make sure we run as the user again
2734 ok = change_to_user_by_fsp(state->dir_fsp);
2735 SMB_ASSERT(ok);
2737 state->retval = state->recv_fn(subreq,
2738 &state->aio_state,
2739 state,
2740 &state->xattr_value);
2741 TALLOC_FREE(subreq);
2742 if (state->retval == -1) {
2743 tevent_req_error(req, state->aio_state.error);
2744 return;
2747 tevent_req_done(req);
2750 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2751 struct vfs_aio_state *aio_state,
2752 TALLOC_CTX *mem_ctx,
2753 uint8_t **xattr_value)
2755 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2756 req, struct smb_vfs_call_getxattrat_state);
2757 size_t xattr_size;
2759 if (tevent_req_is_unix_error(req, &aio_state->error)) {
2760 tevent_req_received(req);
2761 return -1;
2764 *aio_state = state->aio_state;
2765 xattr_size = state->retval;
2766 if (xattr_value != NULL) {
2767 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2770 tevent_req_received(req);
2771 return xattr_size;
2774 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2775 struct files_struct *fsp, const char *name,
2776 void *value, size_t size)
2778 VFS_FIND(fgetxattr);
2779 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2782 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2783 const struct smb_filename *smb_fname,
2784 char *list,
2785 size_t size)
2787 VFS_FIND(listxattr);
2788 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2791 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2792 struct files_struct *fsp, char *list,
2793 size_t size)
2795 VFS_FIND(flistxattr);
2796 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2799 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2800 const struct smb_filename *smb_fname,
2801 const char *name)
2803 VFS_FIND(removexattr);
2804 return handle->fns->removexattr_fn(handle, smb_fname, name);
2807 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2808 struct files_struct *fsp, const char *name)
2810 VFS_FIND(fremovexattr);
2811 return handle->fns->fremovexattr_fn(handle, fsp, name);
2814 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2815 const struct smb_filename *smb_fname,
2816 const char *name,
2817 const void *value,
2818 size_t size,
2819 int flags)
2821 VFS_FIND(setxattr);
2822 return handle->fns->setxattr_fn(handle, smb_fname,
2823 name, value, size, flags);
2826 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2827 struct files_struct *fsp, const char *name,
2828 const void *value, size_t size, int flags)
2830 VFS_FIND(fsetxattr);
2831 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2834 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2835 struct files_struct *fsp)
2837 VFS_FIND(aio_force);
2838 return handle->fns->aio_force_fn(handle, fsp);
2841 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2842 struct files_struct *fsp,
2843 TALLOC_CTX *mem_ctx,
2844 DATA_BLOB *cookie)
2846 VFS_FIND(durable_cookie);
2847 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2850 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2851 struct files_struct *fsp,
2852 const DATA_BLOB old_cookie,
2853 TALLOC_CTX *mem_ctx,
2854 DATA_BLOB *new_cookie)
2856 VFS_FIND(durable_disconnect);
2857 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2858 mem_ctx, new_cookie);
2861 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2862 struct smb_request *smb1req,
2863 struct smbXsrv_open *op,
2864 const DATA_BLOB old_cookie,
2865 TALLOC_CTX *mem_ctx,
2866 struct files_struct **fsp,
2867 DATA_BLOB *new_cookie)
2869 VFS_FIND(durable_reconnect);
2870 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2871 old_cookie, mem_ctx, fsp,
2872 new_cookie);
2875 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2876 const struct smb_filename *fname,
2877 TALLOC_CTX *mem_ctx,
2878 struct readdir_attr_data **attr_data)
2880 VFS_FIND(readdir_attr);
2881 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);