s3: VFS: Change SMB_VFS_CHDIR to use const struct smb_filename * instead of const...
[Samba.git] / source3 / smbd / vfs.c
blob40c41ed27fc29787573444414917586ccc776f44
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);
885 conn->cwd = vfs_GetWd(conn, conn);
886 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
888 return ret;
891 /*******************************************************************
892 Return the absolute current directory path - given a UNIX pathname.
893 Note that this path is returned in DOS format, not UNIX
894 format. Note this can be called with conn == NULL.
895 ********************************************************************/
897 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
899 char *current_dir = NULL;
900 char *result = NULL;
901 DATA_BLOB cache_value;
902 struct file_id key;
903 struct smb_filename *smb_fname_dot = NULL;
904 struct smb_filename *smb_fname_full = NULL;
906 if (!lp_getwd_cache()) {
907 goto nocache;
910 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
911 if (smb_fname_dot == NULL) {
912 errno = ENOMEM;
913 goto out;
916 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
918 * Known to fail for root: the directory may be NFS-mounted
919 * and exported with root_squash (so has no root access).
921 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
922 "(NFS problem ?)\n", strerror(errno) ));
923 goto nocache;
926 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
928 if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
929 data_blob_const(&key, sizeof(key)),
930 &cache_value)) {
931 goto nocache;
934 SMB_ASSERT((cache_value.length > 0)
935 && (cache_value.data[cache_value.length-1] == '\0'));
937 smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
938 NULL, NULL, 0);
939 if (smb_fname_full == NULL) {
940 errno = ENOMEM;
941 goto out;
944 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
945 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
946 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
947 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
949 * Ok, we're done
951 result = talloc_strdup(ctx, smb_fname_full->base_name);
952 if (result == NULL) {
953 errno = ENOMEM;
955 goto out;
958 nocache:
961 * We don't have the information to hand so rely on traditional
962 * methods. The very slow getcwd, which spawns a process on some
963 * systems, or the not quite so bad getwd.
966 current_dir = SMB_VFS_GETWD(conn);
967 if (current_dir == NULL) {
968 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
969 strerror(errno)));
970 goto out;
973 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
974 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
976 memcache_add(smbd_memcache(), GETWD_CACHE,
977 data_blob_const(&key, sizeof(key)),
978 data_blob_const(current_dir,
979 strlen(current_dir)+1));
982 result = talloc_strdup(ctx, current_dir);
983 if (result == NULL) {
984 errno = ENOMEM;
987 out:
988 TALLOC_FREE(smb_fname_dot);
989 TALLOC_FREE(smb_fname_full);
990 SAFE_FREE(current_dir);
991 return result;
994 /*******************************************************************
995 Reduce a file name, removing .. elements and checking that
996 it is below dir in the heirachy. This uses realpath.
997 This function must run as root, and will return names
998 and valid stat structs that can be checked on open.
999 ********************************************************************/
1001 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1002 const char *fname,
1003 struct smb_request *smbreq)
1005 NTSTATUS status;
1006 TALLOC_CTX *ctx = talloc_tos();
1007 const char *conn_rootdir;
1008 size_t rootdir_len;
1009 char *dir_name = NULL;
1010 const char *last_component = NULL;
1011 char *resolved_name = NULL;
1012 char *saved_dir = NULL;
1013 struct smb_filename *saved_dir_fname = NULL;
1014 struct smb_filename *smb_fname_cwd = NULL;
1015 struct privilege_paths *priv_paths = NULL;
1016 int ret;
1018 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1019 fname,
1020 conn->connectpath));
1023 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1024 if (!priv_paths) {
1025 status = NT_STATUS_NO_MEMORY;
1026 goto err;
1029 if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
1030 status = NT_STATUS_NO_MEMORY;
1031 goto err;
1034 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1035 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1037 if (priv_paths->parent_name.base_name == NULL ||
1038 priv_paths->file_name.base_name == NULL) {
1039 status = NT_STATUS_NO_MEMORY;
1040 goto err;
1043 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1044 status = map_nt_error_from_unix(errno);
1045 goto err;
1047 /* Remember where we were. */
1048 saved_dir = vfs_GetWd(ctx, conn);
1049 if (!saved_dir) {
1050 status = map_nt_error_from_unix(errno);
1051 goto err;
1054 saved_dir_fname = synthetic_smb_fname(ctx,
1055 saved_dir,
1056 NULL,
1057 NULL,
1059 if (saved_dir_fname == NULL) {
1060 status = NT_STATUS_NO_MEMORY;
1061 goto err;
1064 /* Go to the parent directory to lock in memory. */
1065 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1066 status = map_nt_error_from_unix(errno);
1067 goto err;
1070 /* Get the absolute path of the parent directory. */
1071 resolved_name = SMB_VFS_REALPATH(conn,".");
1072 if (!resolved_name) {
1073 status = map_nt_error_from_unix(errno);
1074 goto err;
1077 if (*resolved_name != '/') {
1078 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1079 "doesn't return absolute paths !\n"));
1080 status = NT_STATUS_OBJECT_NAME_INVALID;
1081 goto err;
1084 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1085 priv_paths->parent_name.base_name,
1086 resolved_name));
1088 /* Now check the stat value is the same. */
1089 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1090 if (smb_fname_cwd == NULL) {
1091 status = NT_STATUS_NO_MEMORY;
1092 goto err;
1095 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1096 status = map_nt_error_from_unix(errno);
1097 goto err;
1100 /* Ensure we're pointing at the same place. */
1101 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1102 DEBUG(0,("check_reduced_name_with_privilege: "
1103 "device/inode/uid/gid on directory %s changed. "
1104 "Denying access !\n",
1105 priv_paths->parent_name.base_name));
1106 status = NT_STATUS_ACCESS_DENIED;
1107 goto err;
1110 /* Ensure we're below the connect path. */
1112 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1113 if (conn_rootdir == NULL) {
1114 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1115 "conn_rootdir\n"));
1116 status = NT_STATUS_ACCESS_DENIED;
1117 goto err;
1120 rootdir_len = strlen(conn_rootdir);
1123 * In the case of rootdir_len == 1, we know that conn_rootdir is
1124 * "/", and we also know that resolved_name starts with a slash.
1125 * So, in this corner case, resolved_name is automatically a
1126 * sub-directory of the conn_rootdir. Thus we can skip the string
1127 * comparison and the next character checks (which are even
1128 * wrong in this case).
1130 if (rootdir_len != 1) {
1131 bool matched;
1133 matched = (strncmp(conn_rootdir, resolved_name,
1134 rootdir_len) == 0);
1136 if (!matched || (resolved_name[rootdir_len] != '/' &&
1137 resolved_name[rootdir_len] != '\0')) {
1138 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1139 "access attempt: %s is a symlink outside the "
1140 "share path\n",
1141 dir_name));
1142 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1143 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1144 status = NT_STATUS_ACCESS_DENIED;
1145 goto err;
1149 /* Now ensure that the last component either doesn't
1150 exist, or is *NOT* a symlink. */
1152 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1153 if (ret == -1) {
1154 /* Errno must be ENOENT for this be ok. */
1155 if (errno != ENOENT) {
1156 status = map_nt_error_from_unix(errno);
1157 DEBUG(2, ("check_reduced_name_with_privilege: "
1158 "LSTAT on %s failed with %s\n",
1159 priv_paths->file_name.base_name,
1160 nt_errstr(status)));
1161 goto err;
1165 if (VALID_STAT(priv_paths->file_name.st) &&
1166 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1167 DEBUG(2, ("check_reduced_name_with_privilege: "
1168 "Last component %s is a symlink. Denying"
1169 "access.\n",
1170 priv_paths->file_name.base_name));
1171 status = NT_STATUS_ACCESS_DENIED;
1172 goto err;
1175 smbreq->priv_paths = priv_paths;
1176 status = NT_STATUS_OK;
1178 err:
1180 if (saved_dir_fname) {
1181 vfs_ChDir(conn, saved_dir_fname);
1182 TALLOC_FREE(saved_dir);
1183 TALLOC_FREE(saved_dir_fname);
1185 SAFE_FREE(resolved_name);
1186 if (!NT_STATUS_IS_OK(status)) {
1187 TALLOC_FREE(priv_paths);
1189 TALLOC_FREE(dir_name);
1190 return status;
1193 /*******************************************************************
1194 Reduce a file name, removing .. elements and checking that
1195 it is below dir in the heirachy. This uses realpath.
1197 If cwd_name == NULL then fname is a client given path relative
1198 to the root path of the share.
1200 If cwd_name != NULL then fname is a client given path relative
1201 to cwd_name. cwd_name is relative to the root path of the share.
1202 ********************************************************************/
1204 NTSTATUS check_reduced_name(connection_struct *conn,
1205 const char *cwd_name,
1206 const char *fname)
1208 char *resolved_name = NULL;
1209 char *new_fname = NULL;
1210 bool allow_symlinks = true;
1211 bool allow_widelinks = false;
1213 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1215 resolved_name = SMB_VFS_REALPATH(conn,fname);
1217 if (!resolved_name) {
1218 switch (errno) {
1219 case ENOTDIR:
1220 DEBUG(3,("check_reduced_name: Component not a "
1221 "directory in getting realpath for "
1222 "%s\n", fname));
1223 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1224 case ENOENT:
1226 TALLOC_CTX *ctx = talloc_tos();
1227 char *dir_name = NULL;
1228 const char *last_component = NULL;
1229 char *new_name = NULL;
1230 int ret;
1232 /* Last component didn't exist.
1233 Remove it and try and canonicalise
1234 the directory name. */
1235 if (!parent_dirname(ctx, fname,
1236 &dir_name,
1237 &last_component)) {
1238 return NT_STATUS_NO_MEMORY;
1241 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1242 if (!resolved_name) {
1243 NTSTATUS status = map_nt_error_from_unix(errno);
1245 if (errno == ENOENT || errno == ENOTDIR) {
1246 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1249 DEBUG(3,("check_reduce_name: "
1250 "couldn't get realpath for "
1251 "%s (%s)\n",
1252 fname,
1253 nt_errstr(status)));
1254 return status;
1256 ret = asprintf(&new_name, "%s/%s",
1257 resolved_name, last_component);
1258 SAFE_FREE(resolved_name);
1259 if (ret == -1) {
1260 return NT_STATUS_NO_MEMORY;
1262 resolved_name = new_name;
1263 break;
1265 default:
1266 DEBUG(3,("check_reduced_name: couldn't get "
1267 "realpath for %s\n", fname));
1268 return map_nt_error_from_unix(errno);
1272 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1273 resolved_name));
1275 if (*resolved_name != '/') {
1276 DEBUG(0,("check_reduced_name: realpath doesn't return "
1277 "absolute paths !\n"));
1278 SAFE_FREE(resolved_name);
1279 return NT_STATUS_OBJECT_NAME_INVALID;
1282 allow_widelinks = lp_widelinks(SNUM(conn));
1283 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1285 /* Common widelinks and symlinks checks. */
1286 if (!allow_widelinks || !allow_symlinks) {
1287 const char *conn_rootdir;
1288 size_t rootdir_len;
1290 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1291 if (conn_rootdir == NULL) {
1292 DEBUG(2, ("check_reduced_name: Could not get "
1293 "conn_rootdir\n"));
1294 SAFE_FREE(resolved_name);
1295 return NT_STATUS_ACCESS_DENIED;
1298 rootdir_len = strlen(conn_rootdir);
1301 * In the case of rootdir_len == 1, we know that
1302 * conn_rootdir is "/", and we also know that
1303 * resolved_name starts with a slash. So, in this
1304 * corner case, resolved_name is automatically a
1305 * sub-directory of the conn_rootdir. Thus we can skip
1306 * the string comparison and the next character checks
1307 * (which are even wrong in this case).
1309 if (rootdir_len != 1) {
1310 bool matched;
1312 matched = (strncmp(conn_rootdir, resolved_name,
1313 rootdir_len) == 0);
1314 if (!matched || (resolved_name[rootdir_len] != '/' &&
1315 resolved_name[rootdir_len] != '\0')) {
1316 DEBUG(2, ("check_reduced_name: Bad access "
1317 "attempt: %s is a symlink outside the "
1318 "share path\n", fname));
1319 DEBUGADD(2, ("conn_rootdir =%s\n",
1320 conn_rootdir));
1321 DEBUGADD(2, ("resolved_name=%s\n",
1322 resolved_name));
1323 SAFE_FREE(resolved_name);
1324 return NT_STATUS_ACCESS_DENIED;
1328 /* Extra checks if all symlinks are disallowed. */
1329 if (!allow_symlinks) {
1330 /* fname can't have changed in resolved_path. */
1331 const char *p = &resolved_name[rootdir_len];
1334 * UNIX filesystem semantics, names consisting
1335 * only of "." or ".." CANNOT be symlinks.
1337 if (ISDOT(fname) || ISDOTDOT(fname)) {
1338 goto out;
1341 if (*p != '/') {
1342 DEBUG(2, ("check_reduced_name: logic error (%c) "
1343 "in resolved_name: %s\n",
1345 fname));
1346 SAFE_FREE(resolved_name);
1347 return NT_STATUS_ACCESS_DENIED;
1350 p++;
1353 * If cwd_name is present and not ".",
1354 * then fname is relative to that, not
1355 * the root of the share. Make sure the
1356 * path we check is the one the client
1357 * sent (cwd_name+fname).
1359 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1360 new_fname = talloc_asprintf(talloc_tos(),
1361 "%s/%s",
1362 cwd_name,
1363 fname);
1364 if (new_fname == NULL) {
1365 SAFE_FREE(resolved_name);
1366 return NT_STATUS_NO_MEMORY;
1368 fname = new_fname;
1371 if (strcmp(fname, p)!=0) {
1372 DEBUG(2, ("check_reduced_name: Bad access "
1373 "attempt: %s is a symlink to %s\n",
1374 fname, p));
1375 SAFE_FREE(resolved_name);
1376 TALLOC_FREE(new_fname);
1377 return NT_STATUS_ACCESS_DENIED;
1382 out:
1384 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1385 SAFE_FREE(resolved_name);
1386 TALLOC_FREE(new_fname);
1387 return NT_STATUS_OK;
1391 * XXX: This is temporary and there should be no callers of this once
1392 * smb_filename is plumbed through all path based operations.
1394 * Called when we know stream name parsing has already been done.
1396 int vfs_stat_smb_basename(struct connection_struct *conn,
1397 const struct smb_filename *smb_fname_in,
1398 SMB_STRUCT_STAT *psbuf)
1400 struct smb_filename smb_fname = {
1401 .base_name = discard_const_p(char, smb_fname_in->base_name),
1402 .flags = smb_fname_in->flags
1404 int ret;
1406 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1407 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1408 } else {
1409 ret = SMB_VFS_STAT(conn, &smb_fname);
1412 if (ret != -1) {
1413 *psbuf = smb_fname.st;
1415 return ret;
1419 * Ensure LSTAT is called for POSIX paths.
1422 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1424 int ret;
1426 if(fsp->fh->fd == -1) {
1427 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1428 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1429 } else {
1430 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1432 if (ret == -1) {
1433 return map_nt_error_from_unix(errno);
1435 } else {
1436 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1437 return map_nt_error_from_unix(errno);
1440 return NT_STATUS_OK;
1444 * Initialize num_streams and streams, then call VFS op streaminfo
1446 NTSTATUS vfs_streaminfo(connection_struct *conn,
1447 struct files_struct *fsp,
1448 const struct smb_filename *smb_fname,
1449 TALLOC_CTX *mem_ctx,
1450 unsigned int *num_streams,
1451 struct stream_struct **streams)
1453 *num_streams = 0;
1454 *streams = NULL;
1455 return SMB_VFS_STREAMINFO(conn,
1456 fsp,
1457 smb_fname,
1458 mem_ctx,
1459 num_streams,
1460 streams);
1464 generate a file_id from a stat structure
1466 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1468 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1471 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1472 const char *service, const char *user)
1474 VFS_FIND(connect);
1475 return handle->fns->connect_fn(handle, service, user);
1478 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1480 VFS_FIND(disconnect);
1481 handle->fns->disconnect_fn(handle);
1484 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1485 const struct smb_filename *smb_fname,
1486 uint64_t *bsize,
1487 uint64_t *dfree,
1488 uint64_t *dsize)
1490 VFS_FIND(disk_free);
1491 return handle->fns->disk_free_fn(handle, smb_fname,
1492 bsize, dfree, dsize);
1495 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1496 const struct smb_filename *smb_fname,
1497 enum SMB_QUOTA_TYPE qtype,
1498 unid_t id,
1499 SMB_DISK_QUOTA *qt)
1501 VFS_FIND(get_quota);
1502 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1505 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1506 enum SMB_QUOTA_TYPE qtype, unid_t id,
1507 SMB_DISK_QUOTA *qt)
1509 VFS_FIND(set_quota);
1510 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1513 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1514 struct files_struct *fsp,
1515 struct shadow_copy_data *shadow_copy_data,
1516 bool labels)
1518 VFS_FIND(get_shadow_copy_data);
1519 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1520 shadow_copy_data,
1521 labels);
1523 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1524 const struct smb_filename *smb_fname,
1525 struct vfs_statvfs_struct *statbuf)
1527 VFS_FIND(statvfs);
1528 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1531 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1532 enum timestamp_set_resolution *p_ts_res)
1534 VFS_FIND(fs_capabilities);
1535 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1538 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1539 struct dfs_GetDFSReferral *r)
1541 VFS_FIND(get_dfs_referrals);
1542 return handle->fns->get_dfs_referrals_fn(handle, r);
1545 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1546 const struct smb_filename *smb_fname,
1547 const char *mask,
1548 uint32_t attributes)
1550 VFS_FIND(opendir);
1551 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1554 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1555 struct files_struct *fsp,
1556 const char *mask,
1557 uint32_t attributes)
1559 VFS_FIND(fdopendir);
1560 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1563 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1564 DIR *dirp,
1565 SMB_STRUCT_STAT *sbuf)
1567 VFS_FIND(readdir);
1568 return handle->fns->readdir_fn(handle, dirp, sbuf);
1571 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1572 DIR *dirp, long offset)
1574 VFS_FIND(seekdir);
1575 handle->fns->seekdir_fn(handle, dirp, offset);
1578 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1579 DIR *dirp)
1581 VFS_FIND(telldir);
1582 return handle->fns->telldir_fn(handle, dirp);
1585 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1586 DIR *dirp)
1588 VFS_FIND(rewind_dir);
1589 handle->fns->rewind_dir_fn(handle, dirp);
1592 int smb_vfs_call_mkdir(struct vfs_handle_struct *handle,
1593 const struct smb_filename *smb_fname,
1594 mode_t mode)
1596 VFS_FIND(mkdir);
1597 return handle->fns->mkdir_fn(handle, smb_fname, mode);
1600 int smb_vfs_call_rmdir(struct vfs_handle_struct *handle,
1601 const struct smb_filename *smb_fname)
1603 VFS_FIND(rmdir);
1604 return handle->fns->rmdir_fn(handle, smb_fname);
1607 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1608 DIR *dir)
1610 VFS_FIND(closedir);
1611 return handle->fns->closedir_fn(handle, dir);
1614 void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1615 DIR *dirp)
1617 VFS_FIND(init_search_op);
1618 handle->fns->init_search_op_fn(handle, dirp);
1621 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1622 struct smb_filename *smb_fname, struct files_struct *fsp,
1623 int flags, mode_t mode)
1625 VFS_FIND(open);
1626 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1629 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1630 struct smb_request *req,
1631 uint16_t root_dir_fid,
1632 struct smb_filename *smb_fname,
1633 uint32_t access_mask,
1634 uint32_t share_access,
1635 uint32_t create_disposition,
1636 uint32_t create_options,
1637 uint32_t file_attributes,
1638 uint32_t oplock_request,
1639 struct smb2_lease *lease,
1640 uint64_t allocation_size,
1641 uint32_t private_flags,
1642 struct security_descriptor *sd,
1643 struct ea_list *ea_list,
1644 files_struct **result,
1645 int *pinfo,
1646 const struct smb2_create_blobs *in_context_blobs,
1647 struct smb2_create_blobs *out_context_blobs)
1649 VFS_FIND(create_file);
1650 return handle->fns->create_file_fn(
1651 handle, req, root_dir_fid, smb_fname, access_mask,
1652 share_access, create_disposition, create_options,
1653 file_attributes, oplock_request, lease, allocation_size,
1654 private_flags, sd, ea_list,
1655 result, pinfo, in_context_blobs, out_context_blobs);
1658 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1659 struct files_struct *fsp)
1661 VFS_FIND(close);
1662 return handle->fns->close_fn(handle, fsp);
1665 ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1666 struct files_struct *fsp, void *data, size_t n)
1668 VFS_FIND(read);
1669 return handle->fns->read_fn(handle, fsp, data, n);
1672 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1673 struct files_struct *fsp, void *data, size_t n,
1674 off_t offset)
1676 VFS_FIND(pread);
1677 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1680 struct smb_vfs_call_pread_state {
1681 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1682 ssize_t retval;
1683 struct vfs_aio_state vfs_aio_state;
1686 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1688 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1689 TALLOC_CTX *mem_ctx,
1690 struct tevent_context *ev,
1691 struct files_struct *fsp,
1692 void *data,
1693 size_t n, off_t offset)
1695 struct tevent_req *req, *subreq;
1696 struct smb_vfs_call_pread_state *state;
1698 req = tevent_req_create(mem_ctx, &state,
1699 struct smb_vfs_call_pread_state);
1700 if (req == NULL) {
1701 return NULL;
1703 VFS_FIND(pread_send);
1704 state->recv_fn = handle->fns->pread_recv_fn;
1706 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1707 offset);
1708 if (tevent_req_nomem(subreq, req)) {
1709 return tevent_req_post(req, ev);
1711 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1712 return req;
1715 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1717 struct tevent_req *req = tevent_req_callback_data(
1718 subreq, struct tevent_req);
1719 struct smb_vfs_call_pread_state *state = tevent_req_data(
1720 req, struct smb_vfs_call_pread_state);
1722 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1723 TALLOC_FREE(subreq);
1724 if (state->retval == -1) {
1725 tevent_req_error(req, state->vfs_aio_state.error);
1726 return;
1728 tevent_req_done(req);
1731 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1732 struct vfs_aio_state *vfs_aio_state)
1734 struct smb_vfs_call_pread_state *state = tevent_req_data(
1735 req, struct smb_vfs_call_pread_state);
1737 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1738 return -1;
1740 *vfs_aio_state = state->vfs_aio_state;
1741 return state->retval;
1744 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1745 struct files_struct *fsp, const void *data,
1746 size_t n)
1748 VFS_FIND(write);
1749 return handle->fns->write_fn(handle, fsp, data, n);
1752 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1753 struct files_struct *fsp, const void *data,
1754 size_t n, off_t offset)
1756 VFS_FIND(pwrite);
1757 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1760 struct smb_vfs_call_pwrite_state {
1761 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1762 ssize_t retval;
1763 struct vfs_aio_state vfs_aio_state;
1766 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1768 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1769 TALLOC_CTX *mem_ctx,
1770 struct tevent_context *ev,
1771 struct files_struct *fsp,
1772 const void *data,
1773 size_t n, off_t offset)
1775 struct tevent_req *req, *subreq;
1776 struct smb_vfs_call_pwrite_state *state;
1778 req = tevent_req_create(mem_ctx, &state,
1779 struct smb_vfs_call_pwrite_state);
1780 if (req == NULL) {
1781 return NULL;
1783 VFS_FIND(pwrite_send);
1784 state->recv_fn = handle->fns->pwrite_recv_fn;
1786 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1787 offset);
1788 if (tevent_req_nomem(subreq, req)) {
1789 return tevent_req_post(req, ev);
1791 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1792 return req;
1795 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1797 struct tevent_req *req = tevent_req_callback_data(
1798 subreq, struct tevent_req);
1799 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1800 req, struct smb_vfs_call_pwrite_state);
1802 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1803 TALLOC_FREE(subreq);
1804 if (state->retval == -1) {
1805 tevent_req_error(req, state->vfs_aio_state.error);
1806 return;
1808 tevent_req_done(req);
1811 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1812 struct vfs_aio_state *vfs_aio_state)
1814 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1815 req, struct smb_vfs_call_pwrite_state);
1817 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1818 return -1;
1820 *vfs_aio_state = state->vfs_aio_state;
1821 return state->retval;
1824 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1825 struct files_struct *fsp, off_t offset,
1826 int whence)
1828 VFS_FIND(lseek);
1829 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1832 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1833 files_struct *fromfsp, const DATA_BLOB *header,
1834 off_t offset, size_t count)
1836 VFS_FIND(sendfile);
1837 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1838 count);
1841 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1842 files_struct *tofsp, off_t offset,
1843 size_t count)
1845 VFS_FIND(recvfile);
1846 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1849 int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1850 const struct smb_filename *smb_fname_src,
1851 const struct smb_filename *smb_fname_dst)
1853 VFS_FIND(rename);
1854 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1857 int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1858 struct files_struct *fsp)
1860 VFS_FIND(fsync);
1861 return handle->fns->fsync_fn(handle, fsp);
1864 struct smb_vfs_call_fsync_state {
1865 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1866 int retval;
1867 struct vfs_aio_state vfs_aio_state;
1870 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1872 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1873 TALLOC_CTX *mem_ctx,
1874 struct tevent_context *ev,
1875 struct files_struct *fsp)
1877 struct tevent_req *req, *subreq;
1878 struct smb_vfs_call_fsync_state *state;
1880 req = tevent_req_create(mem_ctx, &state,
1881 struct smb_vfs_call_fsync_state);
1882 if (req == NULL) {
1883 return NULL;
1885 VFS_FIND(fsync_send);
1886 state->recv_fn = handle->fns->fsync_recv_fn;
1888 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1889 if (tevent_req_nomem(subreq, req)) {
1890 return tevent_req_post(req, ev);
1892 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1893 return req;
1896 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1898 struct tevent_req *req = tevent_req_callback_data(
1899 subreq, struct tevent_req);
1900 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1901 req, struct smb_vfs_call_fsync_state);
1903 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1904 TALLOC_FREE(subreq);
1905 if (state->retval == -1) {
1906 tevent_req_error(req, state->vfs_aio_state.error);
1907 return;
1909 tevent_req_done(req);
1912 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
1914 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1915 req, struct smb_vfs_call_fsync_state);
1917 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1918 return -1;
1920 *vfs_aio_state = state->vfs_aio_state;
1921 return state->retval;
1925 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1926 struct smb_filename *smb_fname)
1928 VFS_FIND(stat);
1929 return handle->fns->stat_fn(handle, smb_fname);
1932 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1933 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1935 VFS_FIND(fstat);
1936 return handle->fns->fstat_fn(handle, fsp, sbuf);
1939 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1940 struct smb_filename *smb_filename)
1942 VFS_FIND(lstat);
1943 return handle->fns->lstat_fn(handle, smb_filename);
1946 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1947 struct files_struct *fsp,
1948 const SMB_STRUCT_STAT *sbuf)
1950 VFS_FIND(get_alloc_size);
1951 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1954 int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1955 const struct smb_filename *smb_fname)
1957 VFS_FIND(unlink);
1958 return handle->fns->unlink_fn(handle, smb_fname);
1961 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
1962 const struct smb_filename *smb_fname,
1963 mode_t mode)
1965 VFS_FIND(chmod);
1966 return handle->fns->chmod_fn(handle, smb_fname, mode);
1969 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1970 struct files_struct *fsp, mode_t mode)
1972 VFS_FIND(fchmod);
1973 return handle->fns->fchmod_fn(handle, fsp, mode);
1976 int smb_vfs_call_chown(struct vfs_handle_struct *handle,
1977 const struct smb_filename *smb_fname,
1978 uid_t uid,
1979 gid_t gid)
1981 VFS_FIND(chown);
1982 return handle->fns->chown_fn(handle, smb_fname, uid, gid);
1985 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1986 struct files_struct *fsp, uid_t uid, gid_t gid)
1988 VFS_FIND(fchown);
1989 return handle->fns->fchown_fn(handle, fsp, uid, gid);
1992 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
1993 const struct smb_filename *smb_fname,
1994 uid_t uid,
1995 gid_t gid)
1997 VFS_FIND(lchown);
1998 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2001 NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
2003 int ret;
2004 bool as_root = false;
2005 NTSTATUS status;
2007 if (fsp->fh->fd != -1) {
2008 /* Try fchown. */
2009 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
2010 if (ret == 0) {
2011 return NT_STATUS_OK;
2013 if (ret == -1 && errno != ENOSYS) {
2014 return map_nt_error_from_unix(errno);
2018 as_root = (geteuid() == 0);
2020 if (as_root) {
2022 * We are being asked to chown as root. Make
2023 * sure we chdir() into the path to pin it,
2024 * and always act using lchown to ensure we
2025 * don't deref any symbolic links.
2027 char *saved_dir = NULL;
2028 char *parent_dir = NULL;
2029 const char *final_component = NULL;
2030 struct smb_filename *local_smb_fname = NULL;
2031 struct smb_filename parent_dir_fname = {0};
2032 struct smb_filename saved_dir_fname = {0};
2034 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
2035 if (!saved_dir) {
2036 status = map_nt_error_from_unix(errno);
2037 DEBUG(0,("vfs_chown_fsp: failed to get "
2038 "current working directory. Error was %s\n",
2039 strerror(errno)));
2040 return status;
2043 saved_dir_fname = (struct smb_filename) {
2044 .base_name = saved_dir
2047 if (!parent_dirname(talloc_tos(),
2048 fsp->fsp_name->base_name,
2049 &parent_dir,
2050 &final_component)) {
2051 return NT_STATUS_NO_MEMORY;
2054 parent_dir_fname = (struct smb_filename) {
2055 .base_name = parent_dir,
2056 .flags = fsp->fsp_name->flags
2059 /* cd into the parent dir to pin it. */
2060 ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
2061 if (ret == -1) {
2062 return map_nt_error_from_unix(errno);
2065 local_smb_fname = synthetic_smb_fname(talloc_tos(),
2066 final_component,
2067 NULL,
2068 NULL,
2069 fsp->fsp_name->flags);
2070 if (local_smb_fname == NULL) {
2071 status = NT_STATUS_NO_MEMORY;
2072 goto out;
2075 /* Must use lstat here. */
2076 ret = SMB_VFS_LSTAT(fsp->conn, local_smb_fname);
2077 if (ret == -1) {
2078 status = map_nt_error_from_unix(errno);
2079 goto out;
2082 /* Ensure it matches the fsp stat. */
2083 if (!check_same_stat(&local_smb_fname->st,
2084 &fsp->fsp_name->st)) {
2085 status = NT_STATUS_ACCESS_DENIED;
2086 goto out;
2089 ret = SMB_VFS_LCHOWN(fsp->conn,
2090 local_smb_fname,
2091 uid, gid);
2093 if (ret == 0) {
2094 status = NT_STATUS_OK;
2095 } else {
2096 status = map_nt_error_from_unix(errno);
2099 out:
2101 vfs_ChDir(fsp->conn, &saved_dir_fname);
2102 TALLOC_FREE(local_smb_fname);
2103 TALLOC_FREE(saved_dir);
2104 TALLOC_FREE(parent_dir);
2106 return status;
2109 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
2110 ret = SMB_VFS_LCHOWN(fsp->conn,
2111 fsp->fsp_name,
2112 uid, gid);
2113 } else {
2114 ret = SMB_VFS_CHOWN(fsp->conn,
2115 fsp->fsp_name,
2116 uid, gid);
2119 if (ret == 0) {
2120 status = NT_STATUS_OK;
2121 } else {
2122 status = map_nt_error_from_unix(errno);
2124 return status;
2127 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2128 const struct smb_filename *smb_fname)
2130 VFS_FIND(chdir);
2131 return handle->fns->chdir_fn(handle, smb_fname);
2134 char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
2136 VFS_FIND(getwd);
2137 return handle->fns->getwd_fn(handle);
2140 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2141 const struct smb_filename *smb_fname,
2142 struct smb_file_time *ft)
2144 VFS_FIND(ntimes);
2145 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2148 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2149 struct files_struct *fsp, off_t offset)
2151 VFS_FIND(ftruncate);
2152 return handle->fns->ftruncate_fn(handle, fsp, offset);
2155 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2156 struct files_struct *fsp,
2157 uint32_t mode,
2158 off_t offset,
2159 off_t len)
2161 VFS_FIND(fallocate);
2162 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2165 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2166 struct files_struct *fsp, uint32_t share_mode,
2167 uint32_t access_mask)
2169 VFS_FIND(kernel_flock);
2170 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2171 access_mask);
2174 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2175 struct files_struct *fsp, int leasetype)
2177 VFS_FIND(linux_setlease);
2178 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2181 int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
2182 const char *link_target,
2183 const struct smb_filename *new_smb_fname)
2185 VFS_FIND(symlink);
2186 return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
2189 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2190 const struct smb_filename *smb_fname,
2191 char *buf,
2192 size_t bufsiz)
2194 VFS_FIND(readlink);
2195 return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz);
2198 int smb_vfs_call_link(struct vfs_handle_struct *handle,
2199 const struct smb_filename *old_smb_fname,
2200 const struct smb_filename *new_smb_fname)
2202 VFS_FIND(link);
2203 return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
2206 int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
2207 const struct smb_filename *smb_fname,
2208 mode_t mode,
2209 SMB_DEV_T dev)
2211 VFS_FIND(mknod);
2212 return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
2215 char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
2217 VFS_FIND(realpath);
2218 return handle->fns->realpath_fn(handle, path);
2221 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2222 const struct smb_filename *smb_fname,
2223 unsigned int flags)
2225 VFS_FIND(chflags);
2226 return handle->fns->chflags_fn(handle, smb_fname, flags);
2229 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2230 const SMB_STRUCT_STAT *sbuf)
2232 VFS_FIND(file_id_create);
2233 return handle->fns->file_id_create_fn(handle, sbuf);
2236 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2237 struct files_struct *fsp,
2238 const struct smb_filename *smb_fname,
2239 TALLOC_CTX *mem_ctx,
2240 unsigned int *num_streams,
2241 struct stream_struct **streams)
2243 VFS_FIND(streaminfo);
2244 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2245 num_streams, streams);
2248 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2249 const char *path, const char *name,
2250 TALLOC_CTX *mem_ctx, char **found_name)
2252 VFS_FIND(get_real_filename);
2253 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2254 found_name);
2257 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2258 const char *filename)
2260 VFS_FIND(connectpath);
2261 return handle->fns->connectpath_fn(handle, filename);
2264 bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
2265 struct files_struct *fsp,
2266 struct lock_struct *plock)
2268 VFS_FIND(strict_lock);
2269 return handle->fns->strict_lock_fn(handle, fsp, plock);
2272 void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
2273 struct files_struct *fsp,
2274 struct lock_struct *plock)
2276 VFS_FIND(strict_unlock);
2277 handle->fns->strict_unlock_fn(handle, fsp, plock);
2280 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2281 const char *name,
2282 enum vfs_translate_direction direction,
2283 TALLOC_CTX *mem_ctx,
2284 char **mapped_name)
2286 VFS_FIND(translate_name);
2287 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2288 mapped_name);
2291 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2292 struct files_struct *fsp,
2293 TALLOC_CTX *ctx,
2294 uint32_t function,
2295 uint16_t req_flags,
2296 const uint8_t *in_data,
2297 uint32_t in_len,
2298 uint8_t **out_data,
2299 uint32_t max_out_len,
2300 uint32_t *out_len)
2302 VFS_FIND(fsctl);
2303 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2304 in_data, in_len, out_data, max_out_len,
2305 out_len);
2308 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2309 struct smb_filename *smb_fname,
2310 uint32_t *dosmode)
2312 VFS_FIND(get_dos_attributes);
2313 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2316 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2317 struct files_struct *fsp,
2318 uint32_t *dosmode)
2320 VFS_FIND(fget_dos_attributes);
2321 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2324 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2325 const struct smb_filename *smb_fname,
2326 uint32_t dosmode)
2328 VFS_FIND(set_dos_attributes);
2329 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2332 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2333 struct files_struct *fsp,
2334 uint32_t dosmode)
2336 VFS_FIND(set_dos_attributes);
2337 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2340 struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
2341 TALLOC_CTX *mem_ctx,
2342 struct tevent_context *ev,
2343 struct files_struct *src_fsp,
2344 off_t src_off,
2345 struct files_struct *dest_fsp,
2346 off_t dest_off,
2347 off_t num,
2348 uint32_t flags)
2350 VFS_FIND(copy_chunk_send);
2351 return handle->fns->copy_chunk_send_fn(handle, mem_ctx, ev, src_fsp,
2352 src_off, dest_fsp, dest_off, num,
2353 flags);
2356 NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
2357 struct tevent_req *req,
2358 off_t *copied)
2360 VFS_FIND(copy_chunk_recv);
2361 return handle->fns->copy_chunk_recv_fn(handle, req, copied);
2364 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2365 TALLOC_CTX *mem_ctx,
2366 struct files_struct *fsp,
2367 struct smb_filename *smb_fname,
2368 uint16_t *_compression_fmt)
2370 VFS_FIND(get_compression);
2371 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2372 _compression_fmt);
2375 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2376 TALLOC_CTX *mem_ctx,
2377 struct files_struct *fsp,
2378 uint16_t compression_fmt)
2380 VFS_FIND(set_compression);
2381 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2382 compression_fmt);
2385 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2386 TALLOC_CTX *mem_ctx,
2387 const char *service_path,
2388 char **base_volume)
2390 VFS_FIND(snap_check_path);
2391 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2392 base_volume);
2395 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2396 TALLOC_CTX *mem_ctx,
2397 const char *base_volume,
2398 time_t *tstamp,
2399 bool rw,
2400 char **base_path,
2401 char **snap_path)
2403 VFS_FIND(snap_create);
2404 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2405 rw, base_path, snap_path);
2408 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2409 TALLOC_CTX *mem_ctx,
2410 char *base_path,
2411 char *snap_path)
2413 VFS_FIND(snap_delete);
2414 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2415 snap_path);
2418 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2419 struct files_struct *fsp,
2420 uint32_t security_info,
2421 TALLOC_CTX *mem_ctx,
2422 struct security_descriptor **ppdesc)
2424 VFS_FIND(fget_nt_acl);
2425 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2426 mem_ctx, ppdesc);
2429 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2430 const struct smb_filename *smb_fname,
2431 uint32_t security_info,
2432 TALLOC_CTX *mem_ctx,
2433 struct security_descriptor **ppdesc)
2435 VFS_FIND(get_nt_acl);
2436 return handle->fns->get_nt_acl_fn(handle,
2437 smb_fname,
2438 security_info,
2439 mem_ctx,
2440 ppdesc);
2443 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2444 struct files_struct *fsp,
2445 uint32_t security_info_sent,
2446 const struct security_descriptor *psd)
2448 VFS_FIND(fset_nt_acl);
2449 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2450 psd);
2453 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2454 struct smb_filename *file,
2455 struct security_acl *sacl,
2456 uint32_t access_requested,
2457 uint32_t access_denied)
2459 VFS_FIND(audit_file);
2460 return handle->fns->audit_file_fn(handle,
2461 file,
2462 sacl,
2463 access_requested,
2464 access_denied);
2467 int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle,
2468 const struct smb_filename *smb_fname,
2469 mode_t mode)
2471 VFS_FIND(chmod_acl);
2472 return handle->fns->chmod_acl_fn(handle, smb_fname, mode);
2475 int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2476 struct files_struct *fsp, mode_t mode)
2478 VFS_FIND(fchmod_acl);
2479 return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2482 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2483 const struct smb_filename *smb_fname,
2484 SMB_ACL_TYPE_T type,
2485 TALLOC_CTX *mem_ctx)
2487 VFS_FIND(sys_acl_get_file);
2488 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2491 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2492 struct files_struct *fsp,
2493 TALLOC_CTX *mem_ctx)
2495 VFS_FIND(sys_acl_get_fd);
2496 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2499 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2500 const struct smb_filename *smb_fname,
2501 TALLOC_CTX *mem_ctx,
2502 char **blob_description,
2503 DATA_BLOB *blob)
2505 VFS_FIND(sys_acl_blob_get_file);
2506 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2507 mem_ctx, blob_description, blob);
2510 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2511 struct files_struct *fsp,
2512 TALLOC_CTX *mem_ctx,
2513 char **blob_description,
2514 DATA_BLOB *blob)
2516 VFS_FIND(sys_acl_blob_get_fd);
2517 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2520 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2521 const struct smb_filename *smb_fname,
2522 SMB_ACL_TYPE_T acltype,
2523 SMB_ACL_T theacl)
2525 VFS_FIND(sys_acl_set_file);
2526 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2527 acltype, theacl);
2530 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2531 struct files_struct *fsp, SMB_ACL_T theacl)
2533 VFS_FIND(sys_acl_set_fd);
2534 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2537 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2538 const struct smb_filename *smb_fname)
2540 VFS_FIND(sys_acl_delete_def_file);
2541 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2544 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2545 const struct smb_filename *smb_fname,
2546 const char *name,
2547 void *value,
2548 size_t size)
2550 VFS_FIND(getxattr);
2551 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2554 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2555 struct files_struct *fsp, const char *name,
2556 void *value, size_t size)
2558 VFS_FIND(fgetxattr);
2559 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2562 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2563 const struct smb_filename *smb_fname,
2564 char *list,
2565 size_t size)
2567 VFS_FIND(listxattr);
2568 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2571 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2572 struct files_struct *fsp, char *list,
2573 size_t size)
2575 VFS_FIND(flistxattr);
2576 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2579 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2580 const struct smb_filename *smb_fname,
2581 const char *name)
2583 VFS_FIND(removexattr);
2584 return handle->fns->removexattr_fn(handle, smb_fname, name);
2587 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2588 struct files_struct *fsp, const char *name)
2590 VFS_FIND(fremovexattr);
2591 return handle->fns->fremovexattr_fn(handle, fsp, name);
2594 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2595 const struct smb_filename *smb_fname,
2596 const char *name,
2597 const void *value,
2598 size_t size,
2599 int flags)
2601 VFS_FIND(setxattr);
2602 return handle->fns->setxattr_fn(handle, smb_fname,
2603 name, value, size, flags);
2606 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2607 struct files_struct *fsp, const char *name,
2608 const void *value, size_t size, int flags)
2610 VFS_FIND(fsetxattr);
2611 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2614 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2615 struct files_struct *fsp)
2617 VFS_FIND(aio_force);
2618 return handle->fns->aio_force_fn(handle, fsp);
2621 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2622 struct files_struct *fsp,
2623 TALLOC_CTX *mem_ctx,
2624 DATA_BLOB *cookie)
2626 VFS_FIND(durable_cookie);
2627 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2630 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2631 struct files_struct *fsp,
2632 const DATA_BLOB old_cookie,
2633 TALLOC_CTX *mem_ctx,
2634 DATA_BLOB *new_cookie)
2636 VFS_FIND(durable_disconnect);
2637 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2638 mem_ctx, new_cookie);
2641 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2642 struct smb_request *smb1req,
2643 struct smbXsrv_open *op,
2644 const DATA_BLOB old_cookie,
2645 TALLOC_CTX *mem_ctx,
2646 struct files_struct **fsp,
2647 DATA_BLOB *new_cookie)
2649 VFS_FIND(durable_reconnect);
2650 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2651 old_cookie, mem_ctx, fsp,
2652 new_cookie);
2655 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2656 const struct smb_filename *fname,
2657 TALLOC_CTX *mem_ctx,
2658 struct readdir_attr_data **attr_data)
2660 VFS_FIND(readdir_attr);
2661 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);