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