s3/vfs: rename SMB_VFS_STRICT_LOCK to SMB_VFS_STRICT_LOCK_CHECK
[Samba.git] / source3 / smbd / vfs.c
blobdc0d14dc82ffd8e12a166a40c1cdcde71984c446
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 VFS initialisation and support functions
5 Copyright (C) Tim Potter 1999
6 Copyright (C) Alexander Bokovoy 2002
7 Copyright (C) James Peach 2006
8 Copyright (C) Volker Lendecke 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This work was sponsored by Optifacio Software Services, Inc.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "../lib/util/memcache.h"
31 #include "transfer_file.h"
32 #include "ntioctl.h"
33 #include "lib/util/tevent_unix.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_VFS
38 static_decl_vfs;
40 struct vfs_fsp_data {
41 struct vfs_fsp_data *next;
42 struct vfs_handle_struct *owner;
43 void (*destroy)(void *p_data);
44 void *_dummy_;
45 /* NOTE: This structure contains four pointers so that we can guarantee
46 * that the end of the structure is always both 4-byte and 8-byte aligned.
50 struct vfs_init_function_entry {
51 char *name;
52 struct vfs_init_function_entry *prev, *next;
53 const struct vfs_fn_pointers *fns;
56 /****************************************************************************
57 maintain the list of available backends
58 ****************************************************************************/
60 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
62 struct vfs_init_function_entry *entry = backends;
64 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
66 while(entry) {
67 if (strcmp(entry->name, name)==0) return entry;
68 entry = entry->next;
71 return NULL;
74 NTSTATUS smb_register_vfs(int version, const char *name,
75 const struct vfs_fn_pointers *fns)
77 struct vfs_init_function_entry *entry = backends;
79 if ((version != SMB_VFS_INTERFACE_VERSION)) {
80 DEBUG(0, ("Failed to register vfs module.\n"
81 "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
82 "current SMB_VFS_INTERFACE_VERSION is %d.\n"
83 "Please recompile against the current Samba Version!\n",
84 version, SMB_VFS_INTERFACE_VERSION));
85 return NT_STATUS_OBJECT_TYPE_MISMATCH;
88 if (!name || !name[0]) {
89 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
90 return NT_STATUS_INVALID_PARAMETER;
93 if (vfs_find_backend_entry(name)) {
94 DEBUG(0,("VFS module %s already loaded!\n", name));
95 return NT_STATUS_OBJECT_NAME_COLLISION;
98 entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
99 entry->name = smb_xstrdup(name);
100 entry->fns = fns;
102 DLIST_ADD(backends, entry);
103 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
104 return NT_STATUS_OK;
107 /****************************************************************************
108 initialise default vfs hooks
109 ****************************************************************************/
111 static void vfs_init_default(connection_struct *conn)
113 DEBUG(3, ("Initialising default vfs hooks\n"));
114 vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
117 /****************************************************************************
118 initialise custom vfs hooks
119 ****************************************************************************/
121 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
123 char *module_path = NULL;
124 char *module_name = NULL;
125 char *module_param = NULL, *p;
126 vfs_handle_struct *handle;
127 const struct vfs_init_function_entry *entry;
129 if (!conn||!vfs_object||!vfs_object[0]) {
130 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
131 "empty vfs_object!\n"));
132 return False;
135 if(!backends) {
136 static_init_vfs(NULL);
139 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
141 module_path = smb_xstrdup(vfs_object);
143 p = strchr_m(module_path, ':');
145 if (p) {
146 *p = 0;
147 module_param = p+1;
148 trim_char(module_param, ' ', ' ');
151 trim_char(module_path, ' ', ' ');
153 module_name = smb_xstrdup(module_path);
155 if ((module_name[0] == '/') &&
156 (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
159 * Extract the module name from the path. Just use the base
160 * name of the last path component.
163 SAFE_FREE(module_name);
164 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
166 p = strchr_m(module_name, '.');
168 if (p != NULL) {
169 *p = '\0';
173 /* First, try to load the module with the new module system */
174 entry = vfs_find_backend_entry(module_name);
175 if (!entry) {
176 NTSTATUS status;
178 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
179 vfs_object));
181 status = smb_load_module("vfs", module_path);
182 if (!NT_STATUS_IS_OK(status)) {
183 DEBUG(0, ("error probing vfs module '%s': %s\n",
184 module_path, nt_errstr(status)));
185 goto fail;
188 entry = vfs_find_backend_entry(module_name);
189 if (!entry) {
190 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
191 goto fail;
195 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
197 handle = talloc_zero(conn, vfs_handle_struct);
198 if (!handle) {
199 DEBUG(0,("TALLOC_ZERO() failed!\n"));
200 goto fail;
202 handle->conn = conn;
203 handle->fns = entry->fns;
204 if (module_param) {
205 handle->param = talloc_strdup(conn, module_param);
207 DLIST_ADD(conn->vfs_handles, handle);
209 SAFE_FREE(module_path);
210 SAFE_FREE(module_name);
211 return True;
213 fail:
214 SAFE_FREE(module_path);
215 SAFE_FREE(module_name);
216 return False;
219 /*****************************************************************
220 Allow VFS modules to extend files_struct with VFS-specific state.
221 This will be ok for small numbers of extensions, but might need to
222 be refactored if it becomes more widely used.
223 ******************************************************************/
225 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
227 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
228 files_struct *fsp, size_t ext_size,
229 void (*destroy_fn)(void *p_data))
231 struct vfs_fsp_data *ext;
232 void * ext_data;
234 /* Prevent VFS modules adding multiple extensions. */
235 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
236 return ext_data;
239 ext = (struct vfs_fsp_data *)TALLOC_ZERO(
240 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
241 if (ext == NULL) {
242 return NULL;
245 ext->owner = handle;
246 ext->next = fsp->vfs_extension;
247 ext->destroy = destroy_fn;
248 fsp->vfs_extension = ext;
249 return EXT_DATA_AREA(ext);
252 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
254 struct vfs_fsp_data *curr;
255 struct vfs_fsp_data *prev;
257 for (curr = fsp->vfs_extension, prev = NULL;
258 curr;
259 prev = curr, curr = curr->next) {
260 if (curr->owner == handle) {
261 if (prev) {
262 prev->next = curr->next;
263 } else {
264 fsp->vfs_extension = curr->next;
266 if (curr->destroy) {
267 curr->destroy(EXT_DATA_AREA(curr));
269 TALLOC_FREE(curr);
270 return;
275 void vfs_remove_all_fsp_extensions(files_struct *fsp)
277 struct vfs_fsp_data *curr;
278 struct vfs_fsp_data *next;
280 for (curr = fsp->vfs_extension; curr; curr = next) {
282 next = curr->next;
283 fsp->vfs_extension = next;
285 if (curr->destroy) {
286 curr->destroy(EXT_DATA_AREA(curr));
288 TALLOC_FREE(curr);
292 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
294 struct vfs_fsp_data *head;
296 for (head = fsp->vfs_extension; head; head = head->next) {
297 if (head->owner == handle) {
298 return head;
302 return NULL;
305 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
307 struct vfs_fsp_data *head;
309 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
310 if (head != NULL) {
311 return EXT_DATA_AREA(head);
314 return NULL;
317 #undef EXT_DATA_AREA
320 * Ensure this module catches all VFS functions.
322 #ifdef DEVELOPER
323 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
324 const char *module)
326 bool missing_fn = false;
327 unsigned int idx;
328 const uintptr_t *end = (const uintptr_t *)(fns + 1);
330 for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
331 if (*((const uintptr_t *)fns + idx) == 0) {
332 DBG_ERR("VFS function at index %d not implemented "
333 "in module %s\n", idx, module);
334 missing_fn = true;
338 if (missing_fn) {
339 smb_panic("Required VFS function not implemented in module.\n");
342 #else
343 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
344 const char *module)
347 #endif
349 /*****************************************************************
350 Generic VFS init.
351 ******************************************************************/
353 bool smbd_vfs_init(connection_struct *conn)
355 const char **vfs_objects;
356 unsigned int i = 0;
357 int j = 0;
359 /* Normal share - initialise with disk access functions */
360 vfs_init_default(conn);
362 /* No need to load vfs modules for printer connections */
363 if (conn->printer) {
364 return True;
367 vfs_objects = lp_vfs_objects(SNUM(conn));
369 /* Override VFS functions if 'vfs object' was not specified*/
370 if (!vfs_objects || !vfs_objects[0])
371 return True;
373 for (i=0; vfs_objects[i] ;) {
374 i++;
377 for (j=i-1; j >= 0; j--) {
378 if (!vfs_init_custom(conn, vfs_objects[j])) {
379 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
380 return False;
383 return True;
386 /*******************************************************************
387 Check if a file exists in the vfs.
388 ********************************************************************/
390 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
392 /* Only return OK if stat was successful and S_ISREG */
393 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
394 S_ISREG(smb_fname->st.st_ex_mode)) {
395 return NT_STATUS_OK;
398 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
401 /****************************************************************************
402 Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
403 ****************************************************************************/
405 ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
407 size_t total=0;
409 while (total < byte_count)
411 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
412 byte_count - total);
414 if (ret == 0) return total;
415 if (ret == -1) {
416 if (errno == EINTR)
417 continue;
418 else
419 return -1;
421 total += ret;
423 return (ssize_t)total;
426 /****************************************************************************
427 Write data to a fd on the vfs.
428 ****************************************************************************/
430 ssize_t vfs_write_data(struct smb_request *req,
431 files_struct *fsp,
432 const char *buffer,
433 size_t N)
435 size_t total=0;
436 ssize_t ret;
438 if (req && req->unread_bytes) {
439 int sockfd = req->xconn->transport.sock;
440 int old_flags;
441 SMB_ASSERT(req->unread_bytes == N);
442 /* VFS_RECVFILE must drain the socket
443 * before returning. */
444 req->unread_bytes = 0;
445 /* Ensure the socket is blocking. */
446 old_flags = fcntl(sockfd, F_GETFL, 0);
447 if (set_blocking(sockfd, true) == -1) {
448 return (ssize_t)-1;
450 ret = SMB_VFS_RECVFILE(sockfd,
451 fsp,
452 (off_t)-1,
454 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
455 return (ssize_t)-1;
457 return ret;
460 while (total < N) {
461 ret = SMB_VFS_WRITE(fsp, buffer + total, N - total);
463 if (ret == -1)
464 return -1;
465 if (ret == 0)
466 return total;
468 total += ret;
470 return (ssize_t)total;
473 ssize_t vfs_pwrite_data(struct smb_request *req,
474 files_struct *fsp,
475 const char *buffer,
476 size_t N,
477 off_t offset)
479 size_t total=0;
480 ssize_t ret;
482 if (req && req->unread_bytes) {
483 int sockfd = req->xconn->transport.sock;
484 SMB_ASSERT(req->unread_bytes == N);
485 /* VFS_RECVFILE must drain the socket
486 * before returning. */
487 req->unread_bytes = 0;
489 * Leave the socket non-blocking and
490 * use SMB_VFS_RECVFILE. If it returns
491 * EAGAIN || EWOULDBLOCK temporarily set
492 * the socket blocking and retry
493 * the RECVFILE.
495 while (total < N) {
496 ret = SMB_VFS_RECVFILE(sockfd,
497 fsp,
498 offset + total,
499 N - total);
500 if (ret == 0 || (ret == -1 &&
501 (errno == EAGAIN ||
502 errno == EWOULDBLOCK))) {
503 int old_flags;
504 /* Ensure the socket is blocking. */
505 old_flags = fcntl(sockfd, F_GETFL, 0);
506 if (set_blocking(sockfd, true) == -1) {
507 return (ssize_t)-1;
509 ret = SMB_VFS_RECVFILE(sockfd,
510 fsp,
511 offset + total,
512 N - total);
513 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
514 return (ssize_t)-1;
516 if (ret == -1) {
517 return (ssize_t)-1;
519 total += ret;
520 return (ssize_t)total;
522 /* Any other error case. */
523 if (ret == -1) {
524 return ret;
526 total += ret;
528 return (ssize_t)total;
531 while (total < N) {
532 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
533 offset + total);
535 if (ret == -1)
536 return -1;
537 if (ret == 0)
538 return total;
540 total += ret;
542 return (ssize_t)total;
544 /****************************************************************************
545 An allocate file space call using the vfs interface.
546 Allocates space for a file from a filedescriptor.
547 Returns 0 on success, -1 on failure.
548 ****************************************************************************/
550 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
552 int ret;
553 connection_struct *conn = fsp->conn;
554 uint64_t space_avail;
555 uint64_t bsize,dfree,dsize;
556 NTSTATUS status;
559 * Actually try and commit the space on disk....
562 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
563 fsp_str_dbg(fsp), (double)len));
565 if (((off_t)len) < 0) {
566 DEBUG(0,("vfs_allocate_file_space: %s negative len "
567 "requested.\n", fsp_str_dbg(fsp)));
568 errno = EINVAL;
569 return -1;
572 status = vfs_stat_fsp(fsp);
573 if (!NT_STATUS_IS_OK(status)) {
574 return -1;
577 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
578 return 0;
580 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
581 /* Shrink - use ftruncate. */
583 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
584 "size %.0f\n", fsp_str_dbg(fsp),
585 (double)fsp->fsp_name->st.st_ex_size));
587 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
589 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
590 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
591 set_filelen_write_cache(fsp, len);
594 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
596 return ret;
599 /* Grow - we need to test if we have enough space. */
601 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
603 if (lp_strict_allocate(SNUM(fsp->conn))) {
604 /* See if we have a syscall that will allocate beyond
605 end-of-file without changing EOF. */
606 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
607 0, len);
608 } else {
609 ret = 0;
612 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
614 if (ret == 0) {
615 /* We changed the allocation size on disk, but not
616 EOF - exactly as required. We're done ! */
617 return 0;
620 if (ret == -1 && errno == ENOSPC) {
621 return -1;
624 len -= fsp->fsp_name->st.st_ex_size;
625 len /= 1024; /* Len is now number of 1k blocks needed. */
626 space_avail =
627 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
628 if (space_avail == (uint64_t)-1) {
629 return -1;
632 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
633 "needed blocks = %.0f, space avail = %.0f\n",
634 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
635 (double)space_avail));
637 if (len > space_avail) {
638 errno = ENOSPC;
639 return -1;
642 return 0;
645 /****************************************************************************
646 A vfs set_filelen call.
647 set the length of a file from a filedescriptor.
648 Returns 0 on success, -1 on failure.
649 ****************************************************************************/
651 int vfs_set_filelen(files_struct *fsp, off_t len)
653 int ret;
655 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
657 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
658 fsp_str_dbg(fsp), (double)len));
659 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
660 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
661 set_filelen_write_cache(fsp, len);
662 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
663 FILE_NOTIFY_CHANGE_SIZE
664 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
665 fsp->fsp_name->base_name);
668 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
670 return ret;
673 /****************************************************************************
674 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
675 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
676 as this is also called from the default SMB_VFS_FTRUNCATE code.
677 Always extends the file size.
678 Returns 0 on success, -1 on failure.
679 ****************************************************************************/
681 #define SPARSE_BUF_WRITE_SIZE (32*1024)
683 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
685 ssize_t pwrite_ret;
686 size_t total = 0;
688 if (!sparse_buf) {
689 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
690 if (!sparse_buf) {
691 errno = ENOMEM;
692 return -1;
696 while (total < len) {
697 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
699 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
700 if (pwrite_ret == -1) {
701 int saved_errno = errno;
702 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
703 "%s failed with error %s\n",
704 fsp_str_dbg(fsp), strerror(saved_errno)));
705 errno = saved_errno;
706 return -1;
708 total += pwrite_ret;
711 return 0;
714 /****************************************************************************
715 A vfs fill sparse call.
716 Writes zeros from the end of file to len, if len is greater than EOF.
717 Used only by strict_sync.
718 Returns 0 on success, -1 on failure.
719 ****************************************************************************/
721 int vfs_fill_sparse(files_struct *fsp, off_t len)
723 int ret;
724 NTSTATUS status;
725 off_t offset;
726 size_t num_to_write;
728 status = vfs_stat_fsp(fsp);
729 if (!NT_STATUS_IS_OK(status)) {
730 return -1;
733 if (len <= fsp->fsp_name->st.st_ex_size) {
734 return 0;
737 #ifdef S_ISFIFO
738 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
739 return 0;
741 #endif
743 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
744 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
745 (double)fsp->fsp_name->st.st_ex_size, (double)len,
746 (double)(len - fsp->fsp_name->st.st_ex_size)));
748 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
750 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
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 if (ret == 0) {
778 set_filelen_write_cache(fsp, len);
781 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
782 return ret;
785 /****************************************************************************
786 Transfer some data (n bytes) between two file_struct's.
787 ****************************************************************************/
789 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
791 struct files_struct *fsp = (struct files_struct *)file;
793 return SMB_VFS_PREAD(fsp, buf, len, offset);
796 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
798 struct files_struct *fsp = (struct files_struct *)file;
800 return SMB_VFS_PWRITE(fsp, buf, len, offset);
803 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
805 return transfer_file_internal((void *)in, (void *)out, n,
806 vfs_pread_fn, vfs_pwrite_fn);
809 /*******************************************************************
810 A vfs_readdir wrapper which just returns the file name.
811 ********************************************************************/
813 const char *vfs_readdirname(connection_struct *conn, void *p,
814 SMB_STRUCT_STAT *sbuf, char **talloced)
816 struct dirent *ptr= NULL;
817 const char *dname;
818 char *translated;
819 NTSTATUS status;
821 if (!p)
822 return(NULL);
824 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
825 if (!ptr)
826 return(NULL);
828 dname = ptr->d_name;
831 #ifdef NEXT2
832 if (telldir(p) < 0)
833 return(NULL);
834 #endif
836 #ifdef HAVE_BROKEN_READDIR_NAME
837 /* using /usr/ucb/cc is BAD */
838 dname = dname - 2;
839 #endif
841 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
842 talloc_tos(), &translated);
843 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
844 *talloced = NULL;
845 return dname;
847 *talloced = translated;
848 if (!NT_STATUS_IS_OK(status)) {
849 return NULL;
851 return translated;
854 /*******************************************************************
855 A wrapper for vfs_chdir().
856 ********************************************************************/
858 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
860 int ret;
862 if (!LastDir) {
863 LastDir = SMB_STRDUP("");
866 if (ISDOT(smb_fname->base_name)) {
867 return 0;
870 if (*smb_fname->base_name == '/' &&
871 strcsequal(LastDir,smb_fname->base_name)) {
872 return 0;
875 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
877 ret = SMB_VFS_CHDIR(conn, smb_fname);
878 if (ret == 0) {
879 /* Global cache. */
880 SAFE_FREE(LastDir);
881 LastDir = SMB_STRDUP(smb_fname->base_name);
883 /* conn cache. */
884 TALLOC_FREE(conn->cwd_fname);
885 conn->cwd_fname = vfs_GetWd(conn, conn);
886 if (conn->cwd_fname == NULL) {
887 smb_panic("con->cwd getwd failed\n");
888 /* NOTREACHED */
889 return -1;
891 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd_fname->base_name));
893 return ret;
896 /*******************************************************************
897 Return the absolute current directory path - given a UNIX pathname.
898 Note that this path is returned in DOS format, not UNIX
899 format. Note this can be called with conn == NULL.
900 ********************************************************************/
902 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
904 struct smb_filename *current_dir_fname = NULL;
905 struct file_id key;
906 struct smb_filename *smb_fname_dot = NULL;
907 struct smb_filename *smb_fname_full = NULL;
908 struct smb_filename *result = NULL;
910 if (!lp_getwd_cache()) {
911 goto nocache;
914 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
915 if (smb_fname_dot == NULL) {
916 errno = ENOMEM;
917 goto out;
920 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
922 * Known to fail for root: the directory may be NFS-mounted
923 * and exported with root_squash (so has no root access).
925 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
926 "(NFS problem ?)\n", strerror(errno) ));
927 goto nocache;
930 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
932 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
933 smbd_memcache(),
934 GETWD_CACHE,
935 data_blob_const(&key, sizeof(key)));
937 if (smb_fname_full == NULL) {
938 goto nocache;
941 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
942 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
943 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
944 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
946 * Ok, we're done
947 * Note: smb_fname_full is owned by smbd_memcache()
948 * so we must make a copy to return.
950 result = cp_smb_filename(ctx, smb_fname_full);
951 if (result == NULL) {
952 errno = ENOMEM;
954 goto out;
957 nocache:
960 * We don't have the information to hand so rely on traditional
961 * methods. The very slow getcwd, which spawns a process on some
962 * systems, or the not quite so bad getwd.
965 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
966 if (current_dir_fname == NULL) {
967 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
968 strerror(errno)));
969 goto out;
972 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
973 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
976 * smbd_memcache() will own current_dir_fname after the
977 * memcache_add_talloc call, so we must make
978 * a copy on ctx to return.
980 result = cp_smb_filename(ctx, current_dir_fname);
981 if (result == NULL) {
982 errno = ENOMEM;
986 * Ensure the memory going into the cache
987 * doesn't have a destructor so it can be
988 * cleanly freed.
990 talloc_set_destructor(current_dir_fname, NULL);
992 memcache_add_talloc(smbd_memcache(),
993 GETWD_CACHE,
994 data_blob_const(&key, sizeof(key)),
995 &current_dir_fname);
996 /* current_dir_fname is now == NULL here. */
997 } else {
998 /* current_dir_fname is already allocated on ctx. */
999 result = current_dir_fname;
1002 out:
1003 TALLOC_FREE(smb_fname_dot);
1005 * Don't free current_dir_fname here. It's either been moved
1006 * to the memcache or is being returned in result.
1008 return result;
1011 /*******************************************************************
1012 Reduce a file name, removing .. elements and checking that
1013 it is below dir in the heirachy. This uses realpath.
1014 This function must run as root, and will return names
1015 and valid stat structs that can be checked on open.
1016 ********************************************************************/
1018 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1019 const struct smb_filename *smb_fname,
1020 struct smb_request *smbreq)
1022 NTSTATUS status;
1023 TALLOC_CTX *ctx = talloc_tos();
1024 const char *conn_rootdir;
1025 size_t rootdir_len;
1026 char *dir_name = NULL;
1027 char *resolved_name = NULL;
1028 const char *last_component = NULL;
1029 struct smb_filename *resolved_fname = NULL;
1030 struct smb_filename *saved_dir_fname = NULL;
1031 struct smb_filename *smb_fname_cwd = NULL;
1032 struct privilege_paths *priv_paths = NULL;
1033 int ret;
1035 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1036 smb_fname->base_name,
1037 conn->connectpath));
1040 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1041 if (!priv_paths) {
1042 status = NT_STATUS_NO_MEMORY;
1043 goto err;
1046 if (!parent_dirname(ctx, smb_fname->base_name,
1047 &dir_name, &last_component)) {
1048 status = NT_STATUS_NO_MEMORY;
1049 goto err;
1052 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1053 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1055 if (priv_paths->parent_name.base_name == NULL ||
1056 priv_paths->file_name.base_name == NULL) {
1057 status = NT_STATUS_NO_MEMORY;
1058 goto err;
1061 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1062 status = map_nt_error_from_unix(errno);
1063 goto err;
1065 /* Remember where we were. */
1066 saved_dir_fname = vfs_GetWd(ctx, conn);
1067 if (!saved_dir_fname) {
1068 status = map_nt_error_from_unix(errno);
1069 goto err;
1072 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1073 status = map_nt_error_from_unix(errno);
1074 goto err;
1077 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1078 if (smb_fname_cwd == NULL) {
1079 status = NT_STATUS_NO_MEMORY;
1080 goto err;
1083 /* Get the absolute path of the parent directory. */
1084 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1085 if (resolved_fname == NULL) {
1086 status = map_nt_error_from_unix(errno);
1087 goto err;
1089 resolved_name = resolved_fname->base_name;
1091 if (*resolved_name != '/') {
1092 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1093 "doesn't return absolute paths !\n"));
1094 status = NT_STATUS_OBJECT_NAME_INVALID;
1095 goto err;
1098 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1099 priv_paths->parent_name.base_name,
1100 resolved_name));
1102 /* Now check the stat value is the same. */
1103 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1104 status = map_nt_error_from_unix(errno);
1105 goto err;
1108 /* Ensure we're pointing at the same place. */
1109 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1110 DEBUG(0,("check_reduced_name_with_privilege: "
1111 "device/inode/uid/gid on directory %s changed. "
1112 "Denying access !\n",
1113 priv_paths->parent_name.base_name));
1114 status = NT_STATUS_ACCESS_DENIED;
1115 goto err;
1118 /* Ensure we're below the connect path. */
1120 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1121 if (conn_rootdir == NULL) {
1122 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1123 "conn_rootdir\n"));
1124 status = NT_STATUS_ACCESS_DENIED;
1125 goto err;
1128 rootdir_len = strlen(conn_rootdir);
1131 * In the case of rootdir_len == 1, we know that conn_rootdir is
1132 * "/", and we also know that resolved_name starts with a slash.
1133 * So, in this corner case, resolved_name is automatically a
1134 * sub-directory of the conn_rootdir. Thus we can skip the string
1135 * comparison and the next character checks (which are even
1136 * wrong in this case).
1138 if (rootdir_len != 1) {
1139 bool matched;
1141 matched = (strncmp(conn_rootdir, resolved_name,
1142 rootdir_len) == 0);
1144 if (!matched || (resolved_name[rootdir_len] != '/' &&
1145 resolved_name[rootdir_len] != '\0')) {
1146 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1147 "access attempt: %s is a symlink outside the "
1148 "share path\n",
1149 dir_name));
1150 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1151 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1152 status = NT_STATUS_ACCESS_DENIED;
1153 goto err;
1157 /* Now ensure that the last component either doesn't
1158 exist, or is *NOT* a symlink. */
1160 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1161 if (ret == -1) {
1162 /* Errno must be ENOENT for this be ok. */
1163 if (errno != ENOENT) {
1164 status = map_nt_error_from_unix(errno);
1165 DEBUG(2, ("check_reduced_name_with_privilege: "
1166 "LSTAT on %s failed with %s\n",
1167 priv_paths->file_name.base_name,
1168 nt_errstr(status)));
1169 goto err;
1173 if (VALID_STAT(priv_paths->file_name.st) &&
1174 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1175 DEBUG(2, ("check_reduced_name_with_privilege: "
1176 "Last component %s is a symlink. Denying"
1177 "access.\n",
1178 priv_paths->file_name.base_name));
1179 status = NT_STATUS_ACCESS_DENIED;
1180 goto err;
1183 smbreq->priv_paths = priv_paths;
1184 status = NT_STATUS_OK;
1186 err:
1188 if (saved_dir_fname != NULL) {
1189 vfs_ChDir(conn, saved_dir_fname);
1190 TALLOC_FREE(saved_dir_fname);
1192 TALLOC_FREE(resolved_fname);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 TALLOC_FREE(priv_paths);
1196 TALLOC_FREE(dir_name);
1197 return status;
1200 /*******************************************************************
1201 Reduce a file name, removing .. elements and checking that
1202 it is below dir in the heirachy. This uses realpath.
1204 If cwd_name == NULL then fname is a client given path relative
1205 to the root path of the share.
1207 If cwd_name != NULL then fname is a client given path relative
1208 to cwd_name. cwd_name is relative to the root path of the share.
1209 ********************************************************************/
1211 NTSTATUS check_reduced_name(connection_struct *conn,
1212 const struct smb_filename *cwd_fname,
1213 const struct smb_filename *smb_fname)
1215 TALLOC_CTX *ctx = talloc_tos();
1216 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1217 const char *fname = smb_fname->base_name;
1218 struct smb_filename *resolved_fname;
1219 char *resolved_name = NULL;
1220 char *new_fname = NULL;
1221 bool allow_symlinks = true;
1222 bool allow_widelinks = false;
1224 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1226 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1228 if (resolved_fname == NULL) {
1229 switch (errno) {
1230 case ENOTDIR:
1231 DEBUG(3,("check_reduced_name: Component not a "
1232 "directory in getting realpath for "
1233 "%s\n", fname));
1234 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1235 case ENOENT:
1237 char *dir_name = NULL;
1238 struct smb_filename dir_fname = {0};
1239 const char *last_component = NULL;
1241 /* Last component didn't exist.
1242 Remove it and try and canonicalise
1243 the directory name. */
1244 if (!parent_dirname(ctx, fname,
1245 &dir_name,
1246 &last_component)) {
1247 return NT_STATUS_NO_MEMORY;
1250 dir_fname = (struct smb_filename)
1251 { .base_name = dir_name };
1252 resolved_fname = SMB_VFS_REALPATH(conn,
1253 ctx,
1254 &dir_fname);
1255 if (resolved_fname == NULL) {
1256 NTSTATUS status = map_nt_error_from_unix(errno);
1258 if (errno == ENOENT || errno == ENOTDIR) {
1259 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1262 DEBUG(3,("check_reduce_name: "
1263 "couldn't get realpath for "
1264 "%s (%s)\n",
1265 fname,
1266 nt_errstr(status)));
1267 return status;
1269 resolved_name = talloc_asprintf(ctx,
1270 "%s/%s",
1271 resolved_fname->base_name,
1272 last_component);
1273 if (resolved_name == NULL) {
1274 return NT_STATUS_NO_MEMORY;
1276 break;
1278 default:
1279 DEBUG(3,("check_reduced_name: couldn't get "
1280 "realpath for %s\n", fname));
1281 return map_nt_error_from_unix(errno);
1283 } else {
1284 resolved_name = resolved_fname->base_name;
1287 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1288 resolved_name));
1290 if (*resolved_name != '/') {
1291 DEBUG(0,("check_reduced_name: realpath doesn't return "
1292 "absolute paths !\n"));
1293 TALLOC_FREE(resolved_fname);
1294 return NT_STATUS_OBJECT_NAME_INVALID;
1297 allow_widelinks = lp_widelinks(SNUM(conn));
1298 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1300 /* Common widelinks and symlinks checks. */
1301 if (!allow_widelinks || !allow_symlinks) {
1302 const char *conn_rootdir;
1303 size_t rootdir_len;
1305 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1306 if (conn_rootdir == NULL) {
1307 DEBUG(2, ("check_reduced_name: Could not get "
1308 "conn_rootdir\n"));
1309 TALLOC_FREE(resolved_fname);
1310 return NT_STATUS_ACCESS_DENIED;
1313 rootdir_len = strlen(conn_rootdir);
1316 * In the case of rootdir_len == 1, we know that
1317 * conn_rootdir is "/", and we also know that
1318 * resolved_name starts with a slash. So, in this
1319 * corner case, resolved_name is automatically a
1320 * sub-directory of the conn_rootdir. Thus we can skip
1321 * the string comparison and the next character checks
1322 * (which are even wrong in this case).
1324 if (rootdir_len != 1) {
1325 bool matched;
1327 matched = (strncmp(conn_rootdir, resolved_name,
1328 rootdir_len) == 0);
1329 if (!matched || (resolved_name[rootdir_len] != '/' &&
1330 resolved_name[rootdir_len] != '\0')) {
1331 DEBUG(2, ("check_reduced_name: Bad access "
1332 "attempt: %s is a symlink outside the "
1333 "share path\n", fname));
1334 DEBUGADD(2, ("conn_rootdir =%s\n",
1335 conn_rootdir));
1336 DEBUGADD(2, ("resolved_name=%s\n",
1337 resolved_name));
1338 TALLOC_FREE(resolved_fname);
1339 return NT_STATUS_ACCESS_DENIED;
1343 /* Extra checks if all symlinks are disallowed. */
1344 if (!allow_symlinks) {
1345 /* fname can't have changed in resolved_path. */
1346 const char *p = &resolved_name[rootdir_len];
1349 * UNIX filesystem semantics, names consisting
1350 * only of "." or ".." CANNOT be symlinks.
1352 if (ISDOT(fname) || ISDOTDOT(fname)) {
1353 goto out;
1356 if (*p != '/') {
1357 DEBUG(2, ("check_reduced_name: logic error (%c) "
1358 "in resolved_name: %s\n",
1360 fname));
1361 TALLOC_FREE(resolved_fname);
1362 return NT_STATUS_ACCESS_DENIED;
1365 p++;
1368 * If cwd_name is present and not ".",
1369 * then fname is relative to that, not
1370 * the root of the share. Make sure the
1371 * path we check is the one the client
1372 * sent (cwd_name+fname).
1374 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1375 new_fname = talloc_asprintf(ctx,
1376 "%s/%s",
1377 cwd_name,
1378 fname);
1379 if (new_fname == NULL) {
1380 TALLOC_FREE(resolved_fname);
1381 return NT_STATUS_NO_MEMORY;
1383 fname = new_fname;
1386 if (strcmp(fname, p)!=0) {
1387 DEBUG(2, ("check_reduced_name: Bad access "
1388 "attempt: %s is a symlink to %s\n",
1389 fname, p));
1390 TALLOC_FREE(resolved_fname);
1391 TALLOC_FREE(new_fname);
1392 return NT_STATUS_ACCESS_DENIED;
1397 out:
1399 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1400 TALLOC_FREE(resolved_fname);
1401 TALLOC_FREE(new_fname);
1402 return NT_STATUS_OK;
1406 * XXX: This is temporary and there should be no callers of this once
1407 * smb_filename is plumbed through all path based operations.
1409 * Called when we know stream name parsing has already been done.
1411 int vfs_stat_smb_basename(struct connection_struct *conn,
1412 const struct smb_filename *smb_fname_in,
1413 SMB_STRUCT_STAT *psbuf)
1415 struct smb_filename smb_fname = {
1416 .base_name = discard_const_p(char, smb_fname_in->base_name),
1417 .flags = smb_fname_in->flags
1419 int ret;
1421 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1422 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1423 } else {
1424 ret = SMB_VFS_STAT(conn, &smb_fname);
1427 if (ret != -1) {
1428 *psbuf = smb_fname.st;
1430 return ret;
1434 * Ensure LSTAT is called for POSIX paths.
1437 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1439 int ret;
1441 if(fsp->fh->fd == -1) {
1442 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1443 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1444 } else {
1445 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1447 if (ret == -1) {
1448 return map_nt_error_from_unix(errno);
1450 } else {
1451 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1452 return map_nt_error_from_unix(errno);
1455 return NT_STATUS_OK;
1459 * Initialize num_streams and streams, then call VFS op streaminfo
1461 NTSTATUS vfs_streaminfo(connection_struct *conn,
1462 struct files_struct *fsp,
1463 const struct smb_filename *smb_fname,
1464 TALLOC_CTX *mem_ctx,
1465 unsigned int *num_streams,
1466 struct stream_struct **streams)
1468 *num_streams = 0;
1469 *streams = NULL;
1470 return SMB_VFS_STREAMINFO(conn,
1471 fsp,
1472 smb_fname,
1473 mem_ctx,
1474 num_streams,
1475 streams);
1479 generate a file_id from a stat structure
1481 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1483 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1486 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1487 const char *service, const char *user)
1489 VFS_FIND(connect);
1490 return handle->fns->connect_fn(handle, service, user);
1493 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1495 VFS_FIND(disconnect);
1496 handle->fns->disconnect_fn(handle);
1499 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1500 const struct smb_filename *smb_fname,
1501 uint64_t *bsize,
1502 uint64_t *dfree,
1503 uint64_t *dsize)
1505 VFS_FIND(disk_free);
1506 return handle->fns->disk_free_fn(handle, smb_fname,
1507 bsize, dfree, dsize);
1510 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1511 const struct smb_filename *smb_fname,
1512 enum SMB_QUOTA_TYPE qtype,
1513 unid_t id,
1514 SMB_DISK_QUOTA *qt)
1516 VFS_FIND(get_quota);
1517 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1520 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1521 enum SMB_QUOTA_TYPE qtype, unid_t id,
1522 SMB_DISK_QUOTA *qt)
1524 VFS_FIND(set_quota);
1525 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1528 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1529 struct files_struct *fsp,
1530 struct shadow_copy_data *shadow_copy_data,
1531 bool labels)
1533 VFS_FIND(get_shadow_copy_data);
1534 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1535 shadow_copy_data,
1536 labels);
1538 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1539 const struct smb_filename *smb_fname,
1540 struct vfs_statvfs_struct *statbuf)
1542 VFS_FIND(statvfs);
1543 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1546 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1547 enum timestamp_set_resolution *p_ts_res)
1549 VFS_FIND(fs_capabilities);
1550 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1553 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1554 struct dfs_GetDFSReferral *r)
1556 VFS_FIND(get_dfs_referrals);
1557 return handle->fns->get_dfs_referrals_fn(handle, r);
1560 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1561 const struct smb_filename *smb_fname,
1562 const char *mask,
1563 uint32_t attributes)
1565 VFS_FIND(opendir);
1566 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1569 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1570 struct files_struct *fsp,
1571 const char *mask,
1572 uint32_t attributes)
1574 VFS_FIND(fdopendir);
1575 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1578 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1579 DIR *dirp,
1580 SMB_STRUCT_STAT *sbuf)
1582 VFS_FIND(readdir);
1583 return handle->fns->readdir_fn(handle, dirp, sbuf);
1586 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1587 DIR *dirp, long offset)
1589 VFS_FIND(seekdir);
1590 handle->fns->seekdir_fn(handle, dirp, offset);
1593 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1594 DIR *dirp)
1596 VFS_FIND(telldir);
1597 return handle->fns->telldir_fn(handle, dirp);
1600 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1601 DIR *dirp)
1603 VFS_FIND(rewind_dir);
1604 handle->fns->rewind_dir_fn(handle, dirp);
1607 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1608 const struct smb_filename *smb_fname,
1609 mode_t mode)
1611 VFS_FIND(mkdir);
1612 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1615 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1616 const struct smb_filename *smb_fname)
1618 VFS_FIND(rmdir);
1619 return handle->fns->rmdir_fn(handle, smb_fname);
1622 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1623 DIR *dir)
1625 VFS_FIND(closedir);
1626 return handle->fns->closedir_fn(handle, dir);
1629 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1630 DIR *dirp)
1632 VFS_FIND(init_search_op);
1633 handle->fns->init_search_op_fn(handle, dirp);
1636 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1637 struct smb_filename *smb_fname, struct files_struct *fsp,
1638 int flags, mode_t mode)
1640 VFS_FIND(open);
1641 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1644 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1645 struct smb_request *req,
1646 uint16_t root_dir_fid,
1647 struct smb_filename *smb_fname,
1648 uint32_t access_mask,
1649 uint32_t share_access,
1650 uint32_t create_disposition,
1651 uint32_t create_options,
1652 uint32_t file_attributes,
1653 uint32_t oplock_request,
1654 struct smb2_lease *lease,
1655 uint64_t allocation_size,
1656 uint32_t private_flags,
1657 struct security_descriptor *sd,
1658 struct ea_list *ea_list,
1659 files_struct **result,
1660 int *pinfo,
1661 const struct smb2_create_blobs *in_context_blobs,
1662 struct smb2_create_blobs *out_context_blobs)
1664 VFS_FIND(create_file);
1665 return handle->fns->create_file_fn(
1666 handle, req, root_dir_fid, smb_fname, access_mask,
1667 share_access, create_disposition, create_options,
1668 file_attributes, oplock_request, lease, allocation_size,
1669 private_flags, sd, ea_list,
1670 result, pinfo, in_context_blobs, out_context_blobs);
1673 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1674 struct files_struct *fsp)
1676 VFS_FIND(close);
1677 return handle->fns->close_fn(handle, fsp);
1680 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1681 struct files_struct *fsp, void *data, size_t n)
1683 VFS_FIND(read);
1684 return handle->fns->read_fn(handle, fsp, data, n);
1687 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1688 struct files_struct *fsp, void *data, size_t n,
1689 off_t offset)
1691 VFS_FIND(pread);
1692 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1695 struct smb_vfs_call_pread_state {
1696 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1697 ssize_t retval;
1698 struct vfs_aio_state vfs_aio_state;
1701 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1703 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1704 TALLOC_CTX *mem_ctx,
1705 struct tevent_context *ev,
1706 struct files_struct *fsp,
1707 void *data,
1708 size_t n, off_t offset)
1710 struct tevent_req *req, *subreq;
1711 struct smb_vfs_call_pread_state *state;
1713 req = tevent_req_create(mem_ctx, &state,
1714 struct smb_vfs_call_pread_state);
1715 if (req == NULL) {
1716 return NULL;
1718 VFS_FIND(pread_send);
1719 state->recv_fn = handle->fns->pread_recv_fn;
1721 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1722 offset);
1723 if (tevent_req_nomem(subreq, req)) {
1724 return tevent_req_post(req, ev);
1726 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1727 return req;
1730 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1732 struct tevent_req *req = tevent_req_callback_data(
1733 subreq, struct tevent_req);
1734 struct smb_vfs_call_pread_state *state = tevent_req_data(
1735 req, struct smb_vfs_call_pread_state);
1737 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1738 TALLOC_FREE(subreq);
1739 if (state->retval == -1) {
1740 tevent_req_error(req, state->vfs_aio_state.error);
1741 return;
1743 tevent_req_done(req);
1746 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1747 struct vfs_aio_state *vfs_aio_state)
1749 struct smb_vfs_call_pread_state *state = tevent_req_data(
1750 req, struct smb_vfs_call_pread_state);
1752 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1753 return -1;
1755 *vfs_aio_state = state->vfs_aio_state;
1756 return state->retval;
1759 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1760 struct files_struct *fsp, const void *data,
1761 size_t n)
1763 VFS_FIND(write);
1764 return handle->fns->write_fn(handle, fsp, data, n);
1767 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1768 struct files_struct *fsp, const void *data,
1769 size_t n, off_t offset)
1771 VFS_FIND(pwrite);
1772 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1775 struct smb_vfs_call_pwrite_state {
1776 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1777 ssize_t retval;
1778 struct vfs_aio_state vfs_aio_state;
1781 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1783 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1784 TALLOC_CTX *mem_ctx,
1785 struct tevent_context *ev,
1786 struct files_struct *fsp,
1787 const void *data,
1788 size_t n, off_t offset)
1790 struct tevent_req *req, *subreq;
1791 struct smb_vfs_call_pwrite_state *state;
1793 req = tevent_req_create(mem_ctx, &state,
1794 struct smb_vfs_call_pwrite_state);
1795 if (req == NULL) {
1796 return NULL;
1798 VFS_FIND(pwrite_send);
1799 state->recv_fn = handle->fns->pwrite_recv_fn;
1801 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1802 offset);
1803 if (tevent_req_nomem(subreq, req)) {
1804 return tevent_req_post(req, ev);
1806 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1807 return req;
1810 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1812 struct tevent_req *req = tevent_req_callback_data(
1813 subreq, struct tevent_req);
1814 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1815 req, struct smb_vfs_call_pwrite_state);
1817 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1818 TALLOC_FREE(subreq);
1819 if (state->retval == -1) {
1820 tevent_req_error(req, state->vfs_aio_state.error);
1821 return;
1823 tevent_req_done(req);
1826 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1827 struct vfs_aio_state *vfs_aio_state)
1829 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1830 req, struct smb_vfs_call_pwrite_state);
1832 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1833 return -1;
1835 *vfs_aio_state = state->vfs_aio_state;
1836 return state->retval;
1839 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1840 struct files_struct *fsp, off_t offset,
1841 int whence)
1843 VFS_FIND(lseek);
1844 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1847 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1848 files_struct *fromfsp, const DATA_BLOB *header,
1849 off_t offset, size_t count)
1851 VFS_FIND(sendfile);
1852 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1853 count);
1856 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1857 files_struct *tofsp, off_t offset,
1858 size_t count)
1860 VFS_FIND(recvfile);
1861 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1864 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1865 const struct smb_filename *smb_fname_src,
1866 const struct smb_filename *smb_fname_dst)
1868 VFS_FIND(rename);
1869 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1872 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1873 struct files_struct *fsp)
1875 VFS_FIND(fsync);
1876 return handle->fns->fsync_fn(handle, fsp);
1879 struct smb_vfs_call_fsync_state {
1880 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1881 int retval;
1882 struct vfs_aio_state vfs_aio_state;
1885 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1887 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1888 TALLOC_CTX *mem_ctx,
1889 struct tevent_context *ev,
1890 struct files_struct *fsp)
1892 struct tevent_req *req, *subreq;
1893 struct smb_vfs_call_fsync_state *state;
1895 req = tevent_req_create(mem_ctx, &state,
1896 struct smb_vfs_call_fsync_state);
1897 if (req == NULL) {
1898 return NULL;
1900 VFS_FIND(fsync_send);
1901 state->recv_fn = handle->fns->fsync_recv_fn;
1903 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1904 if (tevent_req_nomem(subreq, req)) {
1905 return tevent_req_post(req, ev);
1907 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1908 return req;
1911 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1913 struct tevent_req *req = tevent_req_callback_data(
1914 subreq, struct tevent_req);
1915 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1916 req, struct smb_vfs_call_fsync_state);
1918 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1919 TALLOC_FREE(subreq);
1920 if (state->retval == -1) {
1921 tevent_req_error(req, state->vfs_aio_state.error);
1922 return;
1924 tevent_req_done(req);
1927 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1929 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1930 req, struct smb_vfs_call_fsync_state);
1932 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1933 return -1;
1935 *vfs_aio_state = state->vfs_aio_state;
1936 return state->retval;
1940 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1941 struct smb_filename *smb_fname)
1943 VFS_FIND(stat);
1944 return handle->fns->stat_fn(handle, smb_fname);
1947 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1948 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1950 VFS_FIND(fstat);
1951 return handle->fns->fstat_fn(handle, fsp, sbuf);
1954 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1955 struct smb_filename *smb_filename)
1957 VFS_FIND(lstat);
1958 return handle->fns->lstat_fn(handle, smb_filename);
1961 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1962 struct files_struct *fsp,
1963 const SMB_STRUCT_STAT *sbuf)
1965 VFS_FIND(get_alloc_size);
1966 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1969 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1970 const struct smb_filename *smb_fname)
1972 VFS_FIND(unlink);
1973 return handle->fns->unlink_fn(handle, smb_fname);
1976 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1977 const struct smb_filename *smb_fname,
1978 mode_t mode)
1980 VFS_FIND(chmod);
1981 return handle->fns->chmod_fn(handle, smb_fname, mode);
1984 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1985 struct files_struct *fsp, mode_t mode)
1987 VFS_FIND(fchmod);
1988 return handle->fns->fchmod_fn(handle, fsp, mode);
1991 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1992 const struct smb_filename *smb_fname,
1993 uid_t uid,
1994 gid_t gid)
1996 VFS_FIND(chown);
1997 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
2000 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2001 struct files_struct *fsp, uid_t uid, gid_t gid)
2003 VFS_FIND(fchown);
2004 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2007 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2008 const struct smb_filename *smb_fname,
2009 uid_t uid,
2010 gid_t gid)
2012 VFS_FIND(lchown);
2013 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2016 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2018 int ret;
2019 bool as_root = false;
2020 NTSTATUS status;
2022 if (fsp->fh->fd != -1) {
2023 /* Try fchown. */
2024 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2025 if (ret == 0) {
2026 return NT_STATUS_OK;
2028 if (ret == -1 && errno != ENOSYS) {
2029 return map_nt_error_from_unix(errno);
2033 as_root = (geteuid() == 0);
2035 if (as_root) {
2037 * We are being asked to chown as root. Make
2038 * sure we chdir() into the path to pin it,
2039 * and always act using lchown to ensure we
2040 * don't deref any symbolic links.
2042 char *parent_dir = NULL;
2043 const char *final_component = NULL;
2044 struct smb_filename *local_smb_fname = NULL;
2045 struct smb_filename parent_dir_fname = {0};
2046 struct smb_filename *saved_dir_fname = NULL;
2048 saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
2049 if (!saved_dir_fname) {
2050 status = map_nt_error_from_unix(errno);
2051 DEBUG(0,("vfs_chown_fsp: failed to get "
2052 "current working directory. Error was %s\n",
2053 strerror(errno)));
2054 return status;
2057 if (!parent_dirname(talloc_tos(),
2058 fsp->fsp_name->base_name,
2059 &parent_dir,
2060 &final_component)) {
2061 return NT_STATUS_NO_MEMORY;
2064 parent_dir_fname = (struct smb_filename) {
2065 .base_name = parent_dir,
2066 .flags = fsp->fsp_name->flags
2069 /* cd into the parent dir to pin it. */
2070 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2071 if (ret == -1) {
2072 return map_nt_error_from_unix(errno);
2075 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2076 final_component,
2077 NULL,
2078 NULL,
2079 fsp->fsp_name->flags);
2080 if (local_smb_fname == NULL) {
2081 status = NT_STATUS_NO_MEMORY;
2082 goto out;
2085 /* Must use lstat here. */
2086 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2087 if (ret == -1) {
2088 status = map_nt_error_from_unix(errno);
2089 goto out;
2092 /* Ensure it matches the fsp stat. */
2093 if (!check_same_stat(&local_smb_fname->st,
2094 &fsp->fsp_name->st)) {
2095 status = NT_STATUS_ACCESS_DENIED;
2096 goto out;
2099 ret = SMB_VFS_LCHOWN(fsp->conn,
2100 local_smb_fname,
2101 uid, gid);
2103 if (ret == 0) {
2104 status = NT_STATUS_OK;
2105 } else {
2106 status = map_nt_error_from_unix(errno);
2109 out:
2111 vfs_ChDir(fsp->conn, saved_dir_fname);
2112 TALLOC_FREE(local_smb_fname);
2113 TALLOC_FREE(saved_dir_fname);
2114 TALLOC_FREE(parent_dir);
2116 return status;
2119 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2120 ret = SMB_VFS_LCHOWN(fsp->conn,
2121 fsp->fsp_name,
2122 uid, gid);
2123 } else {
2124 ret = SMB_VFS_CHOWN(fsp->conn,
2125 fsp->fsp_name,
2126 uid, gid);
2129 if (ret == 0) {
2130 status = NT_STATUS_OK;
2131 } else {
2132 status = map_nt_error_from_unix(errno);
2134 return status;
2137 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2138 const struct smb_filename *smb_fname)
2140 VFS_FIND(chdir);
2141 return handle->fns->chdir_fn(handle, smb_fname);
2144 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2145 TALLOC_CTX *ctx)
2147 VFS_FIND(getwd);
2148 return handle->fns->getwd_fn(handle, ctx);
2151 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2152 const struct smb_filename *smb_fname,
2153 struct smb_file_time *ft)
2155 VFS_FIND(ntimes);
2156 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2159 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2160 struct files_struct *fsp, off_t offset)
2162 VFS_FIND(ftruncate);
2163 return handle->fns->ftruncate_fn(handle, fsp, offset);
2166 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2167 struct files_struct *fsp,
2168 uint32_t mode,
2169 off_t offset,
2170 off_t len)
2172 VFS_FIND(fallocate);
2173 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2176 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2177 struct files_struct *fsp, uint32_t share_mode,
2178 uint32_t access_mask)
2180 VFS_FIND(kernel_flock);
2181 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2182 access_mask);
2185 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2186 struct files_struct *fsp, int leasetype)
2188 VFS_FIND(linux_setlease);
2189 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2192 int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
2193 const char *link_target,
2194 const struct smb_filename *new_smb_fname)
2196 VFS_FIND(symlink);
2197 return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
2200 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2201 const struct smb_filename *smb_fname,
2202 char *buf,
2203 size_t bufsiz)
2205 VFS_FIND(readlink);
2206 return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
2209 int smb_vfs_call_link(struct vfs_handle_struct *handle,
2210 const struct smb_filename *old_smb_fname,
2211 const struct smb_filename *new_smb_fname)
2213 VFS_FIND(link);
2214 return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2217 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2218 const struct smb_filename *smb_fname,
2219 mode_t mode,
2220 SMB_DEV_T dev)
2222 VFS_FIND(mknod);
2223 return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2226 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2227 TALLOC_CTX *ctx,
2228 const struct smb_filename *smb_fname)
2230 VFS_FIND(realpath);
2231 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2234 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2235 const struct smb_filename *smb_fname,
2236 unsigned int flags)
2238 VFS_FIND(chflags);
2239 return handle->fns->chflags_fn(handle, smb_fname, flags);
2242 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2243 const SMB_STRUCT_STAT *sbuf)
2245 VFS_FIND(file_id_create);
2246 return handle->fns->file_id_create_fn(handle, sbuf);
2249 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2250 struct files_struct *fsp,
2251 const struct smb_filename *smb_fname,
2252 TALLOC_CTX *mem_ctx,
2253 unsigned int *num_streams,
2254 struct stream_struct **streams)
2256 VFS_FIND(streaminfo);
2257 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2258 num_streams, streams);
2261 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2262 const char *path, const char *name,
2263 TALLOC_CTX *mem_ctx, char **found_name)
2265 VFS_FIND(get_real_filename);
2266 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2267 found_name);
2270 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2271 const struct smb_filename *smb_fname)
2273 VFS_FIND(connectpath);
2274 return handle->fns->connectpath_fn(handle, smb_fname);
2277 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2278 struct files_struct *fsp,
2279 struct lock_struct *plock)
2281 VFS_FIND(strict_lock_check);
2282 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2285 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2286 const char *name,
2287 enum vfs_translate_direction direction,
2288 TALLOC_CTX *mem_ctx,
2289 char **mapped_name)
2291 VFS_FIND(translate_name);
2292 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2293 mapped_name);
2296 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2297 struct files_struct *fsp,
2298 TALLOC_CTX *ctx,
2299 uint32_t function,
2300 uint16_t req_flags,
2301 const uint8_t *in_data,
2302 uint32_t in_len,
2303 uint8_t **out_data,
2304 uint32_t max_out_len,
2305 uint32_t *out_len)
2307 VFS_FIND(fsctl);
2308 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2309 in_data, in_len, out_data, max_out_len,
2310 out_len);
2313 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2314 struct smb_filename *smb_fname,
2315 uint32_t *dosmode)
2317 VFS_FIND(get_dos_attributes);
2318 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2321 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2322 struct files_struct *fsp,
2323 uint32_t *dosmode)
2325 VFS_FIND(fget_dos_attributes);
2326 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2329 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2330 const struct smb_filename *smb_fname,
2331 uint32_t dosmode)
2333 VFS_FIND(set_dos_attributes);
2334 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2337 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2338 struct files_struct *fsp,
2339 uint32_t dosmode)
2341 VFS_FIND(set_dos_attributes);
2342 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2345 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2346 struct tevent_context *ev,
2347 struct vfs_handle_struct *handle,
2348 struct files_struct *fsp,
2349 uint32_t fsctl,
2350 uint32_t ttl,
2351 off_t offset,
2352 size_t to_copy)
2354 VFS_FIND(offload_read_send);
2355 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2356 fsp, fsctl,
2357 ttl, offset, to_copy);
2360 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2361 struct vfs_handle_struct *handle,
2362 TALLOC_CTX *mem_ctx,
2363 DATA_BLOB *token_blob)
2365 VFS_FIND(offload_read_recv);
2366 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2369 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2370 TALLOC_CTX *mem_ctx,
2371 struct tevent_context *ev,
2372 uint32_t fsctl,
2373 DATA_BLOB *token,
2374 off_t transfer_offset,
2375 struct files_struct *dest_fsp,
2376 off_t dest_off,
2377 off_t num)
2379 VFS_FIND(offload_write_send);
2380 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2381 token, transfer_offset,
2382 dest_fsp, dest_off, num);
2385 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2386 struct tevent_req *req,
2387 off_t *copied)
2389 VFS_FIND(offload_write_recv);
2390 return handle->fns->offload_write_recv_fn(handle, req, copied);
2393 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2394 TALLOC_CTX *mem_ctx,
2395 struct files_struct *fsp,
2396 struct smb_filename *smb_fname,
2397 uint16_t *_compression_fmt)
2399 VFS_FIND(get_compression);
2400 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2401 _compression_fmt);
2404 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2405 TALLOC_CTX *mem_ctx,
2406 struct files_struct *fsp,
2407 uint16_t compression_fmt)
2409 VFS_FIND(set_compression);
2410 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2411 compression_fmt);
2414 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2415 TALLOC_CTX *mem_ctx,
2416 const char *service_path,
2417 char **base_volume)
2419 VFS_FIND(snap_check_path);
2420 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2421 base_volume);
2424 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2425 TALLOC_CTX *mem_ctx,
2426 const char *base_volume,
2427 time_t *tstamp,
2428 bool rw,
2429 char **base_path,
2430 char **snap_path)
2432 VFS_FIND(snap_create);
2433 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2434 rw, base_path, snap_path);
2437 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2438 TALLOC_CTX *mem_ctx,
2439 char *base_path,
2440 char *snap_path)
2442 VFS_FIND(snap_delete);
2443 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2444 snap_path);
2447 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2448 struct files_struct *fsp,
2449 uint32_t security_info,
2450 TALLOC_CTX *mem_ctx,
2451 struct security_descriptor **ppdesc)
2453 VFS_FIND(fget_nt_acl);
2454 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2455 mem_ctx, ppdesc);
2458 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2459 const struct smb_filename *smb_fname,
2460 uint32_t security_info,
2461 TALLOC_CTX *mem_ctx,
2462 struct security_descriptor **ppdesc)
2464 VFS_FIND(get_nt_acl);
2465 return handle->fns->get_nt_acl_fn(handle,
2466 smb_fname,
2467 security_info,
2468 mem_ctx,
2469 ppdesc);
2472 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2473 struct files_struct *fsp,
2474 uint32_t security_info_sent,
2475 const struct security_descriptor *psd)
2477 VFS_FIND(fset_nt_acl);
2478 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2479 psd);
2482 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2483 struct smb_filename *file,
2484 struct security_acl *sacl,
2485 uint32_t access_requested,
2486 uint32_t access_denied)
2488 VFS_FIND(audit_file);
2489 return handle->fns->audit_file_fn(handle,
2490 file,
2491 sacl,
2492 access_requested,
2493 access_denied);
2496 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle,
2497 const struct smb_filename *smb_fname,
2498 mode_t mode)
2500 VFS_FIND(chmod_acl);
2501 return handle->fns->chmod_acl_fn(handle, smb_fname, mode);
2504 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2505 struct files_struct *fsp, mode_t mode)
2507 VFS_FIND(fchmod_acl);
2508 return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2511 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2512 const struct smb_filename *smb_fname,
2513 SMB_ACL_TYPE_T type,
2514 TALLOC_CTX *mem_ctx)
2516 VFS_FIND(sys_acl_get_file);
2517 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2520 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2521 struct files_struct *fsp,
2522 TALLOC_CTX *mem_ctx)
2524 VFS_FIND(sys_acl_get_fd);
2525 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2528 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2529 const struct smb_filename *smb_fname,
2530 TALLOC_CTX *mem_ctx,
2531 char **blob_description,
2532 DATA_BLOB *blob)
2534 VFS_FIND(sys_acl_blob_get_file);
2535 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2536 mem_ctx, blob_description, blob);
2539 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2540 struct files_struct *fsp,
2541 TALLOC_CTX *mem_ctx,
2542 char **blob_description,
2543 DATA_BLOB *blob)
2545 VFS_FIND(sys_acl_blob_get_fd);
2546 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2549 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2550 const struct smb_filename *smb_fname,
2551 SMB_ACL_TYPE_T acltype,
2552 SMB_ACL_T theacl)
2554 VFS_FIND(sys_acl_set_file);
2555 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2556 acltype, theacl);
2559 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2560 struct files_struct *fsp, SMB_ACL_T theacl)
2562 VFS_FIND(sys_acl_set_fd);
2563 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2566 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2567 const struct smb_filename *smb_fname)
2569 VFS_FIND(sys_acl_delete_def_file);
2570 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2573 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2574 const struct smb_filename *smb_fname,
2575 const char *name,
2576 void *value,
2577 size_t size)
2579 VFS_FIND(getxattr);
2580 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2583 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2584 struct files_struct *fsp, const char *name,
2585 void *value, size_t size)
2587 VFS_FIND(fgetxattr);
2588 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2591 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2592 const struct smb_filename *smb_fname,
2593 char *list,
2594 size_t size)
2596 VFS_FIND(listxattr);
2597 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2600 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2601 struct files_struct *fsp, char *list,
2602 size_t size)
2604 VFS_FIND(flistxattr);
2605 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2608 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2609 const struct smb_filename *smb_fname,
2610 const char *name)
2612 VFS_FIND(removexattr);
2613 return handle->fns->removexattr_fn(handle, smb_fname, name);
2616 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2617 struct files_struct *fsp, const char *name)
2619 VFS_FIND(fremovexattr);
2620 return handle->fns->fremovexattr_fn(handle, fsp, name);
2623 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2624 const struct smb_filename *smb_fname,
2625 const char *name,
2626 const void *value,
2627 size_t size,
2628 int flags)
2630 VFS_FIND(setxattr);
2631 return handle->fns->setxattr_fn(handle, smb_fname,
2632 name, value, size, flags);
2635 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2636 struct files_struct *fsp, const char *name,
2637 const void *value, size_t size, int flags)
2639 VFS_FIND(fsetxattr);
2640 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2643 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2644 struct files_struct *fsp)
2646 VFS_FIND(aio_force);
2647 return handle->fns->aio_force_fn(handle, fsp);
2650 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2651 struct files_struct *fsp,
2652 TALLOC_CTX *mem_ctx,
2653 DATA_BLOB *cookie)
2655 VFS_FIND(durable_cookie);
2656 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2659 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2660 struct files_struct *fsp,
2661 const DATA_BLOB old_cookie,
2662 TALLOC_CTX *mem_ctx,
2663 DATA_BLOB *new_cookie)
2665 VFS_FIND(durable_disconnect);
2666 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2667 mem_ctx, new_cookie);
2670 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2671 struct smb_request *smb1req,
2672 struct smbXsrv_open *op,
2673 const DATA_BLOB old_cookie,
2674 TALLOC_CTX *mem_ctx,
2675 struct files_struct **fsp,
2676 DATA_BLOB *new_cookie)
2678 VFS_FIND(durable_reconnect);
2679 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2680 old_cookie, mem_ctx, fsp,
2681 new_cookie);
2684 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2685 const struct smb_filename *fname,
2686 TALLOC_CTX *mem_ctx,
2687 struct readdir_attr_data **attr_data)
2689 VFS_FIND(readdir_attr);
2690 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);