s3: VFS: Change SMB_VFS_LINK to use const struct smb_filename * instead of const...
[Samba.git] / source3 / smbd / vfs.c
blobc747bde5569110fa5df70a2c78a37229f562e248
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 char *path)
860 int ret;
862 if (!LastDir) {
863 LastDir = SMB_STRDUP("");
866 if (ISDOT(path)) {
867 return 0;
870 if (*path == '/' && strcsequal(LastDir,path)) {
871 return 0;
874 DEBUG(4,("vfs_ChDir to %s\n",path));
876 ret = SMB_VFS_CHDIR(conn,path);
877 if (ret == 0) {
878 /* Global cache. */
879 SAFE_FREE(LastDir);
880 LastDir = SMB_STRDUP(path);
882 /* conn cache. */
883 TALLOC_FREE(conn->cwd);
884 conn->cwd = vfs_GetWd(conn, conn);
885 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
887 return ret;
890 /*******************************************************************
891 Return the absolute current directory path - given a UNIX pathname.
892 Note that this path is returned in DOS format, not UNIX
893 format. Note this can be called with conn == NULL.
894 ********************************************************************/
896 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
898 char *current_dir = NULL;
899 char *result = NULL;
900 DATA_BLOB cache_value;
901 struct file_id key;
902 struct smb_filename *smb_fname_dot = NULL;
903 struct smb_filename *smb_fname_full = NULL;
905 if (!lp_getwd_cache()) {
906 goto nocache;
909 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
910 if (smb_fname_dot == NULL) {
911 errno = ENOMEM;
912 goto out;
915 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
917 * Known to fail for root: the directory may be NFS-mounted
918 * and exported with root_squash (so has no root access).
920 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
921 "(NFS problem ?)\n", strerror(errno) ));
922 goto nocache;
925 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
927 if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
928 data_blob_const(&key, sizeof(key)),
929 &cache_value)) {
930 goto nocache;
933 SMB_ASSERT((cache_value.length > 0)
934 && (cache_value.data[cache_value.length-1] == '\0'));
936 smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
937 NULL, NULL, 0);
938 if (smb_fname_full == NULL) {
939 errno = ENOMEM;
940 goto out;
943 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
944 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
945 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
946 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
948 * Ok, we're done
950 result = talloc_strdup(ctx, smb_fname_full->base_name);
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 = SMB_VFS_GETWD(conn);
966 if (current_dir == 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);
975 memcache_add(smbd_memcache(), GETWD_CACHE,
976 data_blob_const(&key, sizeof(key)),
977 data_blob_const(current_dir,
978 strlen(current_dir)+1));
981 result = talloc_strdup(ctx, current_dir);
982 if (result == NULL) {
983 errno = ENOMEM;
986 out:
987 TALLOC_FREE(smb_fname_dot);
988 TALLOC_FREE(smb_fname_full);
989 SAFE_FREE(current_dir);
990 return result;
993 /*******************************************************************
994 Reduce a file name, removing .. elements and checking that
995 it is below dir in the heirachy. This uses realpath.
996 This function must run as root, and will return names
997 and valid stat structs that can be checked on open.
998 ********************************************************************/
1000 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1001 const char *fname,
1002 struct smb_request *smbreq)
1004 NTSTATUS status;
1005 TALLOC_CTX *ctx = talloc_tos();
1006 const char *conn_rootdir;
1007 size_t rootdir_len;
1008 char *dir_name = NULL;
1009 const char *last_component = NULL;
1010 char *resolved_name = NULL;
1011 char *saved_dir = NULL;
1012 struct smb_filename *smb_fname_cwd = NULL;
1013 struct privilege_paths *priv_paths = NULL;
1014 int ret;
1016 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1017 fname,
1018 conn->connectpath));
1021 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1022 if (!priv_paths) {
1023 status = NT_STATUS_NO_MEMORY;
1024 goto err;
1027 if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
1028 status = NT_STATUS_NO_MEMORY;
1029 goto err;
1032 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1033 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1035 if (priv_paths->parent_name.base_name == NULL ||
1036 priv_paths->file_name.base_name == NULL) {
1037 status = NT_STATUS_NO_MEMORY;
1038 goto err;
1041 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1042 status = map_nt_error_from_unix(errno);
1043 goto err;
1045 /* Remember where we were. */
1046 saved_dir = vfs_GetWd(ctx, conn);
1047 if (!saved_dir) {
1048 status = map_nt_error_from_unix(errno);
1049 goto err;
1052 /* Go to the parent directory to lock in memory. */
1053 if (vfs_ChDir(conn, priv_paths->parent_name.base_name) == -1) {
1054 status = map_nt_error_from_unix(errno);
1055 goto err;
1058 /* Get the absolute path of the parent directory. */
1059 resolved_name = SMB_VFS_REALPATH(conn,".");
1060 if (!resolved_name) {
1061 status = map_nt_error_from_unix(errno);
1062 goto err;
1065 if (*resolved_name != '/') {
1066 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1067 "doesn't return absolute paths !\n"));
1068 status = NT_STATUS_OBJECT_NAME_INVALID;
1069 goto err;
1072 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1073 priv_paths->parent_name.base_name,
1074 resolved_name));
1076 /* Now check the stat value is the same. */
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 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1084 status = map_nt_error_from_unix(errno);
1085 goto err;
1088 /* Ensure we're pointing at the same place. */
1089 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1090 DEBUG(0,("check_reduced_name_with_privilege: "
1091 "device/inode/uid/gid on directory %s changed. "
1092 "Denying access !\n",
1093 priv_paths->parent_name.base_name));
1094 status = NT_STATUS_ACCESS_DENIED;
1095 goto err;
1098 /* Ensure we're below the connect path. */
1100 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1101 if (conn_rootdir == NULL) {
1102 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1103 "conn_rootdir\n"));
1104 status = NT_STATUS_ACCESS_DENIED;
1105 goto err;
1108 rootdir_len = strlen(conn_rootdir);
1111 * In the case of rootdir_len == 1, we know that conn_rootdir is
1112 * "/", and we also know that resolved_name starts with a slash.
1113 * So, in this corner case, resolved_name is automatically a
1114 * sub-directory of the conn_rootdir. Thus we can skip the string
1115 * comparison and the next character checks (which are even
1116 * wrong in this case).
1118 if (rootdir_len != 1) {
1119 bool matched;
1121 matched = (strncmp(conn_rootdir, resolved_name,
1122 rootdir_len) == 0);
1124 if (!matched || (resolved_name[rootdir_len] != '/' &&
1125 resolved_name[rootdir_len] != '\0')) {
1126 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1127 "access attempt: %s is a symlink outside the "
1128 "share path\n",
1129 dir_name));
1130 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1131 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1132 status = NT_STATUS_ACCESS_DENIED;
1133 goto err;
1137 /* Now ensure that the last component either doesn't
1138 exist, or is *NOT* a symlink. */
1140 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1141 if (ret == -1) {
1142 /* Errno must be ENOENT for this be ok. */
1143 if (errno != ENOENT) {
1144 status = map_nt_error_from_unix(errno);
1145 DEBUG(2, ("check_reduced_name_with_privilege: "
1146 "LSTAT on %s failed with %s\n",
1147 priv_paths->file_name.base_name,
1148 nt_errstr(status)));
1149 goto err;
1153 if (VALID_STAT(priv_paths->file_name.st) &&
1154 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1155 DEBUG(2, ("check_reduced_name_with_privilege: "
1156 "Last component %s is a symlink. Denying"
1157 "access.\n",
1158 priv_paths->file_name.base_name));
1159 status = NT_STATUS_ACCESS_DENIED;
1160 goto err;
1163 smbreq->priv_paths = priv_paths;
1164 status = NT_STATUS_OK;
1166 err:
1168 if (saved_dir) {
1169 vfs_ChDir(conn, saved_dir);
1171 SAFE_FREE(resolved_name);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 TALLOC_FREE(priv_paths);
1175 TALLOC_FREE(dir_name);
1176 return status;
1179 /*******************************************************************
1180 Reduce a file name, removing .. elements and checking that
1181 it is below dir in the heirachy. This uses realpath.
1183 If cwd_name == NULL then fname is a client given path relative
1184 to the root path of the share.
1186 If cwd_name != NULL then fname is a client given path relative
1187 to cwd_name. cwd_name is relative to the root path of the share.
1188 ********************************************************************/
1190 NTSTATUS check_reduced_name(connection_struct *conn,
1191 const char *cwd_name,
1192 const char *fname)
1194 char *resolved_name = NULL;
1195 char *new_fname = NULL;
1196 bool allow_symlinks = true;
1197 bool allow_widelinks = false;
1199 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1201 resolved_name = SMB_VFS_REALPATH(conn,fname);
1203 if (!resolved_name) {
1204 switch (errno) {
1205 case ENOTDIR:
1206 DEBUG(3,("check_reduced_name: Component not a "
1207 "directory in getting realpath for "
1208 "%s\n", fname));
1209 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1210 case ENOENT:
1212 TALLOC_CTX *ctx = talloc_tos();
1213 char *dir_name = NULL;
1214 const char *last_component = NULL;
1215 char *new_name = NULL;
1216 int ret;
1218 /* Last component didn't exist.
1219 Remove it and try and canonicalise
1220 the directory name. */
1221 if (!parent_dirname(ctx, fname,
1222 &dir_name,
1223 &last_component)) {
1224 return NT_STATUS_NO_MEMORY;
1227 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1228 if (!resolved_name) {
1229 NTSTATUS status = map_nt_error_from_unix(errno);
1231 if (errno == ENOENT || errno == ENOTDIR) {
1232 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1235 DEBUG(3,("check_reduce_name: "
1236 "couldn't get realpath for "
1237 "%s (%s)\n",
1238 fname,
1239 nt_errstr(status)));
1240 return status;
1242 ret = asprintf(&new_name, "%s/%s",
1243 resolved_name, last_component);
1244 SAFE_FREE(resolved_name);
1245 if (ret == -1) {
1246 return NT_STATUS_NO_MEMORY;
1248 resolved_name = new_name;
1249 break;
1251 default:
1252 DEBUG(3,("check_reduced_name: couldn't get "
1253 "realpath for %s\n", fname));
1254 return map_nt_error_from_unix(errno);
1258 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1259 resolved_name));
1261 if (*resolved_name != '/') {
1262 DEBUG(0,("check_reduced_name: realpath doesn't return "
1263 "absolute paths !\n"));
1264 SAFE_FREE(resolved_name);
1265 return NT_STATUS_OBJECT_NAME_INVALID;
1268 allow_widelinks = lp_widelinks(SNUM(conn));
1269 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1271 /* Common widelinks and symlinks checks. */
1272 if (!allow_widelinks || !allow_symlinks) {
1273 const char *conn_rootdir;
1274 size_t rootdir_len;
1276 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1277 if (conn_rootdir == NULL) {
1278 DEBUG(2, ("check_reduced_name: Could not get "
1279 "conn_rootdir\n"));
1280 SAFE_FREE(resolved_name);
1281 return NT_STATUS_ACCESS_DENIED;
1284 rootdir_len = strlen(conn_rootdir);
1287 * In the case of rootdir_len == 1, we know that
1288 * conn_rootdir is "/", and we also know that
1289 * resolved_name starts with a slash. So, in this
1290 * corner case, resolved_name is automatically a
1291 * sub-directory of the conn_rootdir. Thus we can skip
1292 * the string comparison and the next character checks
1293 * (which are even wrong in this case).
1295 if (rootdir_len != 1) {
1296 bool matched;
1298 matched = (strncmp(conn_rootdir, resolved_name,
1299 rootdir_len) == 0);
1300 if (!matched || (resolved_name[rootdir_len] != '/' &&
1301 resolved_name[rootdir_len] != '\0')) {
1302 DEBUG(2, ("check_reduced_name: Bad access "
1303 "attempt: %s is a symlink outside the "
1304 "share path\n", fname));
1305 DEBUGADD(2, ("conn_rootdir =%s\n",
1306 conn_rootdir));
1307 DEBUGADD(2, ("resolved_name=%s\n",
1308 resolved_name));
1309 SAFE_FREE(resolved_name);
1310 return NT_STATUS_ACCESS_DENIED;
1314 /* Extra checks if all symlinks are disallowed. */
1315 if (!allow_symlinks) {
1316 /* fname can't have changed in resolved_path. */
1317 const char *p = &resolved_name[rootdir_len];
1320 * UNIX filesystem semantics, names consisting
1321 * only of "." or ".." CANNOT be symlinks.
1323 if (ISDOT(fname) || ISDOTDOT(fname)) {
1324 goto out;
1327 if (*p != '/') {
1328 DEBUG(2, ("check_reduced_name: logic error (%c) "
1329 "in resolved_name: %s\n",
1331 fname));
1332 SAFE_FREE(resolved_name);
1333 return NT_STATUS_ACCESS_DENIED;
1336 p++;
1339 * If cwd_name is present and not ".",
1340 * then fname is relative to that, not
1341 * the root of the share. Make sure the
1342 * path we check is the one the client
1343 * sent (cwd_name+fname).
1345 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1346 new_fname = talloc_asprintf(talloc_tos(),
1347 "%s/%s",
1348 cwd_name,
1349 fname);
1350 if (new_fname == NULL) {
1351 SAFE_FREE(resolved_name);
1352 return NT_STATUS_NO_MEMORY;
1354 fname = new_fname;
1357 if (strcmp(fname, p)!=0) {
1358 DEBUG(2, ("check_reduced_name: Bad access "
1359 "attempt: %s is a symlink to %s\n",
1360 fname, p));
1361 SAFE_FREE(resolved_name);
1362 TALLOC_FREE(new_fname);
1363 return NT_STATUS_ACCESS_DENIED;
1368 out:
1370 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1371 SAFE_FREE(resolved_name);
1372 TALLOC_FREE(new_fname);
1373 return NT_STATUS_OK;
1377 * XXX: This is temporary and there should be no callers of this once
1378 * smb_filename is plumbed through all path based operations.
1380 * Called when we know stream name parsing has already been done.
1382 int vfs_stat_smb_basename(struct connection_struct *conn,
1383 const struct smb_filename *smb_fname_in,
1384 SMB_STRUCT_STAT *psbuf)
1386 struct smb_filename smb_fname = {
1387 .base_name = discard_const_p(char, smb_fname_in->base_name),
1388 .flags = smb_fname_in->flags
1390 int ret;
1392 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1393 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1394 } else {
1395 ret = SMB_VFS_STAT(conn, &smb_fname);
1398 if (ret != -1) {
1399 *psbuf = smb_fname.st;
1401 return ret;
1405 * Ensure LSTAT is called for POSIX paths.
1408 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1410 int ret;
1412 if(fsp->fh->fd == -1) {
1413 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1414 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1415 } else {
1416 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1418 if (ret == -1) {
1419 return map_nt_error_from_unix(errno);
1421 } else {
1422 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1423 return map_nt_error_from_unix(errno);
1426 return NT_STATUS_OK;
1430 * Initialize num_streams and streams, then call VFS op streaminfo
1432 NTSTATUS vfs_streaminfo(connection_struct *conn,
1433 struct files_struct *fsp,
1434 const struct smb_filename *smb_fname,
1435 TALLOC_CTX *mem_ctx,
1436 unsigned int *num_streams,
1437 struct stream_struct **streams)
1439 *num_streams = 0;
1440 *streams = NULL;
1441 return SMB_VFS_STREAMINFO(conn,
1442 fsp,
1443 smb_fname,
1444 mem_ctx,
1445 num_streams,
1446 streams);
1450 generate a file_id from a stat structure
1452 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1454 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1457 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1458 const char *service, const char *user)
1460 VFS_FIND(connect);
1461 return handle->fns->connect_fn(handle, service, user);
1464 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1466 VFS_FIND(disconnect);
1467 handle->fns->disconnect_fn(handle);
1470 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1471 const struct smb_filename *smb_fname,
1472 uint64_t *bsize,
1473 uint64_t *dfree,
1474 uint64_t *dsize)
1476 VFS_FIND(disk_free);
1477 return handle->fns->disk_free_fn(handle, smb_fname,
1478 bsize, dfree, dsize);
1481 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1482 const struct smb_filename *smb_fname,
1483 enum SMB_QUOTA_TYPE qtype,
1484 unid_t id,
1485 SMB_DISK_QUOTA *qt)
1487 VFS_FIND(get_quota);
1488 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1491 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1492 enum SMB_QUOTA_TYPE qtype, unid_t id,
1493 SMB_DISK_QUOTA *qt)
1495 VFS_FIND(set_quota);
1496 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1499 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1500 struct files_struct *fsp,
1501 struct shadow_copy_data *shadow_copy_data,
1502 bool labels)
1504 VFS_FIND(get_shadow_copy_data);
1505 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1506 shadow_copy_data,
1507 labels);
1509 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
1510 struct vfs_statvfs_struct *statbuf)
1512 VFS_FIND(statvfs);
1513 return handle->fns->statvfs_fn(handle, path, statbuf);
1516 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1517 enum timestamp_set_resolution *p_ts_res)
1519 VFS_FIND(fs_capabilities);
1520 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1523 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1524 struct dfs_GetDFSReferral *r)
1526 VFS_FIND(get_dfs_referrals);
1527 return handle->fns->get_dfs_referrals_fn(handle, r);
1530 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1531 const struct smb_filename *smb_fname,
1532 const char *mask,
1533 uint32_t attributes)
1535 VFS_FIND(opendir);
1536 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1539 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1540 struct files_struct *fsp,
1541 const char *mask,
1542 uint32_t attributes)
1544 VFS_FIND(fdopendir);
1545 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1548 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1549 DIR *dirp,
1550 SMB_STRUCT_STAT *sbuf)
1552 VFS_FIND(readdir);
1553 return handle->fns->readdir_fn(handle, dirp, sbuf);
1556 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1557 DIR *dirp, long offset)
1559 VFS_FIND(seekdir);
1560 handle->fns->seekdir_fn(handle, dirp, offset);
1563 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1564 DIR *dirp)
1566 VFS_FIND(telldir);
1567 return handle->fns->telldir_fn(handle, dirp);
1570 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1571 DIR *dirp)
1573 VFS_FIND(rewind_dir);
1574 handle->fns->rewind_dir_fn(handle, dirp);
1577 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1578 const struct smb_filename *smb_fname,
1579 mode_t mode)
1581 VFS_FIND(mkdir);
1582 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1585 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1586 const struct smb_filename *smb_fname)
1588 VFS_FIND(rmdir);
1589 return handle->fns->rmdir_fn(handle, smb_fname);
1592 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1593 DIR *dir)
1595 VFS_FIND(closedir);
1596 return handle->fns->closedir_fn(handle, dir);
1599 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1600 DIR *dirp)
1602 VFS_FIND(init_search_op);
1603 handle->fns->init_search_op_fn(handle, dirp);
1606 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1607 struct smb_filename *smb_fname, struct files_struct *fsp,
1608 int flags, mode_t mode)
1610 VFS_FIND(open);
1611 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1614 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1615 struct smb_request *req,
1616 uint16_t root_dir_fid,
1617 struct smb_filename *smb_fname,
1618 uint32_t access_mask,
1619 uint32_t share_access,
1620 uint32_t create_disposition,
1621 uint32_t create_options,
1622 uint32_t file_attributes,
1623 uint32_t oplock_request,
1624 struct smb2_lease *lease,
1625 uint64_t allocation_size,
1626 uint32_t private_flags,
1627 struct security_descriptor *sd,
1628 struct ea_list *ea_list,
1629 files_struct **result,
1630 int *pinfo,
1631 const struct smb2_create_blobs *in_context_blobs,
1632 struct smb2_create_blobs *out_context_blobs)
1634 VFS_FIND(create_file);
1635 return handle->fns->create_file_fn(
1636 handle, req, root_dir_fid, smb_fname, access_mask,
1637 share_access, create_disposition, create_options,
1638 file_attributes, oplock_request, lease, allocation_size,
1639 private_flags, sd, ea_list,
1640 result, pinfo, in_context_blobs, out_context_blobs);
1643 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1644 struct files_struct *fsp)
1646 VFS_FIND(close);
1647 return handle->fns->close_fn(handle, fsp);
1650 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1651 struct files_struct *fsp, void *data, size_t n)
1653 VFS_FIND(read);
1654 return handle->fns->read_fn(handle, fsp, data, n);
1657 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1658 struct files_struct *fsp, void *data, size_t n,
1659 off_t offset)
1661 VFS_FIND(pread);
1662 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1665 struct smb_vfs_call_pread_state {
1666 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1667 ssize_t retval;
1668 struct vfs_aio_state vfs_aio_state;
1671 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1673 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1674 TALLOC_CTX *mem_ctx,
1675 struct tevent_context *ev,
1676 struct files_struct *fsp,
1677 void *data,
1678 size_t n, off_t offset)
1680 struct tevent_req *req, *subreq;
1681 struct smb_vfs_call_pread_state *state;
1683 req = tevent_req_create(mem_ctx, &state,
1684 struct smb_vfs_call_pread_state);
1685 if (req == NULL) {
1686 return NULL;
1688 VFS_FIND(pread_send);
1689 state->recv_fn = handle->fns->pread_recv_fn;
1691 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1692 offset);
1693 if (tevent_req_nomem(subreq, req)) {
1694 return tevent_req_post(req, ev);
1696 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1697 return req;
1700 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1702 struct tevent_req *req = tevent_req_callback_data(
1703 subreq, struct tevent_req);
1704 struct smb_vfs_call_pread_state *state = tevent_req_data(
1705 req, struct smb_vfs_call_pread_state);
1707 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1708 TALLOC_FREE(subreq);
1709 if (state->retval == -1) {
1710 tevent_req_error(req, state->vfs_aio_state.error);
1711 return;
1713 tevent_req_done(req);
1716 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1717 struct vfs_aio_state *vfs_aio_state)
1719 struct smb_vfs_call_pread_state *state = tevent_req_data(
1720 req, struct smb_vfs_call_pread_state);
1722 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1723 return -1;
1725 *vfs_aio_state = state->vfs_aio_state;
1726 return state->retval;
1729 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1730 struct files_struct *fsp, const void *data,
1731 size_t n)
1733 VFS_FIND(write);
1734 return handle->fns->write_fn(handle, fsp, data, n);
1737 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1738 struct files_struct *fsp, const void *data,
1739 size_t n, off_t offset)
1741 VFS_FIND(pwrite);
1742 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1745 struct smb_vfs_call_pwrite_state {
1746 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1747 ssize_t retval;
1748 struct vfs_aio_state vfs_aio_state;
1751 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1753 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1754 TALLOC_CTX *mem_ctx,
1755 struct tevent_context *ev,
1756 struct files_struct *fsp,
1757 const void *data,
1758 size_t n, off_t offset)
1760 struct tevent_req *req, *subreq;
1761 struct smb_vfs_call_pwrite_state *state;
1763 req = tevent_req_create(mem_ctx, &state,
1764 struct smb_vfs_call_pwrite_state);
1765 if (req == NULL) {
1766 return NULL;
1768 VFS_FIND(pwrite_send);
1769 state->recv_fn = handle->fns->pwrite_recv_fn;
1771 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1772 offset);
1773 if (tevent_req_nomem(subreq, req)) {
1774 return tevent_req_post(req, ev);
1776 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1777 return req;
1780 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1782 struct tevent_req *req = tevent_req_callback_data(
1783 subreq, struct tevent_req);
1784 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1785 req, struct smb_vfs_call_pwrite_state);
1787 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1788 TALLOC_FREE(subreq);
1789 if (state->retval == -1) {
1790 tevent_req_error(req, state->vfs_aio_state.error);
1791 return;
1793 tevent_req_done(req);
1796 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1797 struct vfs_aio_state *vfs_aio_state)
1799 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1800 req, struct smb_vfs_call_pwrite_state);
1802 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1803 return -1;
1805 *vfs_aio_state = state->vfs_aio_state;
1806 return state->retval;
1809 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1810 struct files_struct *fsp, off_t offset,
1811 int whence)
1813 VFS_FIND(lseek);
1814 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1817 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1818 files_struct *fromfsp, const DATA_BLOB *header,
1819 off_t offset, size_t count)
1821 VFS_FIND(sendfile);
1822 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1823 count);
1826 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1827 files_struct *tofsp, off_t offset,
1828 size_t count)
1830 VFS_FIND(recvfile);
1831 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1834 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1835 const struct smb_filename *smb_fname_src,
1836 const struct smb_filename *smb_fname_dst)
1838 VFS_FIND(rename);
1839 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1842 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1843 struct files_struct *fsp)
1845 VFS_FIND(fsync);
1846 return handle->fns->fsync_fn(handle, fsp);
1849 struct smb_vfs_call_fsync_state {
1850 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1851 int retval;
1852 struct vfs_aio_state vfs_aio_state;
1855 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1857 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1858 TALLOC_CTX *mem_ctx,
1859 struct tevent_context *ev,
1860 struct files_struct *fsp)
1862 struct tevent_req *req, *subreq;
1863 struct smb_vfs_call_fsync_state *state;
1865 req = tevent_req_create(mem_ctx, &state,
1866 struct smb_vfs_call_fsync_state);
1867 if (req == NULL) {
1868 return NULL;
1870 VFS_FIND(fsync_send);
1871 state->recv_fn = handle->fns->fsync_recv_fn;
1873 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1874 if (tevent_req_nomem(subreq, req)) {
1875 return tevent_req_post(req, ev);
1877 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1878 return req;
1881 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1883 struct tevent_req *req = tevent_req_callback_data(
1884 subreq, struct tevent_req);
1885 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1886 req, struct smb_vfs_call_fsync_state);
1888 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1889 TALLOC_FREE(subreq);
1890 if (state->retval == -1) {
1891 tevent_req_error(req, state->vfs_aio_state.error);
1892 return;
1894 tevent_req_done(req);
1897 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1899 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1900 req, struct smb_vfs_call_fsync_state);
1902 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1903 return -1;
1905 *vfs_aio_state = state->vfs_aio_state;
1906 return state->retval;
1910 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1911 struct smb_filename *smb_fname)
1913 VFS_FIND(stat);
1914 return handle->fns->stat_fn(handle, smb_fname);
1917 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1918 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1920 VFS_FIND(fstat);
1921 return handle->fns->fstat_fn(handle, fsp, sbuf);
1924 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1925 struct smb_filename *smb_filename)
1927 VFS_FIND(lstat);
1928 return handle->fns->lstat_fn(handle, smb_filename);
1931 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1932 struct files_struct *fsp,
1933 const SMB_STRUCT_STAT *sbuf)
1935 VFS_FIND(get_alloc_size);
1936 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1939 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1940 const struct smb_filename *smb_fname)
1942 VFS_FIND(unlink);
1943 return handle->fns->unlink_fn(handle, smb_fname);
1946 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1947 const struct smb_filename *smb_fname,
1948 mode_t mode)
1950 VFS_FIND(chmod);
1951 return handle->fns->chmod_fn(handle, smb_fname, mode);
1954 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1955 struct files_struct *fsp, mode_t mode)
1957 VFS_FIND(fchmod);
1958 return handle->fns->fchmod_fn(handle, fsp, mode);
1961 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1962 const struct smb_filename *smb_fname,
1963 uid_t uid,
1964 gid_t gid)
1966 VFS_FIND(chown);
1967 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1970 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1971 struct files_struct *fsp, uid_t uid, gid_t gid)
1973 VFS_FIND(fchown);
1974 return handle->fns->fchown_fn(handle, fsp, uid, gid);
1977 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
1978 const struct smb_filename *smb_fname,
1979 uid_t uid,
1980 gid_t gid)
1982 VFS_FIND(lchown);
1983 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
1986 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
1988 int ret;
1989 bool as_root = false;
1990 NTSTATUS status;
1992 if (fsp->fh->fd != -1) {
1993 /* Try fchown. */
1994 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
1995 if (ret == 0) {
1996 return NT_STATUS_OK;
1998 if (ret == -1 && errno != ENOSYS) {
1999 return map_nt_error_from_unix(errno);
2003 as_root = (geteuid() == 0);
2005 if (as_root) {
2007 * We are being asked to chown as root. Make
2008 * sure we chdir() into the path to pin it,
2009 * and always act using lchown to ensure we
2010 * don't deref any symbolic links.
2012 char *saved_dir = NULL;
2013 char *parent_dir = NULL;
2014 const char *final_component = NULL;
2015 struct smb_filename *local_smb_fname = NULL;
2017 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
2018 if (!saved_dir) {
2019 status = map_nt_error_from_unix(errno);
2020 DEBUG(0,("vfs_chown_fsp: failed to get "
2021 "current working directory. Error was %s\n",
2022 strerror(errno)));
2023 return status;
2026 if (!parent_dirname(talloc_tos(),
2027 fsp->fsp_name->base_name,
2028 &parent_dir,
2029 &final_component)) {
2030 return NT_STATUS_NO_MEMORY;
2033 /* cd into the parent dir to pin it. */
2034 ret = vfs_ChDir(fsp->conn, parent_dir);
2035 if (ret == -1) {
2036 return map_nt_error_from_unix(errno);
2039 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2040 final_component,
2041 NULL,
2042 NULL,
2043 fsp->fsp_name->flags);
2044 if (local_smb_fname == NULL) {
2045 status = NT_STATUS_NO_MEMORY;
2046 goto out;
2049 /* Must use lstat here. */
2050 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2051 if (ret == -1) {
2052 status = map_nt_error_from_unix(errno);
2053 goto out;
2056 /* Ensure it matches the fsp stat. */
2057 if (!check_same_stat(&local_smb_fname->st,
2058 &fsp->fsp_name->st)) {
2059 status = NT_STATUS_ACCESS_DENIED;
2060 goto out;
2063 ret = SMB_VFS_LCHOWN(fsp->conn,
2064 local_smb_fname,
2065 uid, gid);
2067 if (ret == 0) {
2068 status = NT_STATUS_OK;
2069 } else {
2070 status = map_nt_error_from_unix(errno);
2073 out:
2075 vfs_ChDir(fsp->conn,saved_dir);
2076 TALLOC_FREE(local_smb_fname);
2077 TALLOC_FREE(saved_dir);
2078 TALLOC_FREE(parent_dir);
2080 return status;
2083 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2084 ret = SMB_VFS_LCHOWN(fsp->conn,
2085 fsp->fsp_name,
2086 uid, gid);
2087 } else {
2088 ret = SMB_VFS_CHOWN(fsp->conn,
2089 fsp->fsp_name,
2090 uid, gid);
2093 if (ret == 0) {
2094 status = NT_STATUS_OK;
2095 } else {
2096 status = map_nt_error_from_unix(errno);
2098 return status;
2101 int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
2103 VFS_FIND(chdir);
2104 return handle->fns->chdir_fn(handle, path);
2107 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
2109 VFS_FIND(getwd);
2110 return handle->fns->getwd_fn(handle);
2113 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2114 const struct smb_filename *smb_fname,
2115 struct smb_file_time *ft)
2117 VFS_FIND(ntimes);
2118 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2121 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2122 struct files_struct *fsp, off_t offset)
2124 VFS_FIND(ftruncate);
2125 return handle->fns->ftruncate_fn(handle, fsp, offset);
2128 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2129 struct files_struct *fsp,
2130 uint32_t mode,
2131 off_t offset,
2132 off_t len)
2134 VFS_FIND(fallocate);
2135 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2138 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2139 struct files_struct *fsp, uint32_t share_mode,
2140 uint32_t access_mask)
2142 VFS_FIND(kernel_flock);
2143 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2144 access_mask);
2147 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2148 struct files_struct *fsp, int leasetype)
2150 VFS_FIND(linux_setlease);
2151 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2154 int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
2155 const char *newpath)
2157 VFS_FIND(symlink);
2158 return handle->fns->symlink_fn(handle, oldpath, newpath);
2161 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2162 const char *path, char *buf, size_t bufsiz)
2164 VFS_FIND(readlink);
2165 return handle->fns->readlink_fn(handle, path, buf, bufsiz);
2168 int smb_vfs_call_link(struct vfs_handle_struct *handle,
2169 const struct smb_filename *old_smb_fname,
2170 const struct smb_filename *new_smb_fname)
2172 VFS_FIND(link);
2173 return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2176 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2177 const struct smb_filename *smb_fname,
2178 mode_t mode,
2179 SMB_DEV_T dev)
2181 VFS_FIND(mknod);
2182 return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2185 char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
2187 VFS_FIND(realpath);
2188 return handle->fns->realpath_fn(handle, path);
2191 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2192 const struct smb_filename *smb_fname,
2193 unsigned int flags)
2195 VFS_FIND(chflags);
2196 return handle->fns->chflags_fn(handle, smb_fname, flags);
2199 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2200 const SMB_STRUCT_STAT *sbuf)
2202 VFS_FIND(file_id_create);
2203 return handle->fns->file_id_create_fn(handle, sbuf);
2206 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2207 struct files_struct *fsp,
2208 const struct smb_filename *smb_fname,
2209 TALLOC_CTX *mem_ctx,
2210 unsigned int *num_streams,
2211 struct stream_struct **streams)
2213 VFS_FIND(streaminfo);
2214 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2215 num_streams, streams);
2218 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2219 const char *path, const char *name,
2220 TALLOC_CTX *mem_ctx, char **found_name)
2222 VFS_FIND(get_real_filename);
2223 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2224 found_name);
2227 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2228 const char *filename)
2230 VFS_FIND(connectpath);
2231 return handle->fns->connectpath_fn(handle, filename);
2234 bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
2235 struct files_struct *fsp,
2236 struct lock_struct *plock)
2238 VFS_FIND(strict_lock);
2239 return handle->fns->strict_lock_fn(handle, fsp, plock);
2242 void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
2243 struct files_struct *fsp,
2244 struct lock_struct *plock)
2246 VFS_FIND(strict_unlock);
2247 handle->fns->strict_unlock_fn(handle, fsp, plock);
2250 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2251 const char *name,
2252 enum vfs_translate_direction direction,
2253 TALLOC_CTX *mem_ctx,
2254 char **mapped_name)
2256 VFS_FIND(translate_name);
2257 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2258 mapped_name);
2261 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2262 struct files_struct *fsp,
2263 TALLOC_CTX *ctx,
2264 uint32_t function,
2265 uint16_t req_flags,
2266 const uint8_t *in_data,
2267 uint32_t in_len,
2268 uint8_t **out_data,
2269 uint32_t max_out_len,
2270 uint32_t *out_len)
2272 VFS_FIND(fsctl);
2273 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2274 in_data, in_len, out_data, max_out_len,
2275 out_len);
2278 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2279 struct smb_filename *smb_fname,
2280 uint32_t *dosmode)
2282 VFS_FIND(get_dos_attributes);
2283 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2286 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2287 struct files_struct *fsp,
2288 uint32_t *dosmode)
2290 VFS_FIND(fget_dos_attributes);
2291 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2294 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2295 const struct smb_filename *smb_fname,
2296 uint32_t dosmode)
2298 VFS_FIND(set_dos_attributes);
2299 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2302 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2303 struct files_struct *fsp,
2304 uint32_t dosmode)
2306 VFS_FIND(set_dos_attributes);
2307 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2310 struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
2311 TALLOC_CTX *mem_ctx,
2312 struct tevent_context *ev,
2313 struct files_struct *src_fsp,
2314 off_t src_off,
2315 struct files_struct *dest_fsp,
2316 off_t dest_off,
2317 off_t num,
2318 uint32_t flags)
2320 VFS_FIND(copy_chunk_send);
2321 return handle->fns->copy_chunk_send_fn(handle, mem_ctx, ev, src_fsp,
2322 src_off, dest_fsp, dest_off, num,
2323 flags);
2326 NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
2327 struct tevent_req *req,
2328 off_t *copied)
2330 VFS_FIND(copy_chunk_recv);
2331 return handle->fns->copy_chunk_recv_fn(handle, req, copied);
2334 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2335 TALLOC_CTX *mem_ctx,
2336 struct files_struct *fsp,
2337 struct smb_filename *smb_fname,
2338 uint16_t *_compression_fmt)
2340 VFS_FIND(get_compression);
2341 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2342 _compression_fmt);
2345 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2346 TALLOC_CTX *mem_ctx,
2347 struct files_struct *fsp,
2348 uint16_t compression_fmt)
2350 VFS_FIND(set_compression);
2351 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2352 compression_fmt);
2355 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2356 TALLOC_CTX *mem_ctx,
2357 const char *service_path,
2358 char **base_volume)
2360 VFS_FIND(snap_check_path);
2361 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2362 base_volume);
2365 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2366 TALLOC_CTX *mem_ctx,
2367 const char *base_volume,
2368 time_t *tstamp,
2369 bool rw,
2370 char **base_path,
2371 char **snap_path)
2373 VFS_FIND(snap_create);
2374 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2375 rw, base_path, snap_path);
2378 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2379 TALLOC_CTX *mem_ctx,
2380 char *base_path,
2381 char *snap_path)
2383 VFS_FIND(snap_delete);
2384 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2385 snap_path);
2388 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2389 struct files_struct *fsp,
2390 uint32_t security_info,
2391 TALLOC_CTX *mem_ctx,
2392 struct security_descriptor **ppdesc)
2394 VFS_FIND(fget_nt_acl);
2395 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2396 mem_ctx, ppdesc);
2399 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2400 const struct smb_filename *smb_fname,
2401 uint32_t security_info,
2402 TALLOC_CTX *mem_ctx,
2403 struct security_descriptor **ppdesc)
2405 VFS_FIND(get_nt_acl);
2406 return handle->fns->get_nt_acl_fn(handle,
2407 smb_fname,
2408 security_info,
2409 mem_ctx,
2410 ppdesc);
2413 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2414 struct files_struct *fsp,
2415 uint32_t security_info_sent,
2416 const struct security_descriptor *psd)
2418 VFS_FIND(fset_nt_acl);
2419 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2420 psd);
2423 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2424 struct smb_filename *file,
2425 struct security_acl *sacl,
2426 uint32_t access_requested,
2427 uint32_t access_denied)
2429 VFS_FIND(audit_file);
2430 return handle->fns->audit_file_fn(handle,
2431 file,
2432 sacl,
2433 access_requested,
2434 access_denied);
2437 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle,
2438 const struct smb_filename *smb_fname,
2439 mode_t mode)
2441 VFS_FIND(chmod_acl);
2442 return handle->fns->chmod_acl_fn(handle, smb_fname, mode);
2445 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2446 struct files_struct *fsp, mode_t mode)
2448 VFS_FIND(fchmod_acl);
2449 return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2452 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2453 const struct smb_filename *smb_fname,
2454 SMB_ACL_TYPE_T type,
2455 TALLOC_CTX *mem_ctx)
2457 VFS_FIND(sys_acl_get_file);
2458 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2461 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2462 struct files_struct *fsp,
2463 TALLOC_CTX *mem_ctx)
2465 VFS_FIND(sys_acl_get_fd);
2466 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2469 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2470 const struct smb_filename *smb_fname,
2471 TALLOC_CTX *mem_ctx,
2472 char **blob_description,
2473 DATA_BLOB *blob)
2475 VFS_FIND(sys_acl_blob_get_file);
2476 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2477 mem_ctx, blob_description, blob);
2480 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2481 struct files_struct *fsp,
2482 TALLOC_CTX *mem_ctx,
2483 char **blob_description,
2484 DATA_BLOB *blob)
2486 VFS_FIND(sys_acl_blob_get_fd);
2487 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2490 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2491 const struct smb_filename *smb_fname,
2492 SMB_ACL_TYPE_T acltype,
2493 SMB_ACL_T theacl)
2495 VFS_FIND(sys_acl_set_file);
2496 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2497 acltype, theacl);
2500 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2501 struct files_struct *fsp, SMB_ACL_T theacl)
2503 VFS_FIND(sys_acl_set_fd);
2504 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2507 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2508 const struct smb_filename *smb_fname)
2510 VFS_FIND(sys_acl_delete_def_file);
2511 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2514 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2515 const struct smb_filename *smb_fname,
2516 const char *name,
2517 void *value,
2518 size_t size)
2520 VFS_FIND(getxattr);
2521 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2524 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2525 struct files_struct *fsp, const char *name,
2526 void *value, size_t size)
2528 VFS_FIND(fgetxattr);
2529 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2532 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2533 const struct smb_filename *smb_fname,
2534 char *list,
2535 size_t size)
2537 VFS_FIND(listxattr);
2538 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2541 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2542 struct files_struct *fsp, char *list,
2543 size_t size)
2545 VFS_FIND(flistxattr);
2546 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2549 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2550 const struct smb_filename *smb_fname,
2551 const char *name)
2553 VFS_FIND(removexattr);
2554 return handle->fns->removexattr_fn(handle, smb_fname, name);
2557 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2558 struct files_struct *fsp, const char *name)
2560 VFS_FIND(fremovexattr);
2561 return handle->fns->fremovexattr_fn(handle, fsp, name);
2564 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2565 const struct smb_filename *smb_fname,
2566 const char *name,
2567 const void *value,
2568 size_t size,
2569 int flags)
2571 VFS_FIND(setxattr);
2572 return handle->fns->setxattr_fn(handle, smb_fname,
2573 name, value, size, flags);
2576 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2577 struct files_struct *fsp, const char *name,
2578 const void *value, size_t size, int flags)
2580 VFS_FIND(fsetxattr);
2581 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2584 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2585 struct files_struct *fsp)
2587 VFS_FIND(aio_force);
2588 return handle->fns->aio_force_fn(handle, fsp);
2591 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2592 struct files_struct *fsp,
2593 TALLOC_CTX *mem_ctx,
2594 DATA_BLOB *cookie)
2596 VFS_FIND(durable_cookie);
2597 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2600 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2601 struct files_struct *fsp,
2602 const DATA_BLOB old_cookie,
2603 TALLOC_CTX *mem_ctx,
2604 DATA_BLOB *new_cookie)
2606 VFS_FIND(durable_disconnect);
2607 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2608 mem_ctx, new_cookie);
2611 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2612 struct smb_request *smb1req,
2613 struct smbXsrv_open *op,
2614 const DATA_BLOB old_cookie,
2615 TALLOC_CTX *mem_ctx,
2616 struct files_struct **fsp,
2617 DATA_BLOB *new_cookie)
2619 VFS_FIND(durable_reconnect);
2620 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2621 old_cookie, mem_ctx, fsp,
2622 new_cookie);
2625 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2626 const struct smb_filename *fname,
2627 TALLOC_CTX *mem_ctx,
2628 struct readdir_attr_data **attr_data)
2630 VFS_FIND(readdir_attr);
2631 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);