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