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