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 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
36
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_VFS
39
40 static_decl_vfs;
41
42 struct vfs_fsp_data {
43 struct vfs_fsp_data *next;
44 struct vfs_handle_struct *owner;
45 void (*destroy)(void *p_data);
46 void *_dummy_;
47 /* NOTE: This structure contains four pointers so that we can guarantee
48 * that the end of the structure is always both 4-byte and 8-byte aligned.
49 */
50 };
51
52 struct vfs_init_function_entry {
53 char *name;
54 struct vfs_init_function_entry *prev, *next;
55 const struct vfs_fn_pointers *fns;
56 };
57
58 /****************************************************************************
59 maintain the list of available backends
60 ****************************************************************************/
61
vfs_find_backend_entry(const char * name)62 static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
63 {
64 struct vfs_init_function_entry *entry = backends;
65
66 DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
67
68 while(entry) {
69 if (strcmp(entry->name, name)==0) return entry;
70 entry = entry->next;
71 }
72
73 return NULL;
74 }
75
smb_register_vfs(int version,const char * name,const struct vfs_fn_pointers * fns)76 NTSTATUS smb_register_vfs(int version, const char *name,
77 const struct vfs_fn_pointers *fns)
78 {
79 struct vfs_init_function_entry *entry = backends;
80
81 if ((version != SMB_VFS_INTERFACE_VERSION)) {
82 DEBUG(0, ("Failed to register vfs module.\n"
83 "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n"
84 "current SMB_VFS_INTERFACE_VERSION is %d.\n"
85 "Please recompile against the current Samba Version!\n",
86 version, SMB_VFS_INTERFACE_VERSION));
87 return NT_STATUS_OBJECT_TYPE_MISMATCH;
88 }
89
90 if (!name || !name[0]) {
91 DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
92 return NT_STATUS_INVALID_PARAMETER;
93 }
94
95 if (vfs_find_backend_entry(name)) {
96 DEBUG(0,("VFS module %s already loaded!\n", name));
97 return NT_STATUS_OBJECT_NAME_COLLISION;
98 }
99
100 entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
101 entry->name = smb_xstrdup(name);
102 entry->fns = fns;
103
104 DLIST_ADD(backends, entry);
105 DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
106 return NT_STATUS_OK;
107 }
108
109 /****************************************************************************
110 initialise default vfs hooks
111 ****************************************************************************/
112
vfs_init_default(connection_struct * conn)113 static void vfs_init_default(connection_struct *conn)
114 {
115 DEBUG(3, ("Initialising default vfs hooks\n"));
116 vfs_init_custom(conn, DEFAULT_VFS_MODULE_NAME);
117 }
118
119 /****************************************************************************
120 initialise custom vfs hooks
121 ****************************************************************************/
122
vfs_init_custom(connection_struct * conn,const char * vfs_object)123 bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
124 {
125 char *module_path = NULL;
126 char *module_name = NULL;
127 char *module_param = NULL, *p;
128 vfs_handle_struct *handle;
129 const struct vfs_init_function_entry *entry;
130
131 if (!conn||!vfs_object||!vfs_object[0]) {
132 DEBUG(0, ("vfs_init_custom() called with NULL pointer or "
133 "empty vfs_object!\n"));
134 return False;
135 }
136
137 if(!backends) {
138 static_init_vfs(NULL);
139 }
140
141 DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object));
142
143 module_path = smb_xstrdup(vfs_object);
144
145 p = strchr_m(module_path, ':');
146
147 if (p) {
148 *p = 0;
149 module_param = p+1;
150 trim_char(module_param, ' ', ' ');
151 }
152
153 trim_char(module_path, ' ', ' ');
154
155 module_name = smb_xstrdup(module_path);
156
157 if ((module_name[0] == '/') &&
158 (strcmp(module_path, DEFAULT_VFS_MODULE_NAME) != 0)) {
159
160 /*
161 * Extract the module name from the path. Just use the base
162 * name of the last path component.
163 */
164
165 SAFE_FREE(module_name);
166 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
167
168 p = strchr_m(module_name, '.');
169
170 if (p != NULL) {
171 *p = '\0';
172 }
173 }
174
175 /* First, try to load the module with the new module system */
176 entry = vfs_find_backend_entry(module_name);
177 if (!entry) {
178 NTSTATUS status;
179
180 DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
181 vfs_object));
182
183 status = smb_load_module("vfs", module_path);
184 if (!NT_STATUS_IS_OK(status)) {
185 DEBUG(0, ("error probing vfs module '%s': %s\n",
186 module_path, nt_errstr(status)));
187 goto fail;
188 }
189
190 entry = vfs_find_backend_entry(module_name);
191 if (!entry) {
192 DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
193 goto fail;
194 }
195 }
196
197 DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
198
199 handle = talloc_zero(conn, vfs_handle_struct);
200 if (!handle) {
201 DEBUG(0,("TALLOC_ZERO() failed!\n"));
202 goto fail;
203 }
204 handle->conn = conn;
205 handle->fns = entry->fns;
206 if (module_param) {
207 handle->param = talloc_strdup(conn, module_param);
208 }
209 DLIST_ADD(conn->vfs_handles, handle);
210
211 SAFE_FREE(module_path);
212 SAFE_FREE(module_name);
213 return True;
214
215 fail:
216 SAFE_FREE(module_path);
217 SAFE_FREE(module_name);
218 return False;
219 }
220
221 /*****************************************************************
222 Allow VFS modules to extend files_struct with VFS-specific state.
223 This will be ok for small numbers of extensions, but might need to
224 be refactored if it becomes more widely used.
225 ******************************************************************/
226
227 #define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
228
vfs_add_fsp_extension_notype(vfs_handle_struct * handle,files_struct * fsp,size_t ext_size,void (* destroy_fn)(void * p_data))229 void *vfs_add_fsp_extension_notype(vfs_handle_struct *handle,
230 files_struct *fsp, size_t ext_size,
231 void (*destroy_fn)(void *p_data))
232 {
233 struct vfs_fsp_data *ext;
234 void * ext_data;
235
236 /* Prevent VFS modules adding multiple extensions. */
237 if ((ext_data = vfs_fetch_fsp_extension(handle, fsp))) {
238 return ext_data;
239 }
240
241 ext = (struct vfs_fsp_data *)TALLOC_ZERO(
242 handle->conn, sizeof(struct vfs_fsp_data) + ext_size);
243 if (ext == NULL) {
244 return NULL;
245 }
246
247 ext->owner = handle;
248 ext->next = fsp->vfs_extension;
249 ext->destroy = destroy_fn;
250 fsp->vfs_extension = ext;
251 return EXT_DATA_AREA(ext);
252 }
253
vfs_remove_fsp_extension(vfs_handle_struct * handle,files_struct * fsp)254 void vfs_remove_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
255 {
256 struct vfs_fsp_data *curr;
257 struct vfs_fsp_data *prev;
258
259 for (curr = fsp->vfs_extension, prev = NULL;
260 curr;
261 prev = curr, curr = curr->next) {
262 if (curr->owner == handle) {
263 if (prev) {
264 prev->next = curr->next;
265 } else {
266 fsp->vfs_extension = curr->next;
267 }
268 if (curr->destroy) {
269 curr->destroy(EXT_DATA_AREA(curr));
270 }
271 TALLOC_FREE(curr);
272 return;
273 }
274 }
275 }
276
vfs_remove_all_fsp_extensions(files_struct * fsp)277 void vfs_remove_all_fsp_extensions(files_struct *fsp)
278 {
279 struct vfs_fsp_data *curr;
280 struct vfs_fsp_data *next;
281
282 for (curr = fsp->vfs_extension; curr; curr = next) {
283
284 next = curr->next;
285 fsp->vfs_extension = next;
286
287 if (curr->destroy) {
288 curr->destroy(EXT_DATA_AREA(curr));
289 }
290 TALLOC_FREE(curr);
291 }
292 }
293
vfs_memctx_fsp_extension(vfs_handle_struct * handle,files_struct * fsp)294 void *vfs_memctx_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
295 {
296 struct vfs_fsp_data *head;
297
298 for (head = fsp->vfs_extension; head; head = head->next) {
299 if (head->owner == handle) {
300 return head;
301 }
302 }
303
304 return NULL;
305 }
306
vfs_fetch_fsp_extension(vfs_handle_struct * handle,files_struct * fsp)307 void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp)
308 {
309 struct vfs_fsp_data *head;
310
311 head = (struct vfs_fsp_data *)vfs_memctx_fsp_extension(handle, fsp);
312 if (head != NULL) {
313 return EXT_DATA_AREA(head);
314 }
315
316 return NULL;
317 }
318
319 #undef EXT_DATA_AREA
320
321 /*
322 * Ensure this module catches all VFS functions.
323 */
324 #ifdef DEVELOPER
smb_vfs_assert_all_fns(const struct vfs_fn_pointers * fns,const char * module)325 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
326 const char *module)
327 {
328 bool missing_fn = false;
329 unsigned int idx;
330 const uintptr_t *end = (const uintptr_t *)(fns + 1);
331
332 for (idx = 0; ((const uintptr_t *)fns + idx) < end; idx++) {
333 if (*((const uintptr_t *)fns + idx) == 0) {
334 DBG_ERR("VFS function at index %d not implemented "
335 "in module %s\n", idx, module);
336 missing_fn = true;
337 }
338 }
339
340 if (missing_fn) {
341 smb_panic("Required VFS function not implemented in module.\n");
342 }
343 }
344 #else
smb_vfs_assert_all_fns(const struct vfs_fn_pointers * fns,const char * module)345 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
346 const char *module)
347 {
348 }
349 #endif
350
351 /*****************************************************************
352 Generic VFS init.
353 ******************************************************************/
354
smbd_vfs_init(connection_struct * conn)355 bool smbd_vfs_init(connection_struct *conn)
356 {
357 const char **vfs_objects;
358 unsigned int i = 0;
359 int j = 0;
360
361 /* Normal share - initialise with disk access functions */
362 vfs_init_default(conn);
363
364 /* No need to load vfs modules for printer connections */
365 if (conn->printer) {
366 return True;
367 }
368
369 vfs_objects = lp_vfs_objects(SNUM(conn));
370
371 /* Override VFS functions if 'vfs object' was not specified*/
372 if (!vfs_objects || !vfs_objects[0])
373 return True;
374
375 for (i=0; vfs_objects[i] ;) {
376 i++;
377 }
378
379 for (j=i-1; j >= 0; j--) {
380 if (!vfs_init_custom(conn, vfs_objects[j])) {
381 DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j]));
382 return False;
383 }
384 }
385 return True;
386 }
387
388 /*******************************************************************
389 Check if a file exists in the vfs.
390 ********************************************************************/
391
vfs_file_exist(connection_struct * conn,struct smb_filename * smb_fname)392 NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
393 {
394 /* Only return OK if stat was successful and S_ISREG */
395 if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
396 S_ISREG(smb_fname->st.st_ex_mode)) {
397 return NT_STATUS_OK;
398 }
399
400 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
401 }
402
vfs_valid_pread_range(off_t offset,size_t length)403 bool vfs_valid_pread_range(off_t offset, size_t length)
404 {
405 return sys_valid_io_range(offset, length);
406 }
407
vfs_valid_pwrite_range(off_t offset,size_t length)408 bool vfs_valid_pwrite_range(off_t offset, size_t length)
409 {
410 /*
411 * See MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write
412 */
413 static const uint64_t maxfilesize = 0xfffffff0000;
414 uint64_t last_byte_ofs;
415 bool ok;
416
417 ok = sys_valid_io_range(offset, length);
418 if (!ok) {
419 return false;
420 }
421
422 if (length == 0) {
423 return true;
424 }
425
426 last_byte_ofs = offset + length;
427 if (last_byte_ofs > maxfilesize) {
428 return false;
429 }
430
431 return true;
432 }
433
vfs_pwrite_data(struct smb_request * req,files_struct * fsp,const char * buffer,size_t N,off_t offset)434 ssize_t vfs_pwrite_data(struct smb_request *req,
435 files_struct *fsp,
436 const char *buffer,
437 size_t N,
438 off_t offset)
439 {
440 size_t total=0;
441 ssize_t ret;
442 bool ok;
443
444 ok = vfs_valid_pwrite_range(offset, N);
445 if (!ok) {
446 errno = EINVAL;
447 return -1;
448 }
449
450 if (req && req->unread_bytes) {
451 int sockfd = req->xconn->transport.sock;
452 SMB_ASSERT(req->unread_bytes == N);
453 /* VFS_RECVFILE must drain the socket
454 * before returning. */
455 req->unread_bytes = 0;
456 /*
457 * Leave the socket non-blocking and
458 * use SMB_VFS_RECVFILE. If it returns
459 * EAGAIN || EWOULDBLOCK temporarily set
460 * the socket blocking and retry
461 * the RECVFILE.
462 */
463 while (total < N) {
464 ret = SMB_VFS_RECVFILE(sockfd,
465 fsp,
466 offset + total,
467 N - total);
468 if (ret == 0 || (ret == -1 &&
469 (errno == EAGAIN ||
470 errno == EWOULDBLOCK))) {
471 int old_flags;
472 /* Ensure the socket is blocking. */
473 old_flags = fcntl(sockfd, F_GETFL, 0);
474 if (set_blocking(sockfd, true) == -1) {
475 return (ssize_t)-1;
476 }
477 ret = SMB_VFS_RECVFILE(sockfd,
478 fsp,
479 offset + total,
480 N - total);
481 if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
482 return (ssize_t)-1;
483 }
484 if (ret == -1) {
485 return (ssize_t)-1;
486 }
487 total += ret;
488 return (ssize_t)total;
489 }
490 /* Any other error case. */
491 if (ret == -1) {
492 return ret;
493 }
494 total += ret;
495 }
496 return (ssize_t)total;
497 }
498
499 while (total < N) {
500 ret = SMB_VFS_PWRITE(fsp, buffer + total, N - total,
501 offset + total);
502
503 if (ret == -1)
504 return -1;
505 if (ret == 0)
506 return total;
507
508 total += ret;
509 }
510 return (ssize_t)total;
511 }
512 /****************************************************************************
513 An allocate file space call using the vfs interface.
514 Allocates space for a file from a filedescriptor.
515 Returns 0 on success, -1 on failure.
516 ****************************************************************************/
517
vfs_allocate_file_space(files_struct * fsp,uint64_t len)518 int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
519 {
520 int ret;
521 connection_struct *conn = fsp->conn;
522 uint64_t space_avail;
523 uint64_t bsize,dfree,dsize;
524 NTSTATUS status;
525 bool ok;
526
527 /*
528 * Actually try and commit the space on disk....
529 */
530
531 DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
532 fsp_str_dbg(fsp), (double)len));
533
534 ok = vfs_valid_pwrite_range((off_t)len, 0);
535 if (!ok) {
536 DEBUG(0,("vfs_allocate_file_space: %s negative/invalid 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 ret = SMB_VFS_FTRUNCATE(fsp, (off_t)len);
560
561 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
562
563 return ret;
564 }
565
566 /* Grow - we need to test if we have enough space. */
567
568 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_GROW);
569
570 if (lp_strict_allocate(SNUM(fsp->conn))) {
571 /* See if we have a syscall that will allocate beyond
572 end-of-file without changing EOF. */
573 ret = SMB_VFS_FALLOCATE(fsp, VFS_FALLOCATE_FL_KEEP_SIZE,
574 0, len);
575 } else {
576 ret = 0;
577 }
578
579 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_ALLOC_GROW);
580
581 if (ret == 0) {
582 /* We changed the allocation size on disk, but not
583 EOF - exactly as required. We're done ! */
584 return 0;
585 }
586
587 if (ret == -1 && errno == ENOSPC) {
588 return -1;
589 }
590
591 len -= fsp->fsp_name->st.st_ex_size;
592 len /= 1024; /* Len is now number of 1k blocks needed. */
593 space_avail =
594 get_dfree_info(conn, fsp->fsp_name, &bsize, &dfree, &dsize);
595 if (space_avail == (uint64_t)-1) {
596 return -1;
597 }
598
599 DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
600 "needed blocks = %.0f, space avail = %.0f\n",
601 fsp_str_dbg(fsp), (double)fsp->fsp_name->st.st_ex_size, (double)len,
602 (double)space_avail));
603
604 if (len > space_avail) {
605 errno = ENOSPC;
606 return -1;
607 }
608
609 return 0;
610 }
611
612 /****************************************************************************
613 A vfs set_filelen call.
614 set the length of a file from a filedescriptor.
615 Returns 0 on success, -1 on failure.
616 ****************************************************************************/
617
vfs_set_filelen(files_struct * fsp,off_t len)618 int vfs_set_filelen(files_struct *fsp, off_t len)
619 {
620 int ret;
621 bool ok;
622
623 ok = vfs_valid_pwrite_range(len, 0);
624 if (!ok) {
625 errno = EINVAL;
626 return -1;
627 }
628
629 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
630
631 DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
632 fsp_str_dbg(fsp), (double)len));
633 if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
634 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
635 FILE_NOTIFY_CHANGE_SIZE
636 | FILE_NOTIFY_CHANGE_ATTRIBUTES,
637 fsp->fsp_name->base_name);
638 }
639
640 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
641
642 return ret;
643 }
644
645 /****************************************************************************
646 A slow version of fallocate. Fallback code if SMB_VFS_FALLOCATE
647 fails. Needs to be outside of the default version of SMB_VFS_FALLOCATE
648 as this is also called from the default SMB_VFS_FTRUNCATE code.
649 Always extends the file size.
650 Returns 0 on success, -1 on failure.
651 ****************************************************************************/
652
653 #define SPARSE_BUF_WRITE_SIZE (32*1024)
654
vfs_slow_fallocate(files_struct * fsp,off_t offset,off_t len)655 int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len)
656 {
657 ssize_t pwrite_ret;
658 size_t total = 0;
659 bool ok;
660
661 ok = vfs_valid_pwrite_range(offset, len);
662 if (!ok) {
663 errno = EINVAL;
664 return -1;
665 }
666
667 if (!sparse_buf) {
668 sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE);
669 if (!sparse_buf) {
670 errno = ENOMEM;
671 return -1;
672 }
673 }
674
675 while (total < len) {
676 size_t curr_write_size = MIN(SPARSE_BUF_WRITE_SIZE, (len - total));
677
678 pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
679 if (pwrite_ret == -1) {
680 int saved_errno = errno;
681 DEBUG(10,("vfs_slow_fallocate: SMB_VFS_PWRITE for file "
682 "%s failed with error %s\n",
683 fsp_str_dbg(fsp), strerror(saved_errno)));
684 errno = saved_errno;
685 return -1;
686 }
687 total += pwrite_ret;
688 }
689
690 return 0;
691 }
692
693 /****************************************************************************
694 A vfs fill sparse call.
695 Writes zeros from the end of file to len, if len is greater than EOF.
696 Used only by strict_sync.
697 Returns 0 on success, -1 on failure.
698 ****************************************************************************/
699
vfs_fill_sparse(files_struct * fsp,off_t len)700 int vfs_fill_sparse(files_struct *fsp, off_t len)
701 {
702 int ret;
703 NTSTATUS status;
704 off_t offset;
705 size_t num_to_write;
706 bool ok;
707
708 ok = vfs_valid_pwrite_range(len, 0);
709 if (!ok) {
710 errno = EINVAL;
711 return -1;
712 }
713
714 status = vfs_stat_fsp(fsp);
715 if (!NT_STATUS_IS_OK(status)) {
716 return -1;
717 }
718
719 if (len <= fsp->fsp_name->st.st_ex_size) {
720 return 0;
721 }
722
723 #ifdef S_ISFIFO
724 if (S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) {
725 return 0;
726 }
727 #endif
728
729 DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
730 "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
731 (double)fsp->fsp_name->st.st_ex_size, (double)len,
732 (double)(len - fsp->fsp_name->st.st_ex_size)));
733
734 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
735
736 offset = fsp->fsp_name->st.st_ex_size;
737 num_to_write = len - fsp->fsp_name->st.st_ex_size;
738
739 /* Only do this on non-stream file handles. */
740 if (fsp->base_fsp == NULL) {
741 /* for allocation try fallocate first. This can fail on some
742 * platforms e.g. when the filesystem doesn't support it and no
743 * emulation is being done by the libc (like on AIX with JFS1). In that
744 * case we do our own emulation. fallocate implementations can
745 * return ENOTSUP or EINVAL in cases like that. */
746 ret = SMB_VFS_FALLOCATE(fsp, 0, offset, num_to_write);
747 if (ret == -1 && errno == ENOSPC) {
748 goto out;
749 }
750 if (ret == 0) {
751 goto out;
752 }
753 DEBUG(10,("vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
754 "error %d. Falling back to slow manual allocation\n", ret));
755 }
756
757 ret = vfs_slow_fallocate(fsp, offset, num_to_write);
758
759 out:
760
761 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_FILL_SPARSE);
762 return ret;
763 }
764
765 /*******************************************************************************
766 Set a fd into blocking/nonblocking mode through VFS
767 *******************************************************************************/
768
vfs_set_blocking(files_struct * fsp,bool set)769 int vfs_set_blocking(files_struct *fsp, bool set)
770 {
771 int val;
772 #ifdef O_NONBLOCK
773 #define FLAG_TO_SET O_NONBLOCK
774 #else
775 #ifdef SYSV
776 #define FLAG_TO_SET O_NDELAY
777 #else /* BSD */
778 #define FLAG_TO_SET FNDELAY
779 #endif
780 #endif
781 val = SMB_VFS_FCNTL(fsp, F_GETFL, 0);
782 if (val == -1) {
783 return -1;
784 }
785
786 if (set) {
787 val &= ~FLAG_TO_SET;
788 } else {
789 val |= FLAG_TO_SET;
790 }
791
792 return SMB_VFS_FCNTL(fsp, F_SETFL, val);
793 #undef FLAG_TO_SET
794 }
795
796 /****************************************************************************
797 Transfer some data (n bytes) between two file_struct's.
798 ****************************************************************************/
799
vfs_pread_fn(void * file,void * buf,size_t len,off_t offset)800 static ssize_t vfs_pread_fn(void *file, void *buf, size_t len, off_t offset)
801 {
802 struct files_struct *fsp = (struct files_struct *)file;
803
804 return SMB_VFS_PREAD(fsp, buf, len, offset);
805 }
806
vfs_pwrite_fn(void * file,const void * buf,size_t len,off_t offset)807 static ssize_t vfs_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
808 {
809 struct files_struct *fsp = (struct files_struct *)file;
810
811 return SMB_VFS_PWRITE(fsp, buf, len, offset);
812 }
813
vfs_transfer_file(files_struct * in,files_struct * out,off_t n)814 off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n)
815 {
816 return transfer_file_internal((void *)in, (void *)out, n,
817 vfs_pread_fn, vfs_pwrite_fn);
818 }
819
820 /*******************************************************************
821 A vfs_readdir wrapper which just returns the file name.
822 ********************************************************************/
823
vfs_readdirname(connection_struct * conn,void * p,SMB_STRUCT_STAT * sbuf,char ** talloced)824 const char *vfs_readdirname(connection_struct *conn, void *p,
825 SMB_STRUCT_STAT *sbuf, char **talloced)
826 {
827 struct dirent *ptr= NULL;
828 const char *dname;
829 char *translated;
830 NTSTATUS status;
831
832 if (!p)
833 return(NULL);
834
835 ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
836 if (!ptr)
837 return(NULL);
838
839 dname = ptr->d_name;
840
841
842 #ifdef NEXT2
843 if (telldir(p) < 0)
844 return(NULL);
845 #endif
846
847 #ifdef HAVE_BROKEN_READDIR_NAME
848 /* using /usr/ucb/cc is BAD */
849 dname = dname - 2;
850 #endif
851
852 status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
853 talloc_tos(), &translated);
854 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
855 *talloced = NULL;
856 return dname;
857 }
858 *talloced = translated;
859 if (!NT_STATUS_IS_OK(status)) {
860 return NULL;
861 }
862 return translated;
863 }
864
865 /*******************************************************************
866 A wrapper for vfs_chdir().
867 ********************************************************************/
868
vfs_ChDir(connection_struct * conn,const struct smb_filename * smb_fname)869 int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
870 {
871 int ret;
872 struct smb_filename *cwd = NULL;
873
874 if (!LastDir) {
875 LastDir = SMB_STRDUP("");
876 }
877
878 if (ISDOT(smb_fname->base_name)) {
879 /*
880 * passing a '.' is a noop,
881 * and we only expect this after
882 * everything is initialized.
883 *
884 * So the first vfs_ChDir() on a given
885 * connection_struct must not be '.'.
886 *
887 * Note: conn_new() sets
888 * conn->cwd_fsp->fh->fd = -1
889 * and vfs_ChDir() leaves with
890 * conn->cwd_fsp->fh->fd = AT_FDCWD
891 * on success!
892 */
893 if (conn->cwd_fsp->fh->fd != AT_FDCWD) {
894 /*
895 * This should never happen and
896 * we might change this to
897 * SMB_ASSERT() in future.
898 */
899 DBG_ERR("Called with '.' as first operation!\n");
900 log_stack_trace();
901 errno = EINVAL;
902 return -1;
903 }
904 return 0;
905 }
906
907 if (smb_fname->base_name[0] == '/' &&
908 strcsequal(LastDir,smb_fname->base_name))
909 {
910 /*
911 * conn->cwd_fsp->fsp_name and the kernel
912 * are already correct, but conn->cwd_fsp->fh->fd
913 * might still be -1 as initialized in conn_new().
914 *
915 * This can happen when a client made a 2nd
916 * tree connect to a share with the same underlying
917 * path (may or may not the same share).
918 */
919 conn->cwd_fsp->fh->fd = AT_FDCWD;
920 return 0;
921 }
922
923 DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
924
925 ret = SMB_VFS_CHDIR(conn, smb_fname);
926 if (ret != 0) {
927 return -1;
928 }
929
930 /*
931 * Always replace conn->cwd_fsp. We
932 * don't know if it's been modified by
933 * VFS modules in the stack.
934 */
935
936 /* conn cache. */
937 cwd = vfs_GetWd(conn, conn);
938 if (cwd == NULL) {
939 /*
940 * vfs_GetWd() failed.
941 * We must be able to read cwd.
942 * Return to original directory
943 * and return -1.
944 */
945 int saved_errno = errno;
946
947 if (conn->cwd_fsp->fsp_name == NULL) {
948 /*
949 * Failed on the very first chdir()+getwd()
950 * for this connection. We can't
951 * continue.
952 */
953 smb_panic("conn->cwd getwd failed\n");
954 /* NOTREACHED */
955 return -1;
956 }
957
958 /* Return to the previous $cwd. */
959 ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name);
960 if (ret != 0) {
961 smb_panic("conn->cwd getwd failed\n");
962 /* NOTREACHED */
963 return -1;
964 }
965 errno = saved_errno;
966 /* And fail the chdir(). */
967 return -1;
968 }
969
970 /* vfs_GetWd() succeeded. */
971 /* Replace global cache. */
972 SAFE_FREE(LastDir);
973 LastDir = SMB_STRDUP(smb_fname->base_name);
974
975 /*
976 * (Indirect) Callers of vfs_ChDir() may still hold references to the
977 * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way
978 * callers can use it for the lifetime of the SMB request.
979 */
980 talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name);
981
982 conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd);
983 conn->cwd_fsp->fh->fd = AT_FDCWD;
984
985 DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp));
986
987 return ret;
988 }
989
990 /*******************************************************************
991 Return the absolute current directory path - given a UNIX pathname.
992 Note that this path is returned in DOS format, not UNIX
993 format. Note this can be called with conn == NULL.
994 ********************************************************************/
995
vfs_GetWd(TALLOC_CTX * ctx,connection_struct * conn)996 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
997 {
998 struct smb_filename *current_dir_fname = NULL;
999 struct file_id key;
1000 struct smb_filename *smb_fname_dot = NULL;
1001 struct smb_filename *smb_fname_full = NULL;
1002 struct smb_filename *result = NULL;
1003
1004 if (!lp_getwd_cache()) {
1005 goto nocache;
1006 }
1007
1008 smb_fname_dot = synthetic_smb_fname(ctx, ".", NULL, NULL, 0);
1009 if (smb_fname_dot == NULL) {
1010 errno = ENOMEM;
1011 goto out;
1012 }
1013
1014 if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
1015 /*
1016 * Known to fail for root: the directory may be NFS-mounted
1017 * and exported with root_squash (so has no root access).
1018 */
1019 DEBUG(1,("vfs_GetWd: couldn't stat \".\" error %s "
1020 "(NFS problem ?)\n", strerror(errno) ));
1021 goto nocache;
1022 }
1023
1024 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1025
1026 smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
1027 smbd_memcache(),
1028 GETWD_CACHE,
1029 data_blob_const(&key, sizeof(key)));
1030
1031 if (smb_fname_full == NULL) {
1032 goto nocache;
1033 }
1034
1035 if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
1036 (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
1037 (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
1038 (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
1039 /*
1040 * Ok, we're done
1041 * Note: smb_fname_full is owned by smbd_memcache()
1042 * so we must make a copy to return.
1043 */
1044 result = cp_smb_filename(ctx, smb_fname_full);
1045 if (result == NULL) {
1046 errno = ENOMEM;
1047 }
1048 goto out;
1049 }
1050
1051 nocache:
1052
1053 /*
1054 * We don't have the information to hand so rely on traditional
1055 * methods. The very slow getcwd, which spawns a process on some
1056 * systems, or the not quite so bad getwd.
1057 */
1058
1059 current_dir_fname = SMB_VFS_GETWD(conn, ctx);
1060 if (current_dir_fname == NULL) {
1061 DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
1062 strerror(errno)));
1063 goto out;
1064 }
1065
1066 if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
1067 key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
1068
1069 /*
1070 * smbd_memcache() will own current_dir_fname after the
1071 * memcache_add_talloc call, so we must make
1072 * a copy on ctx to return.
1073 */
1074 result = cp_smb_filename(ctx, current_dir_fname);
1075 if (result == NULL) {
1076 errno = ENOMEM;
1077 }
1078
1079 /*
1080 * Ensure the memory going into the cache
1081 * doesn't have a destructor so it can be
1082 * cleanly freed.
1083 */
1084 talloc_set_destructor(current_dir_fname, NULL);
1085
1086 memcache_add_talloc(smbd_memcache(),
1087 GETWD_CACHE,
1088 data_blob_const(&key, sizeof(key)),
1089 ¤t_dir_fname);
1090 /* current_dir_fname is now == NULL here. */
1091 } else {
1092 /* current_dir_fname is already allocated on ctx. */
1093 result = current_dir_fname;
1094 }
1095
1096 out:
1097 TALLOC_FREE(smb_fname_dot);
1098 /*
1099 * Don't free current_dir_fname here. It's either been moved
1100 * to the memcache or is being returned in result.
1101 */
1102 return result;
1103 }
1104
1105 /*******************************************************************
1106 Reduce a file name, removing .. elements and checking that
1107 it is below dir in the hierarchy. This uses realpath.
1108 This function must run as root, and will return names
1109 and valid stat structs that can be checked on open.
1110 ********************************************************************/
1111
check_reduced_name_with_privilege(connection_struct * conn,const struct smb_filename * smb_fname,struct smb_request * smbreq)1112 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
1113 const struct smb_filename *smb_fname,
1114 struct smb_request *smbreq)
1115 {
1116 NTSTATUS status;
1117 TALLOC_CTX *ctx = talloc_tos();
1118 const char *conn_rootdir;
1119 size_t rootdir_len;
1120 char *dir_name = NULL;
1121 char *resolved_name = NULL;
1122 const char *last_component = NULL;
1123 struct smb_filename *resolved_fname = NULL;
1124 struct smb_filename *saved_dir_fname = NULL;
1125 struct smb_filename *smb_fname_cwd = NULL;
1126 struct privilege_paths *priv_paths = NULL;
1127 int ret;
1128
1129 DEBUG(3,("check_reduced_name_with_privilege [%s] [%s]\n",
1130 smb_fname->base_name,
1131 conn->connectpath));
1132
1133
1134 priv_paths = talloc_zero(smbreq, struct privilege_paths);
1135 if (!priv_paths) {
1136 status = NT_STATUS_NO_MEMORY;
1137 goto err;
1138 }
1139
1140 if (!parent_dirname(ctx, smb_fname->base_name,
1141 &dir_name, &last_component)) {
1142 status = NT_STATUS_NO_MEMORY;
1143 goto err;
1144 }
1145
1146 priv_paths->parent_name.base_name = talloc_strdup(priv_paths, dir_name);
1147 priv_paths->file_name.base_name = talloc_strdup(priv_paths, last_component);
1148
1149 if (priv_paths->parent_name.base_name == NULL ||
1150 priv_paths->file_name.base_name == NULL) {
1151 status = NT_STATUS_NO_MEMORY;
1152 goto err;
1153 }
1154
1155 if (SMB_VFS_STAT(conn, &priv_paths->parent_name) != 0) {
1156 status = map_nt_error_from_unix(errno);
1157 goto err;
1158 }
1159 /* Remember where we were. */
1160 saved_dir_fname = vfs_GetWd(ctx, conn);
1161 if (!saved_dir_fname) {
1162 status = map_nt_error_from_unix(errno);
1163 goto err;
1164 }
1165
1166 if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
1167 status = map_nt_error_from_unix(errno);
1168 goto err;
1169 }
1170
1171 smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
1172 if (smb_fname_cwd == NULL) {
1173 status = NT_STATUS_NO_MEMORY;
1174 goto err;
1175 }
1176
1177 /* Get the absolute path of the parent directory. */
1178 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
1179 if (resolved_fname == NULL) {
1180 status = map_nt_error_from_unix(errno);
1181 goto err;
1182 }
1183 resolved_name = resolved_fname->base_name;
1184
1185 if (*resolved_name != '/') {
1186 DEBUG(0,("check_reduced_name_with_privilege: realpath "
1187 "doesn't return absolute paths !\n"));
1188 status = NT_STATUS_OBJECT_NAME_INVALID;
1189 goto err;
1190 }
1191
1192 DEBUG(10,("check_reduced_name_with_privilege: realpath [%s] -> [%s]\n",
1193 priv_paths->parent_name.base_name,
1194 resolved_name));
1195
1196 /* Now check the stat value is the same. */
1197 if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
1198 status = map_nt_error_from_unix(errno);
1199 goto err;
1200 }
1201
1202 /* Ensure we're pointing at the same place. */
1203 if (!check_same_stat(&smb_fname_cwd->st, &priv_paths->parent_name.st)) {
1204 DEBUG(0,("check_reduced_name_with_privilege: "
1205 "device/inode/uid/gid on directory %s changed. "
1206 "Denying access !\n",
1207 priv_paths->parent_name.base_name));
1208 status = NT_STATUS_ACCESS_DENIED;
1209 goto err;
1210 }
1211
1212 /* Ensure we're below the connect path. */
1213
1214 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1215 if (conn_rootdir == NULL) {
1216 DEBUG(2, ("check_reduced_name_with_privilege: Could not get "
1217 "conn_rootdir\n"));
1218 status = NT_STATUS_ACCESS_DENIED;
1219 goto err;
1220 }
1221
1222 rootdir_len = strlen(conn_rootdir);
1223
1224 /*
1225 * In the case of rootdir_len == 1, we know that conn_rootdir is
1226 * "/", and we also know that resolved_name starts with a slash.
1227 * So, in this corner case, resolved_name is automatically a
1228 * sub-directory of the conn_rootdir. Thus we can skip the string
1229 * comparison and the next character checks (which are even
1230 * wrong in this case).
1231 */
1232 if (rootdir_len != 1) {
1233 bool matched;
1234
1235 matched = (strncmp(conn_rootdir, resolved_name,
1236 rootdir_len) == 0);
1237
1238 if (!matched || (resolved_name[rootdir_len] != '/' &&
1239 resolved_name[rootdir_len] != '\0')) {
1240 DEBUG(2, ("check_reduced_name_with_privilege: Bad "
1241 "access attempt: %s is a symlink outside the "
1242 "share path\n",
1243 dir_name));
1244 DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
1245 DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
1246 status = NT_STATUS_ACCESS_DENIED;
1247 goto err;
1248 }
1249 }
1250
1251 /* Now ensure that the last component either doesn't
1252 exist, or is *NOT* a symlink. */
1253
1254 ret = SMB_VFS_LSTAT(conn, &priv_paths->file_name);
1255 if (ret == -1) {
1256 /* Errno must be ENOENT for this be ok. */
1257 if (errno != ENOENT) {
1258 status = map_nt_error_from_unix(errno);
1259 DEBUG(2, ("check_reduced_name_with_privilege: "
1260 "LSTAT on %s failed with %s\n",
1261 priv_paths->file_name.base_name,
1262 nt_errstr(status)));
1263 goto err;
1264 }
1265 }
1266
1267 if (VALID_STAT(priv_paths->file_name.st) &&
1268 S_ISLNK(priv_paths->file_name.st.st_ex_mode)) {
1269 DEBUG(2, ("check_reduced_name_with_privilege: "
1270 "Last component %s is a symlink. Denying"
1271 "access.\n",
1272 priv_paths->file_name.base_name));
1273 status = NT_STATUS_ACCESS_DENIED;
1274 goto err;
1275 }
1276
1277 smbreq->priv_paths = priv_paths;
1278 status = NT_STATUS_OK;
1279
1280 err:
1281
1282 if (saved_dir_fname != NULL) {
1283 vfs_ChDir(conn, saved_dir_fname);
1284 TALLOC_FREE(saved_dir_fname);
1285 }
1286 TALLOC_FREE(resolved_fname);
1287 if (!NT_STATUS_IS_OK(status)) {
1288 TALLOC_FREE(priv_paths);
1289 }
1290 TALLOC_FREE(dir_name);
1291 return status;
1292 }
1293
1294 /*******************************************************************
1295 Reduce a file name, removing .. elements and checking that
1296 it is below dir in the hierarchy. This uses realpath.
1297
1298 If cwd_name == NULL then fname is a client given path relative
1299 to the root path of the share.
1300
1301 If cwd_name != NULL then fname is a client given path relative
1302 to cwd_name. cwd_name is relative to the root path of the share.
1303 ********************************************************************/
1304
check_reduced_name(connection_struct * conn,const struct smb_filename * cwd_fname,const struct smb_filename * smb_fname)1305 NTSTATUS check_reduced_name(connection_struct *conn,
1306 const struct smb_filename *cwd_fname,
1307 const struct smb_filename *smb_fname)
1308 {
1309 TALLOC_CTX *ctx = talloc_tos();
1310 const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
1311 const char *fname = smb_fname->base_name;
1312 struct smb_filename *resolved_fname;
1313 char *resolved_name = NULL;
1314 char *new_fname = NULL;
1315 bool allow_symlinks = true;
1316 bool allow_widelinks = false;
1317
1318 DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
1319
1320 resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
1321
1322 if (resolved_fname == NULL) {
1323 switch (errno) {
1324 case ENOTDIR:
1325 DEBUG(3,("check_reduced_name: Component not a "
1326 "directory in getting realpath for "
1327 "%s\n", fname));
1328 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1329 case ENOENT:
1330 {
1331 char *dir_name = NULL;
1332 struct smb_filename dir_fname = {0};
1333 const char *last_component = NULL;
1334
1335 /* Last component didn't exist.
1336 Remove it and try and canonicalise
1337 the directory name. */
1338 if (!parent_dirname(ctx, fname,
1339 &dir_name,
1340 &last_component)) {
1341 return NT_STATUS_NO_MEMORY;
1342 }
1343
1344 dir_fname = (struct smb_filename)
1345 { .base_name = dir_name };
1346 resolved_fname = SMB_VFS_REALPATH(conn,
1347 ctx,
1348 &dir_fname);
1349 if (resolved_fname == NULL) {
1350 NTSTATUS status = map_nt_error_from_unix(errno);
1351
1352 if (errno == ENOENT || errno == ENOTDIR) {
1353 status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1354 }
1355
1356 DEBUG(3,("check_reduce_name: "
1357 "couldn't get realpath for "
1358 "%s (%s)\n",
1359 fname,
1360 nt_errstr(status)));
1361 return status;
1362 }
1363 resolved_name = talloc_asprintf(ctx,
1364 "%s/%s",
1365 resolved_fname->base_name,
1366 last_component);
1367 if (resolved_name == NULL) {
1368 return NT_STATUS_NO_MEMORY;
1369 }
1370 break;
1371 }
1372 default:
1373 DEBUG(3,("check_reduced_name: couldn't get "
1374 "realpath for %s\n", fname));
1375 return map_nt_error_from_unix(errno);
1376 }
1377 } else {
1378 resolved_name = resolved_fname->base_name;
1379 }
1380
1381 DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
1382 resolved_name));
1383
1384 if (*resolved_name != '/') {
1385 DEBUG(0,("check_reduced_name: realpath doesn't return "
1386 "absolute paths !\n"));
1387 TALLOC_FREE(resolved_fname);
1388 return NT_STATUS_OBJECT_NAME_INVALID;
1389 }
1390
1391 allow_widelinks = lp_widelinks(SNUM(conn));
1392 allow_symlinks = lp_follow_symlinks(SNUM(conn));
1393
1394 /* Common widelinks and symlinks checks. */
1395 if (!allow_widelinks || !allow_symlinks) {
1396 const char *conn_rootdir;
1397 size_t rootdir_len;
1398
1399 conn_rootdir = SMB_VFS_CONNECTPATH(conn, smb_fname);
1400 if (conn_rootdir == NULL) {
1401 DEBUG(2, ("check_reduced_name: Could not get "
1402 "conn_rootdir\n"));
1403 TALLOC_FREE(resolved_fname);
1404 return NT_STATUS_ACCESS_DENIED;
1405 }
1406
1407 rootdir_len = strlen(conn_rootdir);
1408
1409 /*
1410 * In the case of rootdir_len == 1, we know that
1411 * conn_rootdir is "/", and we also know that
1412 * resolved_name starts with a slash. So, in this
1413 * corner case, resolved_name is automatically a
1414 * sub-directory of the conn_rootdir. Thus we can skip
1415 * the string comparison and the next character checks
1416 * (which are even wrong in this case).
1417 */
1418 if (rootdir_len != 1) {
1419 bool matched;
1420
1421 matched = (strncmp(conn_rootdir, resolved_name,
1422 rootdir_len) == 0);
1423 if (!matched || (resolved_name[rootdir_len] != '/' &&
1424 resolved_name[rootdir_len] != '\0')) {
1425 DEBUG(2, ("check_reduced_name: Bad access "
1426 "attempt: %s is a symlink outside the "
1427 "share path\n", fname));
1428 DEBUGADD(2, ("conn_rootdir =%s\n",
1429 conn_rootdir));
1430 DEBUGADD(2, ("resolved_name=%s\n",
1431 resolved_name));
1432 TALLOC_FREE(resolved_fname);
1433 return NT_STATUS_ACCESS_DENIED;
1434 }
1435 }
1436
1437 /* Extra checks if all symlinks are disallowed. */
1438 if (!allow_symlinks) {
1439 /* fname can't have changed in resolved_path. */
1440 const char *p = &resolved_name[rootdir_len];
1441
1442 /*
1443 * UNIX filesystem semantics, names consisting
1444 * only of "." or ".." CANNOT be symlinks.
1445 */
1446 if (ISDOT(fname) || ISDOTDOT(fname)) {
1447 goto out;
1448 }
1449
1450 if (*p != '/') {
1451 DEBUG(2, ("check_reduced_name: logic error (%c) "
1452 "in resolved_name: %s\n",
1453 *p,
1454 fname));
1455 TALLOC_FREE(resolved_fname);
1456 return NT_STATUS_ACCESS_DENIED;
1457 }
1458
1459 p++;
1460
1461 /*
1462 * If cwd_name is present and not ".",
1463 * then fname is relative to that, not
1464 * the root of the share. Make sure the
1465 * path we check is the one the client
1466 * sent (cwd_name+fname).
1467 */
1468 if (cwd_name != NULL && !ISDOT(cwd_name)) {
1469 new_fname = talloc_asprintf(ctx,
1470 "%s/%s",
1471 cwd_name,
1472 fname);
1473 if (new_fname == NULL) {
1474 TALLOC_FREE(resolved_fname);
1475 return NT_STATUS_NO_MEMORY;
1476 }
1477 fname = new_fname;
1478 }
1479
1480 if (strcmp(fname, p)!=0) {
1481 DEBUG(2, ("check_reduced_name: Bad access "
1482 "attempt: %s is a symlink to %s\n",
1483 fname, p));
1484 TALLOC_FREE(resolved_fname);
1485 TALLOC_FREE(new_fname);
1486 return NT_STATUS_ACCESS_DENIED;
1487 }
1488 }
1489 }
1490
1491 out:
1492
1493 DBG_INFO("%s reduced to %s\n", fname, resolved_name);
1494 TALLOC_FREE(resolved_fname);
1495 TALLOC_FREE(new_fname);
1496 return NT_STATUS_OK;
1497 }
1498
1499 /**
1500 * XXX: This is temporary and there should be no callers of this once
1501 * smb_filename is plumbed through all path based operations.
1502 *
1503 * Called when we know stream name parsing has already been done.
1504 */
vfs_stat_smb_basename(struct connection_struct * conn,const struct smb_filename * smb_fname_in,SMB_STRUCT_STAT * psbuf)1505 int vfs_stat_smb_basename(struct connection_struct *conn,
1506 const struct smb_filename *smb_fname_in,
1507 SMB_STRUCT_STAT *psbuf)
1508 {
1509 struct smb_filename smb_fname = {
1510 .base_name = discard_const_p(char, smb_fname_in->base_name),
1511 .flags = smb_fname_in->flags
1512 };
1513 int ret;
1514
1515 if (smb_fname.flags & SMB_FILENAME_POSIX_PATH) {
1516 ret = SMB_VFS_LSTAT(conn, &smb_fname);
1517 } else {
1518 ret = SMB_VFS_STAT(conn, &smb_fname);
1519 }
1520
1521 if (ret != -1) {
1522 *psbuf = smb_fname.st;
1523 }
1524 return ret;
1525 }
1526
1527 /**
1528 * Ensure LSTAT is called for POSIX paths.
1529 */
1530
vfs_stat_fsp(files_struct * fsp)1531 NTSTATUS vfs_stat_fsp(files_struct *fsp)
1532 {
1533 int ret;
1534 struct stat_ex saved_stat = fsp->fsp_name->st;
1535
1536 if(fsp->fh->fd == -1) {
1537 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1538 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
1539 } else {
1540 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
1541 }
1542 } else {
1543 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
1544 }
1545 if (ret == -1) {
1546 return map_nt_error_from_unix(errno);
1547 }
1548 update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat);
1549 return NT_STATUS_OK;
1550 }
1551
init_smb_file_time(struct smb_file_time * ft)1552 void init_smb_file_time(struct smb_file_time *ft)
1553 {
1554 *ft = (struct smb_file_time) {
1555 .atime = make_omit_timespec(),
1556 .ctime = make_omit_timespec(),
1557 .mtime = make_omit_timespec(),
1558 .create_time = make_omit_timespec()
1559 };
1560 }
1561
1562 /**
1563 * Initialize num_streams and streams, then call VFS op streaminfo
1564 */
vfs_streaminfo(connection_struct * conn,struct files_struct * fsp,const struct smb_filename * smb_fname,TALLOC_CTX * mem_ctx,unsigned int * num_streams,struct stream_struct ** streams)1565 NTSTATUS vfs_streaminfo(connection_struct *conn,
1566 struct files_struct *fsp,
1567 const struct smb_filename *smb_fname,
1568 TALLOC_CTX *mem_ctx,
1569 unsigned int *num_streams,
1570 struct stream_struct **streams)
1571 {
1572 *num_streams = 0;
1573 *streams = NULL;
1574 return SMB_VFS_STREAMINFO(conn,
1575 fsp,
1576 smb_fname,
1577 mem_ctx,
1578 num_streams,
1579 streams);
1580 }
1581
1582 /*
1583 * This is just a helper to make
1584 * users of vfs_fake_fd() more symetric
1585 */
vfs_fake_fd_close(int fd)1586 int vfs_fake_fd_close(int fd)
1587 {
1588 return close(fd);
1589 }
1590
1591 /*
1592 generate a file_id from a stat structure
1593 */
vfs_file_id_from_sbuf(connection_struct * conn,const SMB_STRUCT_STAT * sbuf)1594 struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
1595 {
1596 return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
1597 }
1598
smb_vfs_call_connect(struct vfs_handle_struct * handle,const char * service,const char * user)1599 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
1600 const char *service, const char *user)
1601 {
1602 VFS_FIND(connect);
1603 return handle->fns->connect_fn(handle, service, user);
1604 }
1605
smb_vfs_call_disconnect(struct vfs_handle_struct * handle)1606 void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
1607 {
1608 VFS_FIND(disconnect);
1609 handle->fns->disconnect_fn(handle);
1610 }
1611
smb_vfs_call_disk_free(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uint64_t * bsize,uint64_t * dfree,uint64_t * dsize)1612 uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
1613 const struct smb_filename *smb_fname,
1614 uint64_t *bsize,
1615 uint64_t *dfree,
1616 uint64_t *dsize)
1617 {
1618 VFS_FIND(disk_free);
1619 return handle->fns->disk_free_fn(handle, smb_fname,
1620 bsize, dfree, dsize);
1621 }
1622
smb_vfs_call_get_quota(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,enum SMB_QUOTA_TYPE qtype,unid_t id,SMB_DISK_QUOTA * qt)1623 int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
1624 const struct smb_filename *smb_fname,
1625 enum SMB_QUOTA_TYPE qtype,
1626 unid_t id,
1627 SMB_DISK_QUOTA *qt)
1628 {
1629 VFS_FIND(get_quota);
1630 return handle->fns->get_quota_fn(handle, smb_fname, qtype, id, qt);
1631 }
1632
smb_vfs_call_set_quota(struct vfs_handle_struct * handle,enum SMB_QUOTA_TYPE qtype,unid_t id,SMB_DISK_QUOTA * qt)1633 int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
1634 enum SMB_QUOTA_TYPE qtype, unid_t id,
1635 SMB_DISK_QUOTA *qt)
1636 {
1637 VFS_FIND(set_quota);
1638 return handle->fns->set_quota_fn(handle, qtype, id, qt);
1639 }
1640
smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct * handle,struct files_struct * fsp,struct shadow_copy_data * shadow_copy_data,bool labels)1641 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
1642 struct files_struct *fsp,
1643 struct shadow_copy_data *shadow_copy_data,
1644 bool labels)
1645 {
1646 VFS_FIND(get_shadow_copy_data);
1647 return handle->fns->get_shadow_copy_data_fn(handle, fsp,
1648 shadow_copy_data,
1649 labels);
1650 }
smb_vfs_call_statvfs(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,struct vfs_statvfs_struct * statbuf)1651 int smb_vfs_call_statvfs(struct vfs_handle_struct *handle,
1652 const struct smb_filename *smb_fname,
1653 struct vfs_statvfs_struct *statbuf)
1654 {
1655 VFS_FIND(statvfs);
1656 return handle->fns->statvfs_fn(handle, smb_fname, statbuf);
1657 }
1658
smb_vfs_call_fs_capabilities(struct vfs_handle_struct * handle,enum timestamp_set_resolution * p_ts_res)1659 uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
1660 enum timestamp_set_resolution *p_ts_res)
1661 {
1662 VFS_FIND(fs_capabilities);
1663 return handle->fns->fs_capabilities_fn(handle, p_ts_res);
1664 }
1665
smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct * handle,struct dfs_GetDFSReferral * r)1666 NTSTATUS smb_vfs_call_get_dfs_referrals(struct vfs_handle_struct *handle,
1667 struct dfs_GetDFSReferral *r)
1668 {
1669 VFS_FIND(get_dfs_referrals);
1670 return handle->fns->get_dfs_referrals_fn(handle, r);
1671 }
1672
smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,const struct referral * reflist,size_t referral_count)1673 NTSTATUS smb_vfs_call_create_dfs_pathat(struct vfs_handle_struct *handle,
1674 struct files_struct *dirfsp,
1675 const struct smb_filename *smb_fname,
1676 const struct referral *reflist,
1677 size_t referral_count)
1678 {
1679 VFS_FIND(create_dfs_pathat);
1680 return handle->fns->create_dfs_pathat_fn(handle,
1681 dirfsp,
1682 smb_fname,
1683 reflist,
1684 referral_count);
1685 }
1686
smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct files_struct * dirfsp,const struct smb_filename * smb_fname,struct referral ** ppreflist,size_t * preferral_count)1687 NTSTATUS smb_vfs_call_read_dfs_pathat(struct vfs_handle_struct *handle,
1688 TALLOC_CTX *mem_ctx,
1689 struct files_struct *dirfsp,
1690 const struct smb_filename *smb_fname,
1691 struct referral **ppreflist,
1692 size_t *preferral_count)
1693 {
1694 VFS_FIND(read_dfs_pathat);
1695 return handle->fns->read_dfs_pathat_fn(handle,
1696 mem_ctx,
1697 dirfsp,
1698 smb_fname,
1699 ppreflist,
1700 preferral_count);
1701 }
1702
smb_vfs_call_opendir(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * mask,uint32_t attributes)1703 DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
1704 const struct smb_filename *smb_fname,
1705 const char *mask,
1706 uint32_t attributes)
1707 {
1708 VFS_FIND(opendir);
1709 return handle->fns->opendir_fn(handle, smb_fname, mask, attributes);
1710 }
1711
smb_vfs_call_fdopendir(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * mask,uint32_t attributes)1712 DIR *smb_vfs_call_fdopendir(struct vfs_handle_struct *handle,
1713 struct files_struct *fsp,
1714 const char *mask,
1715 uint32_t attributes)
1716 {
1717 VFS_FIND(fdopendir);
1718 return handle->fns->fdopendir_fn(handle, fsp, mask, attributes);
1719 }
1720
smb_vfs_call_readdir(struct vfs_handle_struct * handle,DIR * dirp,SMB_STRUCT_STAT * sbuf)1721 struct dirent *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
1722 DIR *dirp,
1723 SMB_STRUCT_STAT *sbuf)
1724 {
1725 VFS_FIND(readdir);
1726 return handle->fns->readdir_fn(handle, dirp, sbuf);
1727 }
1728
smb_vfs_call_seekdir(struct vfs_handle_struct * handle,DIR * dirp,long offset)1729 void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
1730 DIR *dirp, long offset)
1731 {
1732 VFS_FIND(seekdir);
1733 handle->fns->seekdir_fn(handle, dirp, offset);
1734 }
1735
smb_vfs_call_telldir(struct vfs_handle_struct * handle,DIR * dirp)1736 long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
1737 DIR *dirp)
1738 {
1739 VFS_FIND(telldir);
1740 return handle->fns->telldir_fn(handle, dirp);
1741 }
1742
smb_vfs_call_rewind_dir(struct vfs_handle_struct * handle,DIR * dirp)1743 void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
1744 DIR *dirp)
1745 {
1746 VFS_FIND(rewind_dir);
1747 handle->fns->rewind_dir_fn(handle, dirp);
1748 }
1749
smb_vfs_call_mkdirat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,mode_t mode)1750 int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle,
1751 struct files_struct *dirfsp,
1752 const struct smb_filename *smb_fname,
1753 mode_t mode)
1754 {
1755 VFS_FIND(mkdirat);
1756 return handle->fns->mkdirat_fn(handle,
1757 dirfsp,
1758 smb_fname,
1759 mode);
1760 }
1761
smb_vfs_call_closedir(struct vfs_handle_struct * handle,DIR * dir)1762 int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
1763 DIR *dir)
1764 {
1765 VFS_FIND(closedir);
1766 return handle->fns->closedir_fn(handle, dir);
1767 }
1768
smb_vfs_call_open(struct vfs_handle_struct * handle,struct smb_filename * smb_fname,struct files_struct * fsp,int flags,mode_t mode)1769 int smb_vfs_call_open(struct vfs_handle_struct *handle,
1770 struct smb_filename *smb_fname, struct files_struct *fsp,
1771 int flags, mode_t mode)
1772 {
1773 VFS_FIND(open);
1774 return handle->fns->open_fn(handle, smb_fname, fsp, flags, mode);
1775 }
1776
smb_vfs_call_create_file(struct vfs_handle_struct * handle,struct smb_request * req,uint16_t root_dir_fid,struct smb_filename * smb_fname,uint32_t access_mask,uint32_t share_access,uint32_t create_disposition,uint32_t create_options,uint32_t file_attributes,uint32_t oplock_request,const struct smb2_lease * lease,uint64_t allocation_size,uint32_t private_flags,struct security_descriptor * sd,struct ea_list * ea_list,files_struct ** result,int * pinfo,const struct smb2_create_blobs * in_context_blobs,struct smb2_create_blobs * out_context_blobs)1777 NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
1778 struct smb_request *req,
1779 uint16_t root_dir_fid,
1780 struct smb_filename *smb_fname,
1781 uint32_t access_mask,
1782 uint32_t share_access,
1783 uint32_t create_disposition,
1784 uint32_t create_options,
1785 uint32_t file_attributes,
1786 uint32_t oplock_request,
1787 const struct smb2_lease *lease,
1788 uint64_t allocation_size,
1789 uint32_t private_flags,
1790 struct security_descriptor *sd,
1791 struct ea_list *ea_list,
1792 files_struct **result,
1793 int *pinfo,
1794 const struct smb2_create_blobs *in_context_blobs,
1795 struct smb2_create_blobs *out_context_blobs)
1796 {
1797 VFS_FIND(create_file);
1798 return handle->fns->create_file_fn(
1799 handle, req, root_dir_fid, smb_fname, access_mask,
1800 share_access, create_disposition, create_options,
1801 file_attributes, oplock_request, lease, allocation_size,
1802 private_flags, sd, ea_list,
1803 result, pinfo, in_context_blobs, out_context_blobs);
1804 }
1805
smb_vfs_call_close(struct vfs_handle_struct * handle,struct files_struct * fsp)1806 int smb_vfs_call_close(struct vfs_handle_struct *handle,
1807 struct files_struct *fsp)
1808 {
1809 VFS_FIND(close);
1810 return handle->fns->close_fn(handle, fsp);
1811 }
1812
smb_vfs_call_pread(struct vfs_handle_struct * handle,struct files_struct * fsp,void * data,size_t n,off_t offset)1813 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
1814 struct files_struct *fsp, void *data, size_t n,
1815 off_t offset)
1816 {
1817 VFS_FIND(pread);
1818 return handle->fns->pread_fn(handle, fsp, data, n, offset);
1819 }
1820
1821 struct smb_vfs_call_pread_state {
1822 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1823 ssize_t retval;
1824 struct vfs_aio_state vfs_aio_state;
1825 };
1826
1827 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
1828
smb_vfs_call_pread_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct files_struct * fsp,void * data,size_t n,off_t offset)1829 struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
1830 TALLOC_CTX *mem_ctx,
1831 struct tevent_context *ev,
1832 struct files_struct *fsp,
1833 void *data,
1834 size_t n, off_t offset)
1835 {
1836 struct tevent_req *req, *subreq;
1837 struct smb_vfs_call_pread_state *state;
1838
1839 req = tevent_req_create(mem_ctx, &state,
1840 struct smb_vfs_call_pread_state);
1841 if (req == NULL) {
1842 return NULL;
1843 }
1844 VFS_FIND(pread_send);
1845 state->recv_fn = handle->fns->pread_recv_fn;
1846
1847 subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
1848 offset);
1849 if (tevent_req_nomem(subreq, req)) {
1850 return tevent_req_post(req, ev);
1851 }
1852 tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
1853 return req;
1854 }
1855
smb_vfs_call_pread_done(struct tevent_req * subreq)1856 static void smb_vfs_call_pread_done(struct tevent_req *subreq)
1857 {
1858 struct tevent_req *req = tevent_req_callback_data(
1859 subreq, struct tevent_req);
1860 struct smb_vfs_call_pread_state *state = tevent_req_data(
1861 req, struct smb_vfs_call_pread_state);
1862
1863 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1864 TALLOC_FREE(subreq);
1865 if (state->retval == -1) {
1866 tevent_req_error(req, state->vfs_aio_state.error);
1867 return;
1868 }
1869 tevent_req_done(req);
1870 }
1871
SMB_VFS_PREAD_RECV(struct tevent_req * req,struct vfs_aio_state * vfs_aio_state)1872 ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
1873 struct vfs_aio_state *vfs_aio_state)
1874 {
1875 struct smb_vfs_call_pread_state *state = tevent_req_data(
1876 req, struct smb_vfs_call_pread_state);
1877 ssize_t retval;
1878
1879 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1880 tevent_req_received(req);
1881 return -1;
1882 }
1883 *vfs_aio_state = state->vfs_aio_state;
1884 retval = state->retval;
1885 tevent_req_received(req);
1886 return retval;
1887 }
1888
smb_vfs_call_pwrite(struct vfs_handle_struct * handle,struct files_struct * fsp,const void * data,size_t n,off_t offset)1889 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
1890 struct files_struct *fsp, const void *data,
1891 size_t n, off_t offset)
1892 {
1893 VFS_FIND(pwrite);
1894 return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
1895 }
1896
1897 struct smb_vfs_call_pwrite_state {
1898 ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
1899 ssize_t retval;
1900 struct vfs_aio_state vfs_aio_state;
1901 };
1902
1903 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
1904
smb_vfs_call_pwrite_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct files_struct * fsp,const void * data,size_t n,off_t offset)1905 struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
1906 TALLOC_CTX *mem_ctx,
1907 struct tevent_context *ev,
1908 struct files_struct *fsp,
1909 const void *data,
1910 size_t n, off_t offset)
1911 {
1912 struct tevent_req *req, *subreq;
1913 struct smb_vfs_call_pwrite_state *state;
1914
1915 req = tevent_req_create(mem_ctx, &state,
1916 struct smb_vfs_call_pwrite_state);
1917 if (req == NULL) {
1918 return NULL;
1919 }
1920 VFS_FIND(pwrite_send);
1921 state->recv_fn = handle->fns->pwrite_recv_fn;
1922
1923 subreq = handle->fns->pwrite_send_fn(handle, state, ev, fsp, data, n,
1924 offset);
1925 if (tevent_req_nomem(subreq, req)) {
1926 return tevent_req_post(req, ev);
1927 }
1928 tevent_req_set_callback(subreq, smb_vfs_call_pwrite_done, req);
1929 return req;
1930 }
1931
smb_vfs_call_pwrite_done(struct tevent_req * subreq)1932 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
1933 {
1934 struct tevent_req *req = tevent_req_callback_data(
1935 subreq, struct tevent_req);
1936 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1937 req, struct smb_vfs_call_pwrite_state);
1938
1939 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
1940 TALLOC_FREE(subreq);
1941 if (state->retval == -1) {
1942 tevent_req_error(req, state->vfs_aio_state.error);
1943 return;
1944 }
1945 tevent_req_done(req);
1946 }
1947
SMB_VFS_PWRITE_RECV(struct tevent_req * req,struct vfs_aio_state * vfs_aio_state)1948 ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
1949 struct vfs_aio_state *vfs_aio_state)
1950 {
1951 struct smb_vfs_call_pwrite_state *state = tevent_req_data(
1952 req, struct smb_vfs_call_pwrite_state);
1953 ssize_t retval;
1954
1955 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1956 tevent_req_received(req);
1957 return -1;
1958 }
1959 *vfs_aio_state = state->vfs_aio_state;
1960 retval = state->retval;
1961 tevent_req_received(req);
1962 return retval;
1963 }
1964
smb_vfs_call_lseek(struct vfs_handle_struct * handle,struct files_struct * fsp,off_t offset,int whence)1965 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
1966 struct files_struct *fsp, off_t offset,
1967 int whence)
1968 {
1969 VFS_FIND(lseek);
1970 return handle->fns->lseek_fn(handle, fsp, offset, whence);
1971 }
1972
smb_vfs_call_sendfile(struct vfs_handle_struct * handle,int tofd,files_struct * fromfsp,const DATA_BLOB * header,off_t offset,size_t count)1973 ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
1974 files_struct *fromfsp, const DATA_BLOB *header,
1975 off_t offset, size_t count)
1976 {
1977 VFS_FIND(sendfile);
1978 return handle->fns->sendfile_fn(handle, tofd, fromfsp, header, offset,
1979 count);
1980 }
1981
smb_vfs_call_recvfile(struct vfs_handle_struct * handle,int fromfd,files_struct * tofsp,off_t offset,size_t count)1982 ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
1983 files_struct *tofsp, off_t offset,
1984 size_t count)
1985 {
1986 VFS_FIND(recvfile);
1987 return handle->fns->recvfile_fn(handle, fromfd, tofsp, offset, count);
1988 }
1989
smb_vfs_call_renameat(struct vfs_handle_struct * handle,files_struct * srcfsp,const struct smb_filename * smb_fname_src,files_struct * dstfsp,const struct smb_filename * smb_fname_dst)1990 int smb_vfs_call_renameat(struct vfs_handle_struct *handle,
1991 files_struct *srcfsp,
1992 const struct smb_filename *smb_fname_src,
1993 files_struct *dstfsp,
1994 const struct smb_filename *smb_fname_dst)
1995 {
1996 VFS_FIND(renameat);
1997 return handle->fns->renameat_fn(handle,
1998 srcfsp,
1999 smb_fname_src,
2000 dstfsp,
2001 smb_fname_dst);
2002 }
2003
2004 struct smb_vfs_call_fsync_state {
2005 int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
2006 int retval;
2007 struct vfs_aio_state vfs_aio_state;
2008 };
2009
2010 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
2011
smb_vfs_call_fsync_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct files_struct * fsp)2012 struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
2013 TALLOC_CTX *mem_ctx,
2014 struct tevent_context *ev,
2015 struct files_struct *fsp)
2016 {
2017 struct tevent_req *req, *subreq;
2018 struct smb_vfs_call_fsync_state *state;
2019
2020 req = tevent_req_create(mem_ctx, &state,
2021 struct smb_vfs_call_fsync_state);
2022 if (req == NULL) {
2023 return NULL;
2024 }
2025 VFS_FIND(fsync_send);
2026 state->recv_fn = handle->fns->fsync_recv_fn;
2027
2028 subreq = handle->fns->fsync_send_fn(handle, state, ev, fsp);
2029 if (tevent_req_nomem(subreq, req)) {
2030 return tevent_req_post(req, ev);
2031 }
2032 tevent_req_set_callback(subreq, smb_vfs_call_fsync_done, req);
2033 return req;
2034 }
2035
smb_vfs_call_fsync_done(struct tevent_req * subreq)2036 static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
2037 {
2038 struct tevent_req *req = tevent_req_callback_data(
2039 subreq, struct tevent_req);
2040 struct smb_vfs_call_fsync_state *state = tevent_req_data(
2041 req, struct smb_vfs_call_fsync_state);
2042
2043 state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
2044 TALLOC_FREE(subreq);
2045 if (state->retval == -1) {
2046 tevent_req_error(req, state->vfs_aio_state.error);
2047 return;
2048 }
2049 tevent_req_done(req);
2050 }
2051
SMB_VFS_FSYNC_RECV(struct tevent_req * req,struct vfs_aio_state * vfs_aio_state)2052 int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
2053 {
2054 struct smb_vfs_call_fsync_state *state = tevent_req_data(
2055 req, struct smb_vfs_call_fsync_state);
2056 ssize_t retval;
2057
2058 if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
2059 tevent_req_received(req);
2060 return -1;
2061 }
2062 *vfs_aio_state = state->vfs_aio_state;
2063 retval = state->retval;
2064 tevent_req_received(req);
2065 return retval;
2066 }
2067
2068 /*
2069 * Synchronous version of fsync, built from backend
2070 * async VFS primitives. Uses a temporary sub-event
2071 * context (NOT NESTED).
2072 */
2073
smb_vfs_fsync_sync(files_struct * fsp)2074 int smb_vfs_fsync_sync(files_struct *fsp)
2075 {
2076 TALLOC_CTX *frame = talloc_stackframe();
2077 struct tevent_req *req = NULL;
2078 struct vfs_aio_state aio_state = { 0 };
2079 int ret = -1;
2080 bool ok;
2081 struct tevent_context *ev = samba_tevent_context_init(frame);
2082
2083 if (ev == NULL) {
2084 goto out;
2085 }
2086
2087 req = SMB_VFS_FSYNC_SEND(talloc_tos(), ev, fsp);
2088 if (req == NULL) {
2089 goto out;
2090 }
2091
2092 ok = tevent_req_poll(req, ev);
2093 if (!ok) {
2094 goto out;
2095 }
2096
2097 ret = SMB_VFS_FSYNC_RECV(req, &aio_state);
2098
2099 out:
2100
2101 TALLOC_FREE(frame);
2102 if (aio_state.error != 0) {
2103 errno = aio_state.error;
2104 }
2105 return ret;
2106 }
2107
smb_vfs_call_stat(struct vfs_handle_struct * handle,struct smb_filename * smb_fname)2108 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
2109 struct smb_filename *smb_fname)
2110 {
2111 VFS_FIND(stat);
2112 return handle->fns->stat_fn(handle, smb_fname);
2113 }
2114
smb_vfs_call_fstat(struct vfs_handle_struct * handle,struct files_struct * fsp,SMB_STRUCT_STAT * sbuf)2115 int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
2116 struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
2117 {
2118 VFS_FIND(fstat);
2119 return handle->fns->fstat_fn(handle, fsp, sbuf);
2120 }
2121
smb_vfs_call_lstat(struct vfs_handle_struct * handle,struct smb_filename * smb_filename)2122 int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
2123 struct smb_filename *smb_filename)
2124 {
2125 VFS_FIND(lstat);
2126 return handle->fns->lstat_fn(handle, smb_filename);
2127 }
2128
smb_vfs_call_get_alloc_size(struct vfs_handle_struct * handle,struct files_struct * fsp,const SMB_STRUCT_STAT * sbuf)2129 uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
2130 struct files_struct *fsp,
2131 const SMB_STRUCT_STAT *sbuf)
2132 {
2133 VFS_FIND(get_alloc_size);
2134 return handle->fns->get_alloc_size_fn(handle, fsp, sbuf);
2135 }
2136
smb_vfs_call_unlinkat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,int flags)2137 int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
2138 struct files_struct *dirfsp,
2139 const struct smb_filename *smb_fname,
2140 int flags)
2141 {
2142 VFS_FIND(unlinkat);
2143 return handle->fns->unlinkat_fn(handle,
2144 dirfsp,
2145 smb_fname,
2146 flags);
2147 }
2148
smb_vfs_call_chmod(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,mode_t mode)2149 int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
2150 const struct smb_filename *smb_fname,
2151 mode_t mode)
2152 {
2153 VFS_FIND(chmod);
2154 return handle->fns->chmod_fn(handle, smb_fname, mode);
2155 }
2156
smb_vfs_call_fchmod(struct vfs_handle_struct * handle,struct files_struct * fsp,mode_t mode)2157 int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
2158 struct files_struct *fsp, mode_t mode)
2159 {
2160 VFS_FIND(fchmod);
2161 return handle->fns->fchmod_fn(handle, fsp, mode);
2162 }
2163
smb_vfs_call_fchown(struct vfs_handle_struct * handle,struct files_struct * fsp,uid_t uid,gid_t gid)2164 int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
2165 struct files_struct *fsp, uid_t uid, gid_t gid)
2166 {
2167 VFS_FIND(fchown);
2168 return handle->fns->fchown_fn(handle, fsp, uid, gid);
2169 }
2170
smb_vfs_call_lchown(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uid_t uid,gid_t gid)2171 int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
2172 const struct smb_filename *smb_fname,
2173 uid_t uid,
2174 gid_t gid)
2175 {
2176 VFS_FIND(lchown);
2177 return handle->fns->lchown_fn(handle, smb_fname, uid, gid);
2178 }
2179
smb_vfs_call_chdir(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname)2180 int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
2181 const struct smb_filename *smb_fname)
2182 {
2183 VFS_FIND(chdir);
2184 return handle->fns->chdir_fn(handle, smb_fname);
2185 }
2186
smb_vfs_call_getwd(struct vfs_handle_struct * handle,TALLOC_CTX * ctx)2187 struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
2188 TALLOC_CTX *ctx)
2189 {
2190 VFS_FIND(getwd);
2191 return handle->fns->getwd_fn(handle, ctx);
2192 }
2193
smb_vfs_call_ntimes(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,struct smb_file_time * ft)2194 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
2195 const struct smb_filename *smb_fname,
2196 struct smb_file_time *ft)
2197 {
2198 VFS_FIND(ntimes);
2199 return handle->fns->ntimes_fn(handle, smb_fname, ft);
2200 }
2201
smb_vfs_call_ftruncate(struct vfs_handle_struct * handle,struct files_struct * fsp,off_t offset)2202 int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
2203 struct files_struct *fsp, off_t offset)
2204 {
2205 VFS_FIND(ftruncate);
2206 return handle->fns->ftruncate_fn(handle, fsp, offset);
2207 }
2208
smb_vfs_call_fallocate(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t mode,off_t offset,off_t len)2209 int smb_vfs_call_fallocate(struct vfs_handle_struct *handle,
2210 struct files_struct *fsp,
2211 uint32_t mode,
2212 off_t offset,
2213 off_t len)
2214 {
2215 VFS_FIND(fallocate);
2216 return handle->fns->fallocate_fn(handle, fsp, mode, offset, len);
2217 }
2218
smb_vfs_call_kernel_flock(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t share_mode,uint32_t access_mask)2219 int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
2220 struct files_struct *fsp, uint32_t share_mode,
2221 uint32_t access_mask)
2222 {
2223 VFS_FIND(kernel_flock);
2224 return handle->fns->kernel_flock_fn(handle, fsp, share_mode,
2225 access_mask);
2226 }
2227
smb_vfs_call_fcntl(struct vfs_handle_struct * handle,struct files_struct * fsp,int cmd,...)2228 int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
2229 struct files_struct *fsp, int cmd, ...)
2230 {
2231 int result;
2232 va_list cmd_arg;
2233
2234 VFS_FIND(fcntl);
2235
2236 va_start(cmd_arg, cmd);
2237 result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
2238 va_end(cmd_arg);
2239
2240 return result;
2241 }
2242
smb_vfs_call_linux_setlease(struct vfs_handle_struct * handle,struct files_struct * fsp,int leasetype)2243 int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
2244 struct files_struct *fsp, int leasetype)
2245 {
2246 VFS_FIND(linux_setlease);
2247 return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
2248 }
2249
smb_vfs_call_symlinkat(struct vfs_handle_struct * handle,const char * link_target,struct files_struct * dirfsp,const struct smb_filename * new_smb_fname)2250 int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
2251 const char *link_target,
2252 struct files_struct *dirfsp,
2253 const struct smb_filename *new_smb_fname)
2254 {
2255 VFS_FIND(symlinkat);
2256 return handle->fns->symlinkat_fn(handle,
2257 link_target,
2258 dirfsp,
2259 new_smb_fname);
2260 }
2261
smb_vfs_call_readlinkat(struct vfs_handle_struct * handle,files_struct * dirfsp,const struct smb_filename * smb_fname,char * buf,size_t bufsiz)2262 int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
2263 files_struct *dirfsp,
2264 const struct smb_filename *smb_fname,
2265 char *buf,
2266 size_t bufsiz)
2267 {
2268 VFS_FIND(readlinkat);
2269 return handle->fns->readlinkat_fn(handle,
2270 dirfsp,
2271 smb_fname,
2272 buf,
2273 bufsiz);
2274 }
2275
smb_vfs_call_linkat(struct vfs_handle_struct * handle,struct files_struct * srcfsp,const struct smb_filename * old_smb_fname,struct files_struct * dstfsp,const struct smb_filename * new_smb_fname,int flags)2276 int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
2277 struct files_struct *srcfsp,
2278 const struct smb_filename *old_smb_fname,
2279 struct files_struct *dstfsp,
2280 const struct smb_filename *new_smb_fname,
2281 int flags)
2282 {
2283 VFS_FIND(linkat);
2284 return handle->fns->linkat_fn(handle,
2285 srcfsp,
2286 old_smb_fname,
2287 dstfsp,
2288 new_smb_fname,
2289 flags);
2290 }
2291
smb_vfs_call_mknodat(struct vfs_handle_struct * handle,struct files_struct * dirfsp,const struct smb_filename * smb_fname,mode_t mode,SMB_DEV_T dev)2292 int smb_vfs_call_mknodat(struct vfs_handle_struct *handle,
2293 struct files_struct *dirfsp,
2294 const struct smb_filename *smb_fname,
2295 mode_t mode,
2296 SMB_DEV_T dev)
2297 {
2298 VFS_FIND(mknodat);
2299 return handle->fns->mknodat_fn(handle,
2300 dirfsp,
2301 smb_fname,
2302 mode,
2303 dev);
2304 }
2305
smb_vfs_call_realpath(struct vfs_handle_struct * handle,TALLOC_CTX * ctx,const struct smb_filename * smb_fname)2306 struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
2307 TALLOC_CTX *ctx,
2308 const struct smb_filename *smb_fname)
2309 {
2310 VFS_FIND(realpath);
2311 return handle->fns->realpath_fn(handle, ctx, smb_fname);
2312 }
2313
smb_vfs_call_chflags(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,unsigned int flags)2314 int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
2315 const struct smb_filename *smb_fname,
2316 unsigned int flags)
2317 {
2318 VFS_FIND(chflags);
2319 return handle->fns->chflags_fn(handle, smb_fname, flags);
2320 }
2321
smb_vfs_call_file_id_create(struct vfs_handle_struct * handle,const SMB_STRUCT_STAT * sbuf)2322 struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
2323 const SMB_STRUCT_STAT *sbuf)
2324 {
2325 VFS_FIND(file_id_create);
2326 return handle->fns->file_id_create_fn(handle, sbuf);
2327 }
2328
smb_vfs_call_fs_file_id(struct vfs_handle_struct * handle,const SMB_STRUCT_STAT * sbuf)2329 uint64_t smb_vfs_call_fs_file_id(struct vfs_handle_struct *handle,
2330 const SMB_STRUCT_STAT *sbuf)
2331 {
2332 VFS_FIND(fs_file_id);
2333 return handle->fns->fs_file_id_fn(handle, sbuf);
2334 }
2335
smb_vfs_call_streaminfo(struct vfs_handle_struct * handle,struct files_struct * fsp,const struct smb_filename * smb_fname,TALLOC_CTX * mem_ctx,unsigned int * num_streams,struct stream_struct ** streams)2336 NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
2337 struct files_struct *fsp,
2338 const struct smb_filename *smb_fname,
2339 TALLOC_CTX *mem_ctx,
2340 unsigned int *num_streams,
2341 struct stream_struct **streams)
2342 {
2343 VFS_FIND(streaminfo);
2344 return handle->fns->streaminfo_fn(handle, fsp, smb_fname, mem_ctx,
2345 num_streams, streams);
2346 }
2347
smb_vfs_call_get_real_filename(struct vfs_handle_struct * handle,const char * path,const char * name,TALLOC_CTX * mem_ctx,char ** found_name)2348 int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
2349 const char *path, const char *name,
2350 TALLOC_CTX *mem_ctx, char **found_name)
2351 {
2352 VFS_FIND(get_real_filename);
2353 return handle->fns->get_real_filename_fn(handle, path, name, mem_ctx,
2354 found_name);
2355 }
2356
smb_vfs_call_connectpath(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname)2357 const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
2358 const struct smb_filename *smb_fname)
2359 {
2360 VFS_FIND(connectpath);
2361 return handle->fns->connectpath_fn(handle, smb_fname);
2362 }
2363
smb_vfs_call_strict_lock_check(struct vfs_handle_struct * handle,struct files_struct * fsp,struct lock_struct * plock)2364 bool smb_vfs_call_strict_lock_check(struct vfs_handle_struct *handle,
2365 struct files_struct *fsp,
2366 struct lock_struct *plock)
2367 {
2368 VFS_FIND(strict_lock_check);
2369 return handle->fns->strict_lock_check_fn(handle, fsp, plock);
2370 }
2371
smb_vfs_call_translate_name(struct vfs_handle_struct * handle,const char * name,enum vfs_translate_direction direction,TALLOC_CTX * mem_ctx,char ** mapped_name)2372 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
2373 const char *name,
2374 enum vfs_translate_direction direction,
2375 TALLOC_CTX *mem_ctx,
2376 char **mapped_name)
2377 {
2378 VFS_FIND(translate_name);
2379 return handle->fns->translate_name_fn(handle, name, direction, mem_ctx,
2380 mapped_name);
2381 }
2382
smb_vfs_call_fsctl(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * ctx,uint32_t function,uint16_t req_flags,const uint8_t * in_data,uint32_t in_len,uint8_t ** out_data,uint32_t max_out_len,uint32_t * out_len)2383 NTSTATUS smb_vfs_call_fsctl(struct vfs_handle_struct *handle,
2384 struct files_struct *fsp,
2385 TALLOC_CTX *ctx,
2386 uint32_t function,
2387 uint16_t req_flags,
2388 const uint8_t *in_data,
2389 uint32_t in_len,
2390 uint8_t **out_data,
2391 uint32_t max_out_len,
2392 uint32_t *out_len)
2393 {
2394 VFS_FIND(fsctl);
2395 return handle->fns->fsctl_fn(handle, fsp, ctx, function, req_flags,
2396 in_data, in_len, out_data, max_out_len,
2397 out_len);
2398 }
2399
smb_vfs_call_get_dos_attributes(struct vfs_handle_struct * handle,struct smb_filename * smb_fname,uint32_t * dosmode)2400 NTSTATUS smb_vfs_call_get_dos_attributes(struct vfs_handle_struct *handle,
2401 struct smb_filename *smb_fname,
2402 uint32_t *dosmode)
2403 {
2404 VFS_FIND(get_dos_attributes);
2405 return handle->fns->get_dos_attributes_fn(handle, smb_fname, dosmode);
2406 }
2407
smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t * dosmode)2408 NTSTATUS smb_vfs_call_fget_dos_attributes(struct vfs_handle_struct *handle,
2409 struct files_struct *fsp,
2410 uint32_t *dosmode)
2411 {
2412 VFS_FIND(fget_dos_attributes);
2413 return handle->fns->fget_dos_attributes_fn(handle, fsp, dosmode);
2414 }
2415
smb_vfs_call_set_dos_attributes(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uint32_t dosmode)2416 NTSTATUS smb_vfs_call_set_dos_attributes(struct vfs_handle_struct *handle,
2417 const struct smb_filename *smb_fname,
2418 uint32_t dosmode)
2419 {
2420 VFS_FIND(set_dos_attributes);
2421 return handle->fns->set_dos_attributes_fn(handle, smb_fname, dosmode);
2422 }
2423
smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t dosmode)2424 NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
2425 struct files_struct *fsp,
2426 uint32_t dosmode)
2427 {
2428 VFS_FIND(set_dos_attributes);
2429 return handle->fns->fset_dos_attributes_fn(handle, fsp, dosmode);
2430 }
2431
smb_vfs_call_offload_read_send(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t fsctl,uint32_t ttl,off_t offset,size_t to_copy)2432 struct tevent_req *smb_vfs_call_offload_read_send(TALLOC_CTX *mem_ctx,
2433 struct tevent_context *ev,
2434 struct vfs_handle_struct *handle,
2435 struct files_struct *fsp,
2436 uint32_t fsctl,
2437 uint32_t ttl,
2438 off_t offset,
2439 size_t to_copy)
2440 {
2441 VFS_FIND(offload_read_send);
2442 return handle->fns->offload_read_send_fn(mem_ctx, ev, handle,
2443 fsp, fsctl,
2444 ttl, offset, to_copy);
2445 }
2446
smb_vfs_call_offload_read_recv(struct tevent_req * req,struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,DATA_BLOB * token_blob)2447 NTSTATUS smb_vfs_call_offload_read_recv(struct tevent_req *req,
2448 struct vfs_handle_struct *handle,
2449 TALLOC_CTX *mem_ctx,
2450 DATA_BLOB *token_blob)
2451 {
2452 VFS_FIND(offload_read_recv);
2453 return handle->fns->offload_read_recv_fn(req, handle, mem_ctx, token_blob);
2454 }
2455
smb_vfs_call_offload_write_send(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct tevent_context * ev,uint32_t fsctl,DATA_BLOB * token,off_t transfer_offset,struct files_struct * dest_fsp,off_t dest_off,off_t num)2456 struct tevent_req *smb_vfs_call_offload_write_send(struct vfs_handle_struct *handle,
2457 TALLOC_CTX *mem_ctx,
2458 struct tevent_context *ev,
2459 uint32_t fsctl,
2460 DATA_BLOB *token,
2461 off_t transfer_offset,
2462 struct files_struct *dest_fsp,
2463 off_t dest_off,
2464 off_t num)
2465 {
2466 VFS_FIND(offload_write_send);
2467 return handle->fns->offload_write_send_fn(handle, mem_ctx, ev, fsctl,
2468 token, transfer_offset,
2469 dest_fsp, dest_off, num);
2470 }
2471
smb_vfs_call_offload_write_recv(struct vfs_handle_struct * handle,struct tevent_req * req,off_t * copied)2472 NTSTATUS smb_vfs_call_offload_write_recv(struct vfs_handle_struct *handle,
2473 struct tevent_req *req,
2474 off_t *copied)
2475 {
2476 VFS_FIND(offload_write_recv);
2477 return handle->fns->offload_write_recv_fn(handle, req, copied);
2478 }
2479
2480 struct smb_vfs_call_get_dos_attributes_state {
2481 files_struct *dir_fsp;
2482 NTSTATUS (*recv_fn)(struct tevent_req *req,
2483 struct vfs_aio_state *aio_state,
2484 uint32_t *dosmode);
2485 struct vfs_aio_state aio_state;
2486 uint32_t dos_attributes;
2487 };
2488
2489 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
2490
smb_vfs_call_get_dos_attributes_send(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct vfs_handle_struct * handle,files_struct * dir_fsp,struct smb_filename * smb_fname)2491 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
2492 TALLOC_CTX *mem_ctx,
2493 struct tevent_context *ev,
2494 struct vfs_handle_struct *handle,
2495 files_struct *dir_fsp,
2496 struct smb_filename *smb_fname)
2497 {
2498 struct tevent_req *req = NULL;
2499 struct smb_vfs_call_get_dos_attributes_state *state = NULL;
2500 struct tevent_req *subreq = NULL;
2501
2502 req = tevent_req_create(mem_ctx, &state,
2503 struct smb_vfs_call_get_dos_attributes_state);
2504 if (req == NULL) {
2505 return NULL;
2506 }
2507
2508 VFS_FIND(get_dos_attributes_send);
2509
2510 *state = (struct smb_vfs_call_get_dos_attributes_state) {
2511 .dir_fsp = dir_fsp,
2512 .recv_fn = handle->fns->get_dos_attributes_recv_fn,
2513 };
2514
2515 subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
2516 ev,
2517 handle,
2518 dir_fsp,
2519 smb_fname);
2520 if (tevent_req_nomem(subreq, req)) {
2521 return tevent_req_post(req, ev);
2522 }
2523 tevent_req_defer_callback(req, ev);
2524
2525 tevent_req_set_callback(subreq,
2526 smb_vfs_call_get_dos_attributes_done,
2527 req);
2528
2529 return req;
2530 }
2531
smb_vfs_call_get_dos_attributes_done(struct tevent_req * subreq)2532 static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq)
2533 {
2534 struct tevent_req *req =
2535 tevent_req_callback_data(subreq,
2536 struct tevent_req);
2537 struct smb_vfs_call_get_dos_attributes_state *state =
2538 tevent_req_data(req,
2539 struct smb_vfs_call_get_dos_attributes_state);
2540 NTSTATUS status;
2541 bool ok;
2542
2543 /*
2544 * Make sure we run as the user again
2545 */
2546 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2547 SMB_ASSERT(ok);
2548
2549 status = state->recv_fn(subreq,
2550 &state->aio_state,
2551 &state->dos_attributes);
2552 TALLOC_FREE(subreq);
2553 if (tevent_req_nterror(req, status)) {
2554 return;
2555 }
2556
2557 tevent_req_done(req);
2558 }
2559
smb_vfs_call_get_dos_attributes_recv(struct tevent_req * req,struct vfs_aio_state * aio_state,uint32_t * dos_attributes)2560 NTSTATUS smb_vfs_call_get_dos_attributes_recv(
2561 struct tevent_req *req,
2562 struct vfs_aio_state *aio_state,
2563 uint32_t *dos_attributes)
2564 {
2565 struct smb_vfs_call_get_dos_attributes_state *state =
2566 tevent_req_data(req,
2567 struct smb_vfs_call_get_dos_attributes_state);
2568 NTSTATUS status;
2569
2570 if (tevent_req_is_nterror(req, &status)) {
2571 tevent_req_received(req);
2572 return status;
2573 }
2574
2575 *aio_state = state->aio_state;
2576 *dos_attributes = state->dos_attributes;
2577 tevent_req_received(req);
2578 return NT_STATUS_OK;
2579 }
2580
smb_vfs_call_get_compression(vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct files_struct * fsp,struct smb_filename * smb_fname,uint16_t * _compression_fmt)2581 NTSTATUS smb_vfs_call_get_compression(vfs_handle_struct *handle,
2582 TALLOC_CTX *mem_ctx,
2583 struct files_struct *fsp,
2584 struct smb_filename *smb_fname,
2585 uint16_t *_compression_fmt)
2586 {
2587 VFS_FIND(get_compression);
2588 return handle->fns->get_compression_fn(handle, mem_ctx, fsp, smb_fname,
2589 _compression_fmt);
2590 }
2591
smb_vfs_call_set_compression(vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,struct files_struct * fsp,uint16_t compression_fmt)2592 NTSTATUS smb_vfs_call_set_compression(vfs_handle_struct *handle,
2593 TALLOC_CTX *mem_ctx,
2594 struct files_struct *fsp,
2595 uint16_t compression_fmt)
2596 {
2597 VFS_FIND(set_compression);
2598 return handle->fns->set_compression_fn(handle, mem_ctx, fsp,
2599 compression_fmt);
2600 }
2601
smb_vfs_call_snap_check_path(vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,const char * service_path,char ** base_volume)2602 NTSTATUS smb_vfs_call_snap_check_path(vfs_handle_struct *handle,
2603 TALLOC_CTX *mem_ctx,
2604 const char *service_path,
2605 char **base_volume)
2606 {
2607 VFS_FIND(snap_check_path);
2608 return handle->fns->snap_check_path_fn(handle, mem_ctx, service_path,
2609 base_volume);
2610 }
2611
smb_vfs_call_snap_create(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,const char * base_volume,time_t * tstamp,bool rw,char ** base_path,char ** snap_path)2612 NTSTATUS smb_vfs_call_snap_create(struct vfs_handle_struct *handle,
2613 TALLOC_CTX *mem_ctx,
2614 const char *base_volume,
2615 time_t *tstamp,
2616 bool rw,
2617 char **base_path,
2618 char **snap_path)
2619 {
2620 VFS_FIND(snap_create);
2621 return handle->fns->snap_create_fn(handle, mem_ctx, base_volume, tstamp,
2622 rw, base_path, snap_path);
2623 }
2624
smb_vfs_call_snap_delete(struct vfs_handle_struct * handle,TALLOC_CTX * mem_ctx,char * base_path,char * snap_path)2625 NTSTATUS smb_vfs_call_snap_delete(struct vfs_handle_struct *handle,
2626 TALLOC_CTX *mem_ctx,
2627 char *base_path,
2628 char *snap_path)
2629 {
2630 VFS_FIND(snap_delete);
2631 return handle->fns->snap_delete_fn(handle, mem_ctx, base_path,
2632 snap_path);
2633 }
2634
smb_vfs_call_fget_nt_acl(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t security_info,TALLOC_CTX * mem_ctx,struct security_descriptor ** ppdesc)2635 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
2636 struct files_struct *fsp,
2637 uint32_t security_info,
2638 TALLOC_CTX *mem_ctx,
2639 struct security_descriptor **ppdesc)
2640 {
2641 VFS_FIND(fget_nt_acl);
2642 return handle->fns->fget_nt_acl_fn(handle, fsp, security_info,
2643 mem_ctx, ppdesc);
2644 }
2645
smb_vfs_call_get_nt_acl(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,uint32_t security_info,TALLOC_CTX * mem_ctx,struct security_descriptor ** ppdesc)2646 NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
2647 const struct smb_filename *smb_fname,
2648 uint32_t security_info,
2649 TALLOC_CTX *mem_ctx,
2650 struct security_descriptor **ppdesc)
2651 {
2652 VFS_FIND(get_nt_acl);
2653 return handle->fns->get_nt_acl_fn(handle,
2654 smb_fname,
2655 security_info,
2656 mem_ctx,
2657 ppdesc);
2658 }
2659
smb_vfs_call_fset_nt_acl(struct vfs_handle_struct * handle,struct files_struct * fsp,uint32_t security_info_sent,const struct security_descriptor * psd)2660 NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
2661 struct files_struct *fsp,
2662 uint32_t security_info_sent,
2663 const struct security_descriptor *psd)
2664 {
2665 VFS_FIND(fset_nt_acl);
2666 return handle->fns->fset_nt_acl_fn(handle, fsp, security_info_sent,
2667 psd);
2668 }
2669
smb_vfs_call_audit_file(struct vfs_handle_struct * handle,struct smb_filename * file,struct security_acl * sacl,uint32_t access_requested,uint32_t access_denied)2670 NTSTATUS smb_vfs_call_audit_file(struct vfs_handle_struct *handle,
2671 struct smb_filename *file,
2672 struct security_acl *sacl,
2673 uint32_t access_requested,
2674 uint32_t access_denied)
2675 {
2676 VFS_FIND(audit_file);
2677 return handle->fns->audit_file_fn(handle,
2678 file,
2679 sacl,
2680 access_requested,
2681 access_denied);
2682 }
2683
smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,SMB_ACL_TYPE_T type,TALLOC_CTX * mem_ctx)2684 SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
2685 const struct smb_filename *smb_fname,
2686 SMB_ACL_TYPE_T type,
2687 TALLOC_CTX *mem_ctx)
2688 {
2689 VFS_FIND(sys_acl_get_file);
2690 return handle->fns->sys_acl_get_file_fn(handle, smb_fname, type, mem_ctx);
2691 }
2692
smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * mem_ctx)2693 SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
2694 struct files_struct *fsp,
2695 TALLOC_CTX *mem_ctx)
2696 {
2697 VFS_FIND(sys_acl_get_fd);
2698 return handle->fns->sys_acl_get_fd_fn(handle, fsp, mem_ctx);
2699 }
2700
smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,TALLOC_CTX * mem_ctx,char ** blob_description,DATA_BLOB * blob)2701 int smb_vfs_call_sys_acl_blob_get_file(struct vfs_handle_struct *handle,
2702 const struct smb_filename *smb_fname,
2703 TALLOC_CTX *mem_ctx,
2704 char **blob_description,
2705 DATA_BLOB *blob)
2706 {
2707 VFS_FIND(sys_acl_blob_get_file);
2708 return handle->fns->sys_acl_blob_get_file_fn(handle, smb_fname,
2709 mem_ctx, blob_description, blob);
2710 }
2711
smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * mem_ctx,char ** blob_description,DATA_BLOB * blob)2712 int smb_vfs_call_sys_acl_blob_get_fd(struct vfs_handle_struct *handle,
2713 struct files_struct *fsp,
2714 TALLOC_CTX *mem_ctx,
2715 char **blob_description,
2716 DATA_BLOB *blob)
2717 {
2718 VFS_FIND(sys_acl_blob_get_fd);
2719 return handle->fns->sys_acl_blob_get_fd_fn(handle, fsp, mem_ctx, blob_description, blob);
2720 }
2721
smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,SMB_ACL_TYPE_T acltype,SMB_ACL_T theacl)2722 int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
2723 const struct smb_filename *smb_fname,
2724 SMB_ACL_TYPE_T acltype,
2725 SMB_ACL_T theacl)
2726 {
2727 VFS_FIND(sys_acl_set_file);
2728 return handle->fns->sys_acl_set_file_fn(handle, smb_fname,
2729 acltype, theacl);
2730 }
2731
smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct * handle,struct files_struct * fsp,SMB_ACL_T theacl)2732 int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
2733 struct files_struct *fsp, SMB_ACL_T theacl)
2734 {
2735 VFS_FIND(sys_acl_set_fd);
2736 return handle->fns->sys_acl_set_fd_fn(handle, fsp, theacl);
2737 }
2738
smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname)2739 int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
2740 const struct smb_filename *smb_fname)
2741 {
2742 VFS_FIND(sys_acl_delete_def_file);
2743 return handle->fns->sys_acl_delete_def_file_fn(handle, smb_fname);
2744 }
2745
smb_vfs_call_getxattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * name,void * value,size_t size)2746 ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
2747 const struct smb_filename *smb_fname,
2748 const char *name,
2749 void *value,
2750 size_t size)
2751 {
2752 VFS_FIND(getxattr);
2753 return handle->fns->getxattr_fn(handle, smb_fname, name, value, size);
2754 }
2755
2756
2757 struct smb_vfs_call_getxattrat_state {
2758 files_struct *dir_fsp;
2759 ssize_t (*recv_fn)(struct tevent_req *req,
2760 struct vfs_aio_state *aio_state,
2761 TALLOC_CTX *mem_ctx,
2762 uint8_t **xattr_value);
2763 ssize_t retval;
2764 uint8_t *xattr_value;
2765 struct vfs_aio_state aio_state;
2766 };
2767
2768 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
2769
smb_vfs_call_getxattrat_send(TALLOC_CTX * mem_ctx,struct tevent_context * ev,struct vfs_handle_struct * handle,files_struct * dir_fsp,const struct smb_filename * smb_fname,const char * xattr_name,size_t alloc_hint)2770 struct tevent_req *smb_vfs_call_getxattrat_send(
2771 TALLOC_CTX *mem_ctx,
2772 struct tevent_context *ev,
2773 struct vfs_handle_struct *handle,
2774 files_struct *dir_fsp,
2775 const struct smb_filename *smb_fname,
2776 const char *xattr_name,
2777 size_t alloc_hint)
2778 {
2779 struct tevent_req *req = NULL;
2780 struct smb_vfs_call_getxattrat_state *state = NULL;
2781 struct tevent_req *subreq = NULL;
2782
2783 req = tevent_req_create(mem_ctx, &state,
2784 struct smb_vfs_call_getxattrat_state);
2785 if (req == NULL) {
2786 return NULL;
2787 }
2788
2789 VFS_FIND(getxattrat_send);
2790
2791 *state = (struct smb_vfs_call_getxattrat_state) {
2792 .dir_fsp = dir_fsp,
2793 .recv_fn = handle->fns->getxattrat_recv_fn,
2794 };
2795
2796 subreq = handle->fns->getxattrat_send_fn(mem_ctx,
2797 ev,
2798 handle,
2799 dir_fsp,
2800 smb_fname,
2801 xattr_name,
2802 alloc_hint);
2803 if (tevent_req_nomem(subreq, req)) {
2804 return tevent_req_post(req, ev);
2805 }
2806 tevent_req_defer_callback(req, ev);
2807
2808 tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
2809 return req;
2810 }
2811
smb_vfs_call_getxattrat_done(struct tevent_req * subreq)2812 static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq)
2813 {
2814 struct tevent_req *req = tevent_req_callback_data(
2815 subreq, struct tevent_req);
2816 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2817 req, struct smb_vfs_call_getxattrat_state);
2818 bool ok;
2819
2820 /*
2821 * Make sure we run as the user again
2822 */
2823 ok = change_to_user_and_service_by_fsp(state->dir_fsp);
2824 SMB_ASSERT(ok);
2825
2826 state->retval = state->recv_fn(subreq,
2827 &state->aio_state,
2828 state,
2829 &state->xattr_value);
2830 TALLOC_FREE(subreq);
2831 if (state->retval == -1) {
2832 tevent_req_error(req, state->aio_state.error);
2833 return;
2834 }
2835
2836 tevent_req_done(req);
2837 }
2838
smb_vfs_call_getxattrat_recv(struct tevent_req * req,struct vfs_aio_state * aio_state,TALLOC_CTX * mem_ctx,uint8_t ** xattr_value)2839 ssize_t smb_vfs_call_getxattrat_recv(struct tevent_req *req,
2840 struct vfs_aio_state *aio_state,
2841 TALLOC_CTX *mem_ctx,
2842 uint8_t **xattr_value)
2843 {
2844 struct smb_vfs_call_getxattrat_state *state = tevent_req_data(
2845 req, struct smb_vfs_call_getxattrat_state);
2846 size_t xattr_size;
2847
2848 if (tevent_req_is_unix_error(req, &aio_state->error)) {
2849 tevent_req_received(req);
2850 return -1;
2851 }
2852
2853 *aio_state = state->aio_state;
2854 xattr_size = state->retval;
2855 if (xattr_value != NULL) {
2856 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
2857 }
2858
2859 tevent_req_received(req);
2860 return xattr_size;
2861 }
2862
smb_vfs_call_fgetxattr(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * name,void * value,size_t size)2863 ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
2864 struct files_struct *fsp, const char *name,
2865 void *value, size_t size)
2866 {
2867 VFS_FIND(fgetxattr);
2868 return handle->fns->fgetxattr_fn(handle, fsp, name, value, size);
2869 }
2870
smb_vfs_call_listxattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,char * list,size_t size)2871 ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
2872 const struct smb_filename *smb_fname,
2873 char *list,
2874 size_t size)
2875 {
2876 VFS_FIND(listxattr);
2877 return handle->fns->listxattr_fn(handle, smb_fname, list, size);
2878 }
2879
smb_vfs_call_flistxattr(struct vfs_handle_struct * handle,struct files_struct * fsp,char * list,size_t size)2880 ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
2881 struct files_struct *fsp, char *list,
2882 size_t size)
2883 {
2884 VFS_FIND(flistxattr);
2885 return handle->fns->flistxattr_fn(handle, fsp, list, size);
2886 }
2887
smb_vfs_call_removexattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * name)2888 int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
2889 const struct smb_filename *smb_fname,
2890 const char *name)
2891 {
2892 VFS_FIND(removexattr);
2893 return handle->fns->removexattr_fn(handle, smb_fname, name);
2894 }
2895
smb_vfs_call_fremovexattr(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * name)2896 int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
2897 struct files_struct *fsp, const char *name)
2898 {
2899 VFS_FIND(fremovexattr);
2900 return handle->fns->fremovexattr_fn(handle, fsp, name);
2901 }
2902
smb_vfs_call_setxattr(struct vfs_handle_struct * handle,const struct smb_filename * smb_fname,const char * name,const void * value,size_t size,int flags)2903 int smb_vfs_call_setxattr(struct vfs_handle_struct *handle,
2904 const struct smb_filename *smb_fname,
2905 const char *name,
2906 const void *value,
2907 size_t size,
2908 int flags)
2909 {
2910 VFS_FIND(setxattr);
2911 return handle->fns->setxattr_fn(handle, smb_fname,
2912 name, value, size, flags);
2913 }
2914
smb_vfs_call_fsetxattr(struct vfs_handle_struct * handle,struct files_struct * fsp,const char * name,const void * value,size_t size,int flags)2915 int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
2916 struct files_struct *fsp, const char *name,
2917 const void *value, size_t size, int flags)
2918 {
2919 VFS_FIND(fsetxattr);
2920 return handle->fns->fsetxattr_fn(handle, fsp, name, value, size, flags);
2921 }
2922
smb_vfs_call_aio_force(struct vfs_handle_struct * handle,struct files_struct * fsp)2923 bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
2924 struct files_struct *fsp)
2925 {
2926 VFS_FIND(aio_force);
2927 return handle->fns->aio_force_fn(handle, fsp);
2928 }
2929
smb_vfs_call_durable_cookie(struct vfs_handle_struct * handle,struct files_struct * fsp,TALLOC_CTX * mem_ctx,DATA_BLOB * cookie)2930 NTSTATUS smb_vfs_call_durable_cookie(struct vfs_handle_struct *handle,
2931 struct files_struct *fsp,
2932 TALLOC_CTX *mem_ctx,
2933 DATA_BLOB *cookie)
2934 {
2935 VFS_FIND(durable_cookie);
2936 return handle->fns->durable_cookie_fn(handle, fsp, mem_ctx, cookie);
2937 }
2938
smb_vfs_call_durable_disconnect(struct vfs_handle_struct * handle,struct files_struct * fsp,const DATA_BLOB old_cookie,TALLOC_CTX * mem_ctx,DATA_BLOB * new_cookie)2939 NTSTATUS smb_vfs_call_durable_disconnect(struct vfs_handle_struct *handle,
2940 struct files_struct *fsp,
2941 const DATA_BLOB old_cookie,
2942 TALLOC_CTX *mem_ctx,
2943 DATA_BLOB *new_cookie)
2944 {
2945 VFS_FIND(durable_disconnect);
2946 return handle->fns->durable_disconnect_fn(handle, fsp, old_cookie,
2947 mem_ctx, new_cookie);
2948 }
2949
smb_vfs_call_durable_reconnect(struct vfs_handle_struct * handle,struct smb_request * smb1req,struct smbXsrv_open * op,const DATA_BLOB old_cookie,TALLOC_CTX * mem_ctx,struct files_struct ** fsp,DATA_BLOB * new_cookie)2950 NTSTATUS smb_vfs_call_durable_reconnect(struct vfs_handle_struct *handle,
2951 struct smb_request *smb1req,
2952 struct smbXsrv_open *op,
2953 const DATA_BLOB old_cookie,
2954 TALLOC_CTX *mem_ctx,
2955 struct files_struct **fsp,
2956 DATA_BLOB *new_cookie)
2957 {
2958 VFS_FIND(durable_reconnect);
2959 return handle->fns->durable_reconnect_fn(handle, smb1req, op,
2960 old_cookie, mem_ctx, fsp,
2961 new_cookie);
2962 }
2963
smb_vfs_call_readdir_attr(struct vfs_handle_struct * handle,const struct smb_filename * fname,TALLOC_CTX * mem_ctx,struct readdir_attr_data ** attr_data)2964 NTSTATUS smb_vfs_call_readdir_attr(struct vfs_handle_struct *handle,
2965 const struct smb_filename *fname,
2966 TALLOC_CTX *mem_ctx,
2967 struct readdir_attr_data **attr_data)
2968 {
2969 VFS_FIND(readdir_attr);
2970 return handle->fns->readdir_attr_fn(handle, fname, mem_ctx, attr_data);
2971 }
2972