VFS: Fix a typo
[Samba.git] / source3 / smbd / vfs.c
blob570de84381177c38b00d95b0dd6d0c40d0ed98bc
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 = talloc_zero_size(
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,
295 const struct files_struct *fsp)
297 struct vfs_fsp_data *head;
299 for (head = fsp->vfs_extension; head; head = head->next) {
300 if (head->owner == handle) {
301 return head;
305 return NULL;
308 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle,
309 const struct files_struct *fsp)
311 struct vfs_fsp_data *head;
313 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
314 if (head != NULL) {
315 return EXT_DATA_AREA(head);
318 return NULL;
321 #undef EXT_DATA_AREA
324 * Ensure this module catches all VFS functions.
326 #ifdef DEVELOPER
327 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
328 const char *module)
330 bool missing_fn = false;
331 unsigned int idx;
332 const uintptr_t *end = (const uintptr_t *)(fns + 1);
334 for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
335 if (*((const uintptr_t *)fns + idx) == 0) {
336 DBG_ERR("VFS function at index %d not implemented "
337 "in module %s\n", idx, module);
338 missing_fn = true;
342 if (missing_fn) {
343 smb_panic("Required VFS function not implemented in module.\n");
346 #else
347 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
348 const char *module)
351 #endif
353 /*****************************************************************
354 Generic VFS init.
355 ******************************************************************/
357 bool smbd_vfs_init(connection_struct *conn)
359 const char **vfs_objects;
360 unsigned int i = 0;
361 int j = 0;
363 /* Normal share - initialise with disk access functions */
364 vfs_init_default(conn);
366 /* No need to load vfs modules for printer connections */
367 if (conn->printer) {
368 return True;
371 if (lp_widelinks(SNUM(conn))) {
373 * As the widelinks logic is now moving into a
374 * vfs_widelinks module, we need to custom load
375 * it after the default module is initialized.
376 * That way no changes to smb.conf files are
377 * needed.
379 bool ok = vfs_init_custom(conn, "widelinks");
380 if (!ok) {
381 DBG_ERR("widelinks enabled and vfs_init_custom "
382 "failed for vfs_widelinks module\n");
383 return false;
387 vfs_objects = lp_vfs_objects(SNUM(conn));
389 /* Override VFS functions if 'vfs object' was not specified*/
390 if (!vfs_objects || !vfs_objects[0])
391 return True;
393 for (i=0; vfs_objects[i] ;) {
394 i++;
397 for (j=i-1; j >= 0; j--) {
398 if (!vfs_init_custom(conn, vfs_objects[j])) {
399 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
400 return False;
403 return True;
406 /*******************************************************************
407 Check if a file exists in the vfs.
408 ********************************************************************/
410 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
412 /* Only return OK if stat was successful and S_ISREG */
413 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
414 S_ISREG(smb_fname->st.st_ex_mode)) {
415 return NT_STATUS_OK;
418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
421 bool vfs_valid_pread_range(off_t offset, size_t length)
423 return sys_valid_io_range(offset, length);
426 bool vfs_valid_pwrite_range(off_t offset, size_t length)
429 * See MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write
431 static const uint64_t maxfilesize = 0xfffffff0000;
432 uint64_t last_byte_ofs;
433 bool ok;
435 ok = sys_valid_io_range(offset, length);
436 if (!ok) {
437 return false;
440 if (length == 0) {
441 return true;
444 last_byte_ofs = offset + length;
445 if (last_byte_ofs > maxfilesize) {
446 return false;
449 return true;
452 ssize_t vfs_pwrite_data(struct smb_request *req,
453 files_struct *fsp,
454 const char *buffer,
455 size_t N,
456 off_t offset)
458 size_t total=0;
459 ssize_t ret;
460 bool ok;
462 ok = vfs_valid_pwrite_range(offset, N);
463 if (!ok) {
464 errno = EINVAL;
465 return -1;
468 if (req && req->unread_bytes) {
469 int sockfd = req->xconn->transport.sock;
470 SMB_ASSERT(req->unread_bytes == N);
471 /* VFS_RECVFILE must drain the socket
472 * before returning. */
473 req->unread_bytes = 0;
475 * Leave the socket non-blocking and
476 * use SMB_VFS_RECVFILE. If it returns
477 * EAGAIN || EWOULDBLOCK temporarily set
478 * the socket blocking and retry
479 * the RECVFILE.
481 while (total < N) {
482 ret = SMB_VFS_RECVFILE(sockfd,
483 fsp,
484 offset + total,
485 N - total);
486 if (ret == 0 || (ret == -1 &&
487 (errno == EAGAIN ||
488 errno == EWOULDBLOCK))) {
489 int old_flags;
490 /* Ensure the socket is blocking. */
491 old_flags = fcntl(sockfd, F_GETFL, 0);
492 if (set_blocking(sockfd, true) == -1) {
493 return (ssize_t)-1;
495 ret = SMB_VFS_RECVFILE(sockfd,
496 fsp,
497 offset + total,
498 N - total);
499 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
500 return (ssize_t)-1;
502 if (ret == -1) {
503 return (ssize_t)-1;
505 total += ret;
506 return (ssize_t)total;
508 /* Any other error case. */
509 if (ret == -1) {
510 return ret;
512 total += ret;
514 return (ssize_t)total;
517 while (total < N) {
518 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
519 offset + total);
521 if (ret == -1)
522 return -1;
523 if (ret == 0)
524 return total;
526 total += ret;
528 return (ssize_t)total;
530 /****************************************************************************
531 An allocate file space call using the vfs interface.
532 Allocates space for a file from a filedescriptor.
533 Returns 0 on success, -1 on failure.
534 ****************************************************************************/
536 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
538 int ret;
539 connection_struct *conn = fsp->conn;
540 uint64_t space_avail;
541 uint64_t bsize,dfree,dsize;
542 NTSTATUS status;
543 bool ok;
546 * Actually try and commit the space on disk....
549 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
550 fsp_str_dbg(fsp), (double)len));
552 ok = vfs_valid_pwrite_range((off_t)len, 0);
553 if (!ok) {
554 DEBUG(0,("vfs_allocate_file_space: %s negative/invalid len "
555 "requested.\n", fsp_str_dbg(fsp)));
556 errno = EINVAL;
557 return -1;
560 status = vfs_stat_fsp(fsp);
561 if (!NT_STATUS_IS_OK(status)) {
562 return -1;
565 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
566 return 0;
568 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
569 /* Shrink - use ftruncate. */
571 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
572 "size %.0f\n", fsp_str_dbg(fsp),
573 (double)fsp->fsp_name->st.st_ex_size));
575 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
577 ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
579 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
581 return ret;
584 /* Grow - we need to test if we have enough space. */
586 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
588 if (lp_strict_allocate(SNUM(fsp->conn))) {
589 /* See if we have a syscall that will allocate beyond
590 end-of-file without changing EOF. */
591 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
592 0, len);
593 } else {
594 ret = 0;
597 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
599 if (ret == 0) {
600 /* We changed the allocation size on disk, but not
601 EOF - exactly as required. We're done ! */
602 return 0;
605 if (ret == -1 && errno == ENOSPC) {
606 return -1;
609 len -= fsp->fsp_name->st.st_ex_size;
610 len /= 1024; /* Len is now number of 1k blocks needed. */
611 space_avail =
612 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
613 if (space_avail == (uint64_t)-1) {
614 return -1;
617 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
618 "needed blocks = %.0f, space avail = %.0f\n",
619 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
620 (double)space_avail));
622 if (len > space_avail) {
623 errno = ENOSPC;
624 return -1;
627 return 0;
630 /****************************************************************************
631 A vfs set_filelen call.
632 set the length of a file from a filedescriptor.
633 Returns 0 on success, -1 on failure.
634 ****************************************************************************/
636 int vfs_set_filelen(files_struct *fsp, off_t len)
638 int ret;
639 bool ok;
641 ok = vfs_valid_pwrite_range(len, 0);
642 if (!ok) {
643 errno = EINVAL;
644 return -1;
647 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
649 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
650 fsp_str_dbg(fsp), (double)len));
651 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
652 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
653 FILE_NOTIFY_CHANGE_SIZE
654 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
655 fsp->fsp_name->base_name);
658 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
660 return ret;
663 /****************************************************************************
664 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
665 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
666 as this is also called from the default SMB_VFS_FTRUNCATE code.
667 Always extends the file size.
668 Returns 0 on success, -1 on failure.
669 ****************************************************************************/
671 #define SPARSE_BUF_WRITE_SIZE (32*1024)
673 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
675 ssize_t pwrite_ret;
676 size_t total = 0;
677 bool ok;
679 ok = vfs_valid_pwrite_range(offset, len);
680 if (!ok) {
681 errno = EINVAL;
682 return -1;
685 if (!sparse_buf) {
686 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
687 if (!sparse_buf) {
688 errno = ENOMEM;
689 return -1;
693 while (total < len) {
694 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
696 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
697 if (pwrite_ret == -1) {
698 int saved_errno = errno;
699 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
700 "%s failed with error %s\n",
701 fsp_str_dbg(fsp), strerror(saved_errno)));
702 errno = saved_errno;
703 return -1;
705 total += pwrite_ret;
708 return 0;
711 /****************************************************************************
712 A vfs fill sparse call.
713 Writes zeros from the end of file to len, if len is greater than EOF.
714 Used only by strict_sync.
715 Returns 0 on success, -1 on failure.
716 ****************************************************************************/
718 int vfs_fill_sparse(files_struct *fsp, off_t len)
720 int ret;
721 NTSTATUS status;
722 off_t offset;
723 size_t num_to_write;
724 bool ok;
726 ok = vfs_valid_pwrite_range(len, 0);
727 if (!ok) {
728 errno = EINVAL;
729 return -1;
732 status = vfs_stat_fsp(fsp);
733 if (!NT_STATUS_IS_OK(status)) {
734 return -1;
737 if (len <= fsp->fsp_name->st.st_ex_size) {
738 return 0;
741 #ifdef S_ISFIFO
742 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
743 return 0;
745 #endif
747 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
748 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
749 (double)fsp->fsp_name->st.st_ex_size, (double)len,
750 (double)(len - fsp->fsp_name->st.st_ex_size)));
752 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
754 offset = fsp->fsp_name->st.st_ex_size;
755 num_to_write = len - fsp->fsp_name->st.st_ex_size;
757 /* Only do this on non-stream file handles. */
758 if (fsp->base_fsp == NULL) {
759 /* for allocation try fallocate first. This can fail on some
760 * platforms e.g. when the filesystem doesn't support it and no
761 * emulation is being done by the libc (like on AIX with JFS1). In that
762 * case we do our own emulation. fallocate implementations can
763 * return ENOTSUP or EINVAL in cases like that. */
764 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
765 if (ret == -1 && errno == ENOSPC) {
766 goto out;
768 if (ret == 0) {
769 goto out;
771 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
772 "error %d. Falling back to slow manual allocation\n", ret));
775 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
777 out:
779 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
780 return ret;
783 /*******************************************************************************
784 Set a fd into blocking/nonblocking mode through VFS
785 *******************************************************************************/
787 int vfs_set_blocking(files_struct *fsp, bool set)
789 int val;
790 #ifdef O_NONBLOCK
791 #define FLAG_TO_SET O_NONBLOCK
792 #else
793 #ifdef SYSV
794 #define FLAG_TO_SET O_NDELAY
795 #else /* BSD */
796 #define FLAG_TO_SET FNDELAY
797 #endif
798 #endif
800 if (fsp->fsp_flags.is_pathref) {
801 return 0;
804 val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
805 if (val == -1) {
806 return -1;
809 if (set) {
810 val &= ~FLAG_TO_SET;
811 } else {
812 val |= FLAG_TO_SET;
815 return SMB_VFS_FCNTL(fsp, F_SETFL, val);
816 #undef FLAG_TO_SET
819 /****************************************************************************
820 Transfer some data (n bytes) between two file_struct's.
821 ****************************************************************************/
823 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
825 struct files_struct *fsp = (struct files_struct *)file;
827 return SMB_VFS_PREAD(fsp, buf, len, offset);
830 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
832 struct files_struct *fsp = (struct files_struct *)file;
834 return SMB_VFS_PWRITE(fsp, buf, len, offset);
837 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
839 return transfer_file_internal((void *)in, (void *)out, n,
840 vfs_pread_fn, vfs_pwrite_fn);
843 /*******************************************************************
844 A vfs_readdir wrapper which just returns the file name.
845 ********************************************************************/
847 const char *vfs_readdirname(connection_struct *conn,
848 struct files_struct *dirfsp,
849 void *p,
850 SMB_STRUCT_STAT *sbuf,
851 char **talloced)
853 struct dirent *ptr= NULL;
854 const char *dname;
855 char *translated;
856 NTSTATUS status;
858 if (!p)
859 return(NULL);
861 ptr = SMB_VFS_READDIR(conn, dirfsp, (DIR *)p, sbuf);
862 if (!ptr)
863 return(NULL);
865 dname = ptr->d_name;
867 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
868 talloc_tos(), &translated);
869 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
870 *talloced = NULL;
871 return dname;
873 *talloced = translated;
874 if (!NT_STATUS_IS_OK(status)) {
875 return NULL;
877 return translated;
880 /*******************************************************************
881 A wrapper for vfs_chdir().
882 ********************************************************************/
884 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
886 int ret;
887 struct smb_filename *cwd = NULL;
889 if (!LastDir) {
890 LastDir = SMB_STRDUP("");
893 if (ISDOT(smb_fname->base_name)) {
895 * passing a '.' is a noop,
896 * and we only expect this after
897 * everything is initialized.
899 * So the first vfs_ChDir() on a given
900 * connection_struct must not be '.'.
902 * Note: conn_new() sets
903 * conn->cwd_fsp->fh->fd = -1
904 * and vfs_ChDir() leaves with
905 * conn->cwd_fsp->fh->fd = AT_FDCWD
906 * on success!
908 if (fsp_get_pathref_fd(conn->cwd_fsp) != AT_FDCWD) {
910 * This should never happen and
911 * we might change this to
912 * SMB_ASSERT() in future.
914 DBG_ERR("Called with '.' as first operation!\n");
915 log_stack_trace();
916 errno = EINVAL;
917 return -1;
919 return 0;
922 if (smb_fname->base_name[0] == '/' &&
923 strcsequal(LastDir,smb_fname->base_name))
926 * conn->cwd_fsp->fsp_name and the kernel
927 * are already correct, but conn->cwd_fsp->fh->fd
928 * might still be -1 as initialized in conn_new().
930 * This can happen when a client made a 2nd
931 * tree connect to a share with the same underlying
932 * path (may or may not the same share).
934 fsp_set_fd(conn->cwd_fsp, AT_FDCWD);
935 return 0;
938 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
940 ret = SMB_VFS_CHDIR(conn, smb_fname);
941 if (ret != 0) {
942 return -1;
946 * Always replace conn->cwd_fsp. We
947 * don't know if it's been modified by
948 * VFS modules in the stack.
950 fsp_set_fd(conn->cwd_fsp, AT_FDCWD);
952 /* conn cache. */
953 cwd = vfs_GetWd(conn, conn);
954 if (cwd == NULL) {
956 * vfs_GetWd() failed.
957 * We must be able to read cwd.
958 * Return to original directory
959 * and return -1.
961 int saved_errno = errno;
963 if (conn->cwd_fsp->fsp_name == NULL) {
965 * Failed on the very first chdir()+getwd()
966 * for this connection. We can't
967 * continue.
969 smb_panic("conn->cwd getwd failed\n");
970 /* NOTREACHED */
971 return -1;
974 /* Return to the previous $cwd. */
975 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
976 if (ret != 0) {
977 smb_panic("conn->cwd getwd failed\n");
978 /* NOTREACHED */
979 return -1;
981 errno = saved_errno;
982 /* And fail the chdir(). */
983 return -1;
986 /* vfs_GetWd() succeeded. */
987 /* Replace global cache. */
988 SAFE_FREE(LastDir);
989 LastDir = SMB_STRDUP(smb_fname->base_name);
992 * (Indirect) Callers of vfs_ChDir() may still hold references to the
993 * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
994 * callers can use it for the lifetime of the SMB request.
996 talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
998 conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
1000 DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
1002 return ret;
1005 /*******************************************************************
1006 Return the absolute current directory path - given a UNIX pathname.
1007 Note that this path is returned in DOS format, not UNIX
1008 format. Note this can be called with conn == NULL.
1009 ********************************************************************/
1011 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
1013 struct smb_filename *current_dir_fname = NULL;
1014 struct file_id key;
1015 struct smb_filename *smb_fname_dot = NULL;
1016 struct smb_filename *smb_fname_full = NULL;
1017 struct smb_filename *result = NULL;
1019 if (!lp_getwd_cache()) {
1020 goto nocache;
1023 smb_fname_dot = synthetic_smb_fname(ctx,
1024 ".",
1025 NULL,
1026 NULL,
1029 if (smb_fname_dot == NULL) {
1030 errno = ENOMEM;
1031 goto out;
1034 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
1036 * Known to fail for root: the directory may be NFS-mounted
1037 * and exported with root_squash (so has no root access).
1039 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
1040 "(NFS problem ?)\n", strerror(errno) ));
1041 goto nocache;
1044 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1046 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
1047 smbd_memcache(),
1048 GETWD_CACHE,
1049 data_blob_const(&key, sizeof(key)));
1051 if (smb_fname_full == NULL) {
1052 goto nocache;
1055 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
1056 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
1057 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
1058 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
1060 * Ok, we're done
1061 * Note: smb_fname_full is owned by smbd_memcache()
1062 * so we must make a copy to return.
1064 result = cp_smb_filename(ctx, smb_fname_full);
1065 if (result == NULL) {
1066 errno = ENOMEM;
1068 goto out;
1071 nocache:
1074 * We don't have the information to hand so rely on traditional
1075 * methods. The very slow getcwd, which spawns a process on some
1076 * systems, or the not quite so bad getwd.
1079 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
1080 if (current_dir_fname == NULL) {
1081 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
1082 strerror(errno)));
1083 goto out;
1086 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
1087 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1090 * smbd_memcache() will own current_dir_fname after the
1091 * memcache_add_talloc call, so we must make
1092 * a copy on ctx to return.
1094 result = cp_smb_filename(ctx, current_dir_fname);
1095 if (result == NULL) {
1096 errno = ENOMEM;
1100 * Ensure the memory going into the cache
1101 * doesn't have a destructor so it can be
1102 * cleanly freed.
1104 talloc_set_destructor(current_dir_fname, NULL);
1106 memcache_add_talloc(smbd_memcache(),
1107 GETWD_CACHE,
1108 data_blob_const(&key, sizeof(key)),
1109 &current_dir_fname);
1110 /* current_dir_fname is now == NULL here. */
1111 } else {
1112 /* current_dir_fname is already allocated on ctx. */
1113 result = current_dir_fname;
1116 out:
1117 TALLOC_FREE(smb_fname_dot);
1119 * Don't free current_dir_fname here. It's either been moved
1120 * to the memcache or is being returned in result.
1122 return result;
1125 /*******************************************************************
1126 Reduce a file name, removing .. elements and checking that
1127 it is below dir in the hierarchy. This uses realpath.
1128 This function must run as root, and will return names
1129 and valid stat structs that can be checked on open.
1130 ********************************************************************/
1132 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1133 const struct smb_filename *smb_fname,
1134 struct smb_request *smbreq)
1136 NTSTATUS status;
1137 TALLOC_CTX *ctx = talloc_tos();
1138 const char *conn_rootdir;
1139 size_t rootdir_len;
1140 char *resolved_name = NULL;
1141 struct smb_filename *resolved_fname = NULL;
1142 struct smb_filename *saved_dir_fname = NULL;
1143 struct smb_filename *smb_fname_cwd = NULL;
1144 int ret;
1145 struct smb_filename *parent_name = NULL;
1146 struct smb_filename *file_name = NULL;
1148 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1149 smb_fname->base_name,
1150 conn->connectpath));
1152 status = SMB_VFS_PARENT_PATHNAME(conn,
1153 ctx,
1154 smb_fname,
1155 &parent_name,
1156 &file_name);
1157 if (!NT_STATUS_IS_OK(status)) {
1158 goto err;
1161 if (SMB_VFS_STAT(conn, parent_name) != 0) {
1162 status = map_nt_error_from_unix(errno);
1163 goto err;
1165 /* Remember where we were. */
1166 saved_dir_fname = vfs_GetWd(ctx, conn);
1167 if (!saved_dir_fname) {
1168 status = map_nt_error_from_unix(errno);
1169 goto err;
1172 if (vfs_ChDir(conn, parent_name) == -1) {
1173 status = map_nt_error_from_unix(errno);
1174 goto err;
1177 smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
1178 ".",
1179 NULL,
1180 NULL,
1181 parent_name->twrp,
1183 if (smb_fname_cwd == NULL) {
1184 status = NT_STATUS_NO_MEMORY;
1185 goto err;
1188 /* Get the absolute path of the parent directory. */
1189 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1190 if (resolved_fname == NULL) {
1191 status = map_nt_error_from_unix(errno);
1192 goto err;
1194 resolved_name = resolved_fname->base_name;
1196 if (*resolved_name != '/') {
1197 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1198 "doesn't return absolute paths !\n"));
1199 status = NT_STATUS_OBJECT_NAME_INVALID;
1200 goto err;
1203 DBG_DEBUG("realpath [%s] -> [%s]\n",
1204 smb_fname_str_dbg(parent_name),
1205 resolved_name);
1207 /* Now check the stat value is the same. */
1208 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1209 status = map_nt_error_from_unix(errno);
1210 goto err;
1213 /* Ensure we're pointing at the same place. */
1214 if (!check_same_stat(&smb_fname_cwd->st, &parent_name->st)) {
1215 DBG_ERR("device/inode/uid/gid on directory %s changed. "
1216 "Denying access !\n",
1217 smb_fname_str_dbg(parent_name));
1218 status = NT_STATUS_ACCESS_DENIED;
1219 goto err;
1222 /* Ensure we're below the connect path. */
1224 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1225 if (conn_rootdir == NULL) {
1226 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1227 "conn_rootdir\n"));
1228 status = NT_STATUS_ACCESS_DENIED;
1229 goto err;
1232 rootdir_len = strlen(conn_rootdir);
1235 * In the case of rootdir_len == 1, we know that conn_rootdir is
1236 * "/", and we also know that resolved_name starts with a slash.
1237 * So, in this corner case, resolved_name is automatically a
1238 * sub-directory of the conn_rootdir. Thus we can skip the string
1239 * comparison and the next character checks (which are even
1240 * wrong in this case).
1242 if (rootdir_len != 1) {
1243 bool matched;
1245 matched = (strncmp(conn_rootdir, resolved_name,
1246 rootdir_len) == 0);
1248 if (!matched || (resolved_name[rootdir_len] != '/' &&
1249 resolved_name[rootdir_len] != '\0')) {
1250 DBG_WARNING("%s is a symlink outside the "
1251 "share path\n",
1252 smb_fname_str_dbg(parent_name));
1253 DEBUGADD(1, ("conn_rootdir =%s\n", conn_rootdir));
1254 DEBUGADD(1, ("resolved_name=%s\n", resolved_name));
1255 status = NT_STATUS_ACCESS_DENIED;
1256 goto err;
1260 /* Now ensure that the last component either doesn't
1261 exist, or is *NOT* a symlink. */
1263 ret = SMB_VFS_LSTAT(conn, file_name);
1264 if (ret == -1) {
1265 /* Errno must be ENOENT for this be ok. */
1266 if (errno != ENOENT) {
1267 status = map_nt_error_from_unix(errno);
1268 DBG_WARNING("LSTAT on %s failed with %s\n",
1269 smb_fname_str_dbg(file_name),
1270 nt_errstr(status));
1271 goto err;
1275 if (VALID_STAT(file_name->st) &&
1276 S_ISLNK(file_name->st.st_ex_mode))
1278 DBG_WARNING("Last component %s is a symlink. Denying"
1279 "access.\n",
1280 smb_fname_str_dbg(file_name));
1281 status = NT_STATUS_ACCESS_DENIED;
1282 goto err;
1285 status = NT_STATUS_OK;
1287 err:
1289 if (saved_dir_fname != NULL) {
1290 vfs_ChDir(conn, saved_dir_fname);
1291 TALLOC_FREE(saved_dir_fname);
1293 TALLOC_FREE(resolved_fname);
1294 TALLOC_FREE(parent_name);
1295 return status;
1298 /*******************************************************************
1299 Reduce a file name, removing .. elements and checking that
1300 it is below dir in the hierarchy. This uses realpath.
1302 If cwd_name == NULL then fname is a client given path relative
1303 to the root path of the share.
1305 If cwd_name != NULL then fname is a client given path relative
1306 to cwd_name. cwd_name is relative to the root path of the share.
1307 ********************************************************************/
1309 NTSTATUS check_reduced_name(connection_struct *conn,
1310 const struct smb_filename *cwd_fname,
1311 const struct smb_filename *smb_fname)
1313 TALLOC_CTX *ctx = talloc_tos();
1314 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1315 const char *fname = smb_fname->base_name;
1316 struct smb_filename *resolved_fname;
1317 char *resolved_name = NULL;
1318 char *new_fname = NULL;
1319 bool allow_symlinks = true;
1320 const char *conn_rootdir;
1321 size_t rootdir_len;
1323 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1325 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1327 if (resolved_fname == NULL) {
1328 NTSTATUS status;
1329 struct smb_filename *dir_fname = NULL;
1330 struct smb_filename *last_component = NULL;
1332 if (errno == ENOTDIR) {
1333 DBG_NOTICE("Component not a directory in getting "
1334 "realpath for %s\n",
1335 fname);
1336 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1338 if (errno != ENOENT) {
1339 status = map_nt_error_from_unix(errno);
1340 DBG_NOTICE("couldn't get realpath for %s: %s\n",
1341 fname,
1342 strerror(errno));
1343 return status;
1346 /* errno == ENOENT */
1349 * Last component didn't exist. Remove it and try and
1350 * canonicalise the directory name.
1353 status = SMB_VFS_PARENT_PATHNAME(conn,
1354 ctx,
1355 smb_fname,
1356 &dir_fname,
1357 &last_component);
1358 if (!NT_STATUS_IS_OK(status)) {
1359 return status;
1362 resolved_fname = SMB_VFS_REALPATH(conn, ctx, dir_fname);
1363 if (resolved_fname == NULL) {
1364 status = map_nt_error_from_unix(errno);
1366 if (errno == ENOENT || errno == ENOTDIR) {
1367 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1370 DBG_NOTICE("couldn't get realpath for "
1371 "%s (%s)\n",
1372 smb_fname_str_dbg(dir_fname),
1373 nt_errstr(status));
1374 return status;
1376 resolved_name = talloc_asprintf(ctx,
1377 "%s/%s",
1378 resolved_fname->base_name,
1379 last_component->base_name);
1380 if (resolved_name == NULL) {
1381 return NT_STATUS_NO_MEMORY;
1383 } else {
1384 resolved_name = resolved_fname->base_name;
1387 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1388 resolved_name));
1390 if (*resolved_name != '/') {
1391 DEBUG(0,("check_reduced_name: realpath doesn't return "
1392 "absolute paths !\n"));
1393 TALLOC_FREE(resolved_fname);
1394 return NT_STATUS_OBJECT_NAME_INVALID;
1397 /* Common widelinks and symlinks checks. */
1398 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1399 if (conn_rootdir == NULL) {
1400 DBG_NOTICE("Could not get conn_rootdir\n");
1401 TALLOC_FREE(resolved_fname);
1402 return NT_STATUS_ACCESS_DENIED;
1405 rootdir_len = strlen(conn_rootdir);
1408 * In the case of rootdir_len == 1, we know that
1409 * conn_rootdir is "/", and we also know that
1410 * resolved_name starts with a slash. So, in this
1411 * corner case, resolved_name is automatically a
1412 * sub-directory of the conn_rootdir. Thus we can skip
1413 * the string comparison and the next character checks
1414 * (which are even wrong in this case).
1416 if (rootdir_len != 1) {
1417 bool matched;
1419 matched = (strncmp(conn_rootdir, resolved_name,
1420 rootdir_len) == 0);
1421 if (!matched || (resolved_name[rootdir_len] != '/' &&
1422 resolved_name[rootdir_len] != '\0')) {
1423 DBG_NOTICE("Bad access attempt: %s is a symlink "
1424 "outside the "
1425 "share path\n"
1426 "conn_rootdir =%s\n"
1427 "resolved_name=%s\n",
1428 fname,
1429 conn_rootdir,
1430 resolved_name);
1431 TALLOC_FREE(resolved_fname);
1432 return NT_STATUS_ACCESS_DENIED;
1436 /* Extra checks if all symlinks are disallowed. */
1437 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1438 if (!allow_symlinks) {
1439 /* fname can't have changed in resolved_path. */
1440 const char *p = &resolved_name[rootdir_len];
1443 * UNIX filesystem semantics, names consisting
1444 * only of "." or ".." CANNOT be symlinks.
1446 if (ISDOT(fname) || ISDOTDOT(fname)) {
1447 goto out;
1450 if (*p != '/') {
1451 DBG_NOTICE("logic error (%c) "
1452 "in resolved_name: %s\n",
1454 fname);
1455 TALLOC_FREE(resolved_fname);
1456 return NT_STATUS_ACCESS_DENIED;
1459 p++;
1462 * If cwd_name is present and not ".",
1463 * then fname is relative to that, not
1464 * the root of the share. Make sure the
1465 * path we check is the one the client
1466 * sent (cwd_name+fname).
1468 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1469 new_fname = talloc_asprintf(ctx,
1470 "%s/%s",
1471 cwd_name,
1472 fname);
1473 if (new_fname == NULL) {
1474 TALLOC_FREE(resolved_fname);
1475 return NT_STATUS_NO_MEMORY;
1477 fname = new_fname;
1480 if (strcmp(fname, p)!=0) {
1481 DBG_NOTICE("Bad access "
1482 "attempt: %s is a symlink to %s\n",
1483 fname,
1485 TALLOC_FREE(resolved_fname);
1486 TALLOC_FREE(new_fname);
1487 return NT_STATUS_ACCESS_DENIED;
1491 out:
1493 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1494 TALLOC_FREE(resolved_fname);
1495 TALLOC_FREE(new_fname);
1496 return NT_STATUS_OK;
1500 * Ensure LSTAT is called for POSIX paths.
1502 int vfs_stat(struct connection_struct *conn,
1503 struct smb_filename *smb_fname)
1505 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1506 return SMB_VFS_LSTAT(conn, smb_fname);
1508 return SMB_VFS_STAT(conn, smb_fname);
1512 * XXX: This is temporary and there should be no callers of this once
1513 * smb_filename is plumbed through all path based operations.
1515 * Called when we know stream name parsing has already been done.
1517 int vfs_stat_smb_basename(struct connection_struct *conn,
1518 const struct smb_filename *smb_fname_in,
1519 SMB_STRUCT_STAT *psbuf)
1521 struct smb_filename smb_fname = {
1522 .base_name = discard_const_p(char, smb_fname_in->base_name),
1523 .flags = smb_fname_in->flags,
1524 .twrp = smb_fname_in->twrp,
1526 int ret;
1528 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1529 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1530 } else {
1531 ret = SMB_VFS_STAT(conn, &smb_fname);
1534 if (ret != -1) {
1535 *psbuf = smb_fname.st;
1537 return ret;
1541 * Ensure LSTAT is called for POSIX paths.
1544 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1546 int ret;
1547 struct stat_ex saved_stat = fsp->fsp_name->st;
1549 if (fsp_get_pathref_fd(fsp) == -1) {
1550 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1551 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1552 } else {
1553 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1555 } else {
1556 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1558 if (ret == -1) {
1559 return map_nt_error_from_unix(errno);
1561 update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat);
1562 return NT_STATUS_OK;
1565 void init_smb_file_time(struct smb_file_time *ft)
1567 *ft = (struct smb_file_time) {
1568 .atime = make_omit_timespec(),
1569 .ctime = make_omit_timespec(),
1570 .mtime = make_omit_timespec(),
1571 .create_time = make_omit_timespec()
1576 * Initialize num_streams and streams, then call VFS op streaminfo
1579 NTSTATUS vfs_fstreaminfo(struct files_struct *fsp,
1580 TALLOC_CTX *mem_ctx,
1581 unsigned int *num_streams,
1582 struct stream_struct **streams)
1584 *num_streams = 0;
1585 *streams = NULL;
1587 if (fsp == NULL) {
1589 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
1590 * symlink. This is ok, handle it here, by just return no
1591 * streams on a symlink.
1593 return NT_STATUS_OK;
1596 if (fsp_get_pathref_fd(fsp) == -1) {
1598 * No streams on non-real files/directories.
1600 return NT_STATUS_OK;
1603 return SMB_VFS_FSTREAMINFO(fsp,
1604 mem_ctx,
1605 num_streams,
1606 streams);
1609 int vfs_fake_fd(void)
1611 int pipe_fds[2];
1612 int ret;
1615 * Return a valid fd, but ensure any attempt to use
1616 * it returns an error (EPIPE).
1618 ret = pipe(pipe_fds);
1619 if (ret != 0) {
1620 return -1;
1623 close(pipe_fds[1]);
1624 return pipe_fds[0];
1628 * This is just a helper to make
1629 * users of vfs_fake_fd() more symmetric
1631 int vfs_fake_fd_close(int fd)
1633 return close(fd);
1637 generate a file_id from a stat structure
1639 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1641 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1644 NTSTATUS vfs_at_fspcwd(TALLOC_CTX *mem_ctx,
1645 struct connection_struct *conn,
1646 struct files_struct **_fsp)
1648 struct files_struct *fsp = NULL;
1650 fsp = talloc_zero(mem_ctx, struct files_struct);
1651 if (fsp == NULL) {
1652 return NT_STATUS_NO_MEMORY;
1655 fsp->fsp_name = synthetic_smb_fname(fsp, ".", NULL, NULL, 0, 0);
1656 if (fsp->fsp_name == NULL) {
1657 TALLOC_FREE(fsp);
1658 return NT_STATUS_NO_MEMORY;
1661 fsp->fh = fd_handle_create(fsp);
1662 if (fsp->fh == NULL) {
1663 TALLOC_FREE(fsp);
1664 return NT_STATUS_NO_MEMORY;
1667 fsp_set_fd(fsp, AT_FDCWD);
1668 fsp->fnum = FNUM_FIELD_INVALID;
1669 fsp->conn = conn;
1671 *_fsp = fsp;
1672 return NT_STATUS_OK;
1675 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1676 const char *service, const char *user)
1678 VFS_FIND(connect);
1679 return handle->fns->connect_fn(handle, service, user);
1682 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1684 VFS_FIND(disconnect);
1685 handle->fns->disconnect_fn(handle);
1688 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1689 const struct smb_filename *smb_fname,
1690 uint64_t *bsize,
1691 uint64_t *dfree,
1692 uint64_t *dsize)
1694 VFS_FIND(disk_free);
1695 return handle->fns->disk_free_fn(handle, smb_fname,
1696 bsize, dfree, dsize);
1699 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1700 const struct smb_filename *smb_fname,
1701 enum SMB_QUOTA_TYPE qtype,
1702 unid_t id,
1703 SMB_DISK_QUOTA *qt)
1705 VFS_FIND(get_quota);
1706 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1709 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1710 enum SMB_QUOTA_TYPE qtype, unid_t id,
1711 SMB_DISK_QUOTA *qt)
1713 VFS_FIND(set_quota);
1714 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1717 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1718 struct files_struct *fsp,
1719 struct shadow_copy_data *shadow_copy_data,
1720 bool labels)
1722 VFS_FIND(get_shadow_copy_data);
1723 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1724 shadow_copy_data,
1725 labels);
1727 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1728 const struct smb_filename *smb_fname,
1729 struct vfs_statvfs_struct *statbuf)
1731 VFS_FIND(statvfs);
1732 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1735 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1736 enum timestamp_set_resolution *p_ts_res)
1738 VFS_FIND(fs_capabilities);
1739 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1742 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1743 struct dfs_GetDFSReferral *r)
1745 VFS_FIND(get_dfs_referrals);
1746 return handle->fns->get_dfs_referrals_fn(handle, r);
1749 NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
1750 struct files_struct *dirfsp,
1751 const struct smb_filename *smb_fname,
1752 const struct referral *reflist,
1753 size_t referral_count)
1755 VFS_FIND(create_dfs_pathat);
1756 return handle->fns->create_dfs_pathat_fn(handle,
1757 dirfsp,
1758 smb_fname,
1759 reflist,
1760 referral_count);
1763 NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
1764 TALLOC_CTX *mem_ctx,
1765 struct files_struct *dirfsp,
1766 struct smb_filename *smb_fname,
1767 struct referral **ppreflist,
1768 size_t *preferral_count)
1770 VFS_FIND(read_dfs_pathat);
1771 return handle->fns->read_dfs_pathat_fn(handle,
1772 mem_ctx,
1773 dirfsp,
1774 smb_fname,
1775 ppreflist,
1776 preferral_count);
1779 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1780 struct files_struct *fsp,
1781 const char *mask,
1782 uint32_t attributes)
1784 VFS_FIND(fdopendir);
1785 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1788 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1789 struct files_struct *dirfsp,
1790 DIR *dirp,
1791 SMB_STRUCT_STAT *sbuf)
1793 VFS_FIND(readdir);
1794 return handle->fns->readdir_fn(handle, dirfsp, dirp, sbuf);
1797 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1798 DIR *dirp, long offset)
1800 VFS_FIND(seekdir);
1801 handle->fns->seekdir_fn(handle, dirp, offset);
1804 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1805 DIR *dirp)
1807 VFS_FIND(telldir);
1808 return handle->fns->telldir_fn(handle, dirp);
1811 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1812 DIR *dirp)
1814 VFS_FIND(rewind_dir);
1815 handle->fns->rewind_dir_fn(handle, dirp);
1818 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1819 struct files_struct *dirfsp,
1820 const struct smb_filename *smb_fname,
1821 mode_t mode)
1823 VFS_FIND(mkdirat);
1824 return handle->fns->mkdirat_fn(handle,
1825 dirfsp,
1826 smb_fname,
1827 mode);
1830 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1831 DIR *dir)
1833 VFS_FIND(closedir);
1834 return handle->fns->closedir_fn(handle, dir);
1837 int smb_vfs_call_openat(struct vfs_handle_struct *handle,
1838 const struct files_struct *dirfsp,
1839 const struct smb_filename *smb_fname,
1840 struct files_struct *fsp,
1841 int flags,
1842 mode_t mode)
1844 VFS_FIND(openat);
1845 return handle->fns->openat_fn(handle,
1846 dirfsp,
1847 smb_fname,
1848 fsp,
1849 flags,
1850 mode);
1853 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1854 struct smb_request *req,
1855 struct smb_filename *smb_fname,
1856 uint32_t access_mask,
1857 uint32_t share_access,
1858 uint32_t create_disposition,
1859 uint32_t create_options,
1860 uint32_t file_attributes,
1861 uint32_t oplock_request,
1862 const struct smb2_lease *lease,
1863 uint64_t allocation_size,
1864 uint32_t private_flags,
1865 struct security_descriptor *sd,
1866 struct ea_list *ea_list,
1867 files_struct **result,
1868 int *pinfo,
1869 const struct smb2_create_blobs *in_context_blobs,
1870 struct smb2_create_blobs *out_context_blobs)
1872 VFS_FIND(create_file);
1873 return handle->fns->create_file_fn(
1874 handle, req, smb_fname,
1875 access_mask, share_access, create_disposition, create_options,
1876 file_attributes, oplock_request, lease, allocation_size,
1877 private_flags, sd, ea_list,
1878 result, pinfo, in_context_blobs, out_context_blobs);
1881 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1882 struct files_struct *fsp)
1884 VFS_FIND(close);
1885 return handle->fns->close_fn(handle, fsp);
1888 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1889 struct files_struct *fsp, void *data, size_t n,
1890 off_t offset)
1892 VFS_FIND(pread);
1893 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1896 struct smb_vfs_call_pread_state {
1897 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1898 ssize_t retval;
1899 struct vfs_aio_state vfs_aio_state;
1902 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1904 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1905 TALLOC_CTX *mem_ctx,
1906 struct tevent_context *ev,
1907 struct files_struct *fsp,
1908 void *data,
1909 size_t n, off_t offset)
1911 struct tevent_req *req, *subreq;
1912 struct smb_vfs_call_pread_state *state;
1914 req = tevent_req_create(mem_ctx, &state,
1915 struct smb_vfs_call_pread_state);
1916 if (req == NULL) {
1917 return NULL;
1919 VFS_FIND(pread_send);
1920 state->recv_fn = handle->fns->pread_recv_fn;
1922 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1923 offset);
1924 if (tevent_req_nomem(subreq, req)) {
1925 return tevent_req_post(req, ev);
1927 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1928 return req;
1931 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1933 struct tevent_req *req = tevent_req_callback_data(
1934 subreq, struct tevent_req);
1935 struct smb_vfs_call_pread_state *state = tevent_req_data(
1936 req, struct smb_vfs_call_pread_state);
1938 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1939 TALLOC_FREE(subreq);
1940 if (state->retval == -1) {
1941 tevent_req_error(req, state->vfs_aio_state.error);
1942 return;
1944 tevent_req_done(req);
1947 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1948 struct vfs_aio_state *vfs_aio_state)
1950 struct smb_vfs_call_pread_state *state = tevent_req_data(
1951 req, struct smb_vfs_call_pread_state);
1952 ssize_t retval;
1954 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1955 tevent_req_received(req);
1956 return -1;
1958 *vfs_aio_state = state->vfs_aio_state;
1959 retval = state->retval;
1960 tevent_req_received(req);
1961 return retval;
1964 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1965 struct files_struct *fsp, const void *data,
1966 size_t n, off_t offset)
1968 VFS_FIND(pwrite);
1969 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1972 struct smb_vfs_call_pwrite_state {
1973 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1974 ssize_t retval;
1975 struct vfs_aio_state vfs_aio_state;
1978 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1980 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1981 TALLOC_CTX *mem_ctx,
1982 struct tevent_context *ev,
1983 struct files_struct *fsp,
1984 const void *data,
1985 size_t n, off_t offset)
1987 struct tevent_req *req, *subreq;
1988 struct smb_vfs_call_pwrite_state *state;
1990 req = tevent_req_create(mem_ctx, &state,
1991 struct smb_vfs_call_pwrite_state);
1992 if (req == NULL) {
1993 return NULL;
1995 VFS_FIND(pwrite_send);
1996 state->recv_fn = handle->fns->pwrite_recv_fn;
1998 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1999 offset);
2000 if (tevent_req_nomem(subreq, req)) {
2001 return tevent_req_post(req, ev);
2003 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
2004 return req;
2007 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
2009 struct tevent_req *req = tevent_req_callback_data(
2010 subreq, struct tevent_req);
2011 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
2012 req, struct smb_vfs_call_pwrite_state);
2014 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2015 TALLOC_FREE(subreq);
2016 if (state->retval == -1) {
2017 tevent_req_error(req, state->vfs_aio_state.error);
2018 return;
2020 tevent_req_done(req);
2023 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
2024 struct vfs_aio_state *vfs_aio_state)
2026 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
2027 req, struct smb_vfs_call_pwrite_state);
2028 ssize_t retval;
2030 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2031 tevent_req_received(req);
2032 return -1;
2034 *vfs_aio_state = state->vfs_aio_state;
2035 retval = state->retval;
2036 tevent_req_received(req);
2037 return retval;
2040 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
2041 struct files_struct *fsp, off_t offset,
2042 int whence)
2044 VFS_FIND(lseek);
2045 return handle->fns->lseek_fn(handle, fsp, offset, whence);
2048 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
2049 files_struct *fromfsp, const DATA_BLOB *header,
2050 off_t offset, size_t count)
2052 VFS_FIND(sendfile);
2053 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
2054 count);
2057 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
2058 files_struct *tofsp, off_t offset,
2059 size_t count)
2061 VFS_FIND(recvfile);
2062 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
2065 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
2066 files_struct *srcfsp,
2067 const struct smb_filename *smb_fname_src,
2068 files_struct *dstfsp,
2069 const struct smb_filename *smb_fname_dst)
2071 VFS_FIND(renameat);
2072 return handle->fns->renameat_fn(handle,
2073 srcfsp,
2074 smb_fname_src,
2075 dstfsp,
2076 smb_fname_dst);
2079 struct smb_vfs_call_fsync_state {
2080 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
2081 int retval;
2082 struct vfs_aio_state vfs_aio_state;
2085 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
2087 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
2088 TALLOC_CTX *mem_ctx,
2089 struct tevent_context *ev,
2090 struct files_struct *fsp)
2092 struct tevent_req *req, *subreq;
2093 struct smb_vfs_call_fsync_state *state;
2095 req = tevent_req_create(mem_ctx, &state,
2096 struct smb_vfs_call_fsync_state);
2097 if (req == NULL) {
2098 return NULL;
2100 VFS_FIND(fsync_send);
2101 state->recv_fn = handle->fns->fsync_recv_fn;
2103 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
2104 if (tevent_req_nomem(subreq, req)) {
2105 return tevent_req_post(req, ev);
2107 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
2108 return req;
2111 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
2113 struct tevent_req *req = tevent_req_callback_data(
2114 subreq, struct tevent_req);
2115 struct smb_vfs_call_fsync_state *state = tevent_req_data(
2116 req, struct smb_vfs_call_fsync_state);
2118 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2119 TALLOC_FREE(subreq);
2120 if (state->retval == -1) {
2121 tevent_req_error(req, state->vfs_aio_state.error);
2122 return;
2124 tevent_req_done(req);
2127 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
2129 struct smb_vfs_call_fsync_state *state = tevent_req_data(
2130 req, struct smb_vfs_call_fsync_state);
2131 ssize_t retval;
2133 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2134 tevent_req_received(req);
2135 return -1;
2137 *vfs_aio_state = state->vfs_aio_state;
2138 retval = state->retval;
2139 tevent_req_received(req);
2140 return retval;
2144 * Synchronous version of fsync, built from backend
2145 * async VFS primitives. Uses a temporary sub-event
2146 * context (NOT NESTED).
2149 int smb_vfs_fsync_sync(files_struct *fsp)
2151 TALLOC_CTX *frame = talloc_stackframe();
2152 struct tevent_req *req = NULL;
2153 struct vfs_aio_state aio_state = { 0 };
2154 int ret = -1;
2155 bool ok;
2156 struct tevent_context *ev = samba_tevent_context_init(frame);
2158 if (ev == NULL) {
2159 goto out;
2162 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
2163 if (req == NULL) {
2164 goto out;
2167 ok = tevent_req_poll(req, ev);
2168 if (!ok) {
2169 goto out;
2172 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
2174 out:
2176 TALLOC_FREE(frame);
2177 if (aio_state.error != 0) {
2178 errno = aio_state.error;
2180 return ret;
2183 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
2184 struct smb_filename *smb_fname)
2186 VFS_FIND(stat);
2187 return handle->fns->stat_fn(handle, smb_fname);
2190 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2191 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2193 VFS_FIND(fstat);
2194 return handle->fns->fstat_fn(handle, fsp, sbuf);
2197 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2198 struct smb_filename *smb_filename)
2200 VFS_FIND(lstat);
2201 return handle->fns->lstat_fn(handle, smb_filename);
2204 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2205 struct files_struct *fsp,
2206 const SMB_STRUCT_STAT *sbuf)
2208 VFS_FIND(get_alloc_size);
2209 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2212 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
2213 struct files_struct *dirfsp,
2214 const struct smb_filename *smb_fname,
2215 int flags)
2217 VFS_FIND(unlinkat);
2218 return handle->fns->unlinkat_fn(handle,
2219 dirfsp,
2220 smb_fname,
2221 flags);
2224 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2225 struct files_struct *fsp, mode_t mode)
2227 VFS_FIND(fchmod);
2228 return handle->fns->fchmod_fn(handle, fsp, mode);
2231 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2232 struct files_struct *fsp, uid_t uid, gid_t gid)
2234 VFS_FIND(fchown);
2235 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2238 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2239 const struct smb_filename *smb_fname,
2240 uid_t uid,
2241 gid_t gid)
2243 VFS_FIND(lchown);
2244 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2247 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2248 const struct smb_filename *smb_fname)
2250 VFS_FIND(chdir);
2251 return handle->fns->chdir_fn(handle, smb_fname);
2254 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2255 TALLOC_CTX *ctx)
2257 VFS_FIND(getwd);
2258 return handle->fns->getwd_fn(handle, ctx);
2261 int smb_vfs_call_fntimes(struct vfs_handle_struct *handle,
2262 struct files_struct *fsp,
2263 struct smb_file_time *ft)
2265 VFS_FIND(fntimes);
2266 return handle->fns->fntimes_fn(handle, fsp, ft);
2269 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2270 struct files_struct *fsp, off_t offset)
2272 VFS_FIND(ftruncate);
2273 return handle->fns->ftruncate_fn(handle, fsp, offset);
2276 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2277 struct files_struct *fsp,
2278 uint32_t mode,
2279 off_t offset,
2280 off_t len)
2282 VFS_FIND(fallocate);
2283 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2286 int smb_vfs_call_filesystem_sharemode(struct vfs_handle_struct *handle,
2287 struct files_struct *fsp,
2288 uint32_t share_mode,
2289 uint32_t access_mask)
2291 VFS_FIND(filesystem_sharemode);
2292 return handle->fns->filesystem_sharemode_fn(handle,
2293 fsp,
2294 share_mode,
2295 access_mask);
2298 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2299 struct files_struct *fsp, int cmd, ...)
2301 int result;
2302 va_list cmd_arg;
2304 VFS_FIND(fcntl);
2306 va_start(cmd_arg, cmd);
2307 result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2308 va_end(cmd_arg);
2310 return result;
2313 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2314 struct files_struct *fsp, int leasetype)
2316 VFS_FIND(linux_setlease);
2317 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2320 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2321 const struct smb_filename *link_target,
2322 struct files_struct *dirfsp,
2323 const struct smb_filename *new_smb_fname)
2325 VFS_FIND(symlinkat);
2326 return handle->fns->symlinkat_fn(handle,
2327 link_target,
2328 dirfsp,
2329 new_smb_fname);
2332 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2333 const struct files_struct *dirfsp,
2334 const struct smb_filename *smb_fname,
2335 char *buf,
2336 size_t bufsiz)
2338 VFS_FIND(readlinkat);
2339 return handle->fns->readlinkat_fn(handle,
2340 dirfsp,
2341 smb_fname,
2342 buf,
2343 bufsiz);
2346 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2347 struct files_struct *srcfsp,
2348 const struct smb_filename *old_smb_fname,
2349 struct files_struct *dstfsp,
2350 const struct smb_filename *new_smb_fname,
2351 int flags)
2353 VFS_FIND(linkat);
2354 return handle->fns->linkat_fn(handle,
2355 srcfsp,
2356 old_smb_fname,
2357 dstfsp,
2358 new_smb_fname,
2359 flags);
2362 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2363 struct files_struct *dirfsp,
2364 const struct smb_filename *smb_fname,
2365 mode_t mode,
2366 SMB_DEV_T dev)
2368 VFS_FIND(mknodat);
2369 return handle->fns->mknodat_fn(handle,
2370 dirfsp,
2371 smb_fname,
2372 mode,
2373 dev);
2376 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2377 TALLOC_CTX *ctx,
2378 const struct smb_filename *smb_fname)
2380 VFS_FIND(realpath);
2381 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2384 int smb_vfs_call_fchflags(struct vfs_handle_struct *handle,
2385 struct files_struct *fsp,
2386 unsigned int flags)
2388 VFS_FIND(fchflags);
2389 return handle->fns->fchflags_fn(handle, fsp, flags);
2392 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2393 const SMB_STRUCT_STAT *sbuf)
2395 VFS_FIND(file_id_create);
2396 return handle->fns->file_id_create_fn(handle, sbuf);
2399 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2400 const SMB_STRUCT_STAT *sbuf)
2402 VFS_FIND(fs_file_id);
2403 return handle->fns->fs_file_id_fn(handle, sbuf);
2406 NTSTATUS smb_vfs_call_fstreaminfo(struct vfs_handle_struct *handle,
2407 struct files_struct *fsp,
2408 TALLOC_CTX *mem_ctx,
2409 unsigned int *num_streams,
2410 struct stream_struct **streams)
2412 VFS_FIND(fstreaminfo);
2413 return handle->fns->fstreaminfo_fn(handle, fsp, mem_ctx,
2414 num_streams, streams);
2417 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2418 const struct smb_filename *path,
2419 const char *name,
2420 TALLOC_CTX *mem_ctx,
2421 char **found_name)
2423 VFS_FIND(get_real_filename);
2424 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2425 found_name);
2428 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2429 const struct smb_filename *smb_fname)
2431 VFS_FIND(connectpath);
2432 return handle->fns->connectpath_fn(handle, smb_fname);
2435 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2436 struct files_struct *fsp,
2437 struct lock_struct *plock)
2439 VFS_FIND(strict_lock_check);
2440 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2443 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2444 const char *name,
2445 enum vfs_translate_direction direction,
2446 TALLOC_CTX *mem_ctx,
2447 char **mapped_name)
2449 VFS_FIND(translate_name);
2450 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2451 mapped_name);
2454 NTSTATUS smb_vfs_call_parent_pathname(struct vfs_handle_struct *handle,
2455 TALLOC_CTX *mem_ctx,
2456 const struct smb_filename *smb_fname_in,
2457 struct smb_filename **parent_dir_out,
2458 struct smb_filename **atname_out)
2460 VFS_FIND(parent_pathname);
2461 return handle->fns->parent_pathname_fn(handle,
2462 mem_ctx,
2463 smb_fname_in,
2464 parent_dir_out,
2465 atname_out);
2468 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2469 struct files_struct *fsp,
2470 TALLOC_CTX *ctx,
2471 uint32_t function,
2472 uint16_t req_flags,
2473 const uint8_t *in_data,
2474 uint32_t in_len,
2475 uint8_t **out_data,
2476 uint32_t max_out_len,
2477 uint32_t *out_len)
2479 VFS_FIND(fsctl);
2480 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2481 in_data, in_len, out_data, max_out_len,
2482 out_len);
2485 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2486 struct files_struct *fsp,
2487 uint32_t *dosmode)
2489 VFS_FIND(fget_dos_attributes);
2490 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2493 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2494 struct files_struct *fsp,
2495 uint32_t dosmode)
2497 VFS_FIND(fset_dos_attributes);
2498 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2501 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2502 struct tevent_context *ev,
2503 struct vfs_handle_struct *handle,
2504 struct files_struct *fsp,
2505 uint32_t fsctl,
2506 uint32_t ttl,
2507 off_t offset,
2508 size_t to_copy)
2510 VFS_FIND(offload_read_send);
2511 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2512 fsp, fsctl,
2513 ttl, offset, to_copy);
2516 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2517 struct vfs_handle_struct *handle,
2518 TALLOC_CTX *mem_ctx,
2519 uint32_t *flags,
2520 uint64_t *xferlen,
2521 DATA_BLOB *token_blob)
2523 VFS_FIND(offload_read_recv);
2524 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, flags, xferlen, token_blob);
2527 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2528 TALLOC_CTX *mem_ctx,
2529 struct tevent_context *ev,
2530 uint32_t fsctl,
2531 DATA_BLOB *token,
2532 off_t transfer_offset,
2533 struct files_struct *dest_fsp,
2534 off_t dest_off,
2535 off_t num)
2537 VFS_FIND(offload_write_send);
2538 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2539 token, transfer_offset,
2540 dest_fsp, dest_off, num);
2543 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2544 struct tevent_req *req,
2545 off_t *copied)
2547 VFS_FIND(offload_write_recv);
2548 return handle->fns->offload_write_recv_fn(handle, req, copied);
2551 struct smb_vfs_call_get_dos_attributes_state {
2552 files_struct *dir_fsp;
2553 NTSTATUS (*recv_fn)(struct tevent_req *req,
2554 struct vfs_aio_state *aio_state,
2555 uint32_t *dosmode);
2556 struct vfs_aio_state aio_state;
2557 uint32_t dos_attributes;
2560 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2562 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2563 TALLOC_CTX *mem_ctx,
2564 struct tevent_context *ev,
2565 struct vfs_handle_struct *handle,
2566 files_struct *dir_fsp,
2567 struct smb_filename *smb_fname)
2569 struct tevent_req *req = NULL;
2570 struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2571 struct tevent_req *subreq = NULL;
2573 req = tevent_req_create(mem_ctx, &state,
2574 struct smb_vfs_call_get_dos_attributes_state);
2575 if (req == NULL) {
2576 return NULL;
2579 VFS_FIND(get_dos_attributes_send);
2581 *state = (struct smb_vfs_call_get_dos_attributes_state) {
2582 .dir_fsp = dir_fsp,
2583 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2586 subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2588 handle,
2589 dir_fsp,
2590 smb_fname);
2591 if (tevent_req_nomem(subreq, req)) {
2592 return tevent_req_post(req, ev);
2594 tevent_req_defer_callback(req, ev);
2596 tevent_req_set_callback(subreq,
2597 smb_vfs_call_get_dos_attributes_done,
2598 req);
2600 return req;
2603 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2605 struct tevent_req *req =
2606 tevent_req_callback_data(subreq,
2607 struct tevent_req);
2608 struct smb_vfs_call_get_dos_attributes_state *state =
2609 tevent_req_data(req,
2610 struct smb_vfs_call_get_dos_attributes_state);
2611 NTSTATUS status;
2612 bool ok;
2615 * Make sure we run as the user again
2617 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2618 SMB_ASSERT(ok);
2620 status = state->recv_fn(subreq,
2621 &state->aio_state,
2622 &state->dos_attributes);
2623 TALLOC_FREE(subreq);
2624 if (tevent_req_nterror(req, status)) {
2625 return;
2628 tevent_req_done(req);
2631 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2632 struct tevent_req *req,
2633 struct vfs_aio_state *aio_state,
2634 uint32_t *dos_attributes)
2636 struct smb_vfs_call_get_dos_attributes_state *state =
2637 tevent_req_data(req,
2638 struct smb_vfs_call_get_dos_attributes_state);
2639 NTSTATUS status;
2641 if (tevent_req_is_nterror(req, &status)) {
2642 tevent_req_received(req);
2643 return status;
2646 *aio_state = state->aio_state;
2647 *dos_attributes = state->dos_attributes;
2648 tevent_req_received(req);
2649 return NT_STATUS_OK;
2652 NTSTATUS smb_vfs_call_fget_compression(vfs_handle_struct *handle,
2653 TALLOC_CTX *mem_ctx,
2654 struct files_struct *fsp,
2655 uint16_t *_compression_fmt)
2657 VFS_FIND(fget_compression);
2658 return handle->fns->fget_compression_fn(handle, mem_ctx, fsp,
2659 _compression_fmt);
2662 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2663 TALLOC_CTX *mem_ctx,
2664 struct files_struct *fsp,
2665 uint16_t compression_fmt)
2667 VFS_FIND(set_compression);
2668 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2669 compression_fmt);
2672 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2673 TALLOC_CTX *mem_ctx,
2674 const char *service_path,
2675 char **base_volume)
2677 VFS_FIND(snap_check_path);
2678 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2679 base_volume);
2682 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2683 TALLOC_CTX *mem_ctx,
2684 const char *base_volume,
2685 time_t *tstamp,
2686 bool rw,
2687 char **base_path,
2688 char **snap_path)
2690 VFS_FIND(snap_create);
2691 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2692 rw, base_path, snap_path);
2695 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2696 TALLOC_CTX *mem_ctx,
2697 char *base_path,
2698 char *snap_path)
2700 VFS_FIND(snap_delete);
2701 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2702 snap_path);
2705 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2706 struct files_struct *fsp,
2707 uint32_t security_info,
2708 TALLOC_CTX *mem_ctx,
2709 struct security_descriptor **ppdesc)
2711 VFS_FIND(fget_nt_acl);
2712 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2713 mem_ctx, ppdesc);
2716 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2717 struct files_struct *fsp,
2718 uint32_t security_info_sent,
2719 const struct security_descriptor *psd)
2721 VFS_FIND(fset_nt_acl);
2722 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2723 psd);
2726 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2727 struct smb_filename *file,
2728 struct security_acl *sacl,
2729 uint32_t access_requested,
2730 uint32_t access_denied)
2732 VFS_FIND(audit_file);
2733 return handle->fns->audit_file_fn(handle,
2734 file,
2735 sacl,
2736 access_requested,
2737 access_denied);
2740 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2741 struct files_struct *fsp,
2742 SMB_ACL_TYPE_T type,
2743 TALLOC_CTX *mem_ctx)
2745 VFS_FIND(sys_acl_get_fd);
2746 return handle->fns->sys_acl_get_fd_fn(handle, fsp, type, mem_ctx);
2749 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2750 struct files_struct *fsp,
2751 TALLOC_CTX *mem_ctx,
2752 char **blob_description,
2753 DATA_BLOB *blob)
2755 VFS_FIND(sys_acl_blob_get_fd);
2756 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2759 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2760 struct files_struct *fsp,
2761 SMB_ACL_TYPE_T type,
2762 SMB_ACL_T theacl)
2764 VFS_FIND(sys_acl_set_fd);
2765 return handle->fns->sys_acl_set_fd_fn(handle, fsp, type, theacl);
2768 int smb_vfs_call_sys_acl_delete_def_fd(struct vfs_handle_struct *handle,
2769 struct files_struct *fsp)
2771 VFS_FIND(sys_acl_delete_def_fd);
2772 return handle->fns->sys_acl_delete_def_fd_fn(handle, fsp);
2775 struct smb_vfs_call_getxattrat_state {
2776 files_struct *dir_fsp;
2777 ssize_t (*recv_fn)(struct tevent_req *req,
2778 struct vfs_aio_state *aio_state,
2779 TALLOC_CTX *mem_ctx,
2780 uint8_t **xattr_value);
2781 ssize_t retval;
2782 uint8_t *xattr_value;
2783 struct vfs_aio_state aio_state;
2786 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2788 struct tevent_req *smb_vfs_call_getxattrat_send(
2789 TALLOC_CTX *mem_ctx,
2790 struct tevent_context *ev,
2791 struct vfs_handle_struct *handle,
2792 files_struct *dir_fsp,
2793 const struct smb_filename *smb_fname,
2794 const char *xattr_name,
2795 size_t alloc_hint)
2797 struct tevent_req *req = NULL;
2798 struct smb_vfs_call_getxattrat_state *state = NULL;
2799 struct tevent_req *subreq = NULL;
2801 req = tevent_req_create(mem_ctx, &state,
2802 struct smb_vfs_call_getxattrat_state);
2803 if (req == NULL) {
2804 return NULL;
2807 VFS_FIND(getxattrat_send);
2809 *state = (struct smb_vfs_call_getxattrat_state) {
2810 .dir_fsp = dir_fsp,
2811 .recv_fn = handle->fns->getxattrat_recv_fn,
2814 subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2816 handle,
2817 dir_fsp,
2818 smb_fname,
2819 xattr_name,
2820 alloc_hint);
2821 if (tevent_req_nomem(subreq, req)) {
2822 return tevent_req_post(req, ev);
2824 tevent_req_defer_callback(req, ev);
2826 tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2827 return req;
2830 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2832 struct tevent_req *req = tevent_req_callback_data(
2833 subreq, struct tevent_req);
2834 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2835 req, struct smb_vfs_call_getxattrat_state);
2836 bool ok;
2839 * Make sure we run as the user again
2841 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2842 SMB_ASSERT(ok);
2844 state->retval = state->recv_fn(subreq,
2845 &state->aio_state,
2846 state,
2847 &state->xattr_value);
2848 TALLOC_FREE(subreq);
2849 if (state->retval == -1) {
2850 tevent_req_error(req, state->aio_state.error);
2851 return;
2854 tevent_req_done(req);
2857 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2858 struct vfs_aio_state *aio_state,
2859 TALLOC_CTX *mem_ctx,
2860 uint8_t **xattr_value)
2862 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2863 req, struct smb_vfs_call_getxattrat_state);
2864 size_t xattr_size;
2866 if (tevent_req_is_unix_error(req, &aio_state->error)) {
2867 tevent_req_received(req);
2868 return -1;
2871 *aio_state = state->aio_state;
2872 xattr_size = state->retval;
2873 if (xattr_value != NULL) {
2874 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2877 tevent_req_received(req);
2878 return xattr_size;
2881 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2882 struct files_struct *fsp, const char *name,
2883 void *value, size_t size)
2885 VFS_FIND(fgetxattr);
2886 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2889 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2890 struct files_struct *fsp, char *list,
2891 size_t size)
2893 VFS_FIND(flistxattr);
2894 return handle->fns->flistxattr_fn(handle, fsp, list, size);
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_fsetxattr(struct vfs_handle_struct *handle,
2905 struct files_struct *fsp, const char *name,
2906 const void *value, size_t size, int flags)
2908 VFS_FIND(fsetxattr);
2909 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2912 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2913 struct files_struct *fsp)
2915 VFS_FIND(aio_force);
2916 return handle->fns->aio_force_fn(handle, fsp);
2919 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2920 struct files_struct *fsp,
2921 TALLOC_CTX *mem_ctx,
2922 DATA_BLOB *cookie)
2924 VFS_FIND(durable_cookie);
2925 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2928 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2929 struct files_struct *fsp,
2930 const DATA_BLOB old_cookie,
2931 TALLOC_CTX *mem_ctx,
2932 DATA_BLOB *new_cookie)
2934 VFS_FIND(durable_disconnect);
2935 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2936 mem_ctx, new_cookie);
2939 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2940 struct smb_request *smb1req,
2941 struct smbXsrv_open *op,
2942 const DATA_BLOB old_cookie,
2943 TALLOC_CTX *mem_ctx,
2944 struct files_struct **fsp,
2945 DATA_BLOB *new_cookie)
2947 VFS_FIND(durable_reconnect);
2948 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2949 old_cookie, mem_ctx, fsp,
2950 new_cookie);
2953 NTSTATUS smb_vfs_call_freaddir_attr(struct vfs_handle_struct *handle,
2954 struct files_struct *fsp,
2955 TALLOC_CTX *mem_ctx,
2956 struct readdir_attr_data **attr_data)
2958 VFS_FIND(freaddir_attr);
2959 return handle->fns->freaddir_attr_fn(handle,
2960 fsp,
2961 mem_ctx,
2962 attr_data);