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