vfs: add SMB_VFS_OPENAT()
[Samba.git] / source3 / smbd / vfs.c
blobae82dd871c5458a7aa3c1e19beb7388f2a88f459
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"
35 #include "lib/util/sys_rw.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
40 static_decl_vfs;
42 struct vfs_fsp_data {
43 struct vfs_fsp_data *next;
44 struct vfs_handle_struct *owner;
45 void (*destroy)(void *p_data);
46 void *_dummy_;
47 /* NOTE: This structure contains four pointers so that we can guarantee
48 * that the end of the structure is always both 4-byte and 8-byte aligned.
52 struct vfs_init_function_entry {
53 char *name;
54 struct vfs_init_function_entry *prev, *next;
55 const struct vfs_fn_pointers *fns;
58 /****************************************************************************
59 maintain the list of available backends
60 ****************************************************************************/
62 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
64 struct vfs_init_function_entry *entry = backends;
66 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
68 while(entry) {
69 if (strcmp(entry->name, name)==0) return entry;
70 entry = entry->next;
73 return NULL;
76 NTSTATUS smb_register_vfs(int version, const char *name,
77 const struct vfs_fn_pointers *fns)
79 struct vfs_init_function_entry *entry = backends;
81 if ((version != SMB_VFS_INTERFACE_VERSION)) {
82 DEBUG(0, ("Failed to register vfs module.\n"
83 "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
84 "current SMB_VFS_INTERFACE_VERSION is %d.\n"
85 "Please recompile against the current Samba Version!\n",
86 version, SMB_VFS_INTERFACE_VERSION));
87 return NT_STATUS_OBJECT_TYPE_MISMATCH;
90 if (!name || !name[0]) {
91 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
92 return NT_STATUS_INVALID_PARAMETER;
95 if (vfs_find_backend_entry(name)) {
96 DEBUG(0,("VFS module %s already loaded!\n", name));
97 return NT_STATUS_OBJECT_NAME_COLLISION;
100 entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
101 entry->name = smb_xstrdup(name);
102 entry->fns = fns;
104 DLIST_ADD(backends, entry);
105 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
106 return NT_STATUS_OK;
109 /****************************************************************************
110 initialise default vfs hooks
111 ****************************************************************************/
113 static void vfs_init_default(connection_struct *conn)
115 DEBUG(3, ("Initialising default vfs hooks\n"));
116 vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
119 /****************************************************************************
120 initialise custom vfs hooks
121 ****************************************************************************/
123 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
125 char *module_path = NULL;
126 char *module_name = NULL;
127 char *module_param = NULL, *p;
128 vfs_handle_struct *handle;
129 const struct vfs_init_function_entry *entry;
131 if (!conn||!vfs_object||!vfs_object[0]) {
132 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
133 "empty vfs_object!\n"));
134 return False;
137 if(!backends) {
138 static_init_vfs(NULL);
141 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
143 module_path = smb_xstrdup(vfs_object);
145 p = strchr_m(module_path, ':');
147 if (p) {
148 *p = 0;
149 module_param = p+1;
150 trim_char(module_param, ' ', ' ');
153 trim_char(module_path, ' ', ' ');
155 module_name = smb_xstrdup(module_path);
157 if ((module_name[0] == '/') &&
158 (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
161 * Extract the module name from the path. Just use the base
162 * name of the last path component.
165 SAFE_FREE(module_name);
166 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
168 p = strchr_m(module_name, '.');
170 if (p != NULL) {
171 *p = '\0';
175 /* First, try to load the module with the new module system */
176 entry = vfs_find_backend_entry(module_name);
177 if (!entry) {
178 NTSTATUS status;
180 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
181 vfs_object));
183 status = smb_load_module("vfs", module_path);
184 if (!NT_STATUS_IS_OK(status)) {
185 DEBUG(0, ("error probing vfs module '%s': %s\n",
186 module_path, nt_errstr(status)));
187 goto fail;
190 entry = vfs_find_backend_entry(module_name);
191 if (!entry) {
192 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
193 goto fail;
197 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
199 handle = talloc_zero(conn, vfs_handle_struct);
200 if (!handle) {
201 DEBUG(0,("TALLOC_ZERO() failed!\n"));
202 goto fail;
204 handle->conn = conn;
205 handle->fns = entry->fns;
206 if (module_param) {
207 handle->param = talloc_strdup(conn, module_param);
209 DLIST_ADD(conn->vfs_handles, handle);
211 SAFE_FREE(module_path);
212 SAFE_FREE(module_name);
213 return True;
215 fail:
216 SAFE_FREE(module_path);
217 SAFE_FREE(module_name);
218 return False;
221 /*****************************************************************
222 Allow VFS modules to extend files_struct with VFS-specific state.
223 This will be ok for small numbers of extensions, but might need to
224 be refactored if it becomes more widely used.
225 ******************************************************************/
227 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
229 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
230 files_struct *fsp, size_t ext_size,
231 void (*destroy_fn)(void *p_data))
233 struct vfs_fsp_data *ext;
234 void * ext_data;
236 /* Prevent VFS modules adding multiple extensions. */
237 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
238 return ext_data;
241 ext = (struct vfs_fsp_data *)TALLOC_ZERO(
242 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
243 if (ext == NULL) {
244 return NULL;
247 ext->owner = handle;
248 ext->next = fsp->vfs_extension;
249 ext->destroy = destroy_fn;
250 fsp->vfs_extension = ext;
251 return EXT_DATA_AREA(ext);
254 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
256 struct vfs_fsp_data *curr;
257 struct vfs_fsp_data *prev;
259 for (curr = fsp->vfs_extension, prev = NULL;
260 curr;
261 prev = curr, curr = curr->next) {
262 if (curr->owner == handle) {
263 if (prev) {
264 prev->next = curr->next;
265 } else {
266 fsp->vfs_extension = curr->next;
268 if (curr->destroy) {
269 curr->destroy(EXT_DATA_AREA(curr));
271 TALLOC_FREE(curr);
272 return;
277 void vfs_remove_all_fsp_extensions(files_struct *fsp)
279 struct vfs_fsp_data *curr;
280 struct vfs_fsp_data *next;
282 for (curr = fsp->vfs_extension; curr; curr = next) {
284 next = curr->next;
285 fsp->vfs_extension = next;
287 if (curr->destroy) {
288 curr->destroy(EXT_DATA_AREA(curr));
290 TALLOC_FREE(curr);
294 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
296 struct vfs_fsp_data *head;
298 for (head = fsp->vfs_extension; head; head = head->next) {
299 if (head->owner == handle) {
300 return head;
304 return NULL;
307 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
309 struct vfs_fsp_data *head;
311 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
312 if (head != NULL) {
313 return EXT_DATA_AREA(head);
316 return NULL;
319 #undef EXT_DATA_AREA
322 * Ensure this module catches all VFS functions.
324 #ifdef DEVELOPER
325 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
326 const char *module)
328 bool missing_fn = false;
329 unsigned int idx;
330 const uintptr_t *end = (const uintptr_t *)(fns + 1);
332 for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
333 if (*((const uintptr_t *)fns + idx) == 0) {
334 DBG_ERR("VFS function at index %d not implemented "
335 "in module %s\n", idx, module);
336 missing_fn = true;
340 if (missing_fn) {
341 smb_panic("Required VFS function not implemented in module.\n");
344 #else
345 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
346 const char *module)
349 #endif
351 /*****************************************************************
352 Generic VFS init.
353 ******************************************************************/
355 bool smbd_vfs_init(connection_struct *conn)
357 const char **vfs_objects;
358 unsigned int i = 0;
359 int j = 0;
361 /* Normal share - initialise with disk access functions */
362 vfs_init_default(conn);
364 /* No need to load vfs modules for printer connections */
365 if (conn->printer) {
366 return True;
369 if (lp_widelinks(SNUM(conn))) {
371 * As the widelinks logic is now moving into a
372 * vfs_widelinks module, we need to custom load
373 * it after the default module is initialized.
374 * That way no changes to smb.conf files are
375 * needed.
377 bool ok = vfs_init_custom(conn, "widelinks");
378 if (!ok) {
379 DBG_ERR("widelinks enabled and vfs_init_custom "
380 "failed for vfs_widelinks module\n");
381 return false;
385 vfs_objects = lp_vfs_objects(SNUM(conn));
387 /* Override VFS functions if 'vfs object' was not specified*/
388 if (!vfs_objects || !vfs_objects[0])
389 return True;
391 for (i=0; vfs_objects[i] ;) {
392 i++;
395 for (j=i-1; j >= 0; j--) {
396 if (!vfs_init_custom(conn, vfs_objects[j])) {
397 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
398 return False;
401 return True;
404 /*******************************************************************
405 Check if a file exists in the vfs.
406 ********************************************************************/
408 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
410 /* Only return OK if stat was successful and S_ISREG */
411 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
412 S_ISREG(smb_fname->st.st_ex_mode)) {
413 return NT_STATUS_OK;
416 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
419 bool vfs_valid_pread_range(off_t offset, size_t length)
421 return sys_valid_io_range(offset, length);
424 bool vfs_valid_pwrite_range(off_t offset, size_t length)
427 * See MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write
429 static const uint64_t maxfilesize = 0xfffffff0000;
430 uint64_t last_byte_ofs;
431 bool ok;
433 ok = sys_valid_io_range(offset, length);
434 if (!ok) {
435 return false;
438 if (length == 0) {
439 return true;
442 last_byte_ofs = offset + length;
443 if (last_byte_ofs > maxfilesize) {
444 return false;
447 return true;
450 ssize_t vfs_pwrite_data(struct smb_request *req,
451 files_struct *fsp,
452 const char *buffer,
453 size_t N,
454 off_t offset)
456 size_t total=0;
457 ssize_t ret;
458 bool ok;
460 ok = vfs_valid_pwrite_range(offset, N);
461 if (!ok) {
462 errno = EINVAL;
463 return -1;
466 if (req && req->unread_bytes) {
467 int sockfd = req->xconn->transport.sock;
468 SMB_ASSERT(req->unread_bytes == N);
469 /* VFS_RECVFILE must drain the socket
470 * before returning. */
471 req->unread_bytes = 0;
473 * Leave the socket non-blocking and
474 * use SMB_VFS_RECVFILE. If it returns
475 * EAGAIN || EWOULDBLOCK temporarily set
476 * the socket blocking and retry
477 * the RECVFILE.
479 while (total < N) {
480 ret = SMB_VFS_RECVFILE(sockfd,
481 fsp,
482 offset + total,
483 N - total);
484 if (ret == 0 || (ret == -1 &&
485 (errno == EAGAIN ||
486 errno == EWOULDBLOCK))) {
487 int old_flags;
488 /* Ensure the socket is blocking. */
489 old_flags = fcntl(sockfd, F_GETFL, 0);
490 if (set_blocking(sockfd, true) == -1) {
491 return (ssize_t)-1;
493 ret = SMB_VFS_RECVFILE(sockfd,
494 fsp,
495 offset + total,
496 N - total);
497 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
498 return (ssize_t)-1;
500 if (ret == -1) {
501 return (ssize_t)-1;
503 total += ret;
504 return (ssize_t)total;
506 /* Any other error case. */
507 if (ret == -1) {
508 return ret;
510 total += ret;
512 return (ssize_t)total;
515 while (total < N) {
516 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
517 offset + total);
519 if (ret == -1)
520 return -1;
521 if (ret == 0)
522 return total;
524 total += ret;
526 return (ssize_t)total;
528 /****************************************************************************
529 An allocate file space call using the vfs interface.
530 Allocates space for a file from a filedescriptor.
531 Returns 0 on success, -1 on failure.
532 ****************************************************************************/
534 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
536 int ret;
537 connection_struct *conn = fsp->conn;
538 uint64_t space_avail;
539 uint64_t bsize,dfree,dsize;
540 NTSTATUS status;
541 bool ok;
544 * Actually try and commit the space on disk....
547 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
548 fsp_str_dbg(fsp), (double)len));
550 ok = vfs_valid_pwrite_range((off_t)len, 0);
551 if (!ok) {
552 DEBUG(0,("vfs_allocate_file_space: %s negative/invalid len "
553 "requested.\n", fsp_str_dbg(fsp)));
554 errno = EINVAL;
555 return -1;
558 status = vfs_stat_fsp(fsp);
559 if (!NT_STATUS_IS_OK(status)) {
560 return -1;
563 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
564 return 0;
566 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
567 /* Shrink - use ftruncate. */
569 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
570 "size %.0f\n", fsp_str_dbg(fsp),
571 (double)fsp->fsp_name->st.st_ex_size));
573 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
575 ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
577 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
579 return ret;
582 /* Grow - we need to test if we have enough space. */
584 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
586 if (lp_strict_allocate(SNUM(fsp->conn))) {
587 /* See if we have a syscall that will allocate beyond
588 end-of-file without changing EOF. */
589 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
590 0, len);
591 } else {
592 ret = 0;
595 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
597 if (ret == 0) {
598 /* We changed the allocation size on disk, but not
599 EOF - exactly as required. We're done ! */
600 return 0;
603 if (ret == -1 && errno == ENOSPC) {
604 return -1;
607 len -= fsp->fsp_name->st.st_ex_size;
608 len /= 1024; /* Len is now number of 1k blocks needed. */
609 space_avail =
610 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
611 if (space_avail == (uint64_t)-1) {
612 return -1;
615 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
616 "needed blocks = %.0f, space avail = %.0f\n",
617 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
618 (double)space_avail));
620 if (len > space_avail) {
621 errno = ENOSPC;
622 return -1;
625 return 0;
628 /****************************************************************************
629 A vfs set_filelen call.
630 set the length of a file from a filedescriptor.
631 Returns 0 on success, -1 on failure.
632 ****************************************************************************/
634 int vfs_set_filelen(files_struct *fsp, off_t len)
636 int ret;
637 bool ok;
639 ok = vfs_valid_pwrite_range(len, 0);
640 if (!ok) {
641 errno = EINVAL;
642 return -1;
645 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
647 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
648 fsp_str_dbg(fsp), (double)len));
649 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
650 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
651 FILE_NOTIFY_CHANGE_SIZE
652 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
653 fsp->fsp_name->base_name);
656 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
658 return ret;
661 /****************************************************************************
662 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
663 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
664 as this is also called from the default SMB_VFS_FTRUNCATE code.
665 Always extends the file size.
666 Returns 0 on success, -1 on failure.
667 ****************************************************************************/
669 #define SPARSE_BUF_WRITE_SIZE (32*1024)
671 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
673 ssize_t pwrite_ret;
674 size_t total = 0;
675 bool ok;
677 ok = vfs_valid_pwrite_range(offset, len);
678 if (!ok) {
679 errno = EINVAL;
680 return -1;
683 if (!sparse_buf) {
684 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
685 if (!sparse_buf) {
686 errno = ENOMEM;
687 return -1;
691 while (total < len) {
692 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
694 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
695 if (pwrite_ret == -1) {
696 int saved_errno = errno;
697 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
698 "%s failed with error %s\n",
699 fsp_str_dbg(fsp), strerror(saved_errno)));
700 errno = saved_errno;
701 return -1;
703 total += pwrite_ret;
706 return 0;
709 /****************************************************************************
710 A vfs fill sparse call.
711 Writes zeros from the end of file to len, if len is greater than EOF.
712 Used only by strict_sync.
713 Returns 0 on success, -1 on failure.
714 ****************************************************************************/
716 int vfs_fill_sparse(files_struct *fsp, off_t len)
718 int ret;
719 NTSTATUS status;
720 off_t offset;
721 size_t num_to_write;
722 bool ok;
724 ok = vfs_valid_pwrite_range(len, 0);
725 if (!ok) {
726 errno = EINVAL;
727 return -1;
730 status = vfs_stat_fsp(fsp);
731 if (!NT_STATUS_IS_OK(status)) {
732 return -1;
735 if (len <= fsp->fsp_name->st.st_ex_size) {
736 return 0;
739 #ifdef S_ISFIFO
740 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
741 return 0;
743 #endif
745 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
746 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
747 (double)fsp->fsp_name->st.st_ex_size, (double)len,
748 (double)(len - fsp->fsp_name->st.st_ex_size)));
750 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
752 offset = fsp->fsp_name->st.st_ex_size;
753 num_to_write = len - fsp->fsp_name->st.st_ex_size;
755 /* Only do this on non-stream file handles. */
756 if (fsp->base_fsp == NULL) {
757 /* for allocation try fallocate first. This can fail on some
758 * platforms e.g. when the filesystem doesn't support it and no
759 * emulation is being done by the libc (like on AIX with JFS1). In that
760 * case we do our own emulation. fallocate implementations can
761 * return ENOTSUP or EINVAL in cases like that. */
762 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
763 if (ret == -1 && errno == ENOSPC) {
764 goto out;
766 if (ret == 0) {
767 goto out;
769 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
770 "error %d. Falling back to slow manual allocation\n", ret));
773 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
775 out:
777 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
778 return ret;
781 /*******************************************************************************
782 Set a fd into blocking/nonblocking mode through VFS
783 *******************************************************************************/
785 int vfs_set_blocking(files_struct *fsp, bool set)
787 int val;
788 #ifdef O_NONBLOCK
789 #define FLAG_TO_SET O_NONBLOCK
790 #else
791 #ifdef SYSV
792 #define FLAG_TO_SET O_NDELAY
793 #else /* BSD */
794 #define FLAG_TO_SET FNDELAY
795 #endif
796 #endif
797 val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
798 if (val == -1) {
799 return -1;
802 if (set) {
803 val &= ~FLAG_TO_SET;
804 } else {
805 val |= FLAG_TO_SET;
808 return SMB_VFS_FCNTL(fsp, F_SETFL, val);
809 #undef FLAG_TO_SET
812 /****************************************************************************
813 Transfer some data (n bytes) between two file_struct's.
814 ****************************************************************************/
816 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
818 struct files_struct *fsp = (struct files_struct *)file;
820 return SMB_VFS_PREAD(fsp, buf, len, offset);
823 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
825 struct files_struct *fsp = (struct files_struct *)file;
827 return SMB_VFS_PWRITE(fsp, buf, len, offset);
830 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
832 return transfer_file_internal((void *)in, (void *)out, n,
833 vfs_pread_fn, vfs_pwrite_fn);
836 /*******************************************************************
837 A vfs_readdir wrapper which just returns the file name.
838 ********************************************************************/
840 const char *vfs_readdirname(connection_struct *conn, void *p,
841 SMB_STRUCT_STAT *sbuf, char **talloced)
843 struct dirent *ptr= NULL;
844 const char *dname;
845 char *translated;
846 NTSTATUS status;
848 if (!p)
849 return(NULL);
851 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
852 if (!ptr)
853 return(NULL);
855 dname = ptr->d_name;
858 #ifdef NEXT2
859 if (telldir(p) < 0)
860 return(NULL);
861 #endif
863 #ifdef HAVE_BROKEN_READDIR_NAME
864 /* using /usr/ucb/cc is BAD */
865 dname = dname - 2;
866 #endif
868 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
869 talloc_tos(), &translated);
870 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
871 *talloced = NULL;
872 return dname;
874 *talloced = translated;
875 if (!NT_STATUS_IS_OK(status)) {
876 return NULL;
878 return translated;
881 /*******************************************************************
882 A wrapper for vfs_chdir().
883 ********************************************************************/
885 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
887 int ret;
888 struct smb_filename *cwd = NULL;
890 if (!LastDir) {
891 LastDir = SMB_STRDUP("");
894 if (ISDOT(smb_fname->base_name)) {
895 return 0;
898 if (*smb_fname->base_name == '/' &&
899 strcsequal(LastDir,smb_fname->base_name)) {
900 return 0;
903 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
905 ret = SMB_VFS_CHDIR(conn, smb_fname);
906 if (ret != 0) {
907 return -1;
911 * Always replace conn->cwd_fsp. We
912 * don't know if it's been modified by
913 * VFS modules in the stack.
916 /* conn cache. */
917 cwd = vfs_GetWd(conn, conn);
918 if (cwd == NULL) {
920 * vfs_GetWd() failed.
921 * We must be able to read cwd.
922 * Return to original directory
923 * and return -1.
925 int saved_errno = errno;
927 if (conn->cwd_fsp->fsp_name == NULL) {
929 * Failed on the very first chdir()+getwd()
930 * for this connection. We can't
931 * continue.
933 smb_panic("conn->cwd getwd failed\n");
934 /* NOTREACHED */
935 return -1;
938 /* Return to the previous $cwd. */
939 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
940 if (ret != 0) {
941 smb_panic("conn->cwd getwd failed\n");
942 /* NOTREACHED */
943 return -1;
945 errno = saved_errno;
946 /* And fail the chdir(). */
947 return -1;
950 /* vfs_GetWd() succeeded. */
951 /* Replace global cache. */
952 SAFE_FREE(LastDir);
953 LastDir = SMB_STRDUP(smb_fname->base_name);
956 * (Indirect) Callers of vfs_ChDir() may still hold references to the
957 * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
958 * callers can use it for the lifetime of the SMB request.
960 talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
962 conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
963 conn->cwd_fsp->fh->fd = AT_FDCWD;
965 DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
967 return ret;
970 /*******************************************************************
971 Return the absolute current directory path - given a UNIX pathname.
972 Note that this path is returned in DOS format, not UNIX
973 format. Note this can be called with conn == NULL.
974 ********************************************************************/
976 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
978 struct smb_filename *current_dir_fname = NULL;
979 struct file_id key;
980 struct smb_filename *smb_fname_dot = NULL;
981 struct smb_filename *smb_fname_full = NULL;
982 struct smb_filename *result = NULL;
984 if (!lp_getwd_cache()) {
985 goto nocache;
988 smb_fname_dot = synthetic_smb_fname(ctx,
989 ".",
990 NULL,
991 NULL,
994 if (smb_fname_dot == NULL) {
995 errno = ENOMEM;
996 goto out;
999 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
1001 * Known to fail for root: the directory may be NFS-mounted
1002 * and exported with root_squash (so has no root access).
1004 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
1005 "(NFS problem ?)\n", strerror(errno) ));
1006 goto nocache;
1009 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1011 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
1012 smbd_memcache(),
1013 GETWD_CACHE,
1014 data_blob_const(&key, sizeof(key)));
1016 if (smb_fname_full == NULL) {
1017 goto nocache;
1020 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
1021 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
1022 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
1023 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
1025 * Ok, we're done
1026 * Note: smb_fname_full is owned by smbd_memcache()
1027 * so we must make a copy to return.
1029 result = cp_smb_filename(ctx, smb_fname_full);
1030 if (result == NULL) {
1031 errno = ENOMEM;
1033 goto out;
1036 nocache:
1039 * We don't have the information to hand so rely on traditional
1040 * methods. The very slow getcwd, which spawns a process on some
1041 * systems, or the not quite so bad getwd.
1044 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
1045 if (current_dir_fname == NULL) {
1046 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
1047 strerror(errno)));
1048 goto out;
1051 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
1052 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1055 * smbd_memcache() will own current_dir_fname after the
1056 * memcache_add_talloc call, so we must make
1057 * a copy on ctx to return.
1059 result = cp_smb_filename(ctx, current_dir_fname);
1060 if (result == NULL) {
1061 errno = ENOMEM;
1065 * Ensure the memory going into the cache
1066 * doesn't have a destructor so it can be
1067 * cleanly freed.
1069 talloc_set_destructor(current_dir_fname, NULL);
1071 memcache_add_talloc(smbd_memcache(),
1072 GETWD_CACHE,
1073 data_blob_const(&key, sizeof(key)),
1074 &current_dir_fname);
1075 /* current_dir_fname is now == NULL here. */
1076 } else {
1077 /* current_dir_fname is already allocated on ctx. */
1078 result = current_dir_fname;
1081 out:
1082 TALLOC_FREE(smb_fname_dot);
1084 * Don't free current_dir_fname here. It's either been moved
1085 * to the memcache or is being returned in result.
1087 return result;
1090 /*******************************************************************
1091 Reduce a file name, removing .. elements and checking that
1092 it is below dir in the hierarchy. This uses realpath.
1093 This function must run as root, and will return names
1094 and valid stat structs that can be checked on open.
1095 ********************************************************************/
1097 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1098 const struct smb_filename *smb_fname,
1099 struct smb_request *smbreq)
1101 NTSTATUS status;
1102 TALLOC_CTX *ctx = talloc_tos();
1103 const char *conn_rootdir;
1104 size_t rootdir_len;
1105 char *resolved_name = NULL;
1106 struct smb_filename *resolved_fname = NULL;
1107 struct smb_filename *saved_dir_fname = NULL;
1108 struct smb_filename *smb_fname_cwd = NULL;
1109 int ret;
1110 struct smb_filename *parent_name = NULL;
1111 struct smb_filename *file_name = NULL;
1112 bool ok;
1114 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1115 smb_fname->base_name,
1116 conn->connectpath));
1119 ok = parent_smb_fname(ctx,
1120 smb_fname,
1121 &parent_name,
1122 &file_name);
1123 if (!ok) {
1124 status = NT_STATUS_NO_MEMORY;
1125 goto err;
1128 if (SMB_VFS_STAT(conn, parent_name) != 0) {
1129 status = map_nt_error_from_unix(errno);
1130 goto err;
1132 /* Remember where we were. */
1133 saved_dir_fname = vfs_GetWd(ctx, conn);
1134 if (!saved_dir_fname) {
1135 status = map_nt_error_from_unix(errno);
1136 goto err;
1139 if (vfs_ChDir(conn, parent_name) == -1) {
1140 status = map_nt_error_from_unix(errno);
1141 goto err;
1144 smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
1145 ".",
1146 NULL,
1147 NULL,
1148 parent_name->twrp,
1150 if (smb_fname_cwd == NULL) {
1151 status = NT_STATUS_NO_MEMORY;
1152 goto err;
1155 /* Get the absolute path of the parent directory. */
1156 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1157 if (resolved_fname == NULL) {
1158 status = map_nt_error_from_unix(errno);
1159 goto err;
1161 resolved_name = resolved_fname->base_name;
1163 if (*resolved_name != '/') {
1164 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1165 "doesn't return absolute paths !\n"));
1166 status = NT_STATUS_OBJECT_NAME_INVALID;
1167 goto err;
1170 DBG_DEBUG("realpath [%s] -> [%s]\n",
1171 smb_fname_str_dbg(parent_name),
1172 resolved_name);
1174 /* Now check the stat value is the same. */
1175 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1176 status = map_nt_error_from_unix(errno);
1177 goto err;
1180 /* Ensure we're pointing at the same place. */
1181 if (!check_same_stat(&smb_fname_cwd->st, &parent_name->st)) {
1182 DBG_ERR("device/inode/uid/gid on directory %s changed. "
1183 "Denying access !\n",
1184 smb_fname_str_dbg(parent_name));
1185 status = NT_STATUS_ACCESS_DENIED;
1186 goto err;
1189 /* Ensure we're below the connect path. */
1191 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1192 if (conn_rootdir == NULL) {
1193 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1194 "conn_rootdir\n"));
1195 status = NT_STATUS_ACCESS_DENIED;
1196 goto err;
1199 rootdir_len = strlen(conn_rootdir);
1202 * In the case of rootdir_len == 1, we know that conn_rootdir is
1203 * "/", and we also know that resolved_name starts with a slash.
1204 * So, in this corner case, resolved_name is automatically a
1205 * sub-directory of the conn_rootdir. Thus we can skip the string
1206 * comparison and the next character checks (which are even
1207 * wrong in this case).
1209 if (rootdir_len != 1) {
1210 bool matched;
1212 matched = (strncmp(conn_rootdir, resolved_name,
1213 rootdir_len) == 0);
1215 if (!matched || (resolved_name[rootdir_len] != '/' &&
1216 resolved_name[rootdir_len] != '\0')) {
1217 DBG_WARNING("%s is a symlink outside the "
1218 "share path\n",
1219 smb_fname_str_dbg(parent_name));
1220 DEBUGADD(1, ("conn_rootdir =%s\n", conn_rootdir));
1221 DEBUGADD(1, ("resolved_name=%s\n", resolved_name));
1222 status = NT_STATUS_ACCESS_DENIED;
1223 goto err;
1227 /* Now ensure that the last component either doesn't
1228 exist, or is *NOT* a symlink. */
1230 ret = SMB_VFS_LSTAT(conn, file_name);
1231 if (ret == -1) {
1232 /* Errno must be ENOENT for this be ok. */
1233 if (errno != ENOENT) {
1234 status = map_nt_error_from_unix(errno);
1235 DBG_WARNING("LSTAT on %s failed with %s\n",
1236 smb_fname_str_dbg(file_name),
1237 nt_errstr(status));
1238 goto err;
1242 if (VALID_STAT(file_name->st) &&
1243 S_ISLNK(file_name->st.st_ex_mode))
1245 DBG_WARNING("Last component %s is a symlink. Denying"
1246 "access.\n",
1247 smb_fname_str_dbg(file_name));
1248 status = NT_STATUS_ACCESS_DENIED;
1249 goto err;
1252 status = NT_STATUS_OK;
1254 err:
1256 if (saved_dir_fname != NULL) {
1257 vfs_ChDir(conn, saved_dir_fname);
1258 TALLOC_FREE(saved_dir_fname);
1260 TALLOC_FREE(resolved_fname);
1261 TALLOC_FREE(parent_name);
1262 return status;
1265 /*******************************************************************
1266 Reduce a file name, removing .. elements and checking that
1267 it is below dir in the hierarchy. This uses realpath.
1269 If cwd_name == NULL then fname is a client given path relative
1270 to the root path of the share.
1272 If cwd_name != NULL then fname is a client given path relative
1273 to cwd_name. cwd_name is relative to the root path of the share.
1274 ********************************************************************/
1276 NTSTATUS check_reduced_name(connection_struct *conn,
1277 const struct smb_filename *cwd_fname,
1278 const struct smb_filename *smb_fname)
1280 TALLOC_CTX *ctx = talloc_tos();
1281 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1282 const char *fname = smb_fname->base_name;
1283 struct smb_filename *resolved_fname;
1284 char *resolved_name = NULL;
1285 char *new_fname = NULL;
1286 bool allow_symlinks = true;
1287 const char *conn_rootdir;
1288 size_t rootdir_len;
1289 bool ok;
1291 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1293 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1295 if (resolved_fname == NULL) {
1296 switch (errno) {
1297 case ENOTDIR:
1298 DEBUG(3,("check_reduced_name: Component not a "
1299 "directory in getting realpath for "
1300 "%s\n", fname));
1301 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1302 case ENOENT:
1304 struct smb_filename *dir_fname = NULL;
1305 struct smb_filename *last_component = NULL;
1307 /* Last component didn't exist.
1308 Remove it and try and canonicalise
1309 the directory name. */
1311 ok = parent_smb_fname(ctx,
1312 smb_fname,
1313 &dir_fname,
1314 &last_component);
1315 if (!ok) {
1316 return NT_STATUS_NO_MEMORY;
1319 resolved_fname = SMB_VFS_REALPATH(conn,
1320 ctx,
1321 dir_fname);
1322 if (resolved_fname == NULL) {
1323 NTSTATUS status = map_nt_error_from_unix(errno);
1325 if (errno == ENOENT || errno == ENOTDIR) {
1326 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1329 DEBUG(3,("check_reduce_name: "
1330 "couldn't get realpath for "
1331 "%s (%s)\n",
1332 smb_fname_str_dbg(dir_fname),
1333 nt_errstr(status)));
1334 return status;
1336 resolved_name = talloc_asprintf(ctx,
1337 "%s/%s",
1338 resolved_fname->base_name,
1339 last_component->base_name);
1340 if (resolved_name == NULL) {
1341 return NT_STATUS_NO_MEMORY;
1343 break;
1345 default:
1346 DEBUG(3,("check_reduced_name: couldn't get "
1347 "realpath for %s\n", fname));
1348 return map_nt_error_from_unix(errno);
1350 } else {
1351 resolved_name = resolved_fname->base_name;
1354 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1355 resolved_name));
1357 if (*resolved_name != '/') {
1358 DEBUG(0,("check_reduced_name: realpath doesn't return "
1359 "absolute paths !\n"));
1360 TALLOC_FREE(resolved_fname);
1361 return NT_STATUS_OBJECT_NAME_INVALID;
1364 /* Common widelinks and symlinks checks. */
1365 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1366 if (conn_rootdir == NULL) {
1367 DBG_NOTICE("Could not get conn_rootdir\n");
1368 TALLOC_FREE(resolved_fname);
1369 return NT_STATUS_ACCESS_DENIED;
1372 rootdir_len = strlen(conn_rootdir);
1375 * In the case of rootdir_len == 1, we know that
1376 * conn_rootdir is "/", and we also know that
1377 * resolved_name starts with a slash. So, in this
1378 * corner case, resolved_name is automatically a
1379 * sub-directory of the conn_rootdir. Thus we can skip
1380 * the string comparison and the next character checks
1381 * (which are even wrong in this case).
1383 if (rootdir_len != 1) {
1384 bool matched;
1386 matched = (strncmp(conn_rootdir, resolved_name,
1387 rootdir_len) == 0);
1388 if (!matched || (resolved_name[rootdir_len] != '/' &&
1389 resolved_name[rootdir_len] != '\0')) {
1390 DBG_NOTICE("Bad access attempt: %s is a symlink "
1391 "outside the "
1392 "share path\n"
1393 "conn_rootdir =%s\n"
1394 "resolved_name=%s\n",
1395 fname,
1396 conn_rootdir,
1397 resolved_name);
1398 TALLOC_FREE(resolved_fname);
1399 return NT_STATUS_ACCESS_DENIED;
1403 /* Extra checks if all symlinks are disallowed. */
1404 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1405 if (!allow_symlinks) {
1406 /* fname can't have changed in resolved_path. */
1407 const char *p = &resolved_name[rootdir_len];
1410 * UNIX filesystem semantics, names consisting
1411 * only of "." or ".." CANNOT be symlinks.
1413 if (ISDOT(fname) || ISDOTDOT(fname)) {
1414 goto out;
1417 if (*p != '/') {
1418 DBG_NOTICE("logic error (%c) "
1419 "in resolved_name: %s\n",
1421 fname);
1422 TALLOC_FREE(resolved_fname);
1423 return NT_STATUS_ACCESS_DENIED;
1426 p++;
1429 * If cwd_name is present and not ".",
1430 * then fname is relative to that, not
1431 * the root of the share. Make sure the
1432 * path we check is the one the client
1433 * sent (cwd_name+fname).
1435 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1436 new_fname = talloc_asprintf(ctx,
1437 "%s/%s",
1438 cwd_name,
1439 fname);
1440 if (new_fname == NULL) {
1441 TALLOC_FREE(resolved_fname);
1442 return NT_STATUS_NO_MEMORY;
1444 fname = new_fname;
1447 if (strcmp(fname, p)!=0) {
1448 DBG_NOTICE("Bad access "
1449 "attempt: %s is a symlink to %s\n",
1450 fname,
1452 TALLOC_FREE(resolved_fname);
1453 TALLOC_FREE(new_fname);
1454 return NT_STATUS_ACCESS_DENIED;
1458 out:
1460 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1461 TALLOC_FREE(resolved_fname);
1462 TALLOC_FREE(new_fname);
1463 return NT_STATUS_OK;
1467 * XXX: This is temporary and there should be no callers of this once
1468 * smb_filename is plumbed through all path based operations.
1470 * Called when we know stream name parsing has already been done.
1472 int vfs_stat_smb_basename(struct connection_struct *conn,
1473 const struct smb_filename *smb_fname_in,
1474 SMB_STRUCT_STAT *psbuf)
1476 struct smb_filename smb_fname = {
1477 .base_name = discard_const_p(char, smb_fname_in->base_name),
1478 .flags = smb_fname_in->flags,
1479 .twrp = smb_fname_in->twrp,
1481 int ret;
1483 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1484 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1485 } else {
1486 ret = SMB_VFS_STAT(conn, &smb_fname);
1489 if (ret != -1) {
1490 *psbuf = smb_fname.st;
1492 return ret;
1496 * Ensure LSTAT is called for POSIX paths.
1499 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1501 int ret;
1502 struct stat_ex saved_stat = fsp->fsp_name->st;
1504 if(fsp->fh->fd == -1) {
1505 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1506 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1507 } else {
1508 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1510 } else {
1511 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1513 if (ret == -1) {
1514 return map_nt_error_from_unix(errno);
1516 update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat);
1517 return NT_STATUS_OK;
1520 void init_smb_file_time(struct smb_file_time *ft)
1522 *ft = (struct smb_file_time) {
1523 .atime = make_omit_timespec(),
1524 .ctime = make_omit_timespec(),
1525 .mtime = make_omit_timespec(),
1526 .create_time = make_omit_timespec()
1531 * Initialize num_streams and streams, then call VFS op streaminfo
1533 NTSTATUS vfs_streaminfo(connection_struct *conn,
1534 struct files_struct *fsp,
1535 const struct smb_filename *smb_fname,
1536 TALLOC_CTX *mem_ctx,
1537 unsigned int *num_streams,
1538 struct stream_struct **streams)
1540 *num_streams = 0;
1541 *streams = NULL;
1542 return SMB_VFS_STREAMINFO(conn,
1543 fsp,
1544 smb_fname,
1545 mem_ctx,
1546 num_streams,
1547 streams);
1551 generate a file_id from a stat structure
1553 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1555 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1558 NTSTATUS vfs_at_fspcwd(TALLOC_CTX *mem_ctx,
1559 struct connection_struct *conn,
1560 struct files_struct **_fsp)
1562 struct files_struct *fsp = NULL;
1564 fsp = talloc_zero(mem_ctx, struct files_struct);
1565 if (fsp == NULL) {
1566 return NT_STATUS_NO_MEMORY;
1569 fsp->fsp_name = synthetic_smb_fname(fsp, ".", NULL, NULL, 0, 0);
1570 if (fsp->fsp_name == NULL) {
1571 TALLOC_FREE(fsp);
1572 return NT_STATUS_NO_MEMORY;
1575 fsp->fh = talloc_zero(fsp, struct fd_handle);
1576 if (fsp->fh == NULL) {
1577 TALLOC_FREE(fsp);
1578 return NT_STATUS_NO_MEMORY;
1581 fsp->fh->fd = AT_FDCWD;
1582 fsp->fnum = FNUM_FIELD_INVALID;
1583 fsp->conn = conn;
1585 *_fsp = fsp;
1586 return NT_STATUS_OK;
1589 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1590 const char *service, const char *user)
1592 VFS_FIND(connect);
1593 return handle->fns->connect_fn(handle, service, user);
1596 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1598 VFS_FIND(disconnect);
1599 handle->fns->disconnect_fn(handle);
1602 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1603 const struct smb_filename *smb_fname,
1604 uint64_t *bsize,
1605 uint64_t *dfree,
1606 uint64_t *dsize)
1608 VFS_FIND(disk_free);
1609 return handle->fns->disk_free_fn(handle, smb_fname,
1610 bsize, dfree, dsize);
1613 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1614 const struct smb_filename *smb_fname,
1615 enum SMB_QUOTA_TYPE qtype,
1616 unid_t id,
1617 SMB_DISK_QUOTA *qt)
1619 VFS_FIND(get_quota);
1620 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1623 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1624 enum SMB_QUOTA_TYPE qtype, unid_t id,
1625 SMB_DISK_QUOTA *qt)
1627 VFS_FIND(set_quota);
1628 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1631 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1632 struct files_struct *fsp,
1633 struct shadow_copy_data *shadow_copy_data,
1634 bool labels)
1636 VFS_FIND(get_shadow_copy_data);
1637 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1638 shadow_copy_data,
1639 labels);
1641 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1642 const struct smb_filename *smb_fname,
1643 struct vfs_statvfs_struct *statbuf)
1645 VFS_FIND(statvfs);
1646 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1649 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1650 enum timestamp_set_resolution *p_ts_res)
1652 VFS_FIND(fs_capabilities);
1653 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1656 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1657 struct dfs_GetDFSReferral *r)
1659 VFS_FIND(get_dfs_referrals);
1660 return handle->fns->get_dfs_referrals_fn(handle, r);
1663 NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
1664 struct files_struct *dirfsp,
1665 const struct smb_filename *smb_fname,
1666 const struct referral *reflist,
1667 size_t referral_count)
1669 VFS_FIND(create_dfs_pathat);
1670 return handle->fns->create_dfs_pathat_fn(handle,
1671 dirfsp,
1672 smb_fname,
1673 reflist,
1674 referral_count);
1677 NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
1678 TALLOC_CTX *mem_ctx,
1679 struct files_struct *dirfsp,
1680 const struct smb_filename *smb_fname,
1681 struct referral **ppreflist,
1682 size_t *preferral_count)
1684 VFS_FIND(read_dfs_pathat);
1685 return handle->fns->read_dfs_pathat_fn(handle,
1686 mem_ctx,
1687 dirfsp,
1688 smb_fname,
1689 ppreflist,
1690 preferral_count);
1693 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1694 struct files_struct *fsp,
1695 const char *mask,
1696 uint32_t attributes)
1698 VFS_FIND(fdopendir);
1699 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1702 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1703 DIR *dirp,
1704 SMB_STRUCT_STAT *sbuf)
1706 VFS_FIND(readdir);
1707 return handle->fns->readdir_fn(handle, dirp, sbuf);
1710 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1711 DIR *dirp, long offset)
1713 VFS_FIND(seekdir);
1714 handle->fns->seekdir_fn(handle, dirp, offset);
1717 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1718 DIR *dirp)
1720 VFS_FIND(telldir);
1721 return handle->fns->telldir_fn(handle, dirp);
1724 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1725 DIR *dirp)
1727 VFS_FIND(rewind_dir);
1728 handle->fns->rewind_dir_fn(handle, dirp);
1731 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1732 struct files_struct *dirfsp,
1733 const struct smb_filename *smb_fname,
1734 mode_t mode)
1736 VFS_FIND(mkdirat);
1737 return handle->fns->mkdirat_fn(handle,
1738 dirfsp,
1739 smb_fname,
1740 mode);
1743 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1744 DIR *dir)
1746 VFS_FIND(closedir);
1747 return handle->fns->closedir_fn(handle, dir);
1750 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1751 struct smb_filename *smb_fname, struct files_struct *fsp,
1752 int flags, mode_t mode)
1754 VFS_FIND(open);
1755 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1758 int smb_vfs_call_openat(struct vfs_handle_struct *handle,
1759 const struct files_struct *dirfsp,
1760 const struct smb_filename *smb_fname,
1761 struct files_struct *fsp,
1762 int flags,
1763 mode_t mode)
1765 VFS_FIND(openat);
1766 return handle->fns->openat_fn(handle,
1767 dirfsp,
1768 smb_fname,
1769 fsp,
1770 flags,
1771 mode);
1774 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1775 struct smb_request *req,
1776 struct files_struct **dirfsp,
1777 struct smb_filename *smb_fname,
1778 uint32_t access_mask,
1779 uint32_t share_access,
1780 uint32_t create_disposition,
1781 uint32_t create_options,
1782 uint32_t file_attributes,
1783 uint32_t oplock_request,
1784 const struct smb2_lease *lease,
1785 uint64_t allocation_size,
1786 uint32_t private_flags,
1787 struct security_descriptor *sd,
1788 struct ea_list *ea_list,
1789 files_struct **result,
1790 int *pinfo,
1791 const struct smb2_create_blobs *in_context_blobs,
1792 struct smb2_create_blobs *out_context_blobs)
1794 VFS_FIND(create_file);
1795 return handle->fns->create_file_fn(
1796 handle, req, dirfsp, smb_fname,
1797 access_mask, share_access, create_disposition, create_options,
1798 file_attributes, oplock_request, lease, allocation_size,
1799 private_flags, sd, ea_list,
1800 result, pinfo, in_context_blobs, out_context_blobs);
1803 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1804 struct files_struct *fsp)
1806 VFS_FIND(close);
1807 return handle->fns->close_fn(handle, fsp);
1810 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1811 struct files_struct *fsp, void *data, size_t n,
1812 off_t offset)
1814 VFS_FIND(pread);
1815 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1818 struct smb_vfs_call_pread_state {
1819 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1820 ssize_t retval;
1821 struct vfs_aio_state vfs_aio_state;
1824 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1826 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1827 TALLOC_CTX *mem_ctx,
1828 struct tevent_context *ev,
1829 struct files_struct *fsp,
1830 void *data,
1831 size_t n, off_t offset)
1833 struct tevent_req *req, *subreq;
1834 struct smb_vfs_call_pread_state *state;
1836 req = tevent_req_create(mem_ctx, &state,
1837 struct smb_vfs_call_pread_state);
1838 if (req == NULL) {
1839 return NULL;
1841 VFS_FIND(pread_send);
1842 state->recv_fn = handle->fns->pread_recv_fn;
1844 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1845 offset);
1846 if (tevent_req_nomem(subreq, req)) {
1847 return tevent_req_post(req, ev);
1849 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1850 return req;
1853 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1855 struct tevent_req *req = tevent_req_callback_data(
1856 subreq, struct tevent_req);
1857 struct smb_vfs_call_pread_state *state = tevent_req_data(
1858 req, struct smb_vfs_call_pread_state);
1860 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1861 TALLOC_FREE(subreq);
1862 if (state->retval == -1) {
1863 tevent_req_error(req, state->vfs_aio_state.error);
1864 return;
1866 tevent_req_done(req);
1869 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1870 struct vfs_aio_state *vfs_aio_state)
1872 struct smb_vfs_call_pread_state *state = tevent_req_data(
1873 req, struct smb_vfs_call_pread_state);
1874 ssize_t retval;
1876 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1877 tevent_req_received(req);
1878 return -1;
1880 *vfs_aio_state = state->vfs_aio_state;
1881 retval = state->retval;
1882 tevent_req_received(req);
1883 return retval;
1886 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1887 struct files_struct *fsp, const void *data,
1888 size_t n, off_t offset)
1890 VFS_FIND(pwrite);
1891 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1894 struct smb_vfs_call_pwrite_state {
1895 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1896 ssize_t retval;
1897 struct vfs_aio_state vfs_aio_state;
1900 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1902 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1903 TALLOC_CTX *mem_ctx,
1904 struct tevent_context *ev,
1905 struct files_struct *fsp,
1906 const void *data,
1907 size_t n, off_t offset)
1909 struct tevent_req *req, *subreq;
1910 struct smb_vfs_call_pwrite_state *state;
1912 req = tevent_req_create(mem_ctx, &state,
1913 struct smb_vfs_call_pwrite_state);
1914 if (req == NULL) {
1915 return NULL;
1917 VFS_FIND(pwrite_send);
1918 state->recv_fn = handle->fns->pwrite_recv_fn;
1920 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1921 offset);
1922 if (tevent_req_nomem(subreq, req)) {
1923 return tevent_req_post(req, ev);
1925 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1926 return req;
1929 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1931 struct tevent_req *req = tevent_req_callback_data(
1932 subreq, struct tevent_req);
1933 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1934 req, struct smb_vfs_call_pwrite_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 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1946 struct vfs_aio_state *vfs_aio_state)
1948 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1949 req, struct smb_vfs_call_pwrite_state);
1950 ssize_t retval;
1952 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1953 tevent_req_received(req);
1954 return -1;
1956 *vfs_aio_state = state->vfs_aio_state;
1957 retval = state->retval;
1958 tevent_req_received(req);
1959 return retval;
1962 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1963 struct files_struct *fsp, off_t offset,
1964 int whence)
1966 VFS_FIND(lseek);
1967 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1970 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1971 files_struct *fromfsp, const DATA_BLOB *header,
1972 off_t offset, size_t count)
1974 VFS_FIND(sendfile);
1975 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1976 count);
1979 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1980 files_struct *tofsp, off_t offset,
1981 size_t count)
1983 VFS_FIND(recvfile);
1984 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1987 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
1988 files_struct *srcfsp,
1989 const struct smb_filename *smb_fname_src,
1990 files_struct *dstfsp,
1991 const struct smb_filename *smb_fname_dst)
1993 VFS_FIND(renameat);
1994 return handle->fns->renameat_fn(handle,
1995 srcfsp,
1996 smb_fname_src,
1997 dstfsp,
1998 smb_fname_dst);
2001 struct smb_vfs_call_fsync_state {
2002 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
2003 int retval;
2004 struct vfs_aio_state vfs_aio_state;
2007 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
2009 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
2010 TALLOC_CTX *mem_ctx,
2011 struct tevent_context *ev,
2012 struct files_struct *fsp)
2014 struct tevent_req *req, *subreq;
2015 struct smb_vfs_call_fsync_state *state;
2017 req = tevent_req_create(mem_ctx, &state,
2018 struct smb_vfs_call_fsync_state);
2019 if (req == NULL) {
2020 return NULL;
2022 VFS_FIND(fsync_send);
2023 state->recv_fn = handle->fns->fsync_recv_fn;
2025 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
2026 if (tevent_req_nomem(subreq, req)) {
2027 return tevent_req_post(req, ev);
2029 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
2030 return req;
2033 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
2035 struct tevent_req *req = tevent_req_callback_data(
2036 subreq, struct tevent_req);
2037 struct smb_vfs_call_fsync_state *state = tevent_req_data(
2038 req, struct smb_vfs_call_fsync_state);
2040 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2041 TALLOC_FREE(subreq);
2042 if (state->retval == -1) {
2043 tevent_req_error(req, state->vfs_aio_state.error);
2044 return;
2046 tevent_req_done(req);
2049 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
2051 struct smb_vfs_call_fsync_state *state = tevent_req_data(
2052 req, struct smb_vfs_call_fsync_state);
2053 ssize_t retval;
2055 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2056 tevent_req_received(req);
2057 return -1;
2059 *vfs_aio_state = state->vfs_aio_state;
2060 retval = state->retval;
2061 tevent_req_received(req);
2062 return retval;
2066 * Synchronous version of fsync, built from backend
2067 * async VFS primitives. Uses a temporary sub-event
2068 * context (NOT NESTED).
2071 int smb_vfs_fsync_sync(files_struct *fsp)
2073 TALLOC_CTX *frame = talloc_stackframe();
2074 struct tevent_req *req = NULL;
2075 struct vfs_aio_state aio_state = { 0 };
2076 int ret = -1;
2077 bool ok;
2078 struct tevent_context *ev = samba_tevent_context_init(frame);
2080 if (ev == NULL) {
2081 goto out;
2084 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
2085 if (req == NULL) {
2086 goto out;
2089 ok = tevent_req_poll(req, ev);
2090 if (!ok) {
2091 goto out;
2094 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
2096 out:
2098 TALLOC_FREE(frame);
2099 if (aio_state.error != 0) {
2100 errno = aio_state.error;
2102 return ret;
2105 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
2106 struct smb_filename *smb_fname)
2108 VFS_FIND(stat);
2109 return handle->fns->stat_fn(handle, smb_fname);
2112 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2113 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2115 VFS_FIND(fstat);
2116 return handle->fns->fstat_fn(handle, fsp, sbuf);
2119 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2120 struct smb_filename *smb_filename)
2122 VFS_FIND(lstat);
2123 return handle->fns->lstat_fn(handle, smb_filename);
2126 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2127 struct files_struct *fsp,
2128 const SMB_STRUCT_STAT *sbuf)
2130 VFS_FIND(get_alloc_size);
2131 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2134 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
2135 struct files_struct *dirfsp,
2136 const struct smb_filename *smb_fname,
2137 int flags)
2139 VFS_FIND(unlinkat);
2140 return handle->fns->unlinkat_fn(handle,
2141 dirfsp,
2142 smb_fname,
2143 flags);
2146 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
2147 const struct smb_filename *smb_fname,
2148 mode_t mode)
2150 VFS_FIND(chmod);
2151 return handle->fns->chmod_fn(handle, smb_fname, mode);
2154 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2155 struct files_struct *fsp, mode_t mode)
2157 VFS_FIND(fchmod);
2158 return handle->fns->fchmod_fn(handle, fsp, mode);
2161 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2162 struct files_struct *fsp, uid_t uid, gid_t gid)
2164 VFS_FIND(fchown);
2165 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2168 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2169 const struct smb_filename *smb_fname,
2170 uid_t uid,
2171 gid_t gid)
2173 VFS_FIND(lchown);
2174 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2177 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2178 const struct smb_filename *smb_fname)
2180 VFS_FIND(chdir);
2181 return handle->fns->chdir_fn(handle, smb_fname);
2184 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2185 TALLOC_CTX *ctx)
2187 VFS_FIND(getwd);
2188 return handle->fns->getwd_fn(handle, ctx);
2191 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2192 const struct smb_filename *smb_fname,
2193 struct smb_file_time *ft)
2195 VFS_FIND(ntimes);
2196 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2199 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2200 struct files_struct *fsp, off_t offset)
2202 VFS_FIND(ftruncate);
2203 return handle->fns->ftruncate_fn(handle, fsp, offset);
2206 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2207 struct files_struct *fsp,
2208 uint32_t mode,
2209 off_t offset,
2210 off_t len)
2212 VFS_FIND(fallocate);
2213 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2216 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2217 struct files_struct *fsp, uint32_t share_mode,
2218 uint32_t access_mask)
2220 VFS_FIND(kernel_flock);
2221 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2222 access_mask);
2225 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2226 struct files_struct *fsp, int cmd, ...)
2228 int result;
2229 va_list cmd_arg;
2231 VFS_FIND(fcntl);
2233 va_start(cmd_arg, cmd);
2234 result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2235 va_end(cmd_arg);
2237 return result;
2240 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2241 struct files_struct *fsp, int leasetype)
2243 VFS_FIND(linux_setlease);
2244 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2247 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2248 const struct smb_filename *link_target,
2249 struct files_struct *dirfsp,
2250 const struct smb_filename *new_smb_fname)
2252 VFS_FIND(symlinkat);
2253 return handle->fns->symlinkat_fn(handle,
2254 link_target,
2255 dirfsp,
2256 new_smb_fname);
2259 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2260 files_struct *dirfsp,
2261 const struct smb_filename *smb_fname,
2262 char *buf,
2263 size_t bufsiz)
2265 VFS_FIND(readlinkat);
2266 return handle->fns->readlinkat_fn(handle,
2267 dirfsp,
2268 smb_fname,
2269 buf,
2270 bufsiz);
2273 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2274 struct files_struct *srcfsp,
2275 const struct smb_filename *old_smb_fname,
2276 struct files_struct *dstfsp,
2277 const struct smb_filename *new_smb_fname,
2278 int flags)
2280 VFS_FIND(linkat);
2281 return handle->fns->linkat_fn(handle,
2282 srcfsp,
2283 old_smb_fname,
2284 dstfsp,
2285 new_smb_fname,
2286 flags);
2289 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2290 struct files_struct *dirfsp,
2291 const struct smb_filename *smb_fname,
2292 mode_t mode,
2293 SMB_DEV_T dev)
2295 VFS_FIND(mknodat);
2296 return handle->fns->mknodat_fn(handle,
2297 dirfsp,
2298 smb_fname,
2299 mode,
2300 dev);
2303 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2304 TALLOC_CTX *ctx,
2305 const struct smb_filename *smb_fname)
2307 VFS_FIND(realpath);
2308 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2311 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2312 const struct smb_filename *smb_fname,
2313 unsigned int flags)
2315 VFS_FIND(chflags);
2316 return handle->fns->chflags_fn(handle, smb_fname, flags);
2319 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2320 const SMB_STRUCT_STAT *sbuf)
2322 VFS_FIND(file_id_create);
2323 return handle->fns->file_id_create_fn(handle, sbuf);
2326 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2327 const SMB_STRUCT_STAT *sbuf)
2329 VFS_FIND(fs_file_id);
2330 return handle->fns->fs_file_id_fn(handle, sbuf);
2333 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2334 struct files_struct *fsp,
2335 const struct smb_filename *smb_fname,
2336 TALLOC_CTX *mem_ctx,
2337 unsigned int *num_streams,
2338 struct stream_struct **streams)
2340 VFS_FIND(streaminfo);
2341 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2342 num_streams, streams);
2345 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2346 const struct smb_filename *path,
2347 const char *name,
2348 TALLOC_CTX *mem_ctx,
2349 char **found_name)
2351 VFS_FIND(get_real_filename);
2352 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2353 found_name);
2356 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2357 const struct smb_filename *smb_fname)
2359 VFS_FIND(connectpath);
2360 return handle->fns->connectpath_fn(handle, smb_fname);
2363 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2364 struct files_struct *fsp,
2365 struct lock_struct *plock)
2367 VFS_FIND(strict_lock_check);
2368 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2371 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2372 const char *name,
2373 enum vfs_translate_direction direction,
2374 TALLOC_CTX *mem_ctx,
2375 char **mapped_name)
2377 VFS_FIND(translate_name);
2378 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2379 mapped_name);
2382 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2383 struct files_struct *fsp,
2384 TALLOC_CTX *ctx,
2385 uint32_t function,
2386 uint16_t req_flags,
2387 const uint8_t *in_data,
2388 uint32_t in_len,
2389 uint8_t **out_data,
2390 uint32_t max_out_len,
2391 uint32_t *out_len)
2393 VFS_FIND(fsctl);
2394 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2395 in_data, in_len, out_data, max_out_len,
2396 out_len);
2399 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2400 struct smb_filename *smb_fname,
2401 uint32_t *dosmode)
2403 VFS_FIND(get_dos_attributes);
2404 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2407 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2408 struct files_struct *fsp,
2409 uint32_t *dosmode)
2411 VFS_FIND(fget_dos_attributes);
2412 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2415 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2416 const struct smb_filename *smb_fname,
2417 uint32_t dosmode)
2419 VFS_FIND(set_dos_attributes);
2420 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2423 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2424 struct files_struct *fsp,
2425 uint32_t dosmode)
2427 VFS_FIND(set_dos_attributes);
2428 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2431 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2432 struct tevent_context *ev,
2433 struct vfs_handle_struct *handle,
2434 struct files_struct *fsp,
2435 uint32_t fsctl,
2436 uint32_t ttl,
2437 off_t offset,
2438 size_t to_copy)
2440 VFS_FIND(offload_read_send);
2441 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2442 fsp, fsctl,
2443 ttl, offset, to_copy);
2446 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2447 struct vfs_handle_struct *handle,
2448 TALLOC_CTX *mem_ctx,
2449 DATA_BLOB *token_blob)
2451 VFS_FIND(offload_read_recv);
2452 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2455 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2456 TALLOC_CTX *mem_ctx,
2457 struct tevent_context *ev,
2458 uint32_t fsctl,
2459 DATA_BLOB *token,
2460 off_t transfer_offset,
2461 struct files_struct *dest_fsp,
2462 off_t dest_off,
2463 off_t num)
2465 VFS_FIND(offload_write_send);
2466 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2467 token, transfer_offset,
2468 dest_fsp, dest_off, num);
2471 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2472 struct tevent_req *req,
2473 off_t *copied)
2475 VFS_FIND(offload_write_recv);
2476 return handle->fns->offload_write_recv_fn(handle, req, copied);
2479 struct smb_vfs_call_get_dos_attributes_state {
2480 files_struct *dir_fsp;
2481 NTSTATUS (*recv_fn)(struct tevent_req *req,
2482 struct vfs_aio_state *aio_state,
2483 uint32_t *dosmode);
2484 struct vfs_aio_state aio_state;
2485 uint32_t dos_attributes;
2488 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2490 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2491 TALLOC_CTX *mem_ctx,
2492 struct tevent_context *ev,
2493 struct vfs_handle_struct *handle,
2494 files_struct *dir_fsp,
2495 struct smb_filename *smb_fname)
2497 struct tevent_req *req = NULL;
2498 struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2499 struct tevent_req *subreq = NULL;
2501 req = tevent_req_create(mem_ctx, &state,
2502 struct smb_vfs_call_get_dos_attributes_state);
2503 if (req == NULL) {
2504 return NULL;
2507 VFS_FIND(get_dos_attributes_send);
2509 *state = (struct smb_vfs_call_get_dos_attributes_state) {
2510 .dir_fsp = dir_fsp,
2511 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2514 subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2516 handle,
2517 dir_fsp,
2518 smb_fname);
2519 if (tevent_req_nomem(subreq, req)) {
2520 return tevent_req_post(req, ev);
2522 tevent_req_defer_callback(req, ev);
2524 tevent_req_set_callback(subreq,
2525 smb_vfs_call_get_dos_attributes_done,
2526 req);
2528 return req;
2531 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2533 struct tevent_req *req =
2534 tevent_req_callback_data(subreq,
2535 struct tevent_req);
2536 struct smb_vfs_call_get_dos_attributes_state *state =
2537 tevent_req_data(req,
2538 struct smb_vfs_call_get_dos_attributes_state);
2539 NTSTATUS status;
2540 bool ok;
2543 * Make sure we run as the user again
2545 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2546 SMB_ASSERT(ok);
2548 status = state->recv_fn(subreq,
2549 &state->aio_state,
2550 &state->dos_attributes);
2551 TALLOC_FREE(subreq);
2552 if (tevent_req_nterror(req, status)) {
2553 return;
2556 tevent_req_done(req);
2559 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2560 struct tevent_req *req,
2561 struct vfs_aio_state *aio_state,
2562 uint32_t *dos_attributes)
2564 struct smb_vfs_call_get_dos_attributes_state *state =
2565 tevent_req_data(req,
2566 struct smb_vfs_call_get_dos_attributes_state);
2567 NTSTATUS status;
2569 if (tevent_req_is_nterror(req, &status)) {
2570 tevent_req_received(req);
2571 return status;
2574 *aio_state = state->aio_state;
2575 *dos_attributes = state->dos_attributes;
2576 tevent_req_received(req);
2577 return NT_STATUS_OK;
2580 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2581 TALLOC_CTX *mem_ctx,
2582 struct files_struct *fsp,
2583 struct smb_filename *smb_fname,
2584 uint16_t *_compression_fmt)
2586 VFS_FIND(get_compression);
2587 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2588 _compression_fmt);
2591 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2592 TALLOC_CTX *mem_ctx,
2593 struct files_struct *fsp,
2594 uint16_t compression_fmt)
2596 VFS_FIND(set_compression);
2597 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2598 compression_fmt);
2601 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2602 TALLOC_CTX *mem_ctx,
2603 const char *service_path,
2604 char **base_volume)
2606 VFS_FIND(snap_check_path);
2607 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2608 base_volume);
2611 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2612 TALLOC_CTX *mem_ctx,
2613 const char *base_volume,
2614 time_t *tstamp,
2615 bool rw,
2616 char **base_path,
2617 char **snap_path)
2619 VFS_FIND(snap_create);
2620 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2621 rw, base_path, snap_path);
2624 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2625 TALLOC_CTX *mem_ctx,
2626 char *base_path,
2627 char *snap_path)
2629 VFS_FIND(snap_delete);
2630 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2631 snap_path);
2634 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2635 struct files_struct *fsp,
2636 uint32_t security_info,
2637 TALLOC_CTX *mem_ctx,
2638 struct security_descriptor **ppdesc)
2640 VFS_FIND(fget_nt_acl);
2641 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2642 mem_ctx, ppdesc);
2645 NTSTATUS smb_vfs_call_get_nt_acl_at(struct vfs_handle_struct *handle,
2646 struct files_struct *dirfsp,
2647 const struct smb_filename *smb_fname,
2648 uint32_t security_info,
2649 TALLOC_CTX *mem_ctx,
2650 struct security_descriptor **ppdesc)
2652 VFS_FIND(get_nt_acl_at);
2653 return handle->fns->get_nt_acl_at_fn(handle,
2654 dirfsp,
2655 smb_fname,
2656 security_info,
2657 mem_ctx,
2658 ppdesc);
2661 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2662 struct files_struct *fsp,
2663 uint32_t security_info_sent,
2664 const struct security_descriptor *psd)
2666 VFS_FIND(fset_nt_acl);
2667 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2668 psd);
2671 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2672 struct smb_filename *file,
2673 struct security_acl *sacl,
2674 uint32_t access_requested,
2675 uint32_t access_denied)
2677 VFS_FIND(audit_file);
2678 return handle->fns->audit_file_fn(handle,
2679 file,
2680 sacl,
2681 access_requested,
2682 access_denied);
2685 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2686 const struct smb_filename *smb_fname,
2687 SMB_ACL_TYPE_T type,
2688 TALLOC_CTX *mem_ctx)
2690 VFS_FIND(sys_acl_get_file);
2691 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2694 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2695 struct files_struct *fsp,
2696 TALLOC_CTX *mem_ctx)
2698 VFS_FIND(sys_acl_get_fd);
2699 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2702 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2703 const struct smb_filename *smb_fname,
2704 TALLOC_CTX *mem_ctx,
2705 char **blob_description,
2706 DATA_BLOB *blob)
2708 VFS_FIND(sys_acl_blob_get_file);
2709 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2710 mem_ctx, blob_description, blob);
2713 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2714 struct files_struct *fsp,
2715 TALLOC_CTX *mem_ctx,
2716 char **blob_description,
2717 DATA_BLOB *blob)
2719 VFS_FIND(sys_acl_blob_get_fd);
2720 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2723 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2724 const struct smb_filename *smb_fname,
2725 SMB_ACL_TYPE_T acltype,
2726 SMB_ACL_T theacl)
2728 VFS_FIND(sys_acl_set_file);
2729 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2730 acltype, theacl);
2733 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2734 struct files_struct *fsp, SMB_ACL_T theacl)
2736 VFS_FIND(sys_acl_set_fd);
2737 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2740 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2741 const struct smb_filename *smb_fname)
2743 VFS_FIND(sys_acl_delete_def_file);
2744 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2747 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2748 const struct smb_filename *smb_fname,
2749 const char *name,
2750 void *value,
2751 size_t size)
2753 VFS_FIND(getxattr);
2754 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2758 struct smb_vfs_call_getxattrat_state {
2759 files_struct *dir_fsp;
2760 ssize_t (*recv_fn)(struct tevent_req *req,
2761 struct vfs_aio_state *aio_state,
2762 TALLOC_CTX *mem_ctx,
2763 uint8_t **xattr_value);
2764 ssize_t retval;
2765 uint8_t *xattr_value;
2766 struct vfs_aio_state aio_state;
2769 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2771 struct tevent_req *smb_vfs_call_getxattrat_send(
2772 TALLOC_CTX *mem_ctx,
2773 struct tevent_context *ev,
2774 struct vfs_handle_struct *handle,
2775 files_struct *dir_fsp,
2776 const struct smb_filename *smb_fname,
2777 const char *xattr_name,
2778 size_t alloc_hint)
2780 struct tevent_req *req = NULL;
2781 struct smb_vfs_call_getxattrat_state *state = NULL;
2782 struct tevent_req *subreq = NULL;
2784 req = tevent_req_create(mem_ctx, &state,
2785 struct smb_vfs_call_getxattrat_state);
2786 if (req == NULL) {
2787 return NULL;
2790 VFS_FIND(getxattrat_send);
2792 *state = (struct smb_vfs_call_getxattrat_state) {
2793 .dir_fsp = dir_fsp,
2794 .recv_fn = handle->fns->getxattrat_recv_fn,
2797 subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2799 handle,
2800 dir_fsp,
2801 smb_fname,
2802 xattr_name,
2803 alloc_hint);
2804 if (tevent_req_nomem(subreq, req)) {
2805 return tevent_req_post(req, ev);
2807 tevent_req_defer_callback(req, ev);
2809 tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2810 return req;
2813 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2815 struct tevent_req *req = tevent_req_callback_data(
2816 subreq, struct tevent_req);
2817 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2818 req, struct smb_vfs_call_getxattrat_state);
2819 bool ok;
2822 * Make sure we run as the user again
2824 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2825 SMB_ASSERT(ok);
2827 state->retval = state->recv_fn(subreq,
2828 &state->aio_state,
2829 state,
2830 &state->xattr_value);
2831 TALLOC_FREE(subreq);
2832 if (state->retval == -1) {
2833 tevent_req_error(req, state->aio_state.error);
2834 return;
2837 tevent_req_done(req);
2840 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2841 struct vfs_aio_state *aio_state,
2842 TALLOC_CTX *mem_ctx,
2843 uint8_t **xattr_value)
2845 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2846 req, struct smb_vfs_call_getxattrat_state);
2847 size_t xattr_size;
2849 if (tevent_req_is_unix_error(req, &aio_state->error)) {
2850 tevent_req_received(req);
2851 return -1;
2854 *aio_state = state->aio_state;
2855 xattr_size = state->retval;
2856 if (xattr_value != NULL) {
2857 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2860 tevent_req_received(req);
2861 return xattr_size;
2864 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2865 struct files_struct *fsp, const char *name,
2866 void *value, size_t size)
2868 VFS_FIND(fgetxattr);
2869 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2872 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2873 const struct smb_filename *smb_fname,
2874 char *list,
2875 size_t size)
2877 VFS_FIND(listxattr);
2878 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2881 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2882 struct files_struct *fsp, char *list,
2883 size_t size)
2885 VFS_FIND(flistxattr);
2886 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2889 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2890 const struct smb_filename *smb_fname,
2891 const char *name)
2893 VFS_FIND(removexattr);
2894 return handle->fns->removexattr_fn(handle, smb_fname, name);
2897 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2898 struct files_struct *fsp, const char *name)
2900 VFS_FIND(fremovexattr);
2901 return handle->fns->fremovexattr_fn(handle, fsp, name);
2904 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2905 const struct smb_filename *smb_fname,
2906 const char *name,
2907 const void *value,
2908 size_t size,
2909 int flags)
2911 VFS_FIND(setxattr);
2912 return handle->fns->setxattr_fn(handle, smb_fname,
2913 name, value, size, flags);
2916 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2917 struct files_struct *fsp, const char *name,
2918 const void *value, size_t size, int flags)
2920 VFS_FIND(fsetxattr);
2921 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2924 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2925 struct files_struct *fsp)
2927 VFS_FIND(aio_force);
2928 return handle->fns->aio_force_fn(handle, fsp);
2931 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2932 struct files_struct *fsp,
2933 TALLOC_CTX *mem_ctx,
2934 DATA_BLOB *cookie)
2936 VFS_FIND(durable_cookie);
2937 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2940 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2941 struct files_struct *fsp,
2942 const DATA_BLOB old_cookie,
2943 TALLOC_CTX *mem_ctx,
2944 DATA_BLOB *new_cookie)
2946 VFS_FIND(durable_disconnect);
2947 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2948 mem_ctx, new_cookie);
2951 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2952 struct smb_request *smb1req,
2953 struct smbXsrv_open *op,
2954 const DATA_BLOB old_cookie,
2955 TALLOC_CTX *mem_ctx,
2956 struct files_struct **fsp,
2957 DATA_BLOB *new_cookie)
2959 VFS_FIND(durable_reconnect);
2960 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2961 old_cookie, mem_ctx, fsp,
2962 new_cookie);
2965 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2966 const struct smb_filename *fname,
2967 TALLOC_CTX *mem_ctx,
2968 struct readdir_attr_data **attr_data)
2970 VFS_FIND(readdir_attr);
2971 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);