vfs: RIP SMB_VFS_GETXATTR()
[samba.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
40
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_VFS
43
44 /* Check for NULL pointer parameters in vfswrap_* functions */
45
46 /* We don't want to have NULL function pointers lying around.  Someone
47    is sure to try and execute them.  These stubs are used to prevent
48    this possibility. */
49
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
51 {
52         handle->conn->have_proc_fds = sys_have_proc_fds();
53         return 0;    /* Return >= 0 for success */
54 }
55
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 {
58 }
59
60 /* Disk operations */
61
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63                                 const struct smb_filename *smb_fname,
64                                 uint64_t *bsize,
65                                 uint64_t *dfree,
66                                 uint64_t *dsize)
67 {
68         if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
69                 return (uint64_t)-1;
70         }
71
72         *bsize = 512;
73         return *dfree / 2;
74 }
75
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77                                 const struct smb_filename *smb_fname,
78                                 enum SMB_QUOTA_TYPE qtype,
79                                 unid_t id,
80                                 SMB_DISK_QUOTA *qt)
81 {
82 #ifdef HAVE_SYS_QUOTAS
83         int result;
84
85         START_PROFILE(syscall_get_quota);
86         result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87         END_PROFILE(syscall_get_quota);
88         return result;
89 #else
90         errno = ENOSYS;
91         return -1;
92 #endif
93 }
94
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
96 {
97 #ifdef HAVE_SYS_QUOTAS
98         int result;
99
100         START_PROFILE(syscall_set_quota);
101         result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102         END_PROFILE(syscall_set_quota);
103         return result;
104 #else
105         errno = ENOSYS;
106         return -1;
107 #endif
108 }
109
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111                                         struct files_struct *fsp,
112                                         struct shadow_copy_data *shadow_copy_data,
113                                         bool labels)
114 {
115         errno = ENOSYS;
116         return -1;  /* Not implemented. */
117 }
118
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120                                 const struct smb_filename *smb_fname,
121                                 vfs_statvfs_struct *statbuf)
122 {
123         return sys_statvfs(smb_fname->base_name, statbuf);
124 }
125
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127                 enum timestamp_set_resolution *p_ts_res)
128 {
129         const struct loadparm_substitution *lp_sub =
130                 loadparm_s3_global_substitution();
131         connection_struct *conn = handle->conn;
132         uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133         struct smb_filename *smb_fname_cpath = NULL;
134         struct vfs_statvfs_struct statbuf;
135         int ret;
136
137         smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
138                                               conn->connectpath,
139                                               NULL,
140                                               NULL,
141                                               0,
142                                               0);
143         if (smb_fname_cpath == NULL) {
144                 return caps;
145         }
146
147         ZERO_STRUCT(statbuf);
148         ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
149         if (ret == 0) {
150                 caps = statbuf.FsCapabilities;
151         }
152
153         *p_ts_res = TIMESTAMP_SET_SECONDS;
154
155         /* Work out what timestamp resolution we can
156          * use when setting a timestamp. */
157
158         ret = SMB_VFS_STAT(conn, smb_fname_cpath);
159         if (ret == -1) {
160                 TALLOC_FREE(smb_fname_cpath);
161                 return caps;
162         }
163
164         if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165                         smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166                         smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167                 /* If any of the normal UNIX directory timestamps
168                  * have a non-zero tv_nsec component assume
169                  * we might be able to set sub-second timestamps.
170                  * See what filetime set primitives we have.
171                  */
172 #if defined(HAVE_UTIMENSAT)
173                 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175                 /* utimes allows msec timestamps to be set. */
176                 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178                 /* utime only allows sec timestamps to be set. */
179                 *p_ts_res = TIMESTAMP_SET_SECONDS;
180 #endif
181
182                 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
183                         "resolution of %s "
184                         "available on share %s, directory %s\n",
185                         *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186                         lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187                         conn->connectpath ));
188         }
189         TALLOC_FREE(smb_fname_cpath);
190         return caps;
191 }
192
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194                                           struct dfs_GetDFSReferral *r)
195 {
196         struct junction_map *junction = NULL;
197         int consumedcnt = 0;
198         bool self_referral = false;
199         char *pathnamep = NULL;
200         char *local_dfs_path = NULL;
201         NTSTATUS status;
202         size_t i;
203         uint16_t max_referral_level = r->in.req.max_referral_level;
204
205         if (DEBUGLVL(10)) {
206                 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
207         }
208
209         /* get the junction entry */
210         if (r->in.req.servername == NULL) {
211                 return NT_STATUS_NOT_FOUND;
212         }
213
214         /*
215          * Trim pathname sent by client so it begins with only one backslash.
216          * Two backslashes confuse some dfs clients
217          */
218
219         local_dfs_path = talloc_strdup(r, r->in.req.servername);
220         if (local_dfs_path == NULL) {
221                 return NT_STATUS_NO_MEMORY;
222         }
223         pathnamep = local_dfs_path;
224         while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225                IS_DIRECTORY_SEP(pathnamep[1])) {
226                 pathnamep++;
227         }
228
229         junction = talloc_zero(r, struct junction_map);
230         if (junction == NULL) {
231                 return NT_STATUS_NO_MEMORY;
232         }
233
234         /* The following call can change cwd. */
235         status = get_referred_path(r,
236                                    handle->conn->session_info,
237                                    pathnamep,
238                                    handle->conn->sconn->remote_address,
239                                    handle->conn->sconn->local_address,
240                                    !handle->conn->sconn->using_smb2,
241                                    junction, &consumedcnt, &self_referral);
242         if (!NT_STATUS_IS_OK(status)) {
243                 struct smb_filename connectpath_fname = {
244                         .base_name = handle->conn->connectpath
245                 };
246                 vfs_ChDir(handle->conn, &connectpath_fname);
247                 return status;
248         }
249         {
250                 struct smb_filename connectpath_fname = {
251                         .base_name = handle->conn->connectpath
252                 };
253                 vfs_ChDir(handle->conn, &connectpath_fname);
254         }
255
256         if (!self_referral) {
257                 pathnamep[consumedcnt] = '\0';
258
259                 if (DEBUGLVL(3)) {
260                         dbgtext("Path %s to alternate path(s):",
261                                 pathnamep);
262                         for (i=0; i < junction->referral_count; i++) {
263                                 dbgtext(" %s",
264                                 junction->referral_list[i].alternate_path);
265                         }
266                         dbgtext(".\n");
267                 }
268         }
269
270         if (r->in.req.max_referral_level <= 2) {
271                 max_referral_level = 2;
272         }
273         if (r->in.req.max_referral_level >= 3) {
274                 max_referral_level = 3;
275         }
276
277         r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278         if (r->out.resp == NULL) {
279                 return NT_STATUS_NO_MEMORY;
280         }
281
282         r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283         r->out.resp->nb_referrals = junction->referral_count;
284
285         r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
286         if (self_referral) {
287                 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
288         }
289
290         r->out.resp->referral_entries = talloc_zero_array(r,
291                                 struct dfs_referral_type,
292                                 r->out.resp->nb_referrals);
293         if (r->out.resp->referral_entries == NULL) {
294                 return NT_STATUS_NO_MEMORY;
295         }
296
297         switch (max_referral_level) {
298         case 2:
299                 for(i=0; i < junction->referral_count; i++) {
300                         struct referral *ref = &junction->referral_list[i];
301                         TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302                         struct dfs_referral_type *t =
303                                 &r->out.resp->referral_entries[i];
304                         struct dfs_referral_v2 *v2 = &t->referral.v2;
305
306                         t->version = 2;
307                         v2->size = VERSION2_REFERRAL_SIZE;
308                         if (self_referral) {
309                                 v2->server_type = DFS_SERVER_ROOT;
310                         } else {
311                                 v2->server_type = DFS_SERVER_NON_ROOT;
312                         }
313                         v2->entry_flags = 0;
314                         v2->proximity = ref->proximity;
315                         v2->ttl = ref->ttl;
316                         v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317                         if (v2->DFS_path == NULL) {
318                                 return NT_STATUS_NO_MEMORY;
319                         }
320                         v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321                         if (v2->DFS_alt_path == NULL) {
322                                 return NT_STATUS_NO_MEMORY;
323                         }
324                         v2->netw_address = talloc_strdup(mem_ctx,
325                                                          ref->alternate_path);
326                         if (v2->netw_address == NULL) {
327                                 return NT_STATUS_NO_MEMORY;
328                         }
329                 }
330
331                 break;
332         case 3:
333                 for(i=0; i < junction->referral_count; i++) {
334                         struct referral *ref = &junction->referral_list[i];
335                         TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336                         struct dfs_referral_type *t =
337                                 &r->out.resp->referral_entries[i];
338                         struct dfs_referral_v3 *v3 = &t->referral.v3;
339                         struct dfs_normal_referral *r1 = &v3->referrals.r1;
340
341                         t->version = 3;
342                         v3->size = VERSION3_REFERRAL_SIZE;
343                         if (self_referral) {
344                                 v3->server_type = DFS_SERVER_ROOT;
345                         } else {
346                                 v3->server_type = DFS_SERVER_NON_ROOT;
347                         }
348                         v3->entry_flags = 0;
349                         v3->ttl = ref->ttl;
350                         r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351                         if (r1->DFS_path == NULL) {
352                                 return NT_STATUS_NO_MEMORY;
353                         }
354                         r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355                         if (r1->DFS_alt_path == NULL) {
356                                 return NT_STATUS_NO_MEMORY;
357                         }
358                         r1->netw_address = talloc_strdup(mem_ctx,
359                                                          ref->alternate_path);
360                         if (r1->netw_address == NULL) {
361                                 return NT_STATUS_NO_MEMORY;
362                         }
363                 }
364                 break;
365         default:
366                 DEBUG(0,("Invalid dfs referral version: %d\n",
367                         max_referral_level));
368                 return NT_STATUS_INVALID_LEVEL;
369         }
370
371         if (DEBUGLVL(10)) {
372                 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
373         }
374
375         return NT_STATUS_OK;
376 }
377
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379                                 struct files_struct *dirfsp,
380                                 const struct smb_filename *smb_fname,
381                                 const struct referral *reflist,
382                                 size_t referral_count)
383 {
384         TALLOC_CTX *frame = talloc_stackframe();
385         NTSTATUS status = NT_STATUS_NO_MEMORY;
386         int ret;
387         char *msdfs_link = NULL;
388
389         /* Form the msdfs_link contents */
390         msdfs_link = msdfs_link_string(frame,
391                                         reflist,
392                                         referral_count);
393         if (msdfs_link == NULL) {
394                 goto out;
395         }
396
397         ret = symlinkat(msdfs_link,
398                         fsp_get_pathref_fd(dirfsp),
399                         smb_fname->base_name);
400         if (ret == 0) {
401                 status = NT_STATUS_OK;
402         } else {
403                 status = map_nt_error_from_unix(errno);
404         }
405
406   out:
407
408         TALLOC_FREE(frame);
409         return status;
410 }
411
412 /*
413  * Read and return the contents of a DFS redirect given a
414  * pathname. A caller can pass in NULL for ppreflist and
415  * preferral_count but still determine if this was a
416  * DFS redirect point by getting NT_STATUS_OK back
417  * without incurring the overhead of reading and parsing
418  * the referral contents.
419  */
420
421 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
422                                 TALLOC_CTX *mem_ctx,
423                                 struct files_struct *dirfsp,
424                                 struct smb_filename *smb_fname,
425                                 struct referral **ppreflist,
426                                 size_t *preferral_count)
427 {
428         NTSTATUS status = NT_STATUS_NO_MEMORY;
429         size_t bufsize;
430         char *link_target = NULL;
431         int referral_len;
432         bool ok;
433 #if defined(HAVE_BROKEN_READLINK)
434         char link_target_buf[PATH_MAX];
435 #else
436         char link_target_buf[7];
437 #endif
438         int ret;
439
440         SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
441
442         if (is_named_stream(smb_fname)) {
443                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
444                 goto err;
445         }
446
447         if (ppreflist == NULL && preferral_count == NULL) {
448                 /*
449                  * We're only checking if this is a DFS
450                  * redirect. We don't need to return data.
451                  */
452                 bufsize = sizeof(link_target_buf);
453                 link_target = link_target_buf;
454         } else {
455                 bufsize = PATH_MAX;
456                 link_target = talloc_array(mem_ctx, char, bufsize);
457                 if (!link_target) {
458                         goto err;
459                 }
460         }
461
462         referral_len = readlinkat(fsp_get_io_fd(dirfsp),
463                                 smb_fname->base_name,
464                                 link_target,
465                                 bufsize - 1);
466         if (referral_len == -1) {
467                 if (errno == EINVAL) {
468                         /*
469                          * If the path isn't a link, readlinkat
470                          * returns EINVAL. Allow the caller to
471                          * detect this.
472                          */
473                         DBG_INFO("%s is not a link.\n", smb_fname->base_name);
474                         status = NT_STATUS_OBJECT_TYPE_MISMATCH;
475                 } else {
476                         status = map_nt_error_from_unix(errno);
477                         if (errno == ENOENT) {
478                                 DBG_NOTICE("Error reading "
479                                          "msdfs link %s: %s\n",
480                                          smb_fname->base_name,
481                                          strerror(errno));
482                         } else {
483                                 DBG_ERR("Error reading "
484                                         "msdfs link %s: %s\n",
485                                         smb_fname->base_name,
486                                         strerror(errno));
487                         }
488                 }
489                 goto err;
490         }
491         link_target[referral_len] = '\0';
492
493         DBG_INFO("%s -> %s\n",
494                         smb_fname->base_name,
495                         link_target);
496
497         if (!strnequal(link_target, "msdfs:", 6)) {
498                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
499                 goto err;
500         }
501
502         ret = sys_lstat(smb_fname->base_name,
503                         &smb_fname->st,
504                         lp_fake_directory_create_times(SNUM(handle->conn)));
505         if (ret < 0) {
506                 status = map_nt_error_from_unix(errno);
507                 goto err;
508         }
509
510         if (ppreflist == NULL && preferral_count == NULL) {
511                 /* Early return for checking if this is a DFS link. */
512                 return NT_STATUS_OK;
513         }
514
515         ok = parse_msdfs_symlink(mem_ctx,
516                         lp_msdfs_shuffle_referrals(SNUM(handle->conn)),
517                         link_target,
518                         ppreflist,
519                         preferral_count);
520
521         if (ok) {
522                 status = NT_STATUS_OK;
523         } else {
524                 status = NT_STATUS_NO_MEMORY;
525         }
526
527   err:
528
529         if (link_target != link_target_buf) {
530                 TALLOC_FREE(link_target);
531         }
532         return status;
533 }
534
535 static NTSTATUS vfswrap_snap_check_path(struct vfs_handle_struct *handle,
536                                         TALLOC_CTX *mem_ctx,
537                                         const char *service_path,
538                                         char **base_volume)
539 {
540         return NT_STATUS_NOT_SUPPORTED;
541 }
542
543 static NTSTATUS vfswrap_snap_create(struct vfs_handle_struct *handle,
544                                     TALLOC_CTX *mem_ctx,
545                                     const char *base_volume,
546                                     time_t *tstamp,
547                                     bool rw,
548                                     char **base_path,
549                                     char **snap_path)
550 {
551         return NT_STATUS_NOT_SUPPORTED;
552 }
553
554 static NTSTATUS vfswrap_snap_delete(struct vfs_handle_struct *handle,
555                                     TALLOC_CTX *mem_ctx,
556                                     char *base_path,
557                                     char *snap_path)
558 {
559         return NT_STATUS_NOT_SUPPORTED;
560 }
561
562 /* Directory operations */
563
564 static DIR *vfswrap_fdopendir(vfs_handle_struct *handle,
565                         files_struct *fsp,
566                         const char *mask,
567                         uint32_t attr)
568 {
569         DIR *result;
570
571         START_PROFILE(syscall_fdopendir);
572         result = sys_fdopendir(fsp_get_io_fd(fsp));
573         END_PROFILE(syscall_fdopendir);
574         return result;
575 }
576
577
578 static struct dirent *vfswrap_readdir(vfs_handle_struct *handle,
579                                       struct files_struct *dirfsp,
580                                       DIR *dirp,
581                                       SMB_STRUCT_STAT *sbuf)
582 {
583         struct dirent *result;
584         bool do_stat = false;
585         bool fake_ctime = lp_fake_directory_create_times(SNUM(handle->conn));
586         int flags = AT_SYMLINK_NOFOLLOW;
587         struct stat st;
588         int ret;
589
590         START_PROFILE(syscall_readdir);
591
592 #if defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)
593         do_stat = true;
594 #endif
595
596         result = readdir(dirp);
597         END_PROFILE(syscall_readdir);
598
599         if (sbuf == NULL) {
600                 return result;
601         }
602         if (result == NULL) {
603                 return NULL;
604         }
605
606         /*
607          * Default Posix readdir() does not give us stat info.
608          * Set to invalid to indicate we didn't return this info.
609          */
610         SET_STAT_INVALID(*sbuf);
611
612         /* See if we can efficiently return this. */
613         if (!do_stat) {
614                 return result;
615         }
616
617         ret = fstatat(dirfd(dirp),
618                       result->d_name,
619                       &st,
620                       flags);
621         if (ret != 0) {
622                 return result;
623         }
624
625         /*
626          * As this is an optimization, ignore it if we stat'ed a
627          * symlink for non-POSIX context. Make the caller do it again
628          * as we don't know if they wanted the link info, or its
629          * target info.
630          */
631         if (S_ISLNK(st.st_mode) &&
632             !(dirfsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH))
633         {
634                 return result;
635         }
636         init_stat_ex_from_stat(sbuf, &st, fake_ctime);
637
638         return result;
639 }
640
641 static NTSTATUS vfswrap_freaddir_attr(struct vfs_handle_struct *handle,
642                                       struct files_struct *fsp,
643                                       TALLOC_CTX *mem_ctx,
644                                       struct readdir_attr_data **attr_data)
645 {
646         return NT_STATUS_NOT_SUPPORTED;
647 }
648
649 static void vfswrap_seekdir(vfs_handle_struct *handle, DIR *dirp, long offset)
650 {
651         START_PROFILE(syscall_seekdir);
652         seekdir(dirp, offset);
653         END_PROFILE(syscall_seekdir);
654 }
655
656 static long vfswrap_telldir(vfs_handle_struct *handle, DIR *dirp)
657 {
658         long result;
659         START_PROFILE(syscall_telldir);
660         result = telldir(dirp);
661         END_PROFILE(syscall_telldir);
662         return result;
663 }
664
665 static void vfswrap_rewinddir(vfs_handle_struct *handle, DIR *dirp)
666 {
667         START_PROFILE(syscall_rewinddir);
668         rewinddir(dirp);
669         END_PROFILE(syscall_rewinddir);
670 }
671
672 static int vfswrap_mkdirat(vfs_handle_struct *handle,
673                         struct files_struct *dirfsp,
674                         const struct smb_filename *smb_fname,
675                         mode_t mode)
676 {
677         int result;
678
679         START_PROFILE(syscall_mkdirat);
680
681         result = mkdirat(fsp_get_pathref_fd(dirfsp), smb_fname->base_name, mode);
682
683         END_PROFILE(syscall_mkdirat);
684         return result;
685 }
686
687 static int vfswrap_closedir(vfs_handle_struct *handle, DIR *dirp)
688 {
689         int result;
690
691         START_PROFILE(syscall_closedir);
692         result = closedir(dirp);
693         END_PROFILE(syscall_closedir);
694         return result;
695 }
696
697 /* File operations */
698
699 static int vfswrap_openat(vfs_handle_struct *handle,
700                           const struct files_struct *dirfsp,
701                           const struct smb_filename *smb_fname,
702                           files_struct *fsp,
703                           int flags,
704                           mode_t mode)
705 {
706         bool have_opath = false;
707         bool became_root = false;
708         int result;
709
710         START_PROFILE(syscall_openat);
711
712         if (is_named_stream(smb_fname)) {
713                 errno = ENOENT;
714                 result = -1;
715                 goto out;
716         }
717
718 #ifdef O_PATH
719         have_opath = true;
720         if (fsp->fsp_flags.is_pathref) {
721                 flags |= O_PATH;
722         }
723 #endif
724
725         if (fsp->fsp_flags.is_pathref && !have_opath) {
726                 become_root();
727                 became_root = true;
728         }
729
730         result = openat(fsp_get_pathref_fd(dirfsp),
731                         smb_fname->base_name,
732                         flags,
733                         mode);
734
735         if (became_root) {
736                 unbecome_root();
737         }
738
739         fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
740
741 out:
742         END_PROFILE(syscall_openat);
743         return result;
744 }
745 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
746                                     struct smb_request *req,
747                                     struct smb_filename *smb_fname,
748                                     uint32_t access_mask,
749                                     uint32_t share_access,
750                                     uint32_t create_disposition,
751                                     uint32_t create_options,
752                                     uint32_t file_attributes,
753                                     uint32_t oplock_request,
754                                     const struct smb2_lease *lease,
755                                     uint64_t allocation_size,
756                                     uint32_t private_flags,
757                                     struct security_descriptor *sd,
758                                     struct ea_list *ea_list,
759                                     files_struct **result,
760                                     int *pinfo,
761                                     const struct smb2_create_blobs *in_context_blobs,
762                                     struct smb2_create_blobs *out_context_blobs)
763 {
764         return create_file_default(handle->conn, req, smb_fname,
765                                    access_mask, share_access,
766                                    create_disposition, create_options,
767                                    file_attributes, oplock_request, lease,
768                                    allocation_size, private_flags,
769                                    sd, ea_list, result,
770                                    pinfo, in_context_blobs, out_context_blobs);
771 }
772
773 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
774 {
775         int result;
776
777         START_PROFILE(syscall_close);
778         result = fd_close_posix(fsp);
779         END_PROFILE(syscall_close);
780         return result;
781 }
782
783 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
784                         size_t n, off_t offset)
785 {
786         ssize_t result;
787
788 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
789         START_PROFILE_BYTES(syscall_pread, n);
790         result = sys_pread_full(fsp_get_io_fd(fsp), data, n, offset);
791         END_PROFILE_BYTES(syscall_pread);
792
793         if (result == -1 && errno == ESPIPE) {
794                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
795                 result = sys_read(fsp_get_io_fd(fsp), data, n);
796                 fh_set_pos(fsp->fh, 0);
797         }
798
799 #else /* HAVE_PREAD */
800         errno = ENOSYS;
801         result = -1;
802 #endif /* HAVE_PREAD */
803
804         return result;
805 }
806
807 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
808                         size_t n, off_t offset)
809 {
810         ssize_t result;
811
812 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
813         START_PROFILE_BYTES(syscall_pwrite, n);
814         result = sys_pwrite_full(fsp_get_io_fd(fsp), data, n, offset);
815         END_PROFILE_BYTES(syscall_pwrite);
816
817         if (result == -1 && errno == ESPIPE) {
818                 /* Maintain the fiction that pipes can be sought on. */
819                 result = sys_write(fsp_get_io_fd(fsp), data, n);
820         }
821
822 #else /* HAVE_PWRITE */
823         errno = ENOSYS;
824         result = -1;
825 #endif /* HAVE_PWRITE */
826
827         return result;
828 }
829
830 struct vfswrap_pread_state {
831         ssize_t ret;
832         int fd;
833         void *buf;
834         size_t count;
835         off_t offset;
836
837         struct vfs_aio_state vfs_aio_state;
838         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
839 };
840
841 static void vfs_pread_do(void *private_data);
842 static void vfs_pread_done(struct tevent_req *subreq);
843 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state);
844
845 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
846                                              TALLOC_CTX *mem_ctx,
847                                              struct tevent_context *ev,
848                                              struct files_struct *fsp,
849                                              void *data,
850                                              size_t n, off_t offset)
851 {
852         struct tevent_req *req, *subreq;
853         struct vfswrap_pread_state *state;
854
855         req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
856         if (req == NULL) {
857                 return NULL;
858         }
859
860         state->ret = -1;
861         state->fd = fsp_get_io_fd(fsp);
862         state->buf = data;
863         state->count = n;
864         state->offset = offset;
865
866         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
867                                      state->profile_bytes, n);
868         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
869
870         subreq = pthreadpool_tevent_job_send(
871                 state, ev, handle->conn->sconn->pool,
872                 vfs_pread_do, state);
873         if (tevent_req_nomem(subreq, req)) {
874                 return tevent_req_post(req, ev);
875         }
876         tevent_req_set_callback(subreq, vfs_pread_done, req);
877
878         talloc_set_destructor(state, vfs_pread_state_destructor);
879
880         return req;
881 }
882
883 static void vfs_pread_do(void *private_data)
884 {
885         struct vfswrap_pread_state *state = talloc_get_type_abort(
886                 private_data, struct vfswrap_pread_state);
887         struct timespec start_time;
888         struct timespec end_time;
889
890         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
891
892         PROFILE_TIMESTAMP(&start_time);
893
894         state->ret = sys_pread_full(state->fd,
895                                     state->buf,
896                                     state->count,
897                                     state->offset);
898
899         if (state->ret == -1) {
900                 state->vfs_aio_state.error = errno;
901         }
902
903         PROFILE_TIMESTAMP(&end_time);
904
905         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
906
907         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
908 }
909
910 static int vfs_pread_state_destructor(struct vfswrap_pread_state *state)
911 {
912         return -1;
913 }
914
915 static void vfs_pread_done(struct tevent_req *subreq)
916 {
917         struct tevent_req *req = tevent_req_callback_data(
918                 subreq, struct tevent_req);
919         struct vfswrap_pread_state *state = tevent_req_data(
920                 req, struct vfswrap_pread_state);
921         int ret;
922
923         ret = pthreadpool_tevent_job_recv(subreq);
924         TALLOC_FREE(subreq);
925         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
926         talloc_set_destructor(state, NULL);
927         if (ret != 0) {
928                 if (ret != EAGAIN) {
929                         tevent_req_error(req, ret);
930                         return;
931                 }
932                 /*
933                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
934                  * means the lower level pthreadpool failed to create a new
935                  * thread. Fallback to sync processing in that case to allow
936                  * some progress for the client.
937                  */
938                 vfs_pread_do(state);
939         }
940
941         tevent_req_done(req);
942 }
943
944 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
945                                   struct vfs_aio_state *vfs_aio_state)
946 {
947         struct vfswrap_pread_state *state = tevent_req_data(
948                 req, struct vfswrap_pread_state);
949
950         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
951                 return -1;
952         }
953
954         *vfs_aio_state = state->vfs_aio_state;
955         return state->ret;
956 }
957
958 struct vfswrap_pwrite_state {
959         ssize_t ret;
960         int fd;
961         const void *buf;
962         size_t count;
963         off_t offset;
964
965         struct vfs_aio_state vfs_aio_state;
966         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
967 };
968
969 static void vfs_pwrite_do(void *private_data);
970 static void vfs_pwrite_done(struct tevent_req *subreq);
971 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
972
973 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
974                                               TALLOC_CTX *mem_ctx,
975                                               struct tevent_context *ev,
976                                               struct files_struct *fsp,
977                                               const void *data,
978                                               size_t n, off_t offset)
979 {
980         struct tevent_req *req, *subreq;
981         struct vfswrap_pwrite_state *state;
982
983         req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
984         if (req == NULL) {
985                 return NULL;
986         }
987
988         state->ret = -1;
989         state->fd = fsp_get_io_fd(fsp);
990         state->buf = data;
991         state->count = n;
992         state->offset = offset;
993
994         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
995                                      state->profile_bytes, n);
996         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
997
998         subreq = pthreadpool_tevent_job_send(
999                 state, ev, handle->conn->sconn->pool,
1000                 vfs_pwrite_do, state);
1001         if (tevent_req_nomem(subreq, req)) {
1002                 return tevent_req_post(req, ev);
1003         }
1004         tevent_req_set_callback(subreq, vfs_pwrite_done, req);
1005
1006         talloc_set_destructor(state, vfs_pwrite_state_destructor);
1007
1008         return req;
1009 }
1010
1011 static void vfs_pwrite_do(void *private_data)
1012 {
1013         struct vfswrap_pwrite_state *state = talloc_get_type_abort(
1014                 private_data, struct vfswrap_pwrite_state);
1015         struct timespec start_time;
1016         struct timespec end_time;
1017
1018         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1019
1020         PROFILE_TIMESTAMP(&start_time);
1021
1022         state->ret = sys_pwrite_full(state->fd,
1023                                      state->buf,
1024                                      state->count,
1025                                      state->offset);
1026
1027         if (state->ret == -1) {
1028                 state->vfs_aio_state.error = errno;
1029         }
1030
1031         PROFILE_TIMESTAMP(&end_time);
1032
1033         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1034
1035         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1036 }
1037
1038 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1039 {
1040         return -1;
1041 }
1042
1043 static void vfs_pwrite_done(struct tevent_req *subreq)
1044 {
1045         struct tevent_req *req = tevent_req_callback_data(
1046                 subreq, struct tevent_req);
1047         struct vfswrap_pwrite_state *state = tevent_req_data(
1048                 req, struct vfswrap_pwrite_state);
1049         int ret;
1050
1051         ret = pthreadpool_tevent_job_recv(subreq);
1052         TALLOC_FREE(subreq);
1053         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1054         talloc_set_destructor(state, NULL);
1055         if (ret != 0) {
1056                 if (ret != EAGAIN) {
1057                         tevent_req_error(req, ret);
1058                         return;
1059                 }
1060                 /*
1061                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1062                  * means the lower level pthreadpool failed to create a new
1063                  * thread. Fallback to sync processing in that case to allow
1064                  * some progress for the client.
1065                  */
1066                 vfs_pwrite_do(state);
1067         }
1068
1069         tevent_req_done(req);
1070 }
1071
1072 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1073                                    struct vfs_aio_state *vfs_aio_state)
1074 {
1075         struct vfswrap_pwrite_state *state = tevent_req_data(
1076                 req, struct vfswrap_pwrite_state);
1077
1078         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1079                 return -1;
1080         }
1081
1082         *vfs_aio_state = state->vfs_aio_state;
1083         return state->ret;
1084 }
1085
1086 struct vfswrap_fsync_state {
1087         ssize_t ret;
1088         int fd;
1089
1090         struct vfs_aio_state vfs_aio_state;
1091         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1092 };
1093
1094 static void vfs_fsync_do(void *private_data);
1095 static void vfs_fsync_done(struct tevent_req *subreq);
1096 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1097
1098 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1099                                              TALLOC_CTX *mem_ctx,
1100                                              struct tevent_context *ev,
1101                                              struct files_struct *fsp)
1102 {
1103         struct tevent_req *req, *subreq;
1104         struct vfswrap_fsync_state *state;
1105
1106         req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1107         if (req == NULL) {
1108                 return NULL;
1109         }
1110
1111         state->ret = -1;
1112         state->fd = fsp_get_io_fd(fsp);
1113
1114         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1115                                      state->profile_bytes, 0);
1116         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1117
1118         subreq = pthreadpool_tevent_job_send(
1119                 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1120         if (tevent_req_nomem(subreq, req)) {
1121                 return tevent_req_post(req, ev);
1122         }
1123         tevent_req_set_callback(subreq, vfs_fsync_done, req);
1124
1125         talloc_set_destructor(state, vfs_fsync_state_destructor);
1126
1127         return req;
1128 }
1129
1130 static void vfs_fsync_do(void *private_data)
1131 {
1132         struct vfswrap_fsync_state *state = talloc_get_type_abort(
1133                 private_data, struct vfswrap_fsync_state);
1134         struct timespec start_time;
1135         struct timespec end_time;
1136
1137         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1138
1139         PROFILE_TIMESTAMP(&start_time);
1140
1141         do {
1142                 state->ret = fsync(state->fd);
1143         } while ((state->ret == -1) && (errno == EINTR));
1144
1145         if (state->ret == -1) {
1146                 state->vfs_aio_state.error = errno;
1147         }
1148
1149         PROFILE_TIMESTAMP(&end_time);
1150
1151         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1152
1153         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1154 }
1155
1156 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1157 {
1158         return -1;
1159 }
1160
1161 static void vfs_fsync_done(struct tevent_req *subreq)
1162 {
1163         struct tevent_req *req = tevent_req_callback_data(
1164                 subreq, struct tevent_req);
1165         struct vfswrap_fsync_state *state = tevent_req_data(
1166                 req, struct vfswrap_fsync_state);
1167         int ret;
1168
1169         ret = pthreadpool_tevent_job_recv(subreq);
1170         TALLOC_FREE(subreq);
1171         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1172         talloc_set_destructor(state, NULL);
1173         if (ret != 0) {
1174                 if (ret != EAGAIN) {
1175                         tevent_req_error(req, ret);
1176                         return;
1177                 }
1178                 /*
1179                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1180                  * means the lower level pthreadpool failed to create a new
1181                  * thread. Fallback to sync processing in that case to allow
1182                  * some progress for the client.
1183                  */
1184                 vfs_fsync_do(state);
1185         }
1186
1187         tevent_req_done(req);
1188 }
1189
1190 static int vfswrap_fsync_recv(struct tevent_req *req,
1191                               struct vfs_aio_state *vfs_aio_state)
1192 {
1193         struct vfswrap_fsync_state *state = tevent_req_data(
1194                 req, struct vfswrap_fsync_state);
1195
1196         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1197                 return -1;
1198         }
1199
1200         *vfs_aio_state = state->vfs_aio_state;
1201         return state->ret;
1202 }
1203
1204 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1205 {
1206         off_t result = 0;
1207
1208         START_PROFILE(syscall_lseek);
1209
1210         result = lseek(fsp_get_io_fd(fsp), offset, whence);
1211         /*
1212          * We want to maintain the fiction that we can seek
1213          * on a fifo for file system purposes. This allows
1214          * people to set up UNIX fifo's that feed data to Windows
1215          * applications. JRA.
1216          */
1217
1218         if((result == -1) && (errno == ESPIPE)) {
1219                 result = 0;
1220                 errno = 0;
1221         }
1222
1223         END_PROFILE(syscall_lseek);
1224         return result;
1225 }
1226
1227 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1228                         off_t offset, size_t n)
1229 {
1230         ssize_t result;
1231
1232         START_PROFILE_BYTES(syscall_sendfile, n);
1233         result = sys_sendfile(tofd, fsp_get_io_fd(fromfsp), hdr, offset, n);
1234         END_PROFILE_BYTES(syscall_sendfile);
1235         return result;
1236 }
1237
1238 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1239                         int fromfd,
1240                         files_struct *tofsp,
1241                         off_t offset,
1242                         size_t n)
1243 {
1244         ssize_t result;
1245
1246         START_PROFILE_BYTES(syscall_recvfile, n);
1247         result = sys_recvfile(fromfd, fsp_get_io_fd(tofsp), offset, n);
1248         END_PROFILE_BYTES(syscall_recvfile);
1249         return result;
1250 }
1251
1252 static int vfswrap_renameat(vfs_handle_struct *handle,
1253                           files_struct *srcfsp,
1254                           const struct smb_filename *smb_fname_src,
1255                           files_struct *dstfsp,
1256                           const struct smb_filename *smb_fname_dst)
1257 {
1258         int result = -1;
1259
1260         START_PROFILE(syscall_renameat);
1261
1262         if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1263                 errno = ENOENT;
1264                 goto out;
1265         }
1266
1267         result = renameat(fsp_get_pathref_fd(srcfsp),
1268                         smb_fname_src->base_name,
1269                         fsp_get_pathref_fd(dstfsp),
1270                         smb_fname_dst->base_name);
1271
1272  out:
1273         END_PROFILE(syscall_renameat);
1274         return result;
1275 }
1276
1277 static int vfswrap_stat(vfs_handle_struct *handle,
1278                         struct smb_filename *smb_fname)
1279 {
1280         int result = -1;
1281
1282         START_PROFILE(syscall_stat);
1283
1284         if (is_named_stream(smb_fname)) {
1285                 errno = ENOENT;
1286                 goto out;
1287         }
1288
1289         result = sys_stat(smb_fname->base_name, &smb_fname->st,
1290                           lp_fake_directory_create_times(SNUM(handle->conn)));
1291  out:
1292         END_PROFILE(syscall_stat);
1293         return result;
1294 }
1295
1296 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1297 {
1298         int result;
1299
1300         START_PROFILE(syscall_fstat);
1301         result = sys_fstat(fsp_get_pathref_fd(fsp),
1302                            sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1303         END_PROFILE(syscall_fstat);
1304         return result;
1305 }
1306
1307 static int vfswrap_lstat(vfs_handle_struct *handle,
1308                          struct smb_filename *smb_fname)
1309 {
1310         int result = -1;
1311
1312         START_PROFILE(syscall_lstat);
1313
1314         if (is_named_stream(smb_fname)) {
1315                 errno = ENOENT;
1316                 goto out;
1317         }
1318
1319         result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1320                            lp_fake_directory_create_times(SNUM(handle->conn)));
1321  out:
1322         END_PROFILE(syscall_lstat);
1323         return result;
1324 }
1325
1326 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1327                                        const char *name,
1328                                        enum vfs_translate_direction direction,
1329                                        TALLOC_CTX *mem_ctx,
1330                                        char **mapped_name)
1331 {
1332         return NT_STATUS_NONE_MAPPED;
1333 }
1334
1335 /**
1336  * Return allocated parent directory and basename of path
1337  *
1338  * Note: if requesting name, it is returned as talloc child of the
1339  * parent. Freeing the parent is thus sufficient to free both.
1340  */
1341 static NTSTATUS vfswrap_parent_pathname(struct vfs_handle_struct *handle,
1342                                         TALLOC_CTX *mem_ctx,
1343                                         const struct smb_filename *smb_fname_in,
1344                                         struct smb_filename **parent_dir_out,
1345                                         struct smb_filename **atname_out)
1346 {
1347         TALLOC_CTX *frame = talloc_stackframe();
1348         struct smb_filename *parent = NULL;
1349         struct smb_filename *name = NULL;
1350         char *p = NULL;
1351
1352         parent = cp_smb_filename(frame, smb_fname_in);
1353         if (parent == NULL) {
1354                 TALLOC_FREE(frame);
1355                 return NT_STATUS_NO_MEMORY;
1356         }
1357         TALLOC_FREE(parent->stream_name);
1358         SET_STAT_INVALID(parent->st);
1359
1360         p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */
1361         if (p == NULL) {
1362                 TALLOC_FREE(parent->base_name);
1363                 parent->base_name = talloc_strdup(parent, ".");
1364                 if (parent->base_name == NULL) {
1365                         TALLOC_FREE(frame);
1366                         return NT_STATUS_NO_MEMORY;
1367                 }
1368                 p = smb_fname_in->base_name;
1369         } else {
1370                 *p = '\0';
1371                 p++;
1372         }
1373
1374         if (atname_out == NULL) {
1375                 *parent_dir_out = talloc_move(mem_ctx, &parent);
1376                 TALLOC_FREE(frame);
1377                 return NT_STATUS_OK;
1378         }
1379
1380         name = cp_smb_filename(frame, smb_fname_in);
1381         if (name == NULL) {
1382                 TALLOC_FREE(frame);
1383                 return NT_STATUS_NO_MEMORY;
1384         }
1385         TALLOC_FREE(name->base_name);
1386
1387         name->base_name = talloc_strdup(name, p);
1388         if (name->base_name == NULL) {
1389                 TALLOC_FREE(frame);
1390                 return NT_STATUS_NO_MEMORY;
1391         }
1392
1393         *parent_dir_out = talloc_move(mem_ctx, &parent);
1394         *atname_out = talloc_move(*parent_dir_out, &name);
1395         TALLOC_FREE(frame);
1396         return NT_STATUS_OK;
1397 }
1398
1399 /*
1400  * Implement the default fsctl operation.
1401  */
1402 static bool vfswrap_logged_ioctl_message = false;
1403
1404 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1405                               struct files_struct *fsp,
1406                               TALLOC_CTX *ctx,
1407                               uint32_t function,
1408                               uint16_t req_flags, /* Needed for UNICODE ... */
1409                               const uint8_t *_in_data,
1410                               uint32_t in_len,
1411                               uint8_t **_out_data,
1412                               uint32_t max_out_len,
1413                               uint32_t *out_len)
1414 {
1415         const char *in_data = (const char *)_in_data;
1416         char **out_data = (char **)_out_data;
1417         NTSTATUS status;
1418
1419         switch (function) {
1420         case FSCTL_SET_SPARSE:
1421         {
1422                 bool set_sparse = true;
1423
1424                 if (in_len >= 1 && in_data[0] == 0) {
1425                         set_sparse = false;
1426                 }
1427
1428                 status = file_set_sparse(handle->conn, fsp, set_sparse);
1429
1430                 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1431                       ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1432                        smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1433                        nt_errstr(status)));
1434
1435                 return status;
1436         }
1437
1438         case FSCTL_CREATE_OR_GET_OBJECT_ID:
1439         {
1440                 unsigned char objid[16];
1441                 char *return_data = NULL;
1442
1443                 /* This should return the object-id on this file.
1444                  * I think I'll make this be the inode+dev. JRA.
1445                  */
1446
1447                 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1448                           fsp_fnum_dbg(fsp)));
1449
1450                 *out_len = MIN(max_out_len, 64);
1451
1452                 /* Hmmm, will this cause problems if less data asked for? */
1453                 return_data = talloc_array(ctx, char, 64);
1454                 if (return_data == NULL) {
1455                         return NT_STATUS_NO_MEMORY;
1456                 }
1457
1458                 /* For backwards compatibility only store the dev/inode. */
1459                 push_file_id_16(return_data, &fsp->file_id);
1460                 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1461                 push_file_id_16(return_data+32, &fsp->file_id);
1462                 memset(return_data+48, 0, 16);
1463                 *out_data = return_data;
1464                 return NT_STATUS_OK;
1465         }
1466
1467         case FSCTL_GET_REPARSE_POINT:
1468         {
1469                 status = fsctl_get_reparse_point(
1470                         fsp, ctx, out_data, max_out_len, out_len);
1471                 return status;
1472         }
1473
1474         case FSCTL_SET_REPARSE_POINT:
1475         {
1476                 status = fsctl_set_reparse_point(fsp, ctx, _in_data, in_len);
1477                 return status;
1478         }
1479
1480         case FSCTL_DELETE_REPARSE_POINT:
1481         {
1482                 status = fsctl_del_reparse_point(fsp, ctx, _in_data, in_len);
1483                 return status;
1484         }
1485
1486         case FSCTL_GET_SHADOW_COPY_DATA:
1487         {
1488                 /*
1489                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1490                  * and return their volume names.  If max_data_count is 16, then it is just
1491                  * asking for the number of volumes and length of the combined names.
1492                  *
1493                  * pdata is the data allocated by our caller, but that uses
1494                  * total_data_count (which is 0 in our case) rather than max_data_count.
1495                  * Allocate the correct amount and return the pointer to let
1496                  * it be deallocated when we return.
1497                  */
1498                 struct shadow_copy_data *shadow_data = NULL;
1499                 bool labels = False;
1500                 uint32_t labels_data_count = 0;
1501                 uint32_t i;
1502                 char *cur_pdata = NULL;
1503
1504                 if (max_out_len < 16) {
1505                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1506                                 max_out_len));
1507                         return NT_STATUS_INVALID_PARAMETER;
1508                 }
1509
1510                 if (max_out_len > 16) {
1511                         labels = True;
1512                 }
1513
1514                 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1515                 if (shadow_data == NULL) {
1516                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
1517                         return NT_STATUS_NO_MEMORY;
1518                 }
1519
1520                 /*
1521                  * Call the VFS routine to actually do the work.
1522                  */
1523                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1524                         int log_lev = 0;
1525                         if (errno == 0) {
1526                                 /* broken module didn't set errno on error */
1527                                 status = NT_STATUS_UNSUCCESSFUL;
1528                         } else {
1529                                 status = map_nt_error_from_unix(errno);
1530                                 if (NT_STATUS_EQUAL(status,
1531                                                     NT_STATUS_NOT_SUPPORTED)) {
1532                                         log_lev = 5;
1533                                 }
1534                         }
1535                         DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1536                                         "connectpath %s, failed - %s.\n",
1537                                         fsp->conn->connectpath,
1538                                         nt_errstr(status)));
1539                         TALLOC_FREE(shadow_data);
1540                         return status;
1541                 }
1542
1543                 labels_data_count = (shadow_data->num_volumes * 2 *
1544                                         sizeof(SHADOW_COPY_LABEL)) + 2;
1545
1546                 if (!labels) {
1547                         *out_len = 16;
1548                 } else {
1549                         *out_len = 12 + labels_data_count;
1550                 }
1551
1552                 if (max_out_len < *out_len) {
1553                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1554                                 max_out_len, *out_len));
1555                         TALLOC_FREE(shadow_data);
1556                         return NT_STATUS_BUFFER_TOO_SMALL;
1557                 }
1558
1559                 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1560                 if (cur_pdata == NULL) {
1561                         TALLOC_FREE(shadow_data);
1562                         return NT_STATUS_NO_MEMORY;
1563                 }
1564
1565                 *out_data = cur_pdata;
1566
1567                 /* num_volumes 4 bytes */
1568                 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1569
1570                 if (labels) {
1571                         /* num_labels 4 bytes */
1572                         SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1573                 }
1574
1575                 /* needed_data_count 4 bytes */
1576                 SIVAL(cur_pdata, 8, labels_data_count);
1577
1578                 cur_pdata += 12;
1579
1580                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1581                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
1582                 if (labels && shadow_data->labels) {
1583                         for (i=0; i<shadow_data->num_volumes; i++) {
1584                                 size_t len = 0;
1585                                 status = srvstr_push(cur_pdata, req_flags,
1586                                             cur_pdata, shadow_data->labels[i],
1587                                             2 * sizeof(SHADOW_COPY_LABEL),
1588                                             STR_UNICODE|STR_TERMINATE, &len);
1589                                 if (!NT_STATUS_IS_OK(status)) {
1590                                         TALLOC_FREE(*out_data);
1591                                         TALLOC_FREE(shadow_data);
1592                                         return status;
1593                                 }
1594                                 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1595                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1596                         }
1597                 }
1598
1599                 TALLOC_FREE(shadow_data);
1600
1601                 return NT_STATUS_OK;
1602         }
1603
1604         case FSCTL_FIND_FILES_BY_SID:
1605         {
1606                 /* pretend this succeeded -
1607                  *
1608                  * we have to send back a list with all files owned by this SID
1609                  *
1610                  * but I have to check that --metze
1611                  */
1612                 ssize_t ret;
1613                 struct dom_sid sid;
1614                 struct dom_sid_buf buf;
1615                 uid_t uid;
1616                 size_t sid_len;
1617
1618                 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1619                            fsp_fnum_dbg(fsp)));
1620
1621                 if (in_len < 8) {
1622                         /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1623                         return NT_STATUS_INVALID_PARAMETER;
1624                 }
1625
1626                 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1627
1628                 /* unknown 4 bytes: this is not the length of the sid :-(  */
1629                 /*unknown = IVAL(pdata,0);*/
1630
1631                 ret = sid_parse(_in_data + 4, sid_len, &sid);
1632                 if (ret == -1) {
1633                         return NT_STATUS_INVALID_PARAMETER;
1634                 }
1635                 DEBUGADD(10, ("for SID: %s\n",
1636                               dom_sid_str_buf(&sid, &buf)));
1637
1638                 if (!sid_to_uid(&sid, &uid)) {
1639                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1640                                  dom_sid_str_buf(&sid, &buf),
1641                                  (unsigned long)sid_len));
1642                         uid = (-1);
1643                 }
1644
1645                 /* we can take a look at the find source :-)
1646                  *
1647                  * find ./ -uid $uid  -name '*'   is what we need here
1648                  *
1649                  *
1650                  * and send 4bytes len and then NULL terminated unicode strings
1651                  * for each file
1652                  *
1653                  * but I don't know how to deal with the paged results
1654                  * (maybe we can hang the result anywhere in the fsp struct)
1655                  *
1656                  * but I don't know how to deal with the paged results
1657                  * (maybe we can hang the result anywhere in the fsp struct)
1658                  *
1659                  * we don't send all files at once
1660                  * and at the next we should *not* start from the beginning,
1661                  * so we have to cache the result
1662                  *
1663                  * --metze
1664                  */
1665
1666                 /* this works for now... */
1667                 return NT_STATUS_OK;
1668         }
1669
1670         case FSCTL_QUERY_ALLOCATED_RANGES:
1671         {
1672                 /* FIXME: This is just a dummy reply, telling that all of the
1673                  * file is allocated. MKS cp needs that.
1674                  * Adding the real allocated ranges via FIEMAP on Linux
1675                  * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1676                  * this FSCTL correct for sparse files.
1677                  */
1678                 uint64_t offset, length;
1679                 char *out_data_tmp = NULL;
1680
1681                 if (in_len != 16) {
1682                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1683                                 in_len));
1684                         return NT_STATUS_INVALID_PARAMETER;
1685                 }
1686
1687                 if (max_out_len < 16) {
1688                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1689                                 max_out_len));
1690                         return NT_STATUS_INVALID_PARAMETER;
1691                 }
1692
1693                 offset = BVAL(in_data,0);
1694                 length = BVAL(in_data,8);
1695
1696                 if (offset + length < offset) {
1697                         /* No 64-bit integer wrap. */
1698                         return NT_STATUS_INVALID_PARAMETER;
1699                 }
1700
1701                 /* Shouldn't this be SMB_VFS_STAT ... ? */
1702                 status = vfs_stat_fsp(fsp);
1703                 if (!NT_STATUS_IS_OK(status)) {
1704                         return status;
1705                 }
1706
1707                 *out_len = 16;
1708                 out_data_tmp = talloc_array(ctx, char, *out_len);
1709                 if (out_data_tmp == NULL) {
1710                         DEBUG(10, ("unable to allocate memory for response\n"));
1711                         return NT_STATUS_NO_MEMORY;
1712                 }
1713
1714                 if (offset > fsp->fsp_name->st.st_ex_size ||
1715                                 fsp->fsp_name->st.st_ex_size == 0 ||
1716                                 length == 0) {
1717                         memset(out_data_tmp, 0, *out_len);
1718                 } else {
1719                         uint64_t end = offset + length;
1720                         end = MIN(end, fsp->fsp_name->st.st_ex_size);
1721                         SBVAL(out_data_tmp, 0, 0);
1722                         SBVAL(out_data_tmp, 8, end);
1723                 }
1724
1725                 *out_data = out_data_tmp;
1726
1727                 return NT_STATUS_OK;
1728         }
1729
1730         case FSCTL_IS_VOLUME_DIRTY:
1731         {
1732                 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1733                           "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1734                 /*
1735                  * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1736                  * says we have to respond with NT_STATUS_INVALID_PARAMETER
1737                  */
1738                 return NT_STATUS_INVALID_PARAMETER;
1739         }
1740
1741         default:
1742                 /*
1743                  * Only print once ... unfortunately there could be lots of
1744                  * different FSCTLs that are called.
1745                  */
1746                 if (!vfswrap_logged_ioctl_message) {
1747                         vfswrap_logged_ioctl_message = true;
1748                         DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1749                         __func__, function));
1750                 }
1751         }
1752
1753         return NT_STATUS_NOT_SUPPORTED;
1754 }
1755
1756 static bool vfswrap_is_offline(struct connection_struct *conn,
1757                                const struct smb_filename *fname);
1758
1759 struct vfswrap_get_dos_attributes_state {
1760         struct vfs_aio_state aio_state;
1761         connection_struct *conn;
1762         TALLOC_CTX *mem_ctx;
1763         struct tevent_context *ev;
1764         files_struct *dir_fsp;
1765         struct smb_filename *smb_fname;
1766         uint32_t dosmode;
1767         bool as_root;
1768 };
1769
1770 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1771
1772 static struct tevent_req *vfswrap_get_dos_attributes_send(
1773                         TALLOC_CTX *mem_ctx,
1774                         struct tevent_context *ev,
1775                         struct vfs_handle_struct *handle,
1776                         files_struct *dir_fsp,
1777                         struct smb_filename *smb_fname)
1778 {
1779         struct tevent_req *req = NULL;
1780         struct tevent_req *subreq = NULL;
1781         struct vfswrap_get_dos_attributes_state *state = NULL;
1782
1783         req = tevent_req_create(mem_ctx, &state,
1784                                 struct vfswrap_get_dos_attributes_state);
1785         if (req == NULL) {
1786                 return NULL;
1787         }
1788
1789         *state = (struct vfswrap_get_dos_attributes_state) {
1790                 .conn = dir_fsp->conn,
1791                 .mem_ctx = mem_ctx,
1792                 .ev = ev,
1793                 .dir_fsp = dir_fsp,
1794                 .smb_fname = smb_fname,
1795         };
1796
1797         subreq = SMB_VFS_GETXATTRAT_SEND(state,
1798                                          ev,
1799                                          dir_fsp,
1800                                          smb_fname,
1801                                          SAMBA_XATTR_DOS_ATTRIB,
1802                                          sizeof(fstring));
1803         if (tevent_req_nomem(subreq, req)) {
1804                 return tevent_req_post(req, ev);
1805         }
1806         tevent_req_set_callback(subreq,
1807                                 vfswrap_get_dos_attributes_getxattr_done,
1808                                 req);
1809
1810         return req;
1811 }
1812
1813 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1814 {
1815         struct tevent_req *req =
1816                 tevent_req_callback_data(subreq,
1817                 struct tevent_req);
1818         struct vfswrap_get_dos_attributes_state *state =
1819                 tevent_req_data(req,
1820                 struct vfswrap_get_dos_attributes_state);
1821         ssize_t xattr_size;
1822         DATA_BLOB blob = {0};
1823         char *path = NULL;
1824         char *tofree = NULL;
1825         char pathbuf[PATH_MAX+1];
1826         ssize_t pathlen;
1827         struct smb_filename smb_fname;
1828         bool offline;
1829         NTSTATUS status;
1830
1831         xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1832                                              &state->aio_state,
1833                                              state,
1834                                              &blob.data);
1835         TALLOC_FREE(subreq);
1836         if (xattr_size == -1) {
1837                 status = map_nt_error_from_unix(state->aio_state.error);
1838
1839                 if (state->as_root) {
1840                         tevent_req_nterror(req, status);
1841                         return;
1842                 }
1843                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1844                         tevent_req_nterror(req, status);
1845                         return;
1846                 }
1847
1848                 state->as_root = true;
1849
1850                 become_root();
1851                 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1852                                                  state->ev,
1853                                                  state->dir_fsp,
1854                                                  state->smb_fname,
1855                                                  SAMBA_XATTR_DOS_ATTRIB,
1856                                                  sizeof(fstring));
1857                 unbecome_root();
1858                 if (tevent_req_nomem(subreq, req)) {
1859                         return;
1860                 }
1861                 tevent_req_set_callback(subreq,
1862                                         vfswrap_get_dos_attributes_getxattr_done,
1863                                         req);
1864                 return;
1865         }
1866
1867         blob.length = xattr_size;
1868
1869         status = parse_dos_attribute_blob(state->smb_fname,
1870                                           blob,
1871                                           &state->dosmode);
1872         if (!NT_STATUS_IS_OK(status)) {
1873                 tevent_req_nterror(req, status);
1874                 return;
1875         }
1876
1877         pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1878                                 state->smb_fname->base_name,
1879                                 pathbuf,
1880                                 sizeof(pathbuf),
1881                                 &path,
1882                                 &tofree);
1883         if (pathlen == -1) {
1884                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1885                 return;
1886         }
1887
1888         smb_fname = (struct smb_filename) {
1889                 .base_name = path,
1890                 .st = state->smb_fname->st,
1891                 .flags = state->smb_fname->flags,
1892                 .twrp = state->smb_fname->twrp,
1893         };
1894
1895         offline = vfswrap_is_offline(state->conn, &smb_fname);
1896         if (offline) {
1897                 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1898         }
1899         TALLOC_FREE(tofree);
1900
1901         tevent_req_done(req);
1902         return;
1903 }
1904
1905 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1906                                                 struct vfs_aio_state *aio_state,
1907                                                 uint32_t *dosmode)
1908 {
1909         struct vfswrap_get_dos_attributes_state *state =
1910                 tevent_req_data(req,
1911                 struct vfswrap_get_dos_attributes_state);
1912         NTSTATUS status;
1913
1914         if (tevent_req_is_nterror(req, &status)) {
1915                 tevent_req_received(req);
1916                 return status;
1917         }
1918
1919         *aio_state = state->aio_state;
1920         *dosmode = state->dosmode;
1921         tevent_req_received(req);
1922         return NT_STATUS_OK;
1923 }
1924
1925 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1926                                             struct files_struct *fsp,
1927                                             uint32_t *dosmode)
1928 {
1929         bool offline;
1930
1931         offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1932         if (offline) {
1933                 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1934         }
1935
1936         return fget_ea_dos_attribute(fsp, dosmode);
1937 }
1938
1939 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1940                                             struct files_struct *fsp,
1941                                             uint32_t dosmode)
1942 {
1943         return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1944 }
1945
1946 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1947
1948 struct vfswrap_offload_read_state {
1949         DATA_BLOB token;
1950 };
1951
1952 static struct tevent_req *vfswrap_offload_read_send(
1953         TALLOC_CTX *mem_ctx,
1954         struct tevent_context *ev,
1955         struct vfs_handle_struct *handle,
1956         struct files_struct *fsp,
1957         uint32_t fsctl,
1958         uint32_t ttl,
1959         off_t offset,
1960         size_t to_copy)
1961 {
1962         struct tevent_req *req = NULL;
1963         struct vfswrap_offload_read_state *state = NULL;
1964         NTSTATUS status;
1965
1966         req = tevent_req_create(mem_ctx, &state,
1967                                 struct vfswrap_offload_read_state);
1968         if (req == NULL) {
1969                 return NULL;
1970         }
1971
1972         status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1973                                             &vfswrap_offload_ctx);
1974         if (tevent_req_nterror(req, status)) {
1975                 return tevent_req_post(req, ev);
1976         }
1977
1978         if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1979                 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1980                 return tevent_req_post(req, ev);
1981         }
1982
1983         status = vfs_offload_token_create_blob(state, fsp, fsctl,
1984                                                &state->token);
1985         if (tevent_req_nterror(req, status)) {
1986                 return tevent_req_post(req, ev);
1987         }
1988
1989         status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1990                                                 &state->token);
1991         if (tevent_req_nterror(req, status)) {
1992                 return tevent_req_post(req, ev);
1993         }
1994
1995         tevent_req_done(req);
1996         return tevent_req_post(req, ev);
1997 }
1998
1999 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
2000                                           struct vfs_handle_struct *handle,
2001                                           TALLOC_CTX *mem_ctx,
2002                                           DATA_BLOB *token)
2003 {
2004         struct vfswrap_offload_read_state *state = tevent_req_data(
2005                 req, struct vfswrap_offload_read_state);
2006         NTSTATUS status;
2007
2008         if (tevent_req_is_nterror(req, &status)) {
2009                 tevent_req_received(req);
2010                 return status;
2011         }
2012
2013         token->length = state->token.length;
2014         token->data = talloc_move(mem_ctx, &state->token.data);
2015
2016         tevent_req_received(req);
2017         return NT_STATUS_OK;
2018 }
2019
2020 struct vfswrap_offload_write_state {
2021         uint8_t *buf;
2022         bool read_lck_locked;
2023         bool write_lck_locked;
2024         DATA_BLOB *token;
2025         struct tevent_context *src_ev;
2026         struct files_struct *src_fsp;
2027         off_t src_off;
2028         struct tevent_context *dst_ev;
2029         struct files_struct *dst_fsp;
2030         off_t dst_off;
2031         off_t to_copy;
2032         off_t remaining;
2033         off_t copied;
2034         size_t next_io_size;
2035 };
2036
2037 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2038                                           enum tevent_req_state req_state)
2039 {
2040         struct vfswrap_offload_write_state *state = tevent_req_data(
2041                 req, struct vfswrap_offload_write_state);
2042         bool ok;
2043
2044         if (state->dst_fsp == NULL) {
2045                 return;
2046         }
2047
2048         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2049         SMB_ASSERT(ok);
2050         state->dst_fsp = NULL;
2051 }
2052
2053 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
2054 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2055
2056 static struct tevent_req *vfswrap_offload_write_send(
2057         struct vfs_handle_struct *handle,
2058         TALLOC_CTX *mem_ctx,
2059         struct tevent_context *ev,
2060         uint32_t fsctl,
2061         DATA_BLOB *token,
2062         off_t transfer_offset,
2063         struct files_struct *dest_fsp,
2064         off_t dest_off,
2065         off_t to_copy)
2066 {
2067         struct tevent_req *req;
2068         struct vfswrap_offload_write_state *state = NULL;
2069         /* off_t is signed! */
2070         off_t max_offset = INT64_MAX - to_copy;
2071         size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2072         files_struct *src_fsp = NULL;
2073         NTSTATUS status;
2074         bool ok;
2075
2076         req = tevent_req_create(mem_ctx, &state,
2077                                 struct vfswrap_offload_write_state);
2078         if (req == NULL) {
2079                 return NULL;
2080         }
2081
2082         *state = (struct vfswrap_offload_write_state) {
2083                 .token = token,
2084                 .src_off = transfer_offset,
2085                 .dst_ev = ev,
2086                 .dst_fsp = dest_fsp,
2087                 .dst_off = dest_off,
2088                 .to_copy = to_copy,
2089                 .remaining = to_copy,
2090         };
2091
2092         tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2093
2094         switch (fsctl) {
2095         case FSCTL_SRV_COPYCHUNK:
2096         case FSCTL_SRV_COPYCHUNK_WRITE:
2097                 break;
2098
2099         case FSCTL_OFFLOAD_WRITE:
2100                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2101                 return tevent_req_post(req, ev);
2102
2103         case FSCTL_DUP_EXTENTS_TO_FILE:
2104                 DBG_DEBUG("COW clones not supported by vfs_default\n");
2105                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2106                 return tevent_req_post(req, ev);
2107
2108         default:
2109                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2110                 return tevent_req_post(req, ev);
2111         }
2112
2113         /*
2114          * From here on we assume a copy-chunk fsctl
2115          */
2116
2117         if (to_copy == 0) {
2118                 tevent_req_done(req);
2119                 return tevent_req_post(req, ev);
2120         }
2121
2122         if (state->src_off > max_offset) {
2123                 /*
2124                  * Protect integer checks below.
2125                  */
2126                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2127                 return tevent_req_post(req, ev);
2128         }
2129         if (state->src_off < 0) {
2130                 /*
2131                  * Protect integer checks below.
2132                  */
2133                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2134                 return tevent_req_post(req, ev);
2135         }
2136         if (state->dst_off > max_offset) {
2137                 /*
2138                  * Protect integer checks below.
2139                  */
2140                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2141                 return tevent_req_post(req, ev);
2142         }
2143         if (state->dst_off < 0) {
2144                 /*
2145                  * Protect integer checks below.
2146                  */
2147                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2148                 return tevent_req_post(req, ev);
2149         }
2150
2151         status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2152                                                 token, &src_fsp);
2153         if (tevent_req_nterror(req, status)) {
2154                 return tevent_req_post(req, ev);
2155         }
2156
2157         DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2158
2159         status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2160         if (!NT_STATUS_IS_OK(status)) {
2161                 tevent_req_nterror(req, status);
2162                 return tevent_req_post(req, ev);
2163         }
2164
2165         ok = change_to_user_and_service_by_fsp(src_fsp);
2166         if (!ok) {
2167                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2168                 return tevent_req_post(req, ev);
2169         }
2170
2171         state->src_ev = src_fsp->conn->sconn->ev_ctx;
2172         state->src_fsp = src_fsp;
2173
2174         status = vfs_stat_fsp(src_fsp);
2175         if (tevent_req_nterror(req, status)) {
2176                 return tevent_req_post(req, ev);
2177         }
2178
2179         if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2180                 /*
2181                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2182                  *   If the SourceOffset or SourceOffset + Length extends beyond
2183                  *   the end of file, the server SHOULD<240> treat this as a
2184                  *   STATUS_END_OF_FILE error.
2185                  * ...
2186                  *   <240> Section 3.3.5.15.6: Windows servers will return
2187                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2188                  */
2189                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2190                 return tevent_req_post(req, ev);
2191         }
2192
2193         status = vfswrap_offload_copy_file_range(req);
2194         if (NT_STATUS_IS_OK(status)) {
2195                 tevent_req_done(req);
2196                 return tevent_req_post(req, ev);
2197         }
2198         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2199                 tevent_req_nterror(req, status);
2200                 return tevent_req_post(req, ev);
2201         }
2202
2203         state->buf = talloc_array(state, uint8_t, num);
2204         if (tevent_req_nomem(state->buf, req)) {
2205                 return tevent_req_post(req, ev);
2206         }
2207
2208         status = vfswrap_offload_write_loop(req);
2209         if (!NT_STATUS_IS_OK(status)) {
2210                 tevent_req_nterror(req, status);
2211                 return tevent_req_post(req, ev);
2212         }
2213
2214         return req;
2215 }
2216
2217 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
2218 {
2219         struct vfswrap_offload_write_state *state = tevent_req_data(
2220                 req, struct vfswrap_offload_write_state);
2221         struct lock_struct lck;
2222         ssize_t nwritten;
2223         NTSTATUS status;
2224         bool same_file;
2225         bool ok;
2226
2227 #ifndef USE_COPY_FILE_RANGE
2228         return NT_STATUS_MORE_PROCESSING_REQUIRED;
2229 #endif
2230
2231         same_file = file_id_equal(&state->src_fsp->file_id,
2232                                   &state->dst_fsp->file_id);
2233         if (same_file &&
2234             sys_io_ranges_overlap(state->remaining,
2235                                   state->src_off,
2236                                   state->remaining,
2237                                   state->dst_off))
2238         {
2239                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2240         }
2241
2242         if (is_named_stream(state->src_fsp->fsp_name) ||
2243             is_named_stream(state->dst_fsp->fsp_name))
2244         {
2245                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2246         }
2247
2248         init_strict_lock_struct(state->src_fsp,
2249                                 state->src_fsp->op->global->open_persistent_id,
2250                                 state->src_off,
2251                                 state->remaining,
2252                                 READ_LOCK,
2253                                 &lck);
2254
2255         ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2256                                  state->src_fsp,
2257                                  &lck);
2258         if (!ok) {
2259                 return NT_STATUS_FILE_LOCK_CONFLICT;
2260         }
2261
2262         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2263         if (!ok) {
2264                 return NT_STATUS_INTERNAL_ERROR;
2265         }
2266
2267         init_strict_lock_struct(state->dst_fsp,
2268                                 state->dst_fsp->op->global->open_persistent_id,
2269                                 state->dst_off,
2270                                 state->remaining,
2271                                 WRITE_LOCK,
2272                                 &lck);
2273
2274         ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2275                                        state->dst_fsp,
2276                                        &lck);
2277         if (!ok) {
2278                 return NT_STATUS_FILE_LOCK_CONFLICT;
2279         }
2280
2281         while (state->remaining > 0) {
2282                 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
2283                                            &state->src_off,
2284                                            fsp_get_io_fd(state->dst_fsp),
2285                                            &state->dst_off,
2286                                            state->remaining,
2287                                            0);
2288                 if (nwritten == -1) {
2289                         DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2290                                   "n [%jd] failed: %s\n",
2291                                   fsp_str_dbg(state->src_fsp),
2292                                   (intmax_t)state->src_off,
2293                                   fsp_str_dbg(state->dst_fsp),
2294                                   (intmax_t)state->dst_off,
2295                                   (intmax_t)state->remaining,
2296                                   strerror(errno));
2297                         switch (errno) {
2298                         case EXDEV:
2299                                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2300                                 break;
2301                         default:
2302                                 status = map_nt_error_from_unix(errno);
2303                                 if (NT_STATUS_EQUAL(
2304                                             status,
2305                                             NT_STATUS_MORE_PROCESSING_REQUIRED))
2306                                 {
2307                                         /* Avoid triggering the fallback */
2308                                         status = NT_STATUS_INTERNAL_ERROR;
2309                                 }
2310                                 break;
2311                         }
2312                         return status;
2313                 }
2314
2315                 if (state->remaining < nwritten) {
2316                         DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2317                                   "n [%jd] remaining [%jd]\n",
2318                                   fsp_str_dbg(state->src_fsp),
2319                                   fsp_str_dbg(state->dst_fsp),
2320                                   (intmax_t)nwritten,
2321                                   (intmax_t)state->remaining);
2322                         return NT_STATUS_INTERNAL_ERROR;
2323                 }
2324
2325                 if (nwritten == 0) {
2326                         break;
2327                 }
2328                 state->copied += nwritten;
2329                 state->remaining -= nwritten;
2330         }
2331
2332         /*
2333          * Tell the req cleanup function there's no need to call
2334          * change_to_user_and_service_by_fsp() on the dst handle.
2335          */
2336         state->dst_fsp = NULL;
2337         return NT_STATUS_OK;
2338 }
2339
2340 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2341
2342 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2343 {
2344         struct vfswrap_offload_write_state *state = tevent_req_data(
2345                 req, struct vfswrap_offload_write_state);
2346         struct tevent_req *subreq = NULL;
2347         struct lock_struct read_lck;
2348         bool ok;
2349
2350         /*
2351          * This is called under the context of state->src_fsp.
2352          */
2353
2354         state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2355
2356         init_strict_lock_struct(state->src_fsp,
2357                                 state->src_fsp->op->global->open_persistent_id,
2358                                 state->src_off,
2359                                 state->next_io_size,
2360                                 READ_LOCK,
2361                                 &read_lck);
2362
2363         ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2364                                  state->src_fsp,
2365                                  &read_lck);
2366         if (!ok) {
2367                 return NT_STATUS_FILE_LOCK_CONFLICT;
2368         }
2369
2370         subreq = SMB_VFS_PREAD_SEND(state,
2371                                     state->src_ev,
2372                                     state->src_fsp,
2373                                     state->buf,
2374                                     state->next_io_size,
2375                                     state->src_off);
2376         if (subreq == NULL) {
2377                 return NT_STATUS_NO_MEMORY;
2378         }
2379         tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2380
2381         return NT_STATUS_OK;
2382 }
2383
2384 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2385
2386 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2387 {
2388         struct tevent_req *req = tevent_req_callback_data(
2389                 subreq, struct tevent_req);
2390         struct vfswrap_offload_write_state *state = tevent_req_data(
2391                 req, struct vfswrap_offload_write_state);
2392         struct vfs_aio_state aio_state;
2393         struct lock_struct write_lck;
2394         ssize_t nread;
2395         bool ok;
2396
2397         nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2398         TALLOC_FREE(subreq);
2399         if (nread == -1) {
2400                 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2401                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2402                 return;
2403         }
2404         if (nread != state->next_io_size) {
2405                 DBG_ERR("Short read, only %zd of %zu\n",
2406                         nread, state->next_io_size);
2407                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2408                 return;
2409         }
2410
2411         state->src_off += nread;
2412
2413         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2414         if (!ok) {
2415                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2416                 return;
2417         }
2418
2419         init_strict_lock_struct(state->dst_fsp,
2420                                 state->dst_fsp->op->global->open_persistent_id,
2421                                 state->dst_off,
2422                                 state->next_io_size,
2423                                 WRITE_LOCK,
2424                                 &write_lck);
2425
2426         ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2427                                  state->dst_fsp,
2428                                  &write_lck);
2429         if (!ok) {
2430                 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2431                 return;
2432         }
2433
2434         subreq = SMB_VFS_PWRITE_SEND(state,
2435                                      state->dst_ev,
2436                                      state->dst_fsp,
2437                                      state->buf,
2438                                      state->next_io_size,
2439                                      state->dst_off);
2440         if (subreq == NULL) {
2441                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2442                 return;
2443         }
2444         tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2445 }
2446
2447 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2448 {
2449         struct tevent_req *req = tevent_req_callback_data(
2450                 subreq, struct tevent_req);
2451         struct vfswrap_offload_write_state *state = tevent_req_data(
2452                 req, struct vfswrap_offload_write_state);
2453         struct vfs_aio_state aio_state;
2454         ssize_t nwritten;
2455         NTSTATUS status;
2456         bool ok;
2457
2458         nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2459         TALLOC_FREE(subreq);
2460         if (nwritten == -1) {
2461                 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2462                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2463                 return;
2464         }
2465         if (nwritten != state->next_io_size) {
2466                 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2467                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2468                 return;
2469         }
2470
2471         state->dst_off += nwritten;
2472
2473         if (state->remaining < nwritten) {
2474                 /* Paranoia check */
2475                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2476                 return;
2477         }
2478         state->copied += nwritten;
2479         state->remaining -= nwritten;
2480         if (state->remaining == 0) {
2481                 tevent_req_done(req);
2482                 return;
2483         }
2484
2485         ok = change_to_user_and_service_by_fsp(state->src_fsp);
2486         if (!ok) {
2487                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2488                 return;
2489         }
2490
2491         status = vfswrap_offload_write_loop(req);
2492         if (!NT_STATUS_IS_OK(status)) {
2493                 tevent_req_nterror(req, status);
2494                 return;
2495         }
2496
2497         return;
2498 }
2499
2500 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2501                                         struct tevent_req *req,
2502                                         off_t *copied)
2503 {
2504         struct vfswrap_offload_write_state *state = tevent_req_data(
2505                 req, struct vfswrap_offload_write_state);
2506         NTSTATUS status;
2507
2508         if (tevent_req_is_nterror(req, &status)) {
2509                 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2510                 *copied = 0;
2511                 tevent_req_received(req);
2512                 return status;
2513         }
2514
2515         *copied = state->copied;
2516         DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2517         tevent_req_received(req);
2518
2519         return NT_STATUS_OK;
2520 }
2521
2522 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2523                                         TALLOC_CTX *mem_ctx,
2524                                         struct files_struct *fsp,
2525                                         uint16_t *_compression_fmt)
2526 {
2527         return NT_STATUS_INVALID_DEVICE_REQUEST;
2528 }
2529
2530 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2531                                         TALLOC_CTX *mem_ctx,
2532                                         struct files_struct *fsp,
2533                                         uint16_t compression_fmt)
2534 {
2535         return NT_STATUS_INVALID_DEVICE_REQUEST;
2536 }
2537
2538 /********************************************************************
2539  Given a stat buffer return the allocated size on disk, taking into
2540  account sparse files.
2541 ********************************************************************/
2542 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2543                                        struct files_struct *fsp,
2544                                        const SMB_STRUCT_STAT *sbuf)
2545 {
2546         uint64_t result;
2547
2548         START_PROFILE(syscall_get_alloc_size);
2549
2550         if(S_ISDIR(sbuf->st_ex_mode)) {
2551                 result = 0;
2552                 goto out;
2553         }
2554
2555 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2556         /* The type of st_blocksize is blkcnt_t which *MUST* be
2557            signed (according to POSIX) and can be less than 64-bits.
2558            Ensure when we're converting to 64 bits wide we don't
2559            sign extend. */
2560 #if defined(SIZEOF_BLKCNT_T_8)
2561         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2562 #elif defined(SIZEOF_BLKCNT_T_4)
2563         {
2564                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2565                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2566         }
2567 #else
2568 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2569 #endif
2570         if (result == 0) {
2571                 /*
2572                  * Some file systems do not allocate a block for very
2573                  * small files. But for non-empty file should report a
2574                  * positive size.
2575                  */
2576
2577                 uint64_t filesize = get_file_size_stat(sbuf);
2578                 if (filesize > 0) {
2579                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2580                 }
2581         }
2582 #else
2583         result = get_file_size_stat(sbuf);
2584 #endif
2585
2586         if (fsp && fsp->initial_allocation_size)
2587                 result = MAX(result,fsp->initial_allocation_size);
2588
2589         result = smb_roundup(handle->conn, result);
2590
2591  out:
2592         END_PROFILE(syscall_get_alloc_size);
2593         return result;
2594 }
2595
2596 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2597                         struct files_struct *dirfsp,
2598                         const struct smb_filename *smb_fname,
2599                         int flags)
2600 {
2601         int result = -1;
2602
2603         START_PROFILE(syscall_unlinkat);
2604
2605         if (is_named_stream(smb_fname)) {
2606                 errno = ENOENT;
2607                 goto out;
2608         }
2609         result = unlinkat(fsp_get_pathref_fd(dirfsp),
2610                         smb_fname->base_name,
2611                         flags);
2612
2613  out:
2614         END_PROFILE(syscall_unlinkat);
2615         return result;
2616 }
2617
2618 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2619 {
2620         int result;
2621
2622         START_PROFILE(syscall_fchmod);
2623
2624         if (!fsp->fsp_flags.is_pathref) {
2625                 result = fchmod(fsp_get_io_fd(fsp), mode);
2626                 END_PROFILE(syscall_fchmod);
2627                 return result;
2628         }
2629
2630         if (fsp->fsp_flags.have_proc_fds) {
2631                 int fd = fsp_get_pathref_fd(fsp);
2632                 const char *p = NULL;
2633                 char buf[PATH_MAX];
2634
2635                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2636                 if (p != NULL) {
2637                         result = chmod(p, mode);
2638                 } else {
2639                         result = -1;
2640                 }
2641                 END_PROFILE(syscall_fchmod);
2642                 return result;
2643         }
2644
2645         /*
2646          * This is no longer a handle based call.
2647          */
2648         result = chmod(fsp->fsp_name->base_name, mode);
2649
2650         END_PROFILE(syscall_fchmod);
2651         return result;
2652 }
2653
2654 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2655 {
2656 #ifdef HAVE_FCHOWN
2657         int result;
2658
2659         START_PROFILE(syscall_fchown);
2660         if (!fsp->fsp_flags.is_pathref) {
2661                 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2662                 END_PROFILE(syscall_fchown);
2663                 return result;
2664         }
2665
2666         if (fsp->fsp_flags.have_proc_fds) {
2667                 int fd = fsp_get_pathref_fd(fsp);
2668                 const char *p = NULL;
2669                 char buf[PATH_MAX];
2670
2671                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2672                 if (p != NULL) {
2673                         result = chown(p, uid, gid);
2674                 } else {
2675                         result = -1;
2676                 }
2677                 END_PROFILE(syscall_fchown);
2678                 return result;
2679         }
2680
2681         /*
2682          * This is no longer a handle based call.
2683          */
2684         result = chown(fsp->fsp_name->base_name, uid, gid);
2685         END_PROFILE(syscall_fchown);
2686         return result;
2687 #else
2688         errno = ENOSYS;
2689         return -1;
2690 #endif
2691 }
2692
2693 static int vfswrap_lchown(vfs_handle_struct *handle,
2694                         const struct smb_filename *smb_fname,
2695                         uid_t uid,
2696                         gid_t gid)
2697 {
2698         int result;
2699
2700         START_PROFILE(syscall_lchown);
2701         result = lchown(smb_fname->base_name, uid, gid);
2702         END_PROFILE(syscall_lchown);
2703         return result;
2704 }
2705
2706 static int vfswrap_chdir(vfs_handle_struct *handle,
2707                         const struct smb_filename *smb_fname)
2708 {
2709         int result;
2710
2711         START_PROFILE(syscall_chdir);
2712         result = chdir(smb_fname->base_name);
2713         END_PROFILE(syscall_chdir);
2714         return result;
2715 }
2716
2717 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2718                                 TALLOC_CTX *ctx)
2719 {
2720         char *result;
2721         struct smb_filename *smb_fname = NULL;
2722
2723         START_PROFILE(syscall_getwd);
2724         result = sys_getwd();
2725         END_PROFILE(syscall_getwd);
2726
2727         if (result == NULL) {
2728                 return NULL;
2729         }
2730         smb_fname = synthetic_smb_fname(ctx,
2731                                 result,
2732                                 NULL,
2733                                 NULL,
2734                                 0,
2735                                 0);
2736         /*
2737          * sys_getwd() *always* returns malloced memory.
2738          * We must free here to avoid leaks:
2739          * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2740          */
2741         SAFE_FREE(result);
2742         return smb_fname;
2743 }
2744
2745 /*********************************************************************
2746  nsec timestamp resolution call. Convert down to whatever the underlying
2747  system will support.
2748 **********************************************************************/
2749
2750 static int vfswrap_fntimes(vfs_handle_struct *handle,
2751                            files_struct *fsp,
2752                            struct smb_file_time *ft)
2753 {
2754         int result = -1;
2755         struct timespec ts[2];
2756         struct timespec *times = NULL;
2757
2758         START_PROFILE(syscall_fntimes);
2759
2760         if (is_named_stream(fsp->fsp_name)) {
2761                 errno = ENOENT;
2762                 goto out;
2763         }
2764
2765         if (ft != NULL) {
2766                 if (is_omit_timespec(&ft->atime)) {
2767                         ft->atime = fsp->fsp_name->st.st_ex_atime;
2768                 }
2769
2770                 if (is_omit_timespec(&ft->mtime)) {
2771                         ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2772                 }
2773
2774                 if (!is_omit_timespec(&ft->create_time)) {
2775                         set_create_timespec_ea(fsp,
2776                                                ft->create_time);
2777                 }
2778
2779                 if ((timespec_compare(&ft->atime,
2780                                       &fsp->fsp_name->st.st_ex_atime) == 0) &&
2781                     (timespec_compare(&ft->mtime,
2782                                       &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2783                         result = 0;
2784                         goto out;
2785                 }
2786
2787                 ts[0] = ft->atime;
2788                 ts[1] = ft->mtime;
2789                 times = ts;
2790         } else {
2791                 times = NULL;
2792         }
2793
2794         if (!fsp->fsp_flags.is_pathref) {
2795                 result = futimens(fsp_get_io_fd(fsp), times);
2796                 goto out;
2797         }
2798
2799         if (fsp->fsp_flags.have_proc_fds) {
2800                 int fd = fsp_get_pathref_fd(fsp);
2801                 const char *p = NULL;
2802                 char buf[PATH_MAX];
2803
2804                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2805                 if (p != NULL) {
2806                         /*
2807                          * The dirfd argument of utimensat is ignored when
2808                          * pathname is an absolute path
2809                          */
2810                         result = utimensat(AT_FDCWD, p, times, 0);
2811                 } else {
2812                         result = -1;
2813                 }
2814
2815                 goto out;
2816         }
2817
2818         /*
2819          * The fd is a pathref (opened with O_PATH) and there isn't fd to
2820          * path translation mechanism. Fallback to path based call.
2821          */
2822         result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2823
2824 out:
2825         END_PROFILE(syscall_fntimes);
2826
2827         return result;
2828 }
2829
2830
2831 /*********************************************************************
2832  A version of ftruncate that will write the space on disk if strict
2833  allocate is set.
2834 **********************************************************************/
2835
2836 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2837 {
2838         off_t space_to_write;
2839         uint64_t space_avail;
2840         uint64_t bsize,dfree,dsize;
2841         int ret;
2842         NTSTATUS status;
2843         SMB_STRUCT_STAT *pst;
2844         bool ok;
2845
2846         ok = vfs_valid_pwrite_range(len, 0);
2847         if (!ok) {
2848                 errno = EINVAL;
2849                 return -1;
2850         }
2851
2852         status = vfs_stat_fsp(fsp);
2853         if (!NT_STATUS_IS_OK(status)) {
2854                 return -1;
2855         }
2856         pst = &fsp->fsp_name->st;
2857
2858 #ifdef S_ISFIFO
2859         if (S_ISFIFO(pst->st_ex_mode))
2860                 return 0;
2861 #endif
2862
2863         if (pst->st_ex_size == len)
2864                 return 0;
2865
2866         /* Shrink - just ftruncate. */
2867         if (pst->st_ex_size > len)
2868                 return ftruncate(fsp_get_io_fd(fsp), len);
2869
2870         space_to_write = len - pst->st_ex_size;
2871
2872         /* for allocation try fallocate first. This can fail on some
2873            platforms e.g. when the filesystem doesn't support it and no
2874            emulation is being done by the libc (like on AIX with JFS1). In that
2875            case we do our own emulation. fallocate implementations can
2876            return ENOTSUP or EINVAL in cases like that. */
2877         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2878         if (ret == -1 && errno == ENOSPC) {
2879                 return -1;
2880         }
2881         if (ret == 0) {
2882                 return 0;
2883         }
2884         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2885                 "error %d. Falling back to slow manual allocation\n", errno));
2886
2887         /* available disk space is enough or not? */
2888         space_avail =
2889             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2890         /* space_avail is 1k blocks */
2891         if (space_avail == (uint64_t)-1 ||
2892                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2893                 errno = ENOSPC;
2894                 return -1;
2895         }
2896
2897         /* Write out the real space on disk. */
2898         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2899         if (ret != 0) {
2900                 return -1;
2901         }
2902
2903         return 0;
2904 }
2905
2906 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2907 {
2908         int result = -1;
2909         SMB_STRUCT_STAT *pst;
2910         NTSTATUS status;
2911         char c = 0;
2912
2913         START_PROFILE(syscall_ftruncate);
2914
2915         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2916                 result = strict_allocate_ftruncate(handle, fsp, len);
2917                 END_PROFILE(syscall_ftruncate);
2918                 return result;
2919         }
2920
2921         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2922            ftruncate if the system supports it. Then I discovered that
2923            you can have some filesystems that support ftruncate
2924            expansion and some that don't! On Linux fat can't do
2925            ftruncate extend but ext2 can. */
2926
2927         result = ftruncate(fsp_get_io_fd(fsp), len);
2928
2929         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2930            extend a file with ftruncate. Provide alternate implementation
2931            for this */
2932
2933         /* Do an fstat to see if the file is longer than the requested
2934            size in which case the ftruncate above should have
2935            succeeded or shorter, in which case seek to len - 1 and
2936            write 1 byte of zero */
2937         status = vfs_stat_fsp(fsp);
2938         if (!NT_STATUS_IS_OK(status)) {
2939                 goto done;
2940         }
2941
2942         /* We need to update the files_struct after successful ftruncate */
2943         if (result == 0) {
2944                 goto done;
2945         }
2946
2947         pst = &fsp->fsp_name->st;
2948
2949 #ifdef S_ISFIFO
2950         if (S_ISFIFO(pst->st_ex_mode)) {
2951                 result = 0;
2952                 goto done;
2953         }
2954 #endif
2955
2956         if (pst->st_ex_size == len) {
2957                 result = 0;
2958                 goto done;
2959         }
2960
2961         if (pst->st_ex_size > len) {
2962                 /* the ftruncate should have worked */
2963                 goto done;
2964         }
2965
2966         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2967                 goto done;
2968         }
2969
2970         result = 0;
2971
2972   done:
2973
2974         END_PROFILE(syscall_ftruncate);
2975         return result;
2976 }
2977
2978 static int vfswrap_fallocate(vfs_handle_struct *handle,
2979                         files_struct *fsp,
2980                         uint32_t mode,
2981                         off_t offset,
2982                         off_t len)
2983 {
2984         int result;
2985
2986         START_PROFILE(syscall_fallocate);
2987         if (mode == 0) {
2988                 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2989                 /*
2990                  * posix_fallocate returns 0 on success, errno on error
2991                  * and doesn't set errno. Make it behave like fallocate()
2992                  * which returns -1, and sets errno on failure.
2993                  */
2994                 if (result != 0) {
2995                         errno = result;
2996                         result = -1;
2997                 }
2998         } else {
2999                 /* sys_fallocate handles filtering of unsupported mode flags */
3000                 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
3001         }
3002         END_PROFILE(syscall_fallocate);
3003         return result;
3004 }
3005
3006 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
3007 {
3008         bool result;
3009
3010         START_PROFILE(syscall_fcntl_lock);
3011
3012         if (fsp->fsp_flags.use_ofd_locks) {
3013                 op = map_process_lock_to_ofd_lock(op);
3014         }
3015
3016         result =  fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
3017         END_PROFILE(syscall_fcntl_lock);
3018         return result;
3019 }
3020
3021 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
3022                                 uint32_t share_access, uint32_t access_mask)
3023 {
3024         START_PROFILE(syscall_kernel_flock);
3025         kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
3026         END_PROFILE(syscall_kernel_flock);
3027         return 0;
3028 }
3029
3030 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
3031                          va_list cmd_arg)
3032 {
3033         void *argp;
3034         va_list dup_cmd_arg;
3035         int result;
3036         int val;
3037
3038         START_PROFILE(syscall_fcntl);
3039
3040         va_copy(dup_cmd_arg, cmd_arg);
3041
3042         switch(cmd) {
3043         case F_SETLK:
3044         case F_SETLKW:
3045         case F_GETLK:
3046 #if defined(HAVE_OFD_LOCKS)
3047         case F_OFD_SETLK:
3048         case F_OFD_SETLKW:
3049         case F_OFD_GETLK:
3050 #endif
3051 #if defined(HAVE_F_OWNER_EX)
3052         case F_GETOWN_EX:
3053         case F_SETOWN_EX:
3054 #endif
3055 #if defined(HAVE_RW_HINTS)
3056         case F_GET_RW_HINT:
3057         case F_SET_RW_HINT:
3058         case F_GET_FILE_RW_HINT:
3059         case F_SET_FILE_RW_HINT:
3060 #endif
3061                 argp = va_arg(dup_cmd_arg, void *);
3062                 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
3063                 break;
3064         default:
3065                 val = va_arg(dup_cmd_arg, int);
3066                 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
3067         }
3068
3069         va_end(dup_cmd_arg);
3070
3071         END_PROFILE(syscall_fcntl);
3072         return result;
3073 }
3074
3075 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
3076 {
3077         bool result;
3078         int op = F_GETLK;
3079
3080         START_PROFILE(syscall_fcntl_getlock);
3081
3082         if (fsp->fsp_flags.use_ofd_locks) {
3083                 op = map_process_lock_to_ofd_lock(op);
3084         }
3085
3086         result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
3087         END_PROFILE(syscall_fcntl_getlock);
3088         return result;
3089 }
3090
3091 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
3092                                 int leasetype)
3093 {
3094         int result = -1;
3095
3096         START_PROFILE(syscall_linux_setlease);
3097
3098 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3099         result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
3100 #else
3101         errno = ENOSYS;
3102 #endif
3103         END_PROFILE(syscall_linux_setlease);
3104         return result;
3105 }
3106
3107 static int vfswrap_symlinkat(vfs_handle_struct *handle,
3108                         const struct smb_filename *link_target,
3109                         struct files_struct *dirfsp,
3110                         const struct smb_filename *new_smb_fname)
3111 {
3112         int result;
3113
3114         START_PROFILE(syscall_symlinkat);
3115
3116         result = symlinkat(link_target->base_name,
3117                         fsp_get_pathref_fd(dirfsp),
3118                         new_smb_fname->base_name);
3119         END_PROFILE(syscall_symlinkat);
3120         return result;
3121 }
3122
3123 static int vfswrap_readlinkat(vfs_handle_struct *handle,
3124                         const struct files_struct *dirfsp,
3125                         const struct smb_filename *smb_fname,
3126                         char *buf,
3127                         size_t bufsiz)
3128 {
3129         int result;
3130
3131         START_PROFILE(syscall_readlinkat);
3132
3133         result = readlinkat(fsp_get_pathref_fd(dirfsp),
3134                         smb_fname->base_name,
3135                         buf,
3136                         bufsiz);
3137
3138         END_PROFILE(syscall_readlinkat);
3139         return result;
3140 }
3141
3142 static int vfswrap_linkat(vfs_handle_struct *handle,
3143                         files_struct *srcfsp,
3144                         const struct smb_filename *old_smb_fname,
3145                         files_struct *dstfsp,
3146                         const struct smb_filename *new_smb_fname,
3147                         int flags)
3148 {
3149         int result;
3150
3151         START_PROFILE(syscall_linkat);
3152
3153         result = linkat(fsp_get_pathref_fd(srcfsp),
3154                         old_smb_fname->base_name,
3155                         fsp_get_pathref_fd(dstfsp),
3156                         new_smb_fname->base_name,
3157                         flags);
3158
3159         END_PROFILE(syscall_linkat);
3160         return result;
3161 }
3162
3163 static int vfswrap_mknodat(vfs_handle_struct *handle,
3164                         files_struct *dirfsp,
3165                         const struct smb_filename *smb_fname,
3166                         mode_t mode,
3167                         SMB_DEV_T dev)
3168 {
3169         int result;
3170
3171         START_PROFILE(syscall_mknodat);
3172
3173         result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3174                         smb_fname->base_name,
3175                         mode,
3176                         dev);
3177
3178         END_PROFILE(syscall_mknodat);
3179         return result;
3180 }
3181
3182 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3183                         TALLOC_CTX *ctx,
3184                         const struct smb_filename *smb_fname)
3185 {
3186         char *result;
3187         struct smb_filename *result_fname = NULL;
3188
3189         START_PROFILE(syscall_realpath);
3190         result = sys_realpath(smb_fname->base_name);
3191         END_PROFILE(syscall_realpath);
3192         if (result) {
3193                 result_fname = synthetic_smb_fname(ctx,
3194                                                    result,
3195                                                    NULL,
3196                                                    NULL,
3197                                                    0,
3198                                                    0);
3199                 SAFE_FREE(result);
3200         }
3201         return result_fname;
3202 }
3203
3204 static int vfswrap_fchflags(vfs_handle_struct *handle,
3205                         struct files_struct *fsp,
3206                         unsigned int flags)
3207 {
3208 #ifdef HAVE_FCHFLAGS
3209         int fd = fsp_get_pathref_fd(fsp);
3210
3211         if (!fsp->fsp_flags.is_pathref) {
3212                 return fchflags(fd, flags);
3213         }
3214
3215         if (fsp->fsp_flags.have_proc_fds) {
3216                 const char *p = NULL;
3217                 char buf[PATH_MAX];
3218
3219                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3220                 if (p == NULL) {
3221                         return -1;
3222                 }
3223
3224                 return chflags(p, flags);
3225         }
3226
3227         /*
3228          * This is no longer a handle based call.
3229          */
3230         return chflags(fsp->fsp_name->base_name, flags);
3231 #else
3232         errno = ENOSYS;
3233         return -1;
3234 #endif
3235 }
3236
3237 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3238                                              const SMB_STRUCT_STAT *sbuf)
3239 {
3240         struct file_id key;
3241
3242         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3243          * blob */
3244         ZERO_STRUCT(key);
3245
3246         key.devid = sbuf->st_ex_dev;
3247         key.inode = sbuf->st_ex_ino;
3248         /* key.extid is unused by default. */
3249
3250         return key;
3251 }
3252
3253 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3254                                    const SMB_STRUCT_STAT *psbuf)
3255 {
3256         uint64_t file_id;
3257
3258         if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3259                 return psbuf->st_ex_file_id;
3260         }
3261
3262         if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3263                 return (uint64_t)psbuf->st_ex_ino;
3264         }
3265
3266         /* FileIDLow */
3267         file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3268
3269         /* FileIDHigh */
3270         file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3271
3272         return file_id;
3273 }
3274
3275 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3276                                    struct files_struct *fsp,
3277                                    TALLOC_CTX *mem_ctx,
3278                                    unsigned int *pnum_streams,
3279                                    struct stream_struct **pstreams)
3280 {
3281         struct stream_struct *tmp_streams = NULL;
3282         unsigned int num_streams = *pnum_streams;
3283         struct stream_struct *streams = *pstreams;
3284         NTSTATUS status;
3285
3286         if (fsp->fsp_flags.is_directory) {
3287                 /*
3288                  * No default streams on directories
3289                  */
3290                 goto done;
3291         }
3292         status = vfs_stat_fsp(fsp);
3293         if (!NT_STATUS_IS_OK(status)) {
3294                 return status;
3295         }
3296
3297         if (num_streams + 1 < 1) {
3298                 /* Integer wrap. */
3299                 return NT_STATUS_INVALID_PARAMETER;
3300         }
3301
3302         tmp_streams = talloc_realloc(mem_ctx,
3303                                         streams,
3304                                         struct stream_struct,
3305                                         num_streams + 1);
3306         if (tmp_streams == NULL) {
3307                 return NT_STATUS_NO_MEMORY;
3308         }
3309         tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3310         if (tmp_streams[num_streams].name == NULL) {
3311                 return NT_STATUS_NO_MEMORY;
3312         }
3313         tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3314         tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3315                                                 handle->conn,
3316                                                 fsp,
3317                                                 &fsp->fsp_name->st);
3318         num_streams += 1;
3319
3320         *pnum_streams = num_streams;
3321         *pstreams = tmp_streams;
3322  done:
3323         return NT_STATUS_OK;
3324 }
3325
3326 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3327                                      const struct smb_filename *path,
3328                                      const char *name,
3329                                      TALLOC_CTX *mem_ctx,
3330                                      char **found_name)
3331 {
3332         /*
3333          * Don't fall back to get_real_filename so callers can differentiate
3334          * between a full directory scan and an actual case-insensitive stat.
3335          */
3336         errno = EOPNOTSUPP;
3337         return -1;
3338 }
3339
3340 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3341                                    const struct smb_filename *smb_fname)
3342 {
3343         return handle->conn->connectpath;
3344 }
3345
3346 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3347                                          struct byte_range_lock *br_lck,
3348                                          struct lock_struct *plock)
3349 {
3350         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3351
3352         /* Note: blr is not used in the default implementation. */
3353         return brl_lock_windows_default(br_lck, plock);
3354 }
3355
3356 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3357                                        struct byte_range_lock *br_lck,
3358                                        const struct lock_struct *plock)
3359 {
3360         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3361
3362         return brl_unlock_windows_default(br_lck, plock);
3363 }
3364
3365 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3366                                       files_struct *fsp,
3367                                       struct lock_struct *plock)
3368 {
3369         SMB_ASSERT(plock->lock_type == READ_LOCK ||
3370             plock->lock_type == WRITE_LOCK);
3371
3372         return strict_lock_check_default(fsp, plock);
3373 }
3374
3375 /* NT ACL operations. */
3376
3377 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3378                                     files_struct *fsp,
3379                                     uint32_t security_info,
3380                                     TALLOC_CTX *mem_ctx,
3381                                     struct security_descriptor **ppdesc)
3382 {
3383         NTSTATUS result;
3384
3385         START_PROFILE(fget_nt_acl);
3386         result = posix_fget_nt_acl(fsp, security_info,
3387                                    mem_ctx, ppdesc);
3388         END_PROFILE(fget_nt_acl);
3389         return result;
3390 }
3391
3392 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3393 {
3394         NTSTATUS result;
3395
3396         START_PROFILE(fset_nt_acl);
3397         result = set_nt_acl(fsp, security_info_sent, psd);
3398         END_PROFILE(fset_nt_acl);
3399         return result;
3400 }
3401
3402 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3403                                    struct smb_filename *file,
3404                                    struct security_acl *sacl,
3405                                    uint32_t access_requested,
3406                                    uint32_t access_denied)
3407 {
3408         return NT_STATUS_OK; /* Nothing to do here ... */
3409 }
3410
3411 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3412                                         files_struct *fsp,
3413                                         SMB_ACL_TYPE_T type,
3414                                         TALLOC_CTX *mem_ctx)
3415 {
3416         return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3417 }
3418
3419 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3420                                   files_struct *fsp,
3421                                   SMB_ACL_TYPE_T type,
3422                                   SMB_ACL_T theacl)
3423 {
3424         return sys_acl_set_fd(handle, fsp, type, theacl);
3425 }
3426
3427 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3428                                          files_struct *fsp)
3429 {
3430         return sys_acl_delete_def_fd(handle, fsp);
3431 }
3432
3433 /****************************************************************
3434  Extended attribute operations.
3435 *****************************************************************/
3436
3437 struct vfswrap_getxattrat_state {
3438         struct tevent_context *ev;
3439         files_struct *dir_fsp;
3440         const struct smb_filename *smb_fname;
3441
3442         /*
3443          * The following variables are talloced off "state" which is protected
3444          * by a destructor and thus are guaranteed to be safe to be used in the
3445          * job function in the worker thread.
3446          */
3447         char *name;
3448         const char *xattr_name;
3449         uint8_t *xattr_value;
3450         struct security_unix_token *token;
3451
3452         ssize_t xattr_size;
3453         struct vfs_aio_state vfs_aio_state;
3454         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3455 };
3456
3457 static int vfswrap_getxattrat_state_destructor(
3458                 struct vfswrap_getxattrat_state *state)
3459 {
3460         return -1;
3461 }
3462
3463 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3464 static void vfswrap_getxattrat_do_async(void *private_data);
3465 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3466
3467 static struct tevent_req *vfswrap_getxattrat_send(
3468                         TALLOC_CTX *mem_ctx,
3469                         struct tevent_context *ev,
3470                         struct vfs_handle_struct *handle,
3471                         files_struct *dir_fsp,
3472                         const struct smb_filename *smb_fname,
3473                         const char *xattr_name,
3474                         size_t alloc_hint)
3475 {
3476         struct tevent_req *req = NULL;
3477         struct tevent_req *subreq = NULL;
3478         struct vfswrap_getxattrat_state *state = NULL;
3479         size_t max_threads = 0;
3480         bool have_per_thread_cwd = false;
3481         bool have_per_thread_creds = false;
3482         bool do_async = false;
3483
3484         req = tevent_req_create(mem_ctx, &state,
3485                                 struct vfswrap_getxattrat_state);
3486         if (req == NULL) {
3487                 return NULL;
3488         }
3489         *state = (struct vfswrap_getxattrat_state) {
3490                 .ev = ev,
3491                 .dir_fsp = dir_fsp,
3492                 .smb_fname = smb_fname,
3493         };
3494
3495         max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3496         if (max_threads >= 1) {
3497                 /*
3498                  * We need a non sync threadpool!
3499                  */
3500                 have_per_thread_cwd = per_thread_cwd_supported();
3501         }
3502 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3503         have_per_thread_creds = true;
3504 #endif
3505         if (have_per_thread_cwd && have_per_thread_creds) {
3506                 do_async = true;
3507         }
3508
3509         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3510                                      state->profile_bytes, 0);
3511
3512         if (fsp_get_pathref_fd(dir_fsp) == -1) {
3513                 DBG_ERR("Need a valid directory fd\n");
3514                 tevent_req_error(req, EINVAL);
3515                 return tevent_req_post(req, ev);
3516         }
3517
3518         if (alloc_hint > 0) {
3519                 state->xattr_value = talloc_zero_array(state,
3520                                                        uint8_t,
3521                                                        alloc_hint);
3522                 if (tevent_req_nomem(state->xattr_value, req)) {
3523                         return tevent_req_post(req, ev);
3524                 }
3525         }
3526
3527         if (!do_async) {
3528                 vfswrap_getxattrat_do_sync(req);
3529                 return tevent_req_post(req, ev);
3530         }
3531
3532         /*
3533          * Now allocate all parameters from a memory context that won't go away
3534          * no matter what. These paremeters will get used in threads and we
3535          * can't reliably cancel threads, so all buffers passed to the threads
3536          * must not be freed before all referencing threads terminate.
3537          */
3538
3539         state->name = talloc_strdup(state, smb_fname->base_name);
3540         if (tevent_req_nomem(state->name, req)) {
3541                 return tevent_req_post(req, ev);
3542         }
3543
3544         state->xattr_name = talloc_strdup(state, xattr_name);
3545         if (tevent_req_nomem(state->xattr_name, req)) {
3546                 return tevent_req_post(req, ev);
3547         }
3548
3549         /*
3550          * This is a hot codepath so at first glance one might think we should
3551          * somehow optimize away the token allocation and do a
3552          * talloc_reference() or similar black magic instead. But due to the
3553          * talloc_stackframe pool per SMB2 request this should be a simple copy
3554          * without a malloc in most cases.
3555          */
3556         if (geteuid() == sec_initial_uid()) {
3557                 state->token = root_unix_token(state);
3558         } else {
3559                 state->token = copy_unix_token(
3560                                         state,
3561                                         dir_fsp->conn->session_info->unix_token);
3562         }
3563         if (tevent_req_nomem(state->token, req)) {
3564                 return tevent_req_post(req, ev);
3565         }
3566
3567         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3568
3569         subreq = pthreadpool_tevent_job_send(
3570                         state,
3571                         ev,
3572                         dir_fsp->conn->sconn->pool,
3573                         vfswrap_getxattrat_do_async,
3574                         state);
3575         if (tevent_req_nomem(subreq, req)) {
3576                 return tevent_req_post(req, ev);
3577         }
3578         tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3579
3580         talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3581
3582         return req;
3583 }
3584
3585 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3586 {
3587         struct vfswrap_getxattrat_state *state = tevent_req_data(
3588                 req, struct vfswrap_getxattrat_state);
3589         char *path = NULL;
3590         char *tofree = NULL;
3591         char pathbuf[PATH_MAX+1];
3592         ssize_t pathlen;
3593         int err;
3594
3595         pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3596                                 state->smb_fname->base_name,
3597                                 pathbuf,
3598                                 sizeof(pathbuf),
3599                                 &path,
3600                                 &tofree);
3601         if (pathlen == -1) {
3602                 tevent_req_error(req, ENOMEM);
3603                 return;
3604         }
3605
3606         state->xattr_size = getxattr(path,
3607                                      state->xattr_name,
3608                                      state->xattr_value,
3609                                      talloc_array_length(state->xattr_value));
3610         err = errno;
3611         TALLOC_FREE(tofree);
3612         if (state->xattr_size == -1) {
3613                 tevent_req_error(req, err);
3614                 return;
3615         }
3616
3617         tevent_req_done(req);
3618         return;
3619 }
3620
3621 static void vfswrap_getxattrat_do_async(void *private_data)
3622 {
3623         struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3624                 private_data, struct vfswrap_getxattrat_state);
3625         struct timespec start_time;
3626         struct timespec end_time;
3627         int ret;
3628
3629         PROFILE_TIMESTAMP(&start_time);
3630         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3631
3632         /*
3633          * Here we simulate a getxattrat()
3634          * call using fchdir();getxattr()
3635          */
3636
3637         per_thread_cwd_activate();
3638
3639         /* Become the correct credential on this thread. */
3640         ret = set_thread_credentials(state->token->uid,
3641                                      state->token->gid,
3642                                      (size_t)state->token->ngroups,
3643                                      state->token->groups);
3644         if (ret != 0) {
3645                 state->xattr_size = -1;
3646                 state->vfs_aio_state.error = errno;
3647                 goto end_profile;
3648         }
3649
3650         ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3651         if (ret == -1) {
3652                 state->xattr_size = -1;
3653                 state->vfs_aio_state.error = errno;
3654                 goto end_profile;
3655         }
3656
3657         state->xattr_size = getxattr(state->name,
3658                                      state->xattr_name,
3659                                      state->xattr_value,
3660                                      talloc_array_length(state->xattr_value));
3661         if (state->xattr_size == -1) {
3662                 state->vfs_aio_state.error = errno;
3663         }
3664
3665 end_profile:
3666         PROFILE_TIMESTAMP(&end_time);
3667         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3668         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3669 }
3670
3671 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3672 {
3673         struct tevent_req *req = tevent_req_callback_data(
3674                 subreq, struct tevent_req);
3675         struct vfswrap_getxattrat_state *state = tevent_req_data(
3676                 req, struct vfswrap_getxattrat_state);
3677         int ret;
3678         bool ok;
3679
3680         /*
3681          * Make sure we run as the user again
3682          */
3683         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3684         SMB_ASSERT(ok);
3685
3686         ret = pthreadpool_tevent_job_recv(subreq);
3687         TALLOC_FREE(subreq);
3688         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3689         talloc_set_destructor(state, NULL);
3690         if (ret != 0) {
3691                 if (ret != EAGAIN) {
3692                         tevent_req_error(req, ret);
3693                         return;
3694                 }
3695                 /*
3696                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3697                  * means the lower level pthreadpool failed to create a new
3698                  * thread. Fallback to sync processing in that case to allow
3699                  * some progress for the client.
3700                  */
3701                 vfswrap_getxattrat_do_sync(req);
3702                 return;
3703         }
3704
3705         if (state->xattr_size == -1) {
3706                 tevent_req_error(req, state->vfs_aio_state.error);
3707                 return;
3708         }
3709
3710         if (state->xattr_value == NULL) {
3711                 /*
3712                  * The caller only wanted the size.
3713                  */
3714                 tevent_req_done(req);
3715                 return;
3716         }
3717
3718         /*
3719          * shrink the buffer to the returned size.
3720          * (can't fail). It means NULL if size is 0.
3721          */
3722         state->xattr_value = talloc_realloc(state,
3723                                             state->xattr_value,
3724                                             uint8_t,
3725                                             state->xattr_size);
3726
3727         tevent_req_done(req);
3728 }
3729
3730 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3731                                        struct vfs_aio_state *aio_state,
3732                                        TALLOC_CTX *mem_ctx,
3733                                        uint8_t **xattr_value)
3734 {
3735         struct vfswrap_getxattrat_state *state = tevent_req_data(
3736                 req, struct vfswrap_getxattrat_state);
3737         ssize_t xattr_size;
3738
3739         if (tevent_req_is_unix_error(req, &aio_state->error)) {
3740                 tevent_req_received(req);
3741                 return -1;
3742         }
3743
3744         *aio_state = state->vfs_aio_state;
3745         xattr_size = state->xattr_size;
3746         if (xattr_value != NULL) {
3747                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3748         }
3749
3750         tevent_req_received(req);
3751         return xattr_size;
3752 }
3753
3754 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3755                                  struct files_struct *fsp,
3756                                  const char *name,
3757                                  void *value,
3758                                  size_t size)
3759 {
3760         int fd = fsp_get_pathref_fd(fsp);
3761
3762         if (!fsp->fsp_flags.is_pathref) {
3763                 return fgetxattr(fd, name, value, size);
3764         }
3765
3766         if (fsp->fsp_flags.have_proc_fds) {
3767                 const char *p = NULL;
3768                 char buf[PATH_MAX];
3769
3770                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3771                 if (p == NULL) {
3772                         return -1;
3773                 }
3774
3775                 return getxattr(p, name, value, size);
3776         }
3777
3778         /*
3779          * This is no longer a handle based call.
3780          */
3781         return getxattr(fsp->fsp_name->base_name, name, value, size);
3782 }
3783
3784 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3785 {
3786         int fd = fsp_get_pathref_fd(fsp);
3787
3788         if (!fsp->fsp_flags.is_pathref) {
3789                 return flistxattr(fd, list, size);
3790         }
3791
3792         if (fsp->fsp_flags.have_proc_fds) {
3793                 const char *p = NULL;
3794                 char buf[PATH_MAX];
3795
3796                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3797                 if (p == NULL) {
3798                         return -1;
3799                 }
3800
3801                 return listxattr(p, list, size);
3802         }
3803
3804         /*
3805          * This is no longer a handle based call.
3806          */
3807         return listxattr(fsp->fsp_name->base_name, list, size);
3808 }
3809
3810 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3811 {
3812         int fd = fsp_get_pathref_fd(fsp);
3813
3814         if (!fsp->fsp_flags.is_pathref) {
3815                 return fremovexattr(fd, name);
3816         }
3817
3818         if (fsp->fsp_flags.have_proc_fds) {
3819                 const char *p = NULL;
3820                 char buf[PATH_MAX];
3821
3822                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3823                 if (p == NULL) {
3824                         return -1;
3825                 }
3826
3827                 return removexattr(p, name);
3828         }
3829
3830         /*
3831          * This is no longer a handle based call.
3832          */
3833         return removexattr(fsp->fsp_name->base_name, name);
3834 }
3835
3836 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3837 {
3838         int fd = fsp_get_pathref_fd(fsp);
3839
3840         if (!fsp->fsp_flags.is_pathref) {
3841                 return fsetxattr(fd, name, value, size, flags);
3842         }
3843
3844         if (fsp->fsp_flags.have_proc_fds) {
3845                 const char *p = NULL;
3846                 char buf[PATH_MAX];
3847
3848                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3849                 if (p == NULL) {
3850                         return -1;
3851                 }
3852
3853                 return setxattr(p, name, value, size, flags);
3854         }
3855
3856         /*
3857          * This is no longer a handle based call.
3858          */
3859         return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3860 }
3861
3862 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3863 {
3864         return false;
3865 }
3866
3867 static bool vfswrap_is_offline(struct connection_struct *conn,
3868                                const struct smb_filename *fname)
3869 {
3870         NTSTATUS status;
3871         char *path;
3872         bool offline = false;
3873
3874         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3875                 return false;
3876         }
3877
3878         if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3879 #if defined(ENOTSUP)
3880                 errno = ENOTSUP;
3881 #endif
3882                 return false;
3883         }
3884
3885         status = get_full_smb_filename(talloc_tos(), fname, &path);
3886         if (!NT_STATUS_IS_OK(status)) {
3887                 errno = map_errno_from_nt_status(status);
3888                 return false;
3889         }
3890
3891         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3892
3893         TALLOC_FREE(path);
3894
3895         return offline;
3896 }
3897
3898 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3899                                        struct files_struct *fsp,
3900                                        TALLOC_CTX *mem_ctx,
3901                                        DATA_BLOB *cookie)
3902 {
3903         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3904 }
3905
3906 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3907                                            struct files_struct *fsp,
3908                                            const DATA_BLOB old_cookie,
3909                                            TALLOC_CTX *mem_ctx,
3910                                            DATA_BLOB *new_cookie)
3911 {
3912         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3913                                               new_cookie);
3914 }
3915
3916 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3917                                           struct smb_request *smb1req,
3918                                           struct smbXsrv_open *op,
3919                                           const DATA_BLOB old_cookie,
3920                                           TALLOC_CTX *mem_ctx,
3921                                           struct files_struct **fsp,
3922                                           DATA_BLOB *new_cookie)
3923 {
3924         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3925                                              old_cookie, mem_ctx,
3926                                              fsp, new_cookie);
3927 }
3928
3929 static struct vfs_fn_pointers vfs_default_fns = {
3930         /* Disk operations */
3931
3932         .connect_fn = vfswrap_connect,
3933         .disconnect_fn = vfswrap_disconnect,
3934         .disk_free_fn = vfswrap_disk_free,
3935         .get_quota_fn = vfswrap_get_quota,
3936         .set_quota_fn = vfswrap_set_quota,
3937         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3938         .statvfs_fn = vfswrap_statvfs,
3939         .fs_capabilities_fn = vfswrap_fs_capabilities,
3940         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3941         .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3942         .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3943         .snap_check_path_fn = vfswrap_snap_check_path,
3944         .snap_create_fn = vfswrap_snap_create,
3945         .snap_delete_fn = vfswrap_snap_delete,
3946
3947         /* Directory operations */
3948
3949         .fdopendir_fn = vfswrap_fdopendir,
3950         .readdir_fn = vfswrap_readdir,
3951         .freaddir_attr_fn = vfswrap_freaddir_attr,
3952         .seekdir_fn = vfswrap_seekdir,
3953         .telldir_fn = vfswrap_telldir,
3954         .rewind_dir_fn = vfswrap_rewinddir,
3955         .mkdirat_fn = vfswrap_mkdirat,
3956         .closedir_fn = vfswrap_closedir,
3957
3958         /* File operations */
3959
3960         .openat_fn = vfswrap_openat,
3961         .create_file_fn = vfswrap_create_file,
3962         .close_fn = vfswrap_close,
3963         .pread_fn = vfswrap_pread,
3964         .pread_send_fn = vfswrap_pread_send,
3965         .pread_recv_fn = vfswrap_pread_recv,
3966         .pwrite_fn = vfswrap_pwrite,
3967         .pwrite_send_fn = vfswrap_pwrite_send,
3968         .pwrite_recv_fn = vfswrap_pwrite_recv,
3969         .lseek_fn = vfswrap_lseek,
3970         .sendfile_fn = vfswrap_sendfile,
3971         .recvfile_fn = vfswrap_recvfile,
3972         .renameat_fn = vfswrap_renameat,
3973         .fsync_send_fn = vfswrap_fsync_send,
3974         .fsync_recv_fn = vfswrap_fsync_recv,
3975         .stat_fn = vfswrap_stat,
3976         .fstat_fn = vfswrap_fstat,
3977         .lstat_fn = vfswrap_lstat,
3978         .get_alloc_size_fn = vfswrap_get_alloc_size,
3979         .unlinkat_fn = vfswrap_unlinkat,
3980         .fchmod_fn = vfswrap_fchmod,
3981         .fchown_fn = vfswrap_fchown,
3982         .lchown_fn = vfswrap_lchown,
3983         .chdir_fn = vfswrap_chdir,
3984         .getwd_fn = vfswrap_getwd,
3985         .fntimes_fn = vfswrap_fntimes,
3986         .ftruncate_fn = vfswrap_ftruncate,
3987         .fallocate_fn = vfswrap_fallocate,
3988         .lock_fn = vfswrap_lock,
3989         .kernel_flock_fn = vfswrap_kernel_flock,
3990         .fcntl_fn = vfswrap_fcntl,
3991         .linux_setlease_fn = vfswrap_linux_setlease,
3992         .getlock_fn = vfswrap_getlock,
3993         .symlinkat_fn = vfswrap_symlinkat,
3994         .readlinkat_fn = vfswrap_readlinkat,
3995         .linkat_fn = vfswrap_linkat,
3996         .mknodat_fn = vfswrap_mknodat,
3997         .realpath_fn = vfswrap_realpath,
3998         .fchflags_fn = vfswrap_fchflags,
3999         .file_id_create_fn = vfswrap_file_id_create,
4000         .fs_file_id_fn = vfswrap_fs_file_id,
4001         .fstreaminfo_fn = vfswrap_fstreaminfo,
4002         .get_real_filename_fn = vfswrap_get_real_filename,
4003         .connectpath_fn = vfswrap_connectpath,
4004         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
4005         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
4006         .strict_lock_check_fn = vfswrap_strict_lock_check,
4007         .translate_name_fn = vfswrap_translate_name,
4008         .parent_pathname_fn = vfswrap_parent_pathname,
4009         .fsctl_fn = vfswrap_fsctl,
4010         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
4011         .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
4012         .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
4013         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
4014         .offload_read_send_fn = vfswrap_offload_read_send,
4015         .offload_read_recv_fn = vfswrap_offload_read_recv,
4016         .offload_write_send_fn = vfswrap_offload_write_send,
4017         .offload_write_recv_fn = vfswrap_offload_write_recv,
4018         .fget_compression_fn = vfswrap_fget_compression,
4019         .set_compression_fn = vfswrap_set_compression,
4020
4021         /* NT ACL operations. */
4022
4023         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
4024         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
4025         .audit_file_fn = vfswrap_audit_file,
4026
4027         /* POSIX ACL operations. */
4028
4029         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
4030         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
4031         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
4032         .sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd,
4033
4034         /* EA operations. */
4035         .getxattrat_send_fn = vfswrap_getxattrat_send,
4036         .getxattrat_recv_fn = vfswrap_getxattrat_recv,
4037         .fgetxattr_fn = vfswrap_fgetxattr,
4038         .flistxattr_fn = vfswrap_flistxattr,
4039         .fremovexattr_fn = vfswrap_fremovexattr,
4040         .fsetxattr_fn = vfswrap_fsetxattr,
4041
4042         /* aio operations */
4043         .aio_force_fn = vfswrap_aio_force,
4044
4045         /* durable handle operations */
4046         .durable_cookie_fn = vfswrap_durable_cookie,
4047         .durable_disconnect_fn = vfswrap_durable_disconnect,
4048         .durable_reconnect_fn = vfswrap_durable_reconnect,
4049 };
4050
4051 static_decl_vfs;
4052 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
4053 {
4054         /*
4055          * Here we need to implement every call!
4056          *
4057          * As this is the end of the vfs module chain.
4058          */
4059         smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
4060         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
4061                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
4062 }
4063
4064