source: vendor/current/source3/smbd/vfs.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

File size: 64.3 KB
Line 
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
9
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.
14
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.
19
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/>.
22
23 This work was sponsored by Optifacio Software Services, Inc.
24*/
25
26#include "includes.h"
27#include "system/filesys.h"
28#include "smbd/smbd.h"
29#include "smbd/globals.h"
30#include "../lib/util/memcache.h"
31#include "transfer_file.h"
32#include "ntioctl.h"
33#include "lib/util/tevent_unix.h"
34
35#undef DBGC_CLASS
36#define DBGC_CLASS DBGC_VFS
37
38static_decl_vfs;
39
40struct 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.
47 */
48};
49
50struct vfs_init_function_entry {
51 char *name;
52 struct vfs_init_function_entry *prev, *next;
53 const struct vfs_fn_pointers *fns;
54};
55
56/****************************************************************************
57 maintain the list of available backends
58****************************************************************************/
59
60static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
61{
62 struct vfs_init_function_entry *entry = backends;
63
64 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
65
66 while(entry) {
67 if (strcmp(entry->name, name)==0) return entry;
68 entry = entry->next;
69 }
70
71 return NULL;
72}
73
74NTSTATUS smb_register_vfs(int version, const char *name,
75 const struct vfs_fn_pointers *fns)
76{
77 struct vfs_init_function_entry *entry = backends;
78
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;
86 }
87
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;
91 }
92
93 if (vfs_find_backend_entry(name)) {
94 DEBUG(0,("VFS module %s already loaded!\n", name));
95 return NT_STATUS_OBJECT_NAME_COLLISION;
96 }
97
98 entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
99 entry->name = smb_xstrdup(name);
100 entry->fns = fns;
101
102 DLIST_ADD(backends, entry);
103 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
104 return NT_STATUS_OK;
105}
106
107/****************************************************************************
108 initialise default vfs hooks
109****************************************************************************/
110
111static void vfs_init_default(connection_struct *conn)
112{
113 DEBUG(3, ("Initialising default vfs hooks\n"));
114 vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
115}
116
117/****************************************************************************
118 initialise custom vfs hooks
119 ****************************************************************************/
120
121bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
122{
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;
128
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;
133 }
134
135 if(!backends) {
136 static_init_vfs;
137 }
138
139 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
140
141 module_path = smb_xstrdup(vfs_object);
142
143 p = strchr_m(module_path, ':');
144
145 if (p) {
146 *p = 0;
147 module_param = p+1;
148 trim_char(module_param, ' ', ' ');
149 }
150
151 trim_char(module_path, ' ', ' ');
152
153 module_name = smb_xstrdup(module_path);
154
155 if ((module_name[0] == '/') &&
156 (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
157
158 /*
159 * Extract the module name from the path. Just use the base
160 * name of the last path component.
161 */
162
163 SAFE_FREE(module_name);
164 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
165
166 p = strchr_m(module_name, '.');
167
168 if (p != NULL) {
169 *p = '\0';
170 }
171 }
172
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;
177
178 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
179 vfs_object));
180
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;
186 }
187
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;
192 }
193 }
194
195 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
196
197 handle = talloc_zero(conn, vfs_handle_struct);
198 if (!handle) {
199 DEBUG(0,("TALLOC_ZERO() failed!\n"));
200 goto fail;
201 }
202 handle->conn = conn;
203 handle->fns = entry->fns;
204 if (module_param) {
205 handle->param = talloc_strdup(conn, module_param);
206 }
207 DLIST_ADD(conn->vfs_handles, handle);
208
209 SAFE_FREE(module_path);
210 SAFE_FREE(module_name);
211 return True;
212
213 fail:
214 SAFE_FREE(module_path);
215 SAFE_FREE(module_name);
216 return False;
217}
218
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******************************************************************/
224
225#define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
226
227void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
228 files_struct *fsp, size_t ext_size,
229 void (*destroy_fn)(void *p_data))
230{
231 struct vfs_fsp_data *ext;
232 void * ext_data;
233
234 /* Prevent VFS modules adding multiple extensions. */
235 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
236 return ext_data;
237 }
238
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;
243 }
244
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);
250}
251
252void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
253{
254 struct vfs_fsp_data *curr;
255 struct vfs_fsp_data *prev;
256
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;
265 }
266 if (curr->destroy) {
267 curr->destroy(EXT_DATA_AREA(curr));
268 }
269 TALLOC_FREE(curr);
270 return;
271 }
272 }
273}
274
275void vfs_remove_all_fsp_extensions(files_struct *fsp)
276{
277 struct vfs_fsp_data *curr;
278 struct vfs_fsp_data *next;
279
280 for (curr = fsp->vfs_extension; curr; curr = next) {
281
282 next = curr->next;
283 fsp->vfs_extension = next;
284
285 if (curr->destroy) {
286 curr->destroy(EXT_DATA_AREA(curr));
287 }
288 TALLOC_FREE(curr);
289 }
290}
291
292void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
293{
294 struct vfs_fsp_data *head;
295
296 for (head = fsp->vfs_extension; head; head = head->next) {
297 if (head->owner == handle) {
298 return head;
299 }
300 }
301
302 return NULL;
303}
304
305void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
306{
307 struct vfs_fsp_data *head;
308
309 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
310 if (head != NULL) {
311 return EXT_DATA_AREA(head);
312 }
313
314 return NULL;
315}
316
317#undef EXT_DATA_AREA
318
319/*****************************************************************
320 Generic VFS init.
321******************************************************************/
322
323bool smbd_vfs_init(connection_struct *conn)
324{
325 const char **vfs_objects;
326 unsigned int i = 0;
327 int j = 0;
328
329 /* Normal share - initialise with disk access functions */
330 vfs_init_default(conn);
331
332 /* No need to load vfs modules for printer connections */
333 if (conn->printer) {
334 return True;
335 }
336
337 vfs_objects = lp_vfs_objects(SNUM(conn));
338
339 /* Override VFS functions if 'vfs object' was not specified*/
340 if (!vfs_objects || !vfs_objects[0])
341 return True;
342
343 for (i=0; vfs_objects[i] ;) {
344 i++;
345 }
346
347 for (j=i-1; j >= 0; j--) {
348 if (!vfs_init_custom(conn, vfs_objects[j])) {
349 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
350 return False;
351 }
352 }
353 return True;
354}
355
356/*******************************************************************
357 Check if a file exists in the vfs.
358********************************************************************/
359
360NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
361{
362 /* Only return OK if stat was successful and S_ISREG */
363 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
364 S_ISREG(smb_fname->st.st_ex_mode)) {
365 return NT_STATUS_OK;
366 }
367
368 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
369}
370
371/****************************************************************************
372 Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)
373****************************************************************************/
374
375ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count)
376{
377 size_t total=0;
378
379 while (total < byte_count)
380 {
381 ssize_t ret = SMB_VFS_READ(fsp, buf + total,
382 byte_count - total);
383
384 if (ret == 0) return total;
385 if (ret == -1) {
386 if (errno == EINTR)
387 continue;
388 else
389 return -1;
390 }
391 total += ret;
392 }
393 return (ssize_t)total;
394}
395
396/****************************************************************************
397 Write data to a fd on the vfs.
398****************************************************************************/
399
400ssize_t vfs_write_data(struct smb_request *req,
401 files_struct *fsp,
402 const char *buffer,
403 size_t N)
404{
405 size_t total=0;
406 ssize_t ret;
407
408 if (req && req->unread_bytes) {
409 int sockfd = req->xconn->transport.sock;
410 int old_flags;
411 SMB_ASSERT(req->unread_bytes == N);
412 /* VFS_RECVFILE must drain the socket
413 * before returning. */
414 req->unread_bytes = 0;
415 /* Ensure the socket is blocking. */
416 old_flags = fcntl(sockfd, F_GETFL, 0);
417 if (set_blocking(sockfd, true) == -1) {
418 return (ssize_t)-1;
419 }
420 ret = SMB_VFS_RECVFILE(sockfd,
421 fsp,
422 (off_t)-1,
423 N);
424 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
425 return (ssize_t)-1;
426 }
427 return ret;
428 }
429
430 while (total < N) {
431 ret = SMB_VFS_WRITE(fsp, buffer + total, N - total);
432
433 if (ret == -1)
434 return -1;
435 if (ret == 0)
436 return total;
437
438 total += ret;
439 }
440 return (ssize_t)total;
441}
442
443ssize_t vfs_pwrite_data(struct smb_request *req,
444 files_struct *fsp,
445 const char *buffer,
446 size_t N,
447 off_t offset)
448{
449 size_t total=0;
450 ssize_t ret;
451
452 if (req && req->unread_bytes) {
453 int sockfd = req->xconn->transport.sock;
454 SMB_ASSERT(req->unread_bytes == N);
455 /* VFS_RECVFILE must drain the socket
456 * before returning. */
457 req->unread_bytes = 0;
458 /*
459 * Leave the socket non-blocking and
460 * use SMB_VFS_RECVFILE. If it returns
461 * EAGAIN || EWOULDBLOCK temporarily set
462 * the socket blocking and retry
463 * the RECVFILE.
464 */
465 while (total < N) {
466 ret = SMB_VFS_RECVFILE(sockfd,
467 fsp,
468 offset + total,
469 N - total);
470 if (ret == 0 || (ret == -1 &&
471 (errno == EAGAIN ||
472 errno == EWOULDBLOCK))) {
473 int old_flags;
474 /* Ensure the socket is blocking. */
475 old_flags = fcntl(sockfd, F_GETFL, 0);
476 if (set_blocking(sockfd, true) == -1) {
477 return (ssize_t)-1;
478 }
479 ret = SMB_VFS_RECVFILE(sockfd,
480 fsp,
481 offset + total,
482 N - total);
483 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
484 return (ssize_t)-1;
485 }
486 if (ret == -1) {
487 return (ssize_t)-1;
488 }
489 total += ret;
490 return (ssize_t)total;
491 }
492 /* Any other error case. */
493 if (ret == -1) {
494 return ret;
495 }
496 total += ret;
497 }
498 return (ssize_t)total;
499 }
500
501 while (total < N) {
502 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
503 offset + total);
504
505 if (ret == -1)
506 return -1;
507 if (ret == 0)
508 return total;
509
510 total += ret;
511 }
512 return (ssize_t)total;
513}
514/****************************************************************************
515 An allocate file space call using the vfs interface.
516 Allocates space for a file from a filedescriptor.
517 Returns 0 on success, -1 on failure.
518****************************************************************************/
519
520int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
521{
522 int ret;
523 connection_struct *conn = fsp->conn;
524 uint64_t space_avail;
525 uint64_t bsize,dfree,dsize;
526 NTSTATUS status;
527
528 /*
529 * Actually try and commit the space on disk....
530 */
531
532 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
533 fsp_str_dbg(fsp), (double)len));
534
535 if (((off_t)len) < 0) {
536 DEBUG(0,("vfs_allocate_file_space: %s negative len "
537 "requested.\n", fsp_str_dbg(fsp)));
538 errno = EINVAL;
539 return -1;
540 }
541
542 status = vfs_stat_fsp(fsp);
543 if (!NT_STATUS_IS_OK(status)) {
544 return -1;
545 }
546
547 if (len == (uint64_t)fsp->fsp_name->st.st_ex_size)
548 return 0;
549
550 if (len < (uint64_t)fsp->fsp_name->st.st_ex_size) {
551 /* Shrink - use ftruncate. */
552
553 DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
554 "size %.0f\n", fsp_str_dbg(fsp),
555 (double)fsp->fsp_name->st.st_ex_size));
556
557 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
558
559 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
560 if ((ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len)) != -1) {
561 set_filelen_write_cache(fsp, len);
562 }
563
564 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
565
566 return ret;
567 }
568
569 /* Grow - we need to test if we have enough space. */
570
571 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
572
573 if (lp_strict_allocate(SNUM(fsp->conn))) {
574 /* See if we have a syscall that will allocate beyond
575 end-of-file without changing EOF. */
576 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
577 0, len);
578 } else {
579 ret = 0;
580 }
581
582 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
583
584 if (ret == 0) {
585 /* We changed the allocation size on disk, but not
586 EOF - exactly as required. We're done ! */
587 return 0;
588 }
589
590 if (ret == -1 && errno == ENOSPC) {
591 return -1;
592 }
593
594 len -= fsp->fsp_name->st.st_ex_size;
595 len /= 1024; /* Len is now number of 1k blocks needed. */
596 space_avail =
597 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
598 if (space_avail == (uint64_t)-1) {
599 return -1;
600 }
601
602 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
603 "needed blocks = %.0f, space avail = %.0f\n",
604 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
605 (double)space_avail));
606
607 if (len > space_avail) {
608 errno = ENOSPC;
609 return -1;
610 }
611
612 return 0;
613}
614
615/****************************************************************************
616 A vfs set_filelen call.
617 set the length of a file from a filedescriptor.
618 Returns 0 on success, -1 on failure.
619****************************************************************************/
620
621int vfs_set_filelen(files_struct *fsp, off_t len)
622{
623 int ret;
624
625 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
626
627 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
628 fsp_str_dbg(fsp), (double)len));
629 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
630 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
631 set_filelen_write_cache(fsp, len);
632 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
633 FILE_NOTIFY_CHANGE_SIZE
634 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
635 fsp->fsp_name->base_name);
636 }
637
638 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
639
640 return ret;
641}
642
643/****************************************************************************
644 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
645 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
646 as this is also called from the default SMB_VFS_FTRUNCATE code.
647 Always extends the file size.
648 Returns 0 on success, -1 on failure.
649****************************************************************************/
650
651#define SPARSE_BUF_WRITE_SIZE (32*1024)
652
653int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
654{
655 ssize_t pwrite_ret;
656 size_t total = 0;
657
658 if (!sparse_buf) {
659 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
660 if (!sparse_buf) {
661 errno = ENOMEM;
662 return -1;
663 }
664 }
665
666 while (total < len) {
667 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
668
669 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
670 if (pwrite_ret == -1) {
671 int saved_errno = errno;
672 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
673 "%s failed with error %s\n",
674 fsp_str_dbg(fsp), strerror(saved_errno)));
675 errno = saved_errno;
676 return -1;
677 }
678 total += pwrite_ret;
679 }
680
681 return 0;
682}
683
684/****************************************************************************
685 A vfs fill sparse call.
686 Writes zeros from the end of file to len, if len is greater than EOF.
687 Used only by strict_sync.
688 Returns 0 on success, -1 on failure.
689****************************************************************************/
690
691int vfs_fill_sparse(files_struct *fsp, off_t len)
692{
693 int ret;
694 NTSTATUS status;
695 off_t offset;
696 size_t num_to_write;
697
698 status = vfs_stat_fsp(fsp);
699 if (!NT_STATUS_IS_OK(status)) {
700 return -1;
701 }
702
703 if (len <= fsp->fsp_name->st.st_ex_size) {
704 return 0;
705 }
706
707#ifdef S_ISFIFO
708 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
709 return 0;
710 }
711#endif
712
713 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
714 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
715 (double)fsp->fsp_name->st.st_ex_size, (double)len,
716 (double)(len - fsp->fsp_name->st.st_ex_size)));
717
718 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
719
720 flush_write_cache(fsp, SAMBA_SIZECHANGE_FLUSH);
721
722 offset = fsp->fsp_name->st.st_ex_size;
723 num_to_write = len - fsp->fsp_name->st.st_ex_size;
724
725 /* Only do this on non-stream file handles. */
726 if (fsp->base_fsp == NULL) {
727 /* for allocation try fallocate first. This can fail on some
728 * platforms e.g. when the filesystem doesn't support it and no
729 * emulation is being done by the libc (like on AIX with JFS1). In that
730 * case we do our own emulation. fallocate implementations can
731 * return ENOTSUP or EINVAL in cases like that. */
732 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
733 if (ret == -1 && errno == ENOSPC) {
734 goto out;
735 }
736 if (ret == 0) {
737 goto out;
738 }
739 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
740 "error %d. Falling back to slow manual allocation\n", ret));
741 }
742
743 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
744
745 out:
746
747 if (ret == 0) {
748 set_filelen_write_cache(fsp, len);
749 }
750
751 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
752 return ret;
753}
754
755/****************************************************************************
756 Transfer some data (n bytes) between two file_struct's.
757****************************************************************************/
758
759static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
760{
761 struct files_struct *fsp = (struct files_struct *)file;
762
763 return SMB_VFS_PREAD(fsp, buf, len, offset);
764}
765
766static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
767{
768 struct files_struct *fsp = (struct files_struct *)file;
769
770 return SMB_VFS_PWRITE(fsp, buf, len, offset);
771}
772
773off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
774{
775 return transfer_file_internal((void *)in, (void *)out, n,
776 vfs_pread_fn, vfs_pwrite_fn);
777}
778
779/*******************************************************************
780 A vfs_readdir wrapper which just returns the file name.
781********************************************************************/
782
783const char *vfs_readdirname(connection_struct *conn, void *p,
784 SMB_STRUCT_STAT *sbuf, char **talloced)
785{
786 struct dirent *ptr= NULL;
787 const char *dname;
788 char *translated;
789 NTSTATUS status;
790
791 if (!p)
792 return(NULL);
793
794 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
795 if (!ptr)
796 return(NULL);
797
798 dname = ptr->d_name;
799
800
801#ifdef NEXT2
802 if (telldir(p) < 0)
803 return(NULL);
804#endif
805
806#ifdef HAVE_BROKEN_READDIR_NAME
807 /* using /usr/ucb/cc is BAD */
808 dname = dname - 2;
809#endif
810
811 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
812 talloc_tos(), &translated);
813 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
814 *talloced = NULL;
815 return dname;
816 }
817 *talloced = translated;
818 if (!NT_STATUS_IS_OK(status)) {
819 return NULL;
820 }
821 return translated;
822}
823
824/*******************************************************************
825 A wrapper for vfs_chdir().
826********************************************************************/
827
828int vfs_ChDir(connection_struct *conn, const char *path)
829{
830 int ret;
831
832 if (!LastDir) {
833 LastDir = SMB_STRDUP("");
834 }
835
836 if (ISDOT(path)) {
837 return 0;
838 }
839
840 if (*path == '/' && strcsequal(LastDir,path)) {
841 return 0;
842 }
843
844 DEBUG(4,("vfs_ChDir to %s\n",path));
845
846 ret = SMB_VFS_CHDIR(conn,path);
847 if (ret == 0) {
848 /* Global cache. */
849 SAFE_FREE(LastDir);
850 LastDir = SMB_STRDUP(path);
851
852 /* conn cache. */
853 TALLOC_FREE(conn->cwd);
854 conn->cwd = vfs_GetWd(conn, conn);
855 DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
856 }
857 return ret;
858}
859
860/*******************************************************************
861 Return the absolute current directory path - given a UNIX pathname.
862 Note that this path is returned in DOS format, not UNIX
863 format. Note this can be called with conn == NULL.
864********************************************************************/
865
866char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
867{
868 char *current_dir = NULL;
869 char *result = NULL;
870 DATA_BLOB cache_value;
871 struct file_id key;
872 struct smb_filename *smb_fname_dot = NULL;
873 struct smb_filename *smb_fname_full = NULL;
874
875 if (!lp_getwd_cache()) {
876 goto nocache;
877 }
878
879 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL);
880 if (smb_fname_dot == NULL) {
881 errno = ENOMEM;
882 goto out;
883 }
884
885 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
886 /*
887 * Known to fail for root: the directory may be NFS-mounted
888 * and exported with root_squash (so has no root access).
889 */
890 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
891 "(NFS problem ?)\n", strerror(errno) ));
892 goto nocache;
893 }
894
895 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
896
897 if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
898 data_blob_const(&key, sizeof(key)),
899 &cache_value)) {
900 goto nocache;
901 }
902
903 SMB_ASSERT((cache_value.length > 0)
904 && (cache_value.data[cache_value.length-1] == '\0'));
905
906 smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
907 NULL, NULL);
908 if (smb_fname_full == NULL) {
909 errno = ENOMEM;
910 goto out;
911 }
912
913 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
914 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
915 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
916 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
917 /*
918 * Ok, we're done
919 */
920 result = talloc_strdup(ctx, smb_fname_full->base_name);
921 if (result == NULL) {
922 errno = ENOMEM;
923 }
924 goto out;
925 }
926
927 nocache:
928
929 /*
930 * We don't have the information to hand so rely on traditional
931 * methods. The very slow getcwd, which spawns a process on some
932 * systems, or the not quite so bad getwd.
933 */
934
935 current_dir = SMB_VFS_GETWD(conn);
936 if (current_dir == NULL) {
937 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
938 strerror(errno)));
939 goto out;
940 }
941
942 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
943 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
944
945 memcache_add(smbd_memcache(), GETWD_CACHE,
946 data_blob_const(&key, sizeof(key)),
947 data_blob_const(current_dir,
948 strlen(current_dir)+1));
949 }
950
951 result = talloc_strdup(ctx, current_dir);
952 if (result == NULL) {
953 errno = ENOMEM;
954 }
955
956 out:
957 TALLOC_FREE(smb_fname_dot);
958 TALLOC_FREE(smb_fname_full);
959 SAFE_FREE(current_dir);
960 return result;
961}
962
963/*******************************************************************
964 Reduce a file name, removing .. elements and checking that
965 it is below dir in the heirachy. This uses realpath.
966 This function must run as root, and will return names
967 and valid stat structs that can be checked on open.
968********************************************************************/
969
970NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
971 const char *fname,
972 struct smb_request *smbreq)
973{
974 NTSTATUS status;
975 TALLOC_CTX *ctx = talloc_tos();
976 const char *conn_rootdir;
977 size_t rootdir_len;
978 char *dir_name = NULL;
979 const char *last_component = NULL;
980 char *resolved_name = NULL;
981 char *saved_dir = NULL;
982 struct smb_filename *smb_fname_cwd = NULL;
983 struct privilege_paths *priv_paths = NULL;
984 int ret;
985
986 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
987 fname,
988 conn->connectpath));
989
990
991 priv_paths = talloc_zero(smbreq, struct privilege_paths);
992 if (!priv_paths) {
993 status = NT_STATUS_NO_MEMORY;
994 goto err;
995 }
996
997 if (!parent_dirname(ctx, fname, &dir_name, &last_component)) {
998 status = NT_STATUS_NO_MEMORY;
999 goto err;
1000 }
1001
1002 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1003 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1004
1005 if (priv_paths->parent_name.base_name == NULL ||
1006 priv_paths->file_name.base_name == NULL) {
1007 status = NT_STATUS_NO_MEMORY;
1008 goto err;
1009 }
1010
1011 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1012 status = map_nt_error_from_unix(errno);
1013 goto err;
1014 }
1015 /* Remember where we were. */
1016 saved_dir = vfs_GetWd(ctx, conn);
1017 if (!saved_dir) {
1018 status = map_nt_error_from_unix(errno);
1019 goto err;
1020 }
1021
1022 /* Go to the parent directory to lock in memory. */
1023 if (vfs_ChDir(conn, priv_paths->parent_name.base_name) == -1) {
1024 status = map_nt_error_from_unix(errno);
1025 goto err;
1026 }
1027
1028 /* Get the absolute path of the parent directory. */
1029 resolved_name = SMB_VFS_REALPATH(conn,".");
1030 if (!resolved_name) {
1031 status = map_nt_error_from_unix(errno);
1032 goto err;
1033 }
1034
1035 if (*resolved_name != '/') {
1036 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1037 "doesn't return absolute paths !\n"));
1038 status = NT_STATUS_OBJECT_NAME_INVALID;
1039 goto err;
1040 }
1041
1042 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1043 priv_paths->parent_name.base_name,
1044 resolved_name));
1045
1046 /* Now check the stat value is the same. */
1047 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL);
1048 if (smb_fname_cwd == NULL) {
1049 status = NT_STATUS_NO_MEMORY;
1050 goto err;
1051 }
1052
1053 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1054 status = map_nt_error_from_unix(errno);
1055 goto err;
1056 }
1057
1058 /* Ensure we're pointing at the same place. */
1059 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1060 DEBUG(0,("check_reduced_name_with_privilege: "
1061 "device/inode/uid/gid on directory %s changed. "
1062 "Denying access !\n",
1063 priv_paths->parent_name.base_name));
1064 status = NT_STATUS_ACCESS_DENIED;
1065 goto err;
1066 }
1067
1068 /* Ensure we're below the connect path. */
1069
1070 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1071 if (conn_rootdir == NULL) {
1072 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1073 "conn_rootdir\n"));
1074 status = NT_STATUS_ACCESS_DENIED;
1075 goto err;
1076 }
1077
1078 rootdir_len = strlen(conn_rootdir);
1079
1080 /*
1081 * In the case of rootdir_len == 1, we know that conn_rootdir is
1082 * "/", and we also know that resolved_name starts with a slash.
1083 * So, in this corner case, resolved_name is automatically a
1084 * sub-directory of the conn_rootdir. Thus we can skip the string
1085 * comparison and the next character checks (which are even
1086 * wrong in this case).
1087 */
1088 if (rootdir_len != 1) {
1089 bool matched;
1090
1091 matched = (strncmp(conn_rootdir, resolved_name,
1092 rootdir_len) == 0);
1093
1094 if (!matched || (resolved_name[rootdir_len] != '/' &&
1095 resolved_name[rootdir_len] != '\0')) {
1096 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1097 "access attempt: %s is a symlink outside the "
1098 "share path\n",
1099 dir_name));
1100 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1101 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1102 status = NT_STATUS_ACCESS_DENIED;
1103 goto err;
1104 }
1105 }
1106
1107 /* Now ensure that the last component either doesn't
1108 exist, or is *NOT* a symlink. */
1109
1110 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1111 if (ret == -1) {
1112 /* Errno must be ENOENT for this be ok. */
1113 if (errno != ENOENT) {
1114 status = map_nt_error_from_unix(errno);
1115 DEBUG(2, ("check_reduced_name_with_privilege: "
1116 "LSTAT on %s failed with %s\n",
1117 priv_paths->file_name.base_name,
1118 nt_errstr(status)));
1119 goto err;
1120 }
1121 }
1122
1123 if (VALID_STAT(priv_paths->file_name.st) &&
1124 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1125 DEBUG(2, ("check_reduced_name_with_privilege: "
1126 "Last component %s is a symlink. Denying"
1127 "access.\n",
1128 priv_paths->file_name.base_name));
1129 status = NT_STATUS_ACCESS_DENIED;
1130 goto err;
1131 }
1132
1133 smbreq->priv_paths = priv_paths;
1134 status = NT_STATUS_OK;
1135
1136 err:
1137
1138 if (saved_dir) {
1139 vfs_ChDir(conn, saved_dir);
1140 }
1141 SAFE_FREE(resolved_name);
1142 if (!NT_STATUS_IS_OK(status)) {
1143 TALLOC_FREE(priv_paths);
1144 }
1145 TALLOC_FREE(dir_name);
1146 return status;
1147}
1148
1149/*******************************************************************
1150 Reduce a file name, removing .. elements and checking that
1151 it is below dir in the heirachy. This uses realpath.
1152********************************************************************/
1153
1154NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
1155{
1156 char *resolved_name = NULL;
1157 bool allow_symlinks = true;
1158 bool allow_widelinks = false;
1159
1160 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1161
1162 resolved_name = SMB_VFS_REALPATH(conn,fname);
1163
1164 if (!resolved_name) {
1165 switch (errno) {
1166 case ENOTDIR:
1167 DEBUG(3,("check_reduced_name: Component not a "
1168 "directory in getting realpath for "
1169 "%s\n", fname));
1170 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1171 case ENOENT:
1172 {
1173 TALLOC_CTX *ctx = talloc_tos();
1174 char *dir_name = NULL;
1175 const char *last_component = NULL;
1176 char *new_name = NULL;
1177 int ret;
1178
1179 /* Last component didn't exist.
1180 Remove it and try and canonicalise
1181 the directory name. */
1182 if (!parent_dirname(ctx, fname,
1183 &dir_name,
1184 &last_component)) {
1185 return NT_STATUS_NO_MEMORY;
1186 }
1187
1188 resolved_name = SMB_VFS_REALPATH(conn,dir_name);
1189 if (!resolved_name) {
1190 NTSTATUS status = map_nt_error_from_unix(errno);
1191
1192 if (errno == ENOENT || errno == ENOTDIR) {
1193 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1194 }
1195
1196 DEBUG(3,("check_reduce_name: "
1197 "couldn't get realpath for "
1198 "%s (%s)\n",
1199 fname,
1200 nt_errstr(status)));
1201 return status;
1202 }
1203 ret = asprintf(&new_name, "%s/%s",
1204 resolved_name, last_component);
1205 SAFE_FREE(resolved_name);
1206 if (ret == -1) {
1207 return NT_STATUS_NO_MEMORY;
1208 }
1209 resolved_name = new_name;
1210 break;
1211 }
1212 default:
1213 DEBUG(3,("check_reduced_name: couldn't get "
1214 "realpath for %s\n", fname));
1215 return map_nt_error_from_unix(errno);
1216 }
1217 }
1218
1219 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1220 resolved_name));
1221
1222 if (*resolved_name != '/') {
1223 DEBUG(0,("check_reduced_name: realpath doesn't return "
1224 "absolute paths !\n"));
1225 SAFE_FREE(resolved_name);
1226 return NT_STATUS_OBJECT_NAME_INVALID;
1227 }
1228
1229 allow_widelinks = lp_widelinks(SNUM(conn));
1230 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1231
1232 /* Common widelinks and symlinks checks. */
1233 if (!allow_widelinks || !allow_symlinks) {
1234 const char *conn_rootdir;
1235 size_t rootdir_len;
1236
1237 conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
1238 if (conn_rootdir == NULL) {
1239 DEBUG(2, ("check_reduced_name: Could not get "
1240 "conn_rootdir\n"));
1241 SAFE_FREE(resolved_name);
1242 return NT_STATUS_ACCESS_DENIED;
1243 }
1244
1245 rootdir_len = strlen(conn_rootdir);
1246
1247 /*
1248 * In the case of rootdir_len == 1, we know that
1249 * conn_rootdir is "/", and we also know that
1250 * resolved_name starts with a slash. So, in this
1251 * corner case, resolved_name is automatically a
1252 * sub-directory of the conn_rootdir. Thus we can skip
1253 * the string comparison and the next character checks
1254 * (which are even wrong in this case).
1255 */
1256 if (rootdir_len != 1) {
1257 bool matched;
1258
1259 matched = (strncmp(conn_rootdir, resolved_name,
1260 rootdir_len) == 0);
1261 if (!matched || (resolved_name[rootdir_len] != '/' &&
1262 resolved_name[rootdir_len] != '\0')) {
1263 DEBUG(2, ("check_reduced_name: Bad access "
1264 "attempt: %s is a symlink outside the "
1265 "share path\n", fname));
1266 DEBUGADD(2, ("conn_rootdir =%s\n",
1267 conn_rootdir));
1268 DEBUGADD(2, ("resolved_name=%s\n",
1269 resolved_name));
1270 SAFE_FREE(resolved_name);
1271 return NT_STATUS_ACCESS_DENIED;
1272 }
1273 }
1274
1275 /* Extra checks if all symlinks are disallowed. */
1276 if (!allow_symlinks) {
1277 /* fname can't have changed in resolved_path. */
1278 const char *p = &resolved_name[rootdir_len];
1279
1280 /* *p can be '\0' if fname was "." */
1281 if (*p == '\0' && ISDOT(fname)) {
1282 goto out;
1283 }
1284
1285 if (*p != '/') {
1286 DEBUG(2, ("check_reduced_name: logic error (%c) "
1287 "in resolved_name: %s\n",
1288 *p,
1289 fname));
1290 SAFE_FREE(resolved_name);
1291 return NT_STATUS_ACCESS_DENIED;
1292 }
1293
1294 p++;
1295 if (strcmp(fname, p)!=0) {
1296 DEBUG(2, ("check_reduced_name: Bad access "
1297 "attempt: %s is a symlink to %s\n",
1298 fname, p));
1299 SAFE_FREE(resolved_name);
1300 return NT_STATUS_ACCESS_DENIED;
1301 }
1302 }
1303 }
1304
1305 out:
1306
1307 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1308 SAFE_FREE(resolved_name);
1309 return NT_STATUS_OK;
1310}
1311
1312/**
1313 * XXX: This is temporary and there should be no callers of this once
1314 * smb_filename is plumbed through all path based operations.
1315 *
1316 * Called when we know stream name parsing has already been done.
1317 */
1318int vfs_stat_smb_basename(struct connection_struct *conn, const char *fname,
1319 SMB_STRUCT_STAT *psbuf)
1320{
1321 struct smb_filename smb_fname = {
1322 .base_name = discard_const_p(char, fname)
1323 };
1324 int ret;
1325
1326 if (lp_posix_pathnames()) {
1327 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1328 } else {
1329 ret = SMB_VFS_STAT(conn, &smb_fname);
1330 }
1331
1332 if (ret != -1) {
1333 *psbuf = smb_fname.st;
1334 }
1335 return ret;
1336}
1337
1338/**
1339 * Ensure LSTAT is called for POSIX paths.
1340 */
1341
1342NTSTATUS vfs_stat_fsp(files_struct *fsp)
1343{
1344 int ret;
1345
1346 if(fsp->fh->fd == -1) {
1347 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1348 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1349 } else {
1350 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1351 }
1352 if (ret == -1) {
1353 return map_nt_error_from_unix(errno);
1354 }
1355 } else {
1356 if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
1357 return map_nt_error_from_unix(errno);
1358 }
1359 }
1360 return NT_STATUS_OK;
1361}
1362
1363/**
1364 * Initialize num_streams and streams, then call VFS op streaminfo
1365 */
1366NTSTATUS vfs_streaminfo(connection_struct *conn,
1367 struct files_struct *fsp,
1368 const char *fname,
1369 TALLOC_CTX *mem_ctx,
1370 unsigned int *num_streams,
1371 struct stream_struct **streams)
1372{
1373 *num_streams = 0;
1374 *streams = NULL;
1375 return SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams);
1376}
1377
1378/*
1379 generate a file_id from a stat structure
1380 */
1381struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1382{
1383 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1384}
1385
1386int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1387 const char *service, const char *user)
1388{
1389 VFS_FIND(connect);
1390 return handle->fns->connect_fn(handle, service, user);
1391}
1392
1393void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1394{
1395 VFS_FIND(disconnect);
1396 handle->fns->disconnect_fn(handle);
1397}
1398
1399uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1400 const char *path, uint64_t *bsize,
1401 uint64_t *dfree, uint64_t *dsize)
1402{
1403 VFS_FIND(disk_free);
1404 return handle->fns->disk_free_fn(handle, path, bsize, dfree, dsize);
1405}
1406
1407int smb_vfs_call_get_quota(struct vfs_handle_struct *handle, const char *path,
1408 enum SMB_QUOTA_TYPE qtype, unid_t id,
1409 SMB_DISK_QUOTA *qt)
1410{
1411 VFS_FIND(get_quota);
1412 return handle->fns->get_quota_fn(handle, path, qtype, id, qt);
1413}
1414
1415int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1416 enum SMB_QUOTA_TYPE qtype, unid_t id,
1417 SMB_DISK_QUOTA *qt)
1418{
1419 VFS_FIND(set_quota);
1420 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1421}
1422
1423int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1424 struct files_struct *fsp,
1425 struct shadow_copy_data *shadow_copy_data,
1426 bool labels)
1427{
1428 VFS_FIND(get_shadow_copy_data);
1429 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1430 shadow_copy_data,
1431 labels);
1432}
1433int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
1434 struct vfs_statvfs_struct *statbuf)
1435{
1436 VFS_FIND(statvfs);
1437 return handle->fns->statvfs_fn(handle, path, statbuf);
1438}
1439
1440uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1441 enum timestamp_set_resolution *p_ts_res)
1442{
1443 VFS_FIND(fs_capabilities);
1444 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1445}
1446
1447NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1448 struct dfs_GetDFSReferral *r)
1449{
1450 VFS_FIND(get_dfs_referrals);
1451 return handle->fns->get_dfs_referrals_fn(handle, r);
1452}
1453
1454DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1455 const char *fname, const char *mask,
1456 uint32_t attributes)
1457{
1458 VFS_FIND(opendir);
1459 return handle->fns->opendir_fn(handle, fname, mask, attributes);
1460}
1461
1462DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1463 struct files_struct *fsp,
1464 const char *mask,
1465 uint32_t attributes)
1466{
1467 VFS_FIND(fdopendir);
1468 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1469}
1470
1471struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1472 DIR *dirp,
1473 SMB_STRUCT_STAT *sbuf)
1474{
1475 VFS_FIND(readdir);
1476 return handle->fns->readdir_fn(handle, dirp, sbuf);
1477}
1478
1479void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1480 DIR *dirp, long offset)
1481{
1482 VFS_FIND(seekdir);
1483 handle->fns->seekdir_fn(handle, dirp, offset);
1484}
1485
1486long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1487 DIR *dirp)
1488{
1489 VFS_FIND(telldir);
1490 return handle->fns->telldir_fn(handle, dirp);
1491}
1492
1493void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1494 DIR *dirp)
1495{
1496 VFS_FIND(rewind_dir);
1497 handle->fns->rewind_dir_fn(handle, dirp);
1498}
1499
1500int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, const char *path,
1501 mode_t mode)
1502{
1503 VFS_FIND(mkdir);
1504 return handle->fns->mkdir_fn(handle, path, mode);
1505}
1506
1507int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, const char *path)
1508{
1509 VFS_FIND(rmdir);
1510 return handle->fns->rmdir_fn(handle, path);
1511}
1512
1513int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1514 DIR *dir)
1515{
1516 VFS_FIND(closedir);
1517 return handle->fns->closedir_fn(handle, dir);
1518}
1519
1520void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
1521 DIR *dirp)
1522{
1523 VFS_FIND(init_search_op);
1524 handle->fns->init_search_op_fn(handle, dirp);
1525}
1526
1527int smb_vfs_call_open(struct vfs_handle_struct *handle,
1528 struct smb_filename *smb_fname, struct files_struct *fsp,
1529 int flags, mode_t mode)
1530{
1531 VFS_FIND(open);
1532 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1533}
1534
1535NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1536 struct smb_request *req,
1537 uint16_t root_dir_fid,
1538 struct smb_filename *smb_fname,
1539 uint32_t access_mask,
1540 uint32_t share_access,
1541 uint32_t create_disposition,
1542 uint32_t create_options,
1543 uint32_t file_attributes,
1544 uint32_t oplock_request,
1545 struct smb2_lease *lease,
1546 uint64_t allocation_size,
1547 uint32_t private_flags,
1548 struct security_descriptor *sd,
1549 struct ea_list *ea_list,
1550 files_struct **result,
1551 int *pinfo,
1552 const struct smb2_create_blobs *in_context_blobs,
1553 struct smb2_create_blobs *out_context_blobs)
1554{
1555 VFS_FIND(create_file);
1556 return handle->fns->create_file_fn(
1557 handle, req, root_dir_fid, smb_fname, access_mask,
1558 share_access, create_disposition, create_options,
1559 file_attributes, oplock_request, lease, allocation_size,
1560 private_flags, sd, ea_list,
1561 result, pinfo, in_context_blobs, out_context_blobs);
1562}
1563
1564int smb_vfs_call_close(struct vfs_handle_struct *handle,
1565 struct files_struct *fsp)
1566{
1567 VFS_FIND(close);
1568 return handle->fns->close_fn(handle, fsp);
1569}
1570
1571ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
1572 struct files_struct *fsp, void *data, size_t n)
1573{
1574 VFS_FIND(read);
1575 return handle->fns->read_fn(handle, fsp, data, n);
1576}
1577
1578ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1579 struct files_struct *fsp, void *data, size_t n,
1580 off_t offset)
1581{
1582 VFS_FIND(pread);
1583 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1584}
1585
1586struct smb_vfs_call_pread_state {
1587 ssize_t (*recv_fn)(struct tevent_req *req, int *err);
1588 ssize_t retval;
1589};
1590
1591static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1592
1593struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1594 TALLOC_CTX *mem_ctx,
1595 struct tevent_context *ev,
1596 struct files_struct *fsp,
1597 void *data,
1598 size_t n, off_t offset)
1599{
1600 struct tevent_req *req, *subreq;
1601 struct smb_vfs_call_pread_state *state;
1602
1603 req = tevent_req_create(mem_ctx, &state,
1604 struct smb_vfs_call_pread_state);
1605 if (req == NULL) {
1606 return NULL;
1607 }
1608 VFS_FIND(pread_send);
1609 state->recv_fn = handle->fns->pread_recv_fn;
1610
1611 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1612 offset);
1613 if (tevent_req_nomem(subreq, req)) {
1614 return tevent_req_post(req, ev);
1615 }
1616 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1617 return req;
1618}
1619
1620static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1621{
1622 struct tevent_req *req = tevent_req_callback_data(
1623 subreq, struct tevent_req);
1624 struct smb_vfs_call_pread_state *state = tevent_req_data(
1625 req, struct smb_vfs_call_pread_state);
1626 int err;
1627
1628 state->retval = state->recv_fn(subreq, &err);
1629 TALLOC_FREE(subreq);
1630 if (state->retval == -1) {
1631 tevent_req_error(req, err);
1632 return;
1633 }
1634 tevent_req_done(req);
1635}
1636
1637ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno)
1638{
1639 struct smb_vfs_call_pread_state *state = tevent_req_data(
1640 req, struct smb_vfs_call_pread_state);
1641 int err;
1642
1643 if (tevent_req_is_unix_error(req, &err)) {
1644 *perrno = err;
1645 return -1;
1646 }
1647 return state->retval;
1648}
1649
1650ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
1651 struct files_struct *fsp, const void *data,
1652 size_t n)
1653{
1654 VFS_FIND(write);
1655 return handle->fns->write_fn(handle, fsp, data, n);
1656}
1657
1658ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1659 struct files_struct *fsp, const void *data,
1660 size_t n, off_t offset)
1661{
1662 VFS_FIND(pwrite);
1663 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1664}
1665
1666struct smb_vfs_call_pwrite_state {
1667 ssize_t (*recv_fn)(struct tevent_req *req, int *err);
1668 ssize_t retval;
1669};
1670
1671static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1672
1673struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1674 TALLOC_CTX *mem_ctx,
1675 struct tevent_context *ev,
1676 struct files_struct *fsp,
1677 const void *data,
1678 size_t n, off_t offset)
1679{
1680 struct tevent_req *req, *subreq;
1681 struct smb_vfs_call_pwrite_state *state;
1682
1683 req = tevent_req_create(mem_ctx, &state,
1684 struct smb_vfs_call_pwrite_state);
1685 if (req == NULL) {
1686 return NULL;
1687 }
1688 VFS_FIND(pwrite_send);
1689 state->recv_fn = handle->fns->pwrite_recv_fn;
1690
1691 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1692 offset);
1693 if (tevent_req_nomem(subreq, req)) {
1694 return tevent_req_post(req, ev);
1695 }
1696 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1697 return req;
1698}
1699
1700static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1701{
1702 struct tevent_req *req = tevent_req_callback_data(
1703 subreq, struct tevent_req);
1704 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1705 req, struct smb_vfs_call_pwrite_state);
1706 int err;
1707
1708 state->retval = state->recv_fn(subreq, &err);
1709 TALLOC_FREE(subreq);
1710 if (state->retval == -1) {
1711 tevent_req_error(req, err);
1712 return;
1713 }
1714 tevent_req_done(req);
1715}
1716
1717ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, int *perrno)
1718{
1719 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1720 req, struct smb_vfs_call_pwrite_state);
1721 int err;
1722
1723 if (tevent_req_is_unix_error(req, &err)) {
1724 *perrno = err;
1725 return -1;
1726 }
1727 return state->retval;
1728}
1729
1730off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1731 struct files_struct *fsp, off_t offset,
1732 int whence)
1733{
1734 VFS_FIND(lseek);
1735 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1736}
1737
1738ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1739 files_struct *fromfsp, const DATA_BLOB *header,
1740 off_t offset, size_t count)
1741{
1742 VFS_FIND(sendfile);
1743 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1744 count);
1745}
1746
1747ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1748 files_struct *tofsp, off_t offset,
1749 size_t count)
1750{
1751 VFS_FIND(recvfile);
1752 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1753}
1754
1755int smb_vfs_call_rename(struct vfs_handle_struct *handle,
1756 const struct smb_filename *smb_fname_src,
1757 const struct smb_filename *smb_fname_dst)
1758{
1759 VFS_FIND(rename);
1760 return handle->fns->rename_fn(handle, smb_fname_src, smb_fname_dst);
1761}
1762
1763int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
1764 struct files_struct *fsp)
1765{
1766 VFS_FIND(fsync);
1767 return handle->fns->fsync_fn(handle, fsp);
1768}
1769
1770struct smb_vfs_call_fsync_state {
1771 int (*recv_fn)(struct tevent_req *req, int *err);
1772 int retval;
1773};
1774
1775static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
1776
1777struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
1778 TALLOC_CTX *mem_ctx,
1779 struct tevent_context *ev,
1780 struct files_struct *fsp)
1781{
1782 struct tevent_req *req, *subreq;
1783 struct smb_vfs_call_fsync_state *state;
1784
1785 req = tevent_req_create(mem_ctx, &state,
1786 struct smb_vfs_call_fsync_state);
1787 if (req == NULL) {
1788 return NULL;
1789 }
1790 VFS_FIND(fsync_send);
1791 state->recv_fn = handle->fns->fsync_recv_fn;
1792
1793 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
1794 if (tevent_req_nomem(subreq, req)) {
1795 return tevent_req_post(req, ev);
1796 }
1797 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
1798 return req;
1799}
1800
1801static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
1802{
1803 struct tevent_req *req = tevent_req_callback_data(
1804 subreq, struct tevent_req);
1805 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1806 req, struct smb_vfs_call_fsync_state);
1807 int err;
1808
1809 state->retval = state->recv_fn(subreq, &err);
1810 TALLOC_FREE(subreq);
1811 if (state->retval == -1) {
1812 tevent_req_error(req, err);
1813 return;
1814 }
1815 tevent_req_done(req);
1816}
1817
1818int SMB_VFS_FSYNC_RECV(struct tevent_req *req, int *perrno)
1819{
1820 struct smb_vfs_call_fsync_state *state = tevent_req_data(
1821 req, struct smb_vfs_call_fsync_state);
1822 int err;
1823
1824 if (tevent_req_is_unix_error(req, &err)) {
1825 *perrno = err;
1826 return -1;
1827 }
1828 return state->retval;
1829}
1830
1831
1832int smb_vfs_call_stat(struct vfs_handle_struct *handle,
1833 struct smb_filename *smb_fname)
1834{
1835 VFS_FIND(stat);
1836 return handle->fns->stat_fn(handle, smb_fname);
1837}
1838
1839int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
1840 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1841{
1842 VFS_FIND(fstat);
1843 return handle->fns->fstat_fn(handle, fsp, sbuf);
1844}
1845
1846int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
1847 struct smb_filename *smb_filename)
1848{
1849 VFS_FIND(lstat);
1850 return handle->fns->lstat_fn(handle, smb_filename);
1851}
1852
1853uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
1854 struct files_struct *fsp,
1855 const SMB_STRUCT_STAT *sbuf)
1856{
1857 VFS_FIND(get_alloc_size);
1858 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
1859}
1860
1861int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
1862 const struct smb_filename *smb_fname)
1863{
1864 VFS_FIND(unlink);
1865 return handle->fns->unlink_fn(handle, smb_fname);
1866}
1867
1868int smb_vfs_call_chmod(struct vfs_handle_struct *handle, const char *path,
1869 mode_t mode)
1870{
1871 VFS_FIND(chmod);
1872 return handle->fns->chmod_fn(handle, path, mode);
1873}
1874
1875int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
1876 struct files_struct *fsp, mode_t mode)
1877{
1878 VFS_FIND(fchmod);
1879 return handle->fns->fchmod_fn(handle, fsp, mode);
1880}
1881
1882int smb_vfs_call_chown(struct vfs_handle_struct *handle, const char *path,
1883 uid_t uid, gid_t gid)
1884{
1885 VFS_FIND(chown);
1886 return handle->fns->chown_fn(handle, path, uid, gid);
1887}
1888
1889int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
1890 struct files_struct *fsp, uid_t uid, gid_t gid)
1891{
1892 VFS_FIND(fchown);
1893 return handle->fns->fchown_fn(handle, fsp, uid, gid);
1894}
1895
1896int smb_vfs_call_lchown(struct vfs_handle_struct *handle, const char *path,
1897 uid_t uid, gid_t gid)
1898{
1899 VFS_FIND(lchown);
1900 return handle->fns->lchown_fn(handle, path, uid, gid);
1901}
1902
1903NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
1904{
1905 int ret;
1906 bool as_root = false;
1907 const char *path;
1908 char *saved_dir = NULL;
1909 char *parent_dir = NULL;
1910 NTSTATUS status;
1911
1912 if (fsp->fh->fd != -1) {
1913 /* Try fchown. */
1914 ret = SMB_VFS_FCHOWN(fsp, uid, gid);
1915 if (ret == 0) {
1916 return NT_STATUS_OK;
1917 }
1918 if (ret == -1 && errno != ENOSYS) {
1919 return map_nt_error_from_unix(errno);
1920 }
1921 }
1922
1923 as_root = (geteuid() == 0);
1924
1925 if (as_root) {
1926 /*
1927 * We are being asked to chown as root. Make
1928 * sure we chdir() into the path to pin it,
1929 * and always act using lchown to ensure we
1930 * don't deref any symbolic links.
1931 */
1932 const char *final_component = NULL;
1933 struct smb_filename local_fname;
1934
1935 saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
1936 if (!saved_dir) {
1937 status = map_nt_error_from_unix(errno);
1938 DEBUG(0,("vfs_chown_fsp: failed to get "
1939 "current working directory. Error was %s\n",
1940 strerror(errno)));
1941 return status;
1942 }
1943
1944 if (!parent_dirname(talloc_tos(),
1945 fsp->fsp_name->base_name,
1946 &parent_dir,
1947 &final_component)) {
1948 return NT_STATUS_NO_MEMORY;
1949 }
1950
1951 /* cd into the parent dir to pin it. */
1952 ret = vfs_ChDir(fsp->conn, parent_dir);
1953 if (ret == -1) {
1954 return map_nt_error_from_unix(errno);
1955 }
1956
1957 ZERO_STRUCT(local_fname);
1958 local_fname.base_name = discard_const_p(char, final_component);
1959
1960 /* Must use lstat here. */
1961 ret = SMB_VFS_LSTAT(fsp->conn, &local_fname);
1962 if (ret == -1) {
1963 status = map_nt_error_from_unix(errno);
1964 goto out;
1965 }
1966
1967 /* Ensure it matches the fsp stat. */
1968 if (!check_same_stat(&local_fname.st, &fsp->fsp_name->st)) {
1969 status = NT_STATUS_ACCESS_DENIED;
1970 goto out;
1971 }
1972 path = final_component;
1973 } else {
1974 path = fsp->fsp_name->base_name;
1975 }
1976
1977 if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || as_root) {
1978 ret = SMB_VFS_LCHOWN(fsp->conn,
1979 path,
1980 uid, gid);
1981 } else {
1982 ret = SMB_VFS_CHOWN(fsp->conn,
1983 path,
1984 uid, gid);
1985 }
1986
1987 if (ret == 0) {
1988 status = NT_STATUS_OK;
1989 } else {
1990 status = map_nt_error_from_unix(errno);
1991 }
1992
1993 out:
1994
1995 if (as_root) {
1996 vfs_ChDir(fsp->conn,saved_dir);
1997 TALLOC_FREE(saved_dir);
1998 TALLOC_FREE(parent_dir);
1999 }
2000 return status;
2001}
2002
2003int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
2004{
2005 VFS_FIND(chdir);
2006 return handle->fns->chdir_fn(handle, path);
2007}
2008
2009char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
2010{
2011 VFS_FIND(getwd);
2012 return handle->fns->getwd_fn(handle);
2013}
2014
2015int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2016 const struct smb_filename *smb_fname,
2017 struct smb_file_time *ft)
2018{
2019 VFS_FIND(ntimes);
2020 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2021}
2022
2023int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2024 struct files_struct *fsp, off_t offset)
2025{
2026 VFS_FIND(ftruncate);
2027 return handle->fns->ftruncate_fn(handle, fsp, offset);
2028}
2029
2030int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2031 struct files_struct *fsp,
2032 uint32_t mode,
2033 off_t offset,
2034 off_t len)
2035{
2036 VFS_FIND(fallocate);
2037 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2038}
2039
2040int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2041 struct files_struct *fsp, uint32_t share_mode,
2042 uint32_t access_mask)
2043{
2044 VFS_FIND(kernel_flock);
2045 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2046 access_mask);
2047}
2048
2049int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2050 struct files_struct *fsp, int leasetype)
2051{
2052 VFS_FIND(linux_setlease);
2053 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2054}
2055
2056int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
2057 const char *newpath)
2058{
2059 VFS_FIND(symlink);
2060 return handle->fns->symlink_fn(handle, oldpath, newpath);
2061}
2062
2063int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
2064 const char *path, char *buf, size_t bufsiz)
2065{
2066 VFS_FIND(readlink);
2067 return handle->fns->readlink_fn(handle, path, buf, bufsiz);
2068}
2069
2070int smb_vfs_call_link(struct vfs_handle_struct *handle, const char *oldpath,
2071 const char *newpath)
2072{
2073 VFS_FIND(link);
2074 return handle->fns->link_fn(handle, oldpath, newpath);
2075}
2076
2077int smb_vfs_call_mknod(struct vfs_handle_struct *handle, const char *path,
2078 mode_t mode, SMB_DEV_T dev)
2079{
2080 VFS_FIND(mknod);
2081 return handle->fns->mknod_fn(handle, path, mode, dev);
2082}
2083
2084char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
2085{
2086 VFS_FIND(realpath);
2087 return handle->fns->realpath_fn(handle, path);
2088}
2089
2090int smb_vfs_call_chflags(struct vfs_handle_struct *handle, const char *path,
2091 unsigned int flags)
2092{
2093 VFS_FIND(chflags);
2094 return handle->fns->chflags_fn(handle, path, flags);
2095}
2096
2097struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2098 const SMB_STRUCT_STAT *sbuf)
2099{
2100 VFS_FIND(file_id_create);
2101 return handle->fns->file_id_create_fn(handle, sbuf);
2102}
2103
2104NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2105 struct files_struct *fsp,
2106 const char *fname,
2107 TALLOC_CTX *mem_ctx,
2108 unsigned int *num_streams,
2109 struct stream_struct **streams)
2110{
2111 VFS_FIND(streaminfo);
2112 return handle->fns->streaminfo_fn(handle, fsp, fname, mem_ctx,
2113 num_streams, streams);
2114}
2115
2116int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2117 const char *path, const char *name,
2118 TALLOC_CTX *mem_ctx, char **found_name)
2119{
2120 VFS_FIND(get_real_filename);
2121 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2122 found_name);
2123}
2124
2125const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2126 const char *filename)
2127{
2128 VFS_FIND(connectpath);
2129 return handle->fns->connectpath_fn(handle, filename);
2130}
2131
2132bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
2133 struct files_struct *fsp,
2134 struct lock_struct *plock)
2135{
2136 VFS_FIND(strict_lock);
2137 return handle->fns->strict_lock_fn(handle, fsp, plock);
2138}
2139
2140void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
2141 struct files_struct *fsp,
2142 struct lock_struct *plock)
2143{
2144 VFS_FIND(strict_unlock);
2145 handle->fns->strict_unlock_fn(handle, fsp, plock);
2146}
2147
2148NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2149 const char *name,
2150 enum vfs_translate_direction direction,
2151 TALLOC_CTX *mem_ctx,
2152 char **mapped_name)
2153{
2154 VFS_FIND(translate_name);
2155 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2156 mapped_name);
2157}
2158
2159NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2160 struct files_struct *fsp,
2161 TALLOC_CTX *ctx,
2162 uint32_t function,
2163 uint16_t req_flags,
2164 const uint8_t *in_data,
2165 uint32_t in_len,
2166 uint8_t **out_data,
2167 uint32_t max_out_len,
2168 uint32_t *out_len)
2169{
2170 VFS_FIND(fsctl);
2171 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2172 in_data, in_len, out_data, max_out_len,
2173 out_len);
2174}
2175
2176struct tevent_req *smb_vfs_call_copy_chunk_send(struct vfs_handle_struct *handle,
2177 TALLOC_CTX *mem_ctx,
2178 struct tevent_context *ev,
2179 struct files_struct *src_fsp,
2180 off_t src_off,
2181 struct files_struct *dest_fsp,
2182 off_t dest_off,
2183 off_t num)
2184{
2185 VFS_FIND(copy_chunk_send);
2186 return handle->fns->copy_chunk_send_fn(handle, mem_ctx, ev, src_fsp,
2187 src_off, dest_fsp, dest_off, num);
2188}
2189
2190NTSTATUS smb_vfs_call_copy_chunk_recv(struct vfs_handle_struct *handle,
2191 struct tevent_req *req,
2192 off_t *copied)
2193{
2194 VFS_FIND(copy_chunk_recv);
2195 return handle->fns->copy_chunk_recv_fn(handle, req, copied);
2196}
2197
2198NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2199 TALLOC_CTX *mem_ctx,
2200 struct files_struct *fsp,
2201 struct smb_filename *smb_fname,
2202 uint16_t *_compression_fmt)
2203{
2204 VFS_FIND(get_compression);
2205 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2206 _compression_fmt);
2207}
2208
2209NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2210 TALLOC_CTX *mem_ctx,
2211 struct files_struct *fsp,
2212 uint16_t compression_fmt)
2213{
2214 VFS_FIND(set_compression);
2215 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2216 compression_fmt);
2217}
2218
2219NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2220 TALLOC_CTX *mem_ctx,
2221 const char *service_path,
2222 char **base_volume)
2223{
2224 VFS_FIND(snap_check_path);
2225 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2226 base_volume);
2227}
2228
2229NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2230 TALLOC_CTX *mem_ctx,
2231 const char *base_volume,
2232 time_t *tstamp,
2233 bool rw,
2234 char **base_path,
2235 char **snap_path)
2236{
2237 VFS_FIND(snap_create);
2238 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2239 rw, base_path, snap_path);
2240}
2241
2242NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2243 TALLOC_CTX *mem_ctx,
2244 char *base_path,
2245 char *snap_path)
2246{
2247 VFS_FIND(snap_delete);
2248 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2249 snap_path);
2250}
2251
2252NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2253 struct files_struct *fsp,
2254 uint32_t security_info,
2255 TALLOC_CTX *mem_ctx,
2256 struct security_descriptor **ppdesc)
2257{
2258 VFS_FIND(fget_nt_acl);
2259 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2260 mem_ctx, ppdesc);
2261}
2262
2263NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2264 const char *name,
2265 uint32_t security_info,
2266 TALLOC_CTX *mem_ctx,
2267 struct security_descriptor **ppdesc)
2268{
2269 VFS_FIND(get_nt_acl);
2270 return handle->fns->get_nt_acl_fn(handle, name, security_info, mem_ctx, ppdesc);
2271}
2272
2273NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2274 struct files_struct *fsp,
2275 uint32_t security_info_sent,
2276 const struct security_descriptor *psd)
2277{
2278 VFS_FIND(fset_nt_acl);
2279 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2280 psd);
2281}
2282
2283NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2284 struct smb_filename *file,
2285 struct security_acl *sacl,
2286 uint32_t access_requested,
2287 uint32_t access_denied)
2288{
2289 VFS_FIND(audit_file);
2290 return handle->fns->audit_file_fn(handle,
2291 file,
2292 sacl,
2293 access_requested,
2294 access_denied);
2295}
2296
2297int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle, const char *name,
2298 mode_t mode)
2299{
2300 VFS_FIND(chmod_acl);
2301 return handle->fns->chmod_acl_fn(handle, name, mode);
2302}
2303
2304int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
2305 struct files_struct *fsp, mode_t mode)
2306{
2307 VFS_FIND(fchmod_acl);
2308 return handle->fns->fchmod_acl_fn(handle, fsp, mode);
2309}
2310
2311SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2312 const char *path_p,
2313 SMB_ACL_TYPE_T type,
2314 TALLOC_CTX *mem_ctx)
2315{
2316 VFS_FIND(sys_acl_get_file);
2317 return handle->fns->sys_acl_get_file_fn(handle, path_p, type, mem_ctx);
2318}
2319
2320SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2321 struct files_struct *fsp,
2322 TALLOC_CTX *mem_ctx)
2323{
2324 VFS_FIND(sys_acl_get_fd);
2325 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2326}
2327
2328int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2329 const char *path_p,
2330 TALLOC_CTX *mem_ctx,
2331 char **blob_description,
2332 DATA_BLOB *blob)
2333{
2334 VFS_FIND(sys_acl_blob_get_file);
2335 return handle->fns->sys_acl_blob_get_file_fn(handle, path_p, mem_ctx, blob_description, blob);
2336}
2337
2338int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2339 struct files_struct *fsp,
2340 TALLOC_CTX *mem_ctx,
2341 char **blob_description,
2342 DATA_BLOB *blob)
2343{
2344 VFS_FIND(sys_acl_blob_get_fd);
2345 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2346}
2347
2348int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2349 const char *name, SMB_ACL_TYPE_T acltype,
2350 SMB_ACL_T theacl)
2351{
2352 VFS_FIND(sys_acl_set_file);
2353 return handle->fns->sys_acl_set_file_fn(handle, name, acltype, theacl);
2354}
2355
2356int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2357 struct files_struct *fsp, SMB_ACL_T theacl)
2358{
2359 VFS_FIND(sys_acl_set_fd);
2360 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2361}
2362
2363int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2364 const char *path)
2365{
2366 VFS_FIND(sys_acl_delete_def_file);
2367 return handle->fns->sys_acl_delete_def_file_fn(handle, path);
2368}
2369
2370ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2371 const char *path, const char *name, void *value,
2372 size_t size)
2373{
2374 VFS_FIND(getxattr);
2375 return handle->fns->getxattr_fn(handle, path, name, value, size);
2376}
2377
2378ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2379 struct files_struct *fsp, const char *name,
2380 void *value, size_t size)
2381{
2382 VFS_FIND(fgetxattr);
2383 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2384}
2385
2386ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2387 const char *path, char *list, size_t size)
2388{
2389 VFS_FIND(listxattr);
2390 return handle->fns->listxattr_fn(handle, path, list, size);
2391}
2392
2393ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2394 struct files_struct *fsp, char *list,
2395 size_t size)
2396{
2397 VFS_FIND(flistxattr);
2398 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2399}
2400
2401int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2402 const char *path, const char *name)
2403{
2404 VFS_FIND(removexattr);
2405 return handle->fns->removexattr_fn(handle, path, name);
2406}
2407
2408int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2409 struct files_struct *fsp, const char *name)
2410{
2411 VFS_FIND(fremovexattr);
2412 return handle->fns->fremovexattr_fn(handle, fsp, name);
2413}
2414
2415int smb_vfs_call_setxattr(struct vfs_handle_struct *handle, const char *path,
2416 const char *name, const void *value, size_t size,
2417 int flags)
2418{
2419 VFS_FIND(setxattr);
2420 return handle->fns->setxattr_fn(handle, path, name, value, size, flags);
2421}
2422
2423int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2424 struct files_struct *fsp, const char *name,
2425 const void *value, size_t size, int flags)
2426{
2427 VFS_FIND(fsetxattr);
2428 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2429}
2430
2431bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2432 struct files_struct *fsp)
2433{
2434 VFS_FIND(aio_force);
2435 return handle->fns->aio_force_fn(handle, fsp);
2436}
2437
2438bool smb_vfs_call_is_offline(struct vfs_handle_struct *handle,
2439 const struct smb_filename *fname,
2440 SMB_STRUCT_STAT *sbuf)
2441{
2442 VFS_FIND(is_offline);
2443 return handle->fns->is_offline_fn(handle, fname, sbuf);
2444}
2445
2446int smb_vfs_call_set_offline(struct vfs_handle_struct *handle,
2447 const struct smb_filename *fname)
2448{
2449 VFS_FIND(set_offline);
2450 return handle->fns->set_offline_fn(handle, fname);
2451}
2452
2453NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2454 struct files_struct *fsp,
2455 TALLOC_CTX *mem_ctx,
2456 DATA_BLOB *cookie)
2457{
2458 VFS_FIND(durable_cookie);
2459 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2460}
2461
2462NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2463 struct files_struct *fsp,
2464 const DATA_BLOB old_cookie,
2465 TALLOC_CTX *mem_ctx,
2466 DATA_BLOB *new_cookie)
2467{
2468 VFS_FIND(durable_disconnect);
2469 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2470 mem_ctx, new_cookie);
2471}
2472
2473NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2474 struct smb_request *smb1req,
2475 struct smbXsrv_open *op,
2476 const DATA_BLOB old_cookie,
2477 TALLOC_CTX *mem_ctx,
2478 struct files_struct **fsp,
2479 DATA_BLOB *new_cookie)
2480{
2481 VFS_FIND(durable_reconnect);
2482 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2483 old_cookie, mem_ctx, fsp,
2484 new_cookie);
2485}
2486
2487NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2488 const struct smb_filename *fname,
2489 TALLOC_CTX *mem_ctx,
2490 struct readdir_attr_data **attr_data)
2491{
2492 VFS_FIND(readdir_attr);
2493 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
2494}
Note: See TracBrowser for help on using the repository browser.