vfs: Fix a typo
[samba.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38 #include "util_reparse.h"
39 #include "lib/util/string_wrappers.h"
40
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_VFS
43
44 /* Check for NULL pointer parameters in vfswrap_* functions */
45
46 /* We don't want to have NULL function pointers lying around.  Someone
47    is sure to try and execute them.  These stubs are used to prevent
48    this possibility. */
49
50 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
51 {
52         handle->conn->have_proc_fds = sys_have_proc_fds();
53         return 0;    /* Return >= 0 for success */
54 }
55
56 static void vfswrap_disconnect(vfs_handle_struct *handle)
57 {
58 }
59
60 /* Disk operations */
61
62 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
63                                 const struct smb_filename *smb_fname,
64                                 uint64_t *bsize,
65                                 uint64_t *dfree,
66                                 uint64_t *dsize)
67 {
68         if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
69                 return (uint64_t)-1;
70         }
71
72         *bsize = 512;
73         return *dfree / 2;
74 }
75
76 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
77                                 const struct smb_filename *smb_fname,
78                                 enum SMB_QUOTA_TYPE qtype,
79                                 unid_t id,
80                                 SMB_DISK_QUOTA *qt)
81 {
82 #ifdef HAVE_SYS_QUOTAS
83         int result;
84
85         START_PROFILE(syscall_get_quota);
86         result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
87         END_PROFILE(syscall_get_quota);
88         return result;
89 #else
90         errno = ENOSYS;
91         return -1;
92 #endif
93 }
94
95 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
96 {
97 #ifdef HAVE_SYS_QUOTAS
98         int result;
99
100         START_PROFILE(syscall_set_quota);
101         result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
102         END_PROFILE(syscall_set_quota);
103         return result;
104 #else
105         errno = ENOSYS;
106         return -1;
107 #endif
108 }
109
110 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
111                                         struct files_struct *fsp,
112                                         struct shadow_copy_data *shadow_copy_data,
113                                         bool labels)
114 {
115         errno = ENOSYS;
116         return -1;  /* Not implemented. */
117 }
118
119 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
120                                 const struct smb_filename *smb_fname,
121                                 vfs_statvfs_struct *statbuf)
122 {
123         return sys_statvfs(smb_fname->base_name, statbuf);
124 }
125
126 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
127                 enum timestamp_set_resolution *p_ts_res)
128 {
129         const struct loadparm_substitution *lp_sub =
130                 loadparm_s3_global_substitution();
131         connection_struct *conn = handle->conn;
132         uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
133         struct smb_filename *smb_fname_cpath = NULL;
134         struct vfs_statvfs_struct statbuf;
135         int ret;
136
137         smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
138                                               conn->connectpath,
139                                               NULL,
140                                               NULL,
141                                               0,
142                                               0);
143         if (smb_fname_cpath == NULL) {
144                 return caps;
145         }
146
147         ZERO_STRUCT(statbuf);
148         ret = SMB_VFS_STATVFS(conn, smb_fname_cpath, &statbuf);
149         if (ret == 0) {
150                 caps = statbuf.FsCapabilities;
151         }
152
153         *p_ts_res = TIMESTAMP_SET_SECONDS;
154
155         /* Work out what timestamp resolution we can
156          * use when setting a timestamp. */
157
158         ret = SMB_VFS_STAT(conn, smb_fname_cpath);
159         if (ret == -1) {
160                 TALLOC_FREE(smb_fname_cpath);
161                 return caps;
162         }
163
164         if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
165                         smb_fname_cpath->st.st_ex_atime.tv_nsec ||
166                         smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
167                 /* If any of the normal UNIX directory timestamps
168                  * have a non-zero tv_nsec component assume
169                  * we might be able to set sub-second timestamps.
170                  * See what filetime set primitives we have.
171                  */
172 #if defined(HAVE_UTIMENSAT)
173                 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
174 #elif defined(HAVE_UTIMES)
175                 /* utimes allows msec timestamps to be set. */
176                 *p_ts_res = TIMESTAMP_SET_MSEC;
177 #elif defined(HAVE_UTIME)
178                 /* utime only allows sec timestamps to be set. */
179                 *p_ts_res = TIMESTAMP_SET_SECONDS;
180 #endif
181
182                 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
183                         "resolution of %s "
184                         "available on share %s, directory %s\n",
185                         *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
186                         lp_servicename(talloc_tos(), lp_sub, conn->params->service),
187                         conn->connectpath ));
188         }
189         TALLOC_FREE(smb_fname_cpath);
190         return caps;
191 }
192
193 static NTSTATUS vfswrap_get_dfs_referrals(struct vfs_handle_struct *handle,
194                                           struct dfs_GetDFSReferral *r)
195 {
196         struct junction_map *junction = NULL;
197         int consumedcnt = 0;
198         bool self_referral = false;
199         char *pathnamep = NULL;
200         char *local_dfs_path = NULL;
201         NTSTATUS status;
202         size_t i;
203         uint16_t max_referral_level = r->in.req.max_referral_level;
204
205         if (DEBUGLVL(10)) {
206                 NDR_PRINT_IN_DEBUG(dfs_GetDFSReferral, r);
207         }
208
209         /* get the junction entry */
210         if (r->in.req.servername == NULL) {
211                 return NT_STATUS_NOT_FOUND;
212         }
213
214         /*
215          * Trim pathname sent by client so it begins with only one backslash.
216          * Two backslashes confuse some dfs clients
217          */
218
219         local_dfs_path = talloc_strdup(r, r->in.req.servername);
220         if (local_dfs_path == NULL) {
221                 return NT_STATUS_NO_MEMORY;
222         }
223         pathnamep = local_dfs_path;
224         while (IS_DIRECTORY_SEP(pathnamep[0]) &&
225                IS_DIRECTORY_SEP(pathnamep[1])) {
226                 pathnamep++;
227         }
228
229         junction = talloc_zero(r, struct junction_map);
230         if (junction == NULL) {
231                 return NT_STATUS_NO_MEMORY;
232         }
233
234         /* The following call can change cwd. */
235         status = get_referred_path(r,
236                                    handle->conn->session_info,
237                                    pathnamep,
238                                    handle->conn->sconn->remote_address,
239                                    handle->conn->sconn->local_address,
240                                    !handle->conn->sconn->using_smb2,
241                                    junction, &consumedcnt, &self_referral);
242         if (!NT_STATUS_IS_OK(status)) {
243                 struct smb_filename connectpath_fname = {
244                         .base_name = handle->conn->connectpath
245                 };
246                 vfs_ChDir(handle->conn, &connectpath_fname);
247                 return status;
248         }
249         {
250                 struct smb_filename connectpath_fname = {
251                         .base_name = handle->conn->connectpath
252                 };
253                 vfs_ChDir(handle->conn, &connectpath_fname);
254         }
255
256         if (!self_referral) {
257                 pathnamep[consumedcnt] = '\0';
258
259                 if (DEBUGLVL(3)) {
260                         dbgtext("Path %s to alternate path(s):",
261                                 pathnamep);
262                         for (i=0; i < junction->referral_count; i++) {
263                                 dbgtext(" %s",
264                                 junction->referral_list[i].alternate_path);
265                         }
266                         dbgtext(".\n");
267                 }
268         }
269
270         if (r->in.req.max_referral_level <= 2) {
271                 max_referral_level = 2;
272         }
273         if (r->in.req.max_referral_level >= 3) {
274                 max_referral_level = 3;
275         }
276
277         r->out.resp = talloc_zero(r, struct dfs_referral_resp);
278         if (r->out.resp == NULL) {
279                 return NT_STATUS_NO_MEMORY;
280         }
281
282         r->out.resp->path_consumed = strlen_m(pathnamep) * 2;
283         r->out.resp->nb_referrals = junction->referral_count;
284
285         r->out.resp->header_flags = DFS_HEADER_FLAG_STORAGE_SVR;
286         if (self_referral) {
287                 r->out.resp->header_flags |= DFS_HEADER_FLAG_REFERAL_SVR;
288         }
289
290         r->out.resp->referral_entries = talloc_zero_array(r,
291                                 struct dfs_referral_type,
292                                 r->out.resp->nb_referrals);
293         if (r->out.resp->referral_entries == NULL) {
294                 return NT_STATUS_NO_MEMORY;
295         }
296
297         switch (max_referral_level) {
298         case 2:
299                 for(i=0; i < junction->referral_count; i++) {
300                         struct referral *ref = &junction->referral_list[i];
301                         TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
302                         struct dfs_referral_type *t =
303                                 &r->out.resp->referral_entries[i];
304                         struct dfs_referral_v2 *v2 = &t->referral.v2;
305
306                         t->version = 2;
307                         v2->size = VERSION2_REFERRAL_SIZE;
308                         if (self_referral) {
309                                 v2->server_type = DFS_SERVER_ROOT;
310                         } else {
311                                 v2->server_type = DFS_SERVER_NON_ROOT;
312                         }
313                         v2->entry_flags = 0;
314                         v2->proximity = ref->proximity;
315                         v2->ttl = ref->ttl;
316                         v2->DFS_path = talloc_strdup(mem_ctx, pathnamep);
317                         if (v2->DFS_path == NULL) {
318                                 return NT_STATUS_NO_MEMORY;
319                         }
320                         v2->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
321                         if (v2->DFS_alt_path == NULL) {
322                                 return NT_STATUS_NO_MEMORY;
323                         }
324                         v2->netw_address = talloc_strdup(mem_ctx,
325                                                          ref->alternate_path);
326                         if (v2->netw_address == NULL) {
327                                 return NT_STATUS_NO_MEMORY;
328                         }
329                 }
330
331                 break;
332         case 3:
333                 for(i=0; i < junction->referral_count; i++) {
334                         struct referral *ref = &junction->referral_list[i];
335                         TALLOC_CTX *mem_ctx = r->out.resp->referral_entries;
336                         struct dfs_referral_type *t =
337                                 &r->out.resp->referral_entries[i];
338                         struct dfs_referral_v3 *v3 = &t->referral.v3;
339                         struct dfs_normal_referral *r1 = &v3->referrals.r1;
340
341                         t->version = 3;
342                         v3->size = VERSION3_REFERRAL_SIZE;
343                         if (self_referral) {
344                                 v3->server_type = DFS_SERVER_ROOT;
345                         } else {
346                                 v3->server_type = DFS_SERVER_NON_ROOT;
347                         }
348                         v3->entry_flags = 0;
349                         v3->ttl = ref->ttl;
350                         r1->DFS_path = talloc_strdup(mem_ctx, pathnamep);
351                         if (r1->DFS_path == NULL) {
352                                 return NT_STATUS_NO_MEMORY;
353                         }
354                         r1->DFS_alt_path = talloc_strdup(mem_ctx, pathnamep);
355                         if (r1->DFS_alt_path == NULL) {
356                                 return NT_STATUS_NO_MEMORY;
357                         }
358                         r1->netw_address = talloc_strdup(mem_ctx,
359                                                          ref->alternate_path);
360                         if (r1->netw_address == NULL) {
361                                 return NT_STATUS_NO_MEMORY;
362                         }
363                 }
364                 break;
365         default:
366                 DEBUG(0,("Invalid dfs referral version: %d\n",
367                         max_referral_level));
368                 return NT_STATUS_INVALID_LEVEL;
369         }
370
371         if (DEBUGLVL(10)) {
372                 NDR_PRINT_OUT_DEBUG(dfs_GetDFSReferral, r);
373         }
374
375         return NT_STATUS_OK;
376 }
377
378 static NTSTATUS vfswrap_create_dfs_pathat(struct vfs_handle_struct *handle,
379                                 struct files_struct *dirfsp,
380                                 const struct smb_filename *smb_fname,
381                                 const struct referral *reflist,
382                                 size_t referral_count)
383 {
384         TALLOC_CTX *frame = talloc_stackframe();
385         NTSTATUS status = NT_STATUS_NO_MEMORY;
386         int ret;
387         char *msdfs_link = NULL;
388
389         /* Form the msdfs_link contents */
390         msdfs_link = msdfs_link_string(frame,
391                                         reflist,
392                                         referral_count);
393         if (msdfs_link == NULL) {
394                 goto out;
395         }
396
397         ret = symlinkat(msdfs_link,
398                         fsp_get_pathref_fd(dirfsp),
399                         smb_fname->base_name);
400         if (ret == 0) {
401                 status = NT_STATUS_OK;
402         } else {
403                 status = map_nt_error_from_unix(errno);
404         }
405
406   out:
407
408         TALLOC_FREE(frame);
409         return status;
410 }
411
412 /*
413  * Read and return the contents of a DFS redirect given a
414  * pathname. A caller can pass in NULL for ppreflist and
415  * preferral_count but still determine if this was a
416  * DFS redirect point by getting NT_STATUS_OK back
417  * without incurring the overhead of reading and parsing
418  * the referral contents.
419  */
420
421 static NTSTATUS vfswrap_read_dfs_pathat(struct vfs_handle_struct *handle,
422                                 TALLOC_CTX *mem_ctx,
423                                 struct files_struct *dirfsp,
424                                 struct smb_filename *smb_fname,
425                                 struct referral **ppreflist,
426                                 size_t *preferral_count)
427 {
428         NTSTATUS status = NT_STATUS_NO_MEMORY;
429         size_t bufsize;
430         char *link_target = NULL;
431         int referral_len;
432         bool ok;
433 #if defined(HAVE_BROKEN_READLINK)
434         char link_target_buf[PATH_MAX];
435 #else
436         char link_target_buf[7];
437 #endif
438         int ret;
439
440         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         subreq = SMB_VFS_GETXATTRAT_SEND(state,
1788                                          ev,
1789                                          dir_fsp,
1790                                          smb_fname,
1791                                          SAMBA_XATTR_DOS_ATTRIB,
1792                                          sizeof(fstring));
1793         if (tevent_req_nomem(subreq, req)) {
1794                 return tevent_req_post(req, ev);
1795         }
1796         tevent_req_set_callback(subreq,
1797                                 vfswrap_get_dos_attributes_getxattr_done,
1798                                 req);
1799
1800         return req;
1801 }
1802
1803 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1804 {
1805         struct tevent_req *req =
1806                 tevent_req_callback_data(subreq,
1807                 struct tevent_req);
1808         struct vfswrap_get_dos_attributes_state *state =
1809                 tevent_req_data(req,
1810                 struct vfswrap_get_dos_attributes_state);
1811         ssize_t xattr_size;
1812         DATA_BLOB blob = {0};
1813         char *path = NULL;
1814         char *tofree = NULL;
1815         char pathbuf[PATH_MAX+1];
1816         ssize_t pathlen;
1817         struct smb_filename smb_fname;
1818         bool offline;
1819         NTSTATUS status;
1820
1821         xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1822                                              &state->aio_state,
1823                                              state,
1824                                              &blob.data);
1825         TALLOC_FREE(subreq);
1826         if (xattr_size == -1) {
1827                 status = map_nt_error_from_unix(state->aio_state.error);
1828
1829                 if (state->as_root) {
1830                         tevent_req_nterror(req, status);
1831                         return;
1832                 }
1833                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1834                         tevent_req_nterror(req, status);
1835                         return;
1836                 }
1837
1838                 state->as_root = true;
1839
1840                 become_root();
1841                 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1842                                                  state->ev,
1843                                                  state->dir_fsp,
1844                                                  state->smb_fname,
1845                                                  SAMBA_XATTR_DOS_ATTRIB,
1846                                                  sizeof(fstring));
1847                 unbecome_root();
1848                 if (tevent_req_nomem(subreq, req)) {
1849                         return;
1850                 }
1851                 tevent_req_set_callback(subreq,
1852                                         vfswrap_get_dos_attributes_getxattr_done,
1853                                         req);
1854                 return;
1855         }
1856
1857         blob.length = xattr_size;
1858
1859         status = parse_dos_attribute_blob(state->smb_fname,
1860                                           blob,
1861                                           &state->dosmode);
1862         if (!NT_STATUS_IS_OK(status)) {
1863                 tevent_req_nterror(req, status);
1864                 return;
1865         }
1866
1867         pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1868                                 state->smb_fname->base_name,
1869                                 pathbuf,
1870                                 sizeof(pathbuf),
1871                                 &path,
1872                                 &tofree);
1873         if (pathlen == -1) {
1874                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1875                 return;
1876         }
1877
1878         smb_fname = (struct smb_filename) {
1879                 .base_name = path,
1880                 .st = state->smb_fname->st,
1881                 .flags = state->smb_fname->flags,
1882                 .twrp = state->smb_fname->twrp,
1883         };
1884
1885         offline = vfswrap_is_offline(state->conn, &smb_fname);
1886         if (offline) {
1887                 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1888         }
1889         TALLOC_FREE(tofree);
1890
1891         tevent_req_done(req);
1892         return;
1893 }
1894
1895 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1896                                                 struct vfs_aio_state *aio_state,
1897                                                 uint32_t *dosmode)
1898 {
1899         struct vfswrap_get_dos_attributes_state *state =
1900                 tevent_req_data(req,
1901                 struct vfswrap_get_dos_attributes_state);
1902         NTSTATUS status;
1903
1904         if (tevent_req_is_nterror(req, &status)) {
1905                 tevent_req_received(req);
1906                 return status;
1907         }
1908
1909         *aio_state = state->aio_state;
1910         *dosmode = state->dosmode;
1911         tevent_req_received(req);
1912         return NT_STATUS_OK;
1913 }
1914
1915 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1916                                             struct files_struct *fsp,
1917                                             uint32_t *dosmode)
1918 {
1919         bool offline;
1920
1921         offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1922         if (offline) {
1923                 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1924         }
1925
1926         return fget_ea_dos_attribute(fsp, dosmode);
1927 }
1928
1929 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1930                                             struct files_struct *fsp,
1931                                             uint32_t dosmode)
1932 {
1933         return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1934 }
1935
1936 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1937
1938 struct vfswrap_offload_read_state {
1939         DATA_BLOB token;
1940 };
1941
1942 static struct tevent_req *vfswrap_offload_read_send(
1943         TALLOC_CTX *mem_ctx,
1944         struct tevent_context *ev,
1945         struct vfs_handle_struct *handle,
1946         struct files_struct *fsp,
1947         uint32_t fsctl,
1948         uint32_t ttl,
1949         off_t offset,
1950         size_t to_copy)
1951 {
1952         struct tevent_req *req = NULL;
1953         struct vfswrap_offload_read_state *state = NULL;
1954         NTSTATUS status;
1955
1956         req = tevent_req_create(mem_ctx, &state,
1957                                 struct vfswrap_offload_read_state);
1958         if (req == NULL) {
1959                 return NULL;
1960         }
1961
1962         status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1963                                             &vfswrap_offload_ctx);
1964         if (tevent_req_nterror(req, status)) {
1965                 return tevent_req_post(req, ev);
1966         }
1967
1968         if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1969                 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1970                 return tevent_req_post(req, ev);
1971         }
1972
1973         status = vfs_offload_token_create_blob(state, fsp, fsctl,
1974                                                &state->token);
1975         if (tevent_req_nterror(req, status)) {
1976                 return tevent_req_post(req, ev);
1977         }
1978
1979         status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1980                                                 &state->token);
1981         if (tevent_req_nterror(req, status)) {
1982                 return tevent_req_post(req, ev);
1983         }
1984
1985         tevent_req_done(req);
1986         return tevent_req_post(req, ev);
1987 }
1988
1989 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1990                                           struct vfs_handle_struct *handle,
1991                                           TALLOC_CTX *mem_ctx,
1992                                           uint32_t *flags,
1993                                           uint64_t *xferlen,
1994                                           DATA_BLOB *token)
1995 {
1996         struct vfswrap_offload_read_state *state = tevent_req_data(
1997                 req, struct vfswrap_offload_read_state);
1998         NTSTATUS status;
1999
2000         if (tevent_req_is_nterror(req, &status)) {
2001                 tevent_req_received(req);
2002                 return status;
2003         }
2004
2005         *flags = 0;
2006         *xferlen = 0;
2007         token->length = state->token.length;
2008         token->data = talloc_move(mem_ctx, &state->token.data);
2009
2010         tevent_req_received(req);
2011         return NT_STATUS_OK;
2012 }
2013
2014 struct vfswrap_offload_write_state {
2015         uint8_t *buf;
2016         bool read_lck_locked;
2017         bool write_lck_locked;
2018         DATA_BLOB *token;
2019         struct tevent_context *src_ev;
2020         struct files_struct *src_fsp;
2021         off_t src_off;
2022         struct tevent_context *dst_ev;
2023         struct files_struct *dst_fsp;
2024         off_t dst_off;
2025         off_t to_copy;
2026         off_t remaining;
2027         off_t copied;
2028         size_t next_io_size;
2029 };
2030
2031 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2032                                           enum tevent_req_state req_state)
2033 {
2034         struct vfswrap_offload_write_state *state = tevent_req_data(
2035                 req, struct vfswrap_offload_write_state);
2036         bool ok;
2037
2038         if (state->dst_fsp == NULL) {
2039                 return;
2040         }
2041
2042         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2043         SMB_ASSERT(ok);
2044         state->dst_fsp = NULL;
2045 }
2046
2047 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req);
2048 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2049
2050 static struct tevent_req *vfswrap_offload_write_send(
2051         struct vfs_handle_struct *handle,
2052         TALLOC_CTX *mem_ctx,
2053         struct tevent_context *ev,
2054         uint32_t fsctl,
2055         DATA_BLOB *token,
2056         off_t transfer_offset,
2057         struct files_struct *dest_fsp,
2058         off_t dest_off,
2059         off_t to_copy)
2060 {
2061         struct tevent_req *req;
2062         struct vfswrap_offload_write_state *state = NULL;
2063         /* off_t is signed! */
2064         off_t max_offset = INT64_MAX - to_copy;
2065         size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2066         files_struct *src_fsp = NULL;
2067         NTSTATUS status;
2068         bool ok;
2069
2070         req = tevent_req_create(mem_ctx, &state,
2071                                 struct vfswrap_offload_write_state);
2072         if (req == NULL) {
2073                 return NULL;
2074         }
2075
2076         *state = (struct vfswrap_offload_write_state) {
2077                 .token = token,
2078                 .src_off = transfer_offset,
2079                 .dst_ev = ev,
2080                 .dst_fsp = dest_fsp,
2081                 .dst_off = dest_off,
2082                 .to_copy = to_copy,
2083                 .remaining = to_copy,
2084         };
2085
2086         tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2087
2088         switch (fsctl) {
2089         case FSCTL_SRV_COPYCHUNK:
2090         case FSCTL_SRV_COPYCHUNK_WRITE:
2091                 break;
2092
2093         case FSCTL_OFFLOAD_WRITE:
2094                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2095                 return tevent_req_post(req, ev);
2096
2097         case FSCTL_DUP_EXTENTS_TO_FILE:
2098                 DBG_DEBUG("COW clones not supported by vfs_default\n");
2099                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100                 return tevent_req_post(req, ev);
2101
2102         default:
2103                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2104                 return tevent_req_post(req, ev);
2105         }
2106
2107         /*
2108          * From here on we assume a copy-chunk fsctl
2109          */
2110
2111         if (to_copy == 0) {
2112                 tevent_req_done(req);
2113                 return tevent_req_post(req, ev);
2114         }
2115
2116         if (state->src_off > max_offset) {
2117                 /*
2118                  * Protect integer checks below.
2119                  */
2120                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2121                 return tevent_req_post(req, ev);
2122         }
2123         if (state->src_off < 0) {
2124                 /*
2125                  * Protect integer checks below.
2126                  */
2127                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2128                 return tevent_req_post(req, ev);
2129         }
2130         if (state->dst_off > max_offset) {
2131                 /*
2132                  * Protect integer checks below.
2133                  */
2134                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2135                 return tevent_req_post(req, ev);
2136         }
2137         if (state->dst_off < 0) {
2138                 /*
2139                  * Protect integer checks below.
2140                  */
2141                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2142                 return tevent_req_post(req, ev);
2143         }
2144
2145         status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2146                                                 token, &src_fsp);
2147         if (tevent_req_nterror(req, status)) {
2148                 return tevent_req_post(req, ev);
2149         }
2150
2151         DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2152
2153         status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2154         if (!NT_STATUS_IS_OK(status)) {
2155                 tevent_req_nterror(req, status);
2156                 return tevent_req_post(req, ev);
2157         }
2158
2159         ok = change_to_user_and_service_by_fsp(src_fsp);
2160         if (!ok) {
2161                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2162                 return tevent_req_post(req, ev);
2163         }
2164
2165         state->src_ev = src_fsp->conn->sconn->ev_ctx;
2166         state->src_fsp = src_fsp;
2167
2168         status = vfs_stat_fsp(src_fsp);
2169         if (tevent_req_nterror(req, status)) {
2170                 return tevent_req_post(req, ev);
2171         }
2172
2173         if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2174                 /*
2175                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2176                  *   If the SourceOffset or SourceOffset + Length extends beyond
2177                  *   the end of file, the server SHOULD<240> treat this as a
2178                  *   STATUS_END_OF_FILE error.
2179                  * ...
2180                  *   <240> Section 3.3.5.15.6: Windows servers will return
2181                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2182                  */
2183                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2184                 return tevent_req_post(req, ev);
2185         }
2186
2187         status = vfswrap_offload_copy_file_range(req);
2188         if (NT_STATUS_IS_OK(status)) {
2189                 tevent_req_done(req);
2190                 return tevent_req_post(req, ev);
2191         }
2192         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2193                 tevent_req_nterror(req, status);
2194                 return tevent_req_post(req, ev);
2195         }
2196
2197         state->buf = talloc_array(state, uint8_t, num);
2198         if (tevent_req_nomem(state->buf, req)) {
2199                 return tevent_req_post(req, ev);
2200         }
2201
2202         status = vfswrap_offload_write_loop(req);
2203         if (!NT_STATUS_IS_OK(status)) {
2204                 tevent_req_nterror(req, status);
2205                 return tevent_req_post(req, ev);
2206         }
2207
2208         return req;
2209 }
2210
2211 static NTSTATUS vfswrap_offload_copy_file_range(struct tevent_req *req)
2212 {
2213         struct vfswrap_offload_write_state *state = tevent_req_data(
2214                 req, struct vfswrap_offload_write_state);
2215         struct lock_struct lck;
2216         ssize_t nwritten;
2217         NTSTATUS status;
2218         bool same_file;
2219         bool ok;
2220         static bool try_copy_file_range = true;
2221
2222         if (!try_copy_file_range) {
2223                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2224         }
2225
2226         same_file = file_id_equal(&state->src_fsp->file_id,
2227                                   &state->dst_fsp->file_id);
2228         if (same_file &&
2229             sys_io_ranges_overlap(state->remaining,
2230                                   state->src_off,
2231                                   state->remaining,
2232                                   state->dst_off))
2233         {
2234                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2235         }
2236
2237         if (is_named_stream(state->src_fsp->fsp_name) ||
2238             is_named_stream(state->dst_fsp->fsp_name))
2239         {
2240                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
2241         }
2242
2243         init_strict_lock_struct(state->src_fsp,
2244                                 state->src_fsp->op->global->open_persistent_id,
2245                                 state->src_off,
2246                                 state->remaining,
2247                                 READ_LOCK,
2248                                 lp_posix_cifsu_locktype(state->src_fsp),
2249                                 &lck);
2250
2251         ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2252                                  state->src_fsp,
2253                                  &lck);
2254         if (!ok) {
2255                 return NT_STATUS_FILE_LOCK_CONFLICT;
2256         }
2257
2258         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2259         if (!ok) {
2260                 return NT_STATUS_INTERNAL_ERROR;
2261         }
2262
2263         init_strict_lock_struct(state->dst_fsp,
2264                                 state->dst_fsp->op->global->open_persistent_id,
2265                                 state->dst_off,
2266                                 state->remaining,
2267                                 WRITE_LOCK,
2268                                 lp_posix_cifsu_locktype(state->dst_fsp),
2269                                 &lck);
2270
2271         ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2272                                        state->dst_fsp,
2273                                        &lck);
2274         if (!ok) {
2275                 return NT_STATUS_FILE_LOCK_CONFLICT;
2276         }
2277
2278         while (state->remaining > 0) {
2279                 nwritten = copy_file_range(fsp_get_io_fd(state->src_fsp),
2280                                            &state->src_off,
2281                                            fsp_get_io_fd(state->dst_fsp),
2282                                            &state->dst_off,
2283                                            state->remaining,
2284                                            0);
2285                 if (nwritten == -1) {
2286                         DBG_DEBUG("copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
2287                                   "n [%jd] failed: %s\n",
2288                                   fsp_str_dbg(state->src_fsp),
2289                                   (intmax_t)state->src_off,
2290                                   fsp_str_dbg(state->dst_fsp),
2291                                   (intmax_t)state->dst_off,
2292                                   (intmax_t)state->remaining,
2293                                   strerror(errno));
2294                         switch (errno) {
2295                         case EOPNOTSUPP:
2296                         case ENOSYS:
2297                                 try_copy_file_range = false;
2298                                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2299                                 break;
2300                         case EXDEV:
2301                                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
2302                                 break;
2303                         default:
2304                                 status = map_nt_error_from_unix(errno);
2305                                 if (NT_STATUS_EQUAL(
2306                                             status,
2307                                             NT_STATUS_MORE_PROCESSING_REQUIRED))
2308                                 {
2309                                         /* Avoid triggering the fallback */
2310                                         status = NT_STATUS_INTERNAL_ERROR;
2311                                 }
2312                                 break;
2313                         }
2314                         return status;
2315                 }
2316
2317                 if (state->remaining < nwritten) {
2318                         DBG_DEBUG("copy_file_range src [%s] dst [%s] "
2319                                   "n [%jd] remaining [%jd]\n",
2320                                   fsp_str_dbg(state->src_fsp),
2321                                   fsp_str_dbg(state->dst_fsp),
2322                                   (intmax_t)nwritten,
2323                                   (intmax_t)state->remaining);
2324                         return NT_STATUS_INTERNAL_ERROR;
2325                 }
2326
2327                 if (nwritten == 0) {
2328                         break;
2329                 }
2330                 state->copied += nwritten;
2331                 state->remaining -= nwritten;
2332         }
2333
2334         /*
2335          * Tell the req cleanup function there's no need to call
2336          * change_to_user_and_service_by_fsp() on the dst handle.
2337          */
2338         state->dst_fsp = NULL;
2339         return NT_STATUS_OK;
2340 }
2341
2342 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2343
2344 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2345 {
2346         struct vfswrap_offload_write_state *state = tevent_req_data(
2347                 req, struct vfswrap_offload_write_state);
2348         struct tevent_req *subreq = NULL;
2349         struct lock_struct read_lck;
2350         bool ok;
2351
2352         /*
2353          * This is called under the context of state->src_fsp.
2354          */
2355
2356         state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2357
2358         init_strict_lock_struct(state->src_fsp,
2359                                 state->src_fsp->op->global->open_persistent_id,
2360                                 state->src_off,
2361                                 state->next_io_size,
2362                                 READ_LOCK,
2363                                 lp_posix_cifsu_locktype(state->src_fsp),
2364                                 &read_lck);
2365
2366         ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2367                                  state->src_fsp,
2368                                  &read_lck);
2369         if (!ok) {
2370                 return NT_STATUS_FILE_LOCK_CONFLICT;
2371         }
2372
2373         subreq = SMB_VFS_PREAD_SEND(state,
2374                                     state->src_ev,
2375                                     state->src_fsp,
2376                                     state->buf,
2377                                     state->next_io_size,
2378                                     state->src_off);
2379         if (subreq == NULL) {
2380                 return NT_STATUS_NO_MEMORY;
2381         }
2382         tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2383
2384         return NT_STATUS_OK;
2385 }
2386
2387 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2388
2389 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2390 {
2391         struct tevent_req *req = tevent_req_callback_data(
2392                 subreq, struct tevent_req);
2393         struct vfswrap_offload_write_state *state = tevent_req_data(
2394                 req, struct vfswrap_offload_write_state);
2395         struct vfs_aio_state aio_state;
2396         struct lock_struct write_lck;
2397         ssize_t nread;
2398         bool ok;
2399
2400         nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2401         TALLOC_FREE(subreq);
2402         if (nread == -1) {
2403                 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2404                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2405                 return;
2406         }
2407         if (nread != state->next_io_size) {
2408                 DBG_ERR("Short read, only %zd of %zu\n",
2409                         nread, state->next_io_size);
2410                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2411                 return;
2412         }
2413
2414         state->src_off += nread;
2415
2416         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2417         if (!ok) {
2418                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2419                 return;
2420         }
2421
2422         init_strict_lock_struct(state->dst_fsp,
2423                                 state->dst_fsp->op->global->open_persistent_id,
2424                                 state->dst_off,
2425                                 state->next_io_size,
2426                                 WRITE_LOCK,
2427                                 lp_posix_cifsu_locktype(state->dst_fsp),
2428                                 &write_lck);
2429
2430         ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2431                                  state->dst_fsp,
2432                                  &write_lck);
2433         if (!ok) {
2434                 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2435                 return;
2436         }
2437
2438         subreq = SMB_VFS_PWRITE_SEND(state,
2439                                      state->dst_ev,
2440                                      state->dst_fsp,
2441                                      state->buf,
2442                                      state->next_io_size,
2443                                      state->dst_off);
2444         if (subreq == NULL) {
2445                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2446                 return;
2447         }
2448         tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2449 }
2450
2451 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2452 {
2453         struct tevent_req *req = tevent_req_callback_data(
2454                 subreq, struct tevent_req);
2455         struct vfswrap_offload_write_state *state = tevent_req_data(
2456                 req, struct vfswrap_offload_write_state);
2457         struct vfs_aio_state aio_state;
2458         ssize_t nwritten;
2459         NTSTATUS status;
2460         bool ok;
2461
2462         nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2463         TALLOC_FREE(subreq);
2464         if (nwritten == -1) {
2465                 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2466                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2467                 return;
2468         }
2469         if (nwritten != state->next_io_size) {
2470                 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2471                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2472                 return;
2473         }
2474
2475         state->dst_off += nwritten;
2476
2477         if (state->remaining < nwritten) {
2478                 /* Paranoia check */
2479                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2480                 return;
2481         }
2482         state->copied += nwritten;
2483         state->remaining -= nwritten;
2484         if (state->remaining == 0) {
2485                 tevent_req_done(req);
2486                 return;
2487         }
2488
2489         ok = change_to_user_and_service_by_fsp(state->src_fsp);
2490         if (!ok) {
2491                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2492                 return;
2493         }
2494
2495         status = vfswrap_offload_write_loop(req);
2496         if (!NT_STATUS_IS_OK(status)) {
2497                 tevent_req_nterror(req, status);
2498                 return;
2499         }
2500
2501         return;
2502 }
2503
2504 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2505                                         struct tevent_req *req,
2506                                         off_t *copied)
2507 {
2508         struct vfswrap_offload_write_state *state = tevent_req_data(
2509                 req, struct vfswrap_offload_write_state);
2510         NTSTATUS status;
2511
2512         if (tevent_req_is_nterror(req, &status)) {
2513                 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2514                 *copied = 0;
2515                 tevent_req_received(req);
2516                 return status;
2517         }
2518
2519         *copied = state->copied;
2520         DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2521         tevent_req_received(req);
2522
2523         return NT_STATUS_OK;
2524 }
2525
2526 static NTSTATUS vfswrap_fget_compression(struct vfs_handle_struct *handle,
2527                                         TALLOC_CTX *mem_ctx,
2528                                         struct files_struct *fsp,
2529                                         uint16_t *_compression_fmt)
2530 {
2531         return NT_STATUS_INVALID_DEVICE_REQUEST;
2532 }
2533
2534 static NTSTATUS vfswrap_set_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 /********************************************************************
2543  Given a stat buffer return the allocated size on disk, taking into
2544  account sparse files.
2545 ********************************************************************/
2546 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2547                                        struct files_struct *fsp,
2548                                        const SMB_STRUCT_STAT *sbuf)
2549 {
2550         uint64_t result;
2551
2552         START_PROFILE(syscall_get_alloc_size);
2553
2554         if(S_ISDIR(sbuf->st_ex_mode)) {
2555                 result = 0;
2556                 goto out;
2557         }
2558
2559 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2560         /* The type of st_blocksize is blkcnt_t which *MUST* be
2561            signed (according to POSIX) and can be less than 64-bits.
2562            Ensure when we're converting to 64 bits wide we don't
2563            sign extend. */
2564 #if defined(SIZEOF_BLKCNT_T_8)
2565         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2566 #elif defined(SIZEOF_BLKCNT_T_4)
2567         {
2568                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2569                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2570         }
2571 #else
2572 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2573 #endif
2574         if (result == 0) {
2575                 /*
2576                  * Some file systems do not allocate a block for very
2577                  * small files. But for non-empty file should report a
2578                  * positive size.
2579                  */
2580
2581                 uint64_t filesize = get_file_size_stat(sbuf);
2582                 if (filesize > 0) {
2583                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2584                 }
2585         }
2586 #else
2587         result = get_file_size_stat(sbuf);
2588 #endif
2589
2590         if (fsp && fsp->initial_allocation_size)
2591                 result = MAX(result,fsp->initial_allocation_size);
2592
2593         result = smb_roundup(handle->conn, result);
2594
2595  out:
2596         END_PROFILE(syscall_get_alloc_size);
2597         return result;
2598 }
2599
2600 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2601                         struct files_struct *dirfsp,
2602                         const struct smb_filename *smb_fname,
2603                         int flags)
2604 {
2605         int result = -1;
2606
2607         START_PROFILE(syscall_unlinkat);
2608
2609         if (is_named_stream(smb_fname)) {
2610                 errno = ENOENT;
2611                 goto out;
2612         }
2613         result = unlinkat(fsp_get_pathref_fd(dirfsp),
2614                         smb_fname->base_name,
2615                         flags);
2616
2617  out:
2618         END_PROFILE(syscall_unlinkat);
2619         return result;
2620 }
2621
2622 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2623 {
2624         int result;
2625
2626         START_PROFILE(syscall_fchmod);
2627
2628         if (!fsp->fsp_flags.is_pathref) {
2629                 result = fchmod(fsp_get_io_fd(fsp), mode);
2630                 END_PROFILE(syscall_fchmod);
2631                 return result;
2632         }
2633
2634         if (fsp->fsp_flags.have_proc_fds) {
2635                 int fd = fsp_get_pathref_fd(fsp);
2636                 const char *p = NULL;
2637                 char buf[PATH_MAX];
2638
2639                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2640                 if (p != NULL) {
2641                         result = chmod(p, mode);
2642                 } else {
2643                         result = -1;
2644                 }
2645                 END_PROFILE(syscall_fchmod);
2646                 return result;
2647         }
2648
2649         /*
2650          * This is no longer a handle based call.
2651          */
2652         result = chmod(fsp->fsp_name->base_name, mode);
2653
2654         END_PROFILE(syscall_fchmod);
2655         return result;
2656 }
2657
2658 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2659 {
2660 #ifdef HAVE_FCHOWN
2661         int result;
2662
2663         START_PROFILE(syscall_fchown);
2664         if (!fsp->fsp_flags.is_pathref) {
2665                 result = fchown(fsp_get_io_fd(fsp), uid, gid);
2666                 END_PROFILE(syscall_fchown);
2667                 return result;
2668         }
2669
2670         if (fsp->fsp_flags.have_proc_fds) {
2671                 int fd = fsp_get_pathref_fd(fsp);
2672                 const char *p = NULL;
2673                 char buf[PATH_MAX];
2674
2675                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2676                 if (p != NULL) {
2677                         result = chown(p, uid, gid);
2678                 } else {
2679                         result = -1;
2680                 }
2681                 END_PROFILE(syscall_fchown);
2682                 return result;
2683         }
2684
2685         /*
2686          * This is no longer a handle based call.
2687          */
2688         result = chown(fsp->fsp_name->base_name, uid, gid);
2689         END_PROFILE(syscall_fchown);
2690         return result;
2691 #else
2692         errno = ENOSYS;
2693         return -1;
2694 #endif
2695 }
2696
2697 static int vfswrap_lchown(vfs_handle_struct *handle,
2698                         const struct smb_filename *smb_fname,
2699                         uid_t uid,
2700                         gid_t gid)
2701 {
2702         int result;
2703
2704         START_PROFILE(syscall_lchown);
2705         result = lchown(smb_fname->base_name, uid, gid);
2706         END_PROFILE(syscall_lchown);
2707         return result;
2708 }
2709
2710 static int vfswrap_chdir(vfs_handle_struct *handle,
2711                         const struct smb_filename *smb_fname)
2712 {
2713         int result;
2714
2715         START_PROFILE(syscall_chdir);
2716         result = chdir(smb_fname->base_name);
2717         END_PROFILE(syscall_chdir);
2718         return result;
2719 }
2720
2721 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2722                                 TALLOC_CTX *ctx)
2723 {
2724         char *result;
2725         struct smb_filename *smb_fname = NULL;
2726
2727         START_PROFILE(syscall_getwd);
2728         result = sys_getwd();
2729         END_PROFILE(syscall_getwd);
2730
2731         if (result == NULL) {
2732                 return NULL;
2733         }
2734         smb_fname = synthetic_smb_fname(ctx,
2735                                 result,
2736                                 NULL,
2737                                 NULL,
2738                                 0,
2739                                 0);
2740         /*
2741          * sys_getwd() *always* returns malloced memory.
2742          * We must free here to avoid leaks:
2743          * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2744          */
2745         SAFE_FREE(result);
2746         return smb_fname;
2747 }
2748
2749 /*********************************************************************
2750  nsec timestamp resolution call. Convert down to whatever the underlying
2751  system will support.
2752 **********************************************************************/
2753
2754 static int vfswrap_fntimes(vfs_handle_struct *handle,
2755                            files_struct *fsp,
2756                            struct smb_file_time *ft)
2757 {
2758         int result = -1;
2759         struct timespec ts[2];
2760         struct timespec *times = NULL;
2761
2762         START_PROFILE(syscall_fntimes);
2763
2764         if (is_named_stream(fsp->fsp_name)) {
2765                 errno = ENOENT;
2766                 goto out;
2767         }
2768
2769         if (ft != NULL) {
2770                 if (is_omit_timespec(&ft->atime)) {
2771                         ft->atime = fsp->fsp_name->st.st_ex_atime;
2772                 }
2773
2774                 if (is_omit_timespec(&ft->mtime)) {
2775                         ft->mtime = fsp->fsp_name->st.st_ex_mtime;
2776                 }
2777
2778                 if (!is_omit_timespec(&ft->create_time)) {
2779                         set_create_timespec_ea(fsp,
2780                                                ft->create_time);
2781                 }
2782
2783                 if ((timespec_compare(&ft->atime,
2784                                       &fsp->fsp_name->st.st_ex_atime) == 0) &&
2785                     (timespec_compare(&ft->mtime,
2786                                       &fsp->fsp_name->st.st_ex_mtime) == 0)) {
2787                         result = 0;
2788                         goto out;
2789                 }
2790
2791                 ts[0] = ft->atime;
2792                 ts[1] = ft->mtime;
2793                 times = ts;
2794         } else {
2795                 times = NULL;
2796         }
2797
2798         if (!fsp->fsp_flags.is_pathref) {
2799                 result = futimens(fsp_get_io_fd(fsp), times);
2800                 goto out;
2801         }
2802
2803         if (fsp->fsp_flags.have_proc_fds) {
2804                 int fd = fsp_get_pathref_fd(fsp);
2805                 const char *p = NULL;
2806                 char buf[PATH_MAX];
2807
2808                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
2809                 if (p != NULL) {
2810                         /*
2811                          * The dirfd argument of utimensat is ignored when
2812                          * pathname is an absolute path
2813                          */
2814                         result = utimensat(AT_FDCWD, p, times, 0);
2815                 } else {
2816                         result = -1;
2817                 }
2818
2819                 goto out;
2820         }
2821
2822         /*
2823          * The fd is a pathref (opened with O_PATH) and there isn't fd to
2824          * path translation mechanism. Fallback to path based call.
2825          */
2826         result = utimensat(AT_FDCWD, fsp->fsp_name->base_name, times, 0);
2827
2828 out:
2829         END_PROFILE(syscall_fntimes);
2830
2831         return result;
2832 }
2833
2834
2835 /*********************************************************************
2836  A version of ftruncate that will write the space on disk if strict
2837  allocate is set.
2838 **********************************************************************/
2839
2840 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2841 {
2842         off_t space_to_write;
2843         uint64_t space_avail;
2844         uint64_t bsize,dfree,dsize;
2845         int ret;
2846         NTSTATUS status;
2847         SMB_STRUCT_STAT *pst;
2848         bool ok;
2849
2850         ok = vfs_valid_pwrite_range(len, 0);
2851         if (!ok) {
2852                 errno = EINVAL;
2853                 return -1;
2854         }
2855
2856         status = vfs_stat_fsp(fsp);
2857         if (!NT_STATUS_IS_OK(status)) {
2858                 return -1;
2859         }
2860         pst = &fsp->fsp_name->st;
2861
2862 #ifdef S_ISFIFO
2863         if (S_ISFIFO(pst->st_ex_mode))
2864                 return 0;
2865 #endif
2866
2867         if (pst->st_ex_size == len)
2868                 return 0;
2869
2870         /* Shrink - just ftruncate. */
2871         if (pst->st_ex_size > len)
2872                 return ftruncate(fsp_get_io_fd(fsp), len);
2873
2874         space_to_write = len - pst->st_ex_size;
2875
2876         /* for allocation try fallocate first. This can fail on some
2877            platforms e.g. when the filesystem doesn't support it and no
2878            emulation is being done by the libc (like on AIX with JFS1). In that
2879            case we do our own emulation. fallocate implementations can
2880            return ENOTSUP or EINVAL in cases like that. */
2881         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2882         if (ret == -1 && errno == ENOSPC) {
2883                 return -1;
2884         }
2885         if (ret == 0) {
2886                 return 0;
2887         }
2888         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2889                 "error %d. Falling back to slow manual allocation\n", errno));
2890
2891         /* available disk space is enough or not? */
2892         space_avail =
2893             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2894         /* space_avail is 1k blocks */
2895         if (space_avail == (uint64_t)-1 ||
2896                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2897                 errno = ENOSPC;
2898                 return -1;
2899         }
2900
2901         /* Write out the real space on disk. */
2902         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2903         if (ret != 0) {
2904                 return -1;
2905         }
2906
2907         return 0;
2908 }
2909
2910 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2911 {
2912         int result = -1;
2913         SMB_STRUCT_STAT *pst;
2914         NTSTATUS status;
2915         char c = 0;
2916
2917         START_PROFILE(syscall_ftruncate);
2918
2919         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2920                 result = strict_allocate_ftruncate(handle, fsp, len);
2921                 END_PROFILE(syscall_ftruncate);
2922                 return result;
2923         }
2924
2925         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2926            ftruncate if the system supports it. Then I discovered that
2927            you can have some filesystems that support ftruncate
2928            expansion and some that don't! On Linux fat can't do
2929            ftruncate extend but ext2 can. */
2930
2931         result = ftruncate(fsp_get_io_fd(fsp), len);
2932
2933         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2934            extend a file with ftruncate. Provide alternate implementation
2935            for this */
2936
2937         /* Do an fstat to see if the file is longer than the requested
2938            size in which case the ftruncate above should have
2939            succeeded or shorter, in which case seek to len - 1 and
2940            write 1 byte of zero */
2941         status = vfs_stat_fsp(fsp);
2942         if (!NT_STATUS_IS_OK(status)) {
2943                 goto done;
2944         }
2945
2946         /* We need to update the files_struct after successful ftruncate */
2947         if (result == 0) {
2948                 goto done;
2949         }
2950
2951         pst = &fsp->fsp_name->st;
2952
2953 #ifdef S_ISFIFO
2954         if (S_ISFIFO(pst->st_ex_mode)) {
2955                 result = 0;
2956                 goto done;
2957         }
2958 #endif
2959
2960         if (pst->st_ex_size == len) {
2961                 result = 0;
2962                 goto done;
2963         }
2964
2965         if (pst->st_ex_size > len) {
2966                 /* the ftruncate should have worked */
2967                 goto done;
2968         }
2969
2970         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2971                 goto done;
2972         }
2973
2974         result = 0;
2975
2976   done:
2977
2978         END_PROFILE(syscall_ftruncate);
2979         return result;
2980 }
2981
2982 static int vfswrap_fallocate(vfs_handle_struct *handle,
2983                         files_struct *fsp,
2984                         uint32_t mode,
2985                         off_t offset,
2986                         off_t len)
2987 {
2988         int result;
2989
2990         START_PROFILE(syscall_fallocate);
2991         if (mode == 0) {
2992                 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2993                 /*
2994                  * posix_fallocate returns 0 on success, errno on error
2995                  * and doesn't set errno. Make it behave like fallocate()
2996                  * which returns -1, and sets errno on failure.
2997                  */
2998                 if (result != 0) {
2999                         errno = result;
3000                         result = -1;
3001                 }
3002         } else {
3003                 /* sys_fallocate handles filtering of unsupported mode flags */
3004                 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
3005         }
3006         END_PROFILE(syscall_fallocate);
3007         return result;
3008 }
3009
3010 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
3011 {
3012         bool result;
3013
3014         START_PROFILE(syscall_fcntl_lock);
3015
3016         if (fsp->fsp_flags.use_ofd_locks) {
3017                 op = map_process_lock_to_ofd_lock(op);
3018         }
3019
3020         result =  fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
3021         END_PROFILE(syscall_fcntl_lock);
3022         return result;
3023 }
3024
3025 static int vfswrap_filesystem_sharemode(vfs_handle_struct *handle,
3026                                         files_struct *fsp,
3027                                         uint32_t share_access,
3028                                         uint32_t access_mask)
3029 {
3030         errno = ENOTSUP;
3031         return -1;
3032 }
3033
3034 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
3035                          va_list cmd_arg)
3036 {
3037         void *argp;
3038         va_list dup_cmd_arg;
3039         int result;
3040         int val;
3041
3042         START_PROFILE(syscall_fcntl);
3043
3044         va_copy(dup_cmd_arg, cmd_arg);
3045
3046         switch(cmd) {
3047         case F_SETLK:
3048         case F_SETLKW:
3049         case F_GETLK:
3050 #if defined(HAVE_OFD_LOCKS)
3051         case F_OFD_SETLK:
3052         case F_OFD_SETLKW:
3053         case F_OFD_GETLK:
3054 #endif
3055 #if defined(HAVE_F_OWNER_EX)
3056         case F_GETOWN_EX:
3057         case F_SETOWN_EX:
3058 #endif
3059 #if defined(HAVE_RW_HINTS)
3060         case F_GET_RW_HINT:
3061         case F_SET_RW_HINT:
3062         case F_GET_FILE_RW_HINT:
3063         case F_SET_FILE_RW_HINT:
3064 #endif
3065                 argp = va_arg(dup_cmd_arg, void *);
3066                 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
3067                 break;
3068         default:
3069                 val = va_arg(dup_cmd_arg, int);
3070                 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
3071         }
3072
3073         va_end(dup_cmd_arg);
3074
3075         END_PROFILE(syscall_fcntl);
3076         return result;
3077 }
3078
3079 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
3080 {
3081         bool result;
3082         int op = F_GETLK;
3083
3084         START_PROFILE(syscall_fcntl_getlock);
3085
3086         if (fsp->fsp_flags.use_ofd_locks) {
3087                 op = map_process_lock_to_ofd_lock(op);
3088         }
3089
3090         result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
3091         END_PROFILE(syscall_fcntl_getlock);
3092         return result;
3093 }
3094
3095 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
3096                                 int leasetype)
3097 {
3098         int result = -1;
3099
3100         START_PROFILE(syscall_linux_setlease);
3101
3102 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
3103         result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
3104 #else
3105         errno = ENOSYS;
3106 #endif
3107         END_PROFILE(syscall_linux_setlease);
3108         return result;
3109 }
3110
3111 static int vfswrap_symlinkat(vfs_handle_struct *handle,
3112                         const struct smb_filename *link_target,
3113                         struct files_struct *dirfsp,
3114                         const struct smb_filename *new_smb_fname)
3115 {
3116         int result;
3117
3118         START_PROFILE(syscall_symlinkat);
3119
3120         result = symlinkat(link_target->base_name,
3121                         fsp_get_pathref_fd(dirfsp),
3122                         new_smb_fname->base_name);
3123         END_PROFILE(syscall_symlinkat);
3124         return result;
3125 }
3126
3127 static int vfswrap_readlinkat(vfs_handle_struct *handle,
3128                         const struct files_struct *dirfsp,
3129                         const struct smb_filename *smb_fname,
3130                         char *buf,
3131                         size_t bufsiz)
3132 {
3133         int result;
3134
3135         START_PROFILE(syscall_readlinkat);
3136
3137         result = readlinkat(fsp_get_pathref_fd(dirfsp),
3138                         smb_fname->base_name,
3139                         buf,
3140                         bufsiz);
3141
3142         END_PROFILE(syscall_readlinkat);
3143         return result;
3144 }
3145
3146 static int vfswrap_linkat(vfs_handle_struct *handle,
3147                         files_struct *srcfsp,
3148                         const struct smb_filename *old_smb_fname,
3149                         files_struct *dstfsp,
3150                         const struct smb_filename *new_smb_fname,
3151                         int flags)
3152 {
3153         int result;
3154
3155         START_PROFILE(syscall_linkat);
3156
3157         result = linkat(fsp_get_pathref_fd(srcfsp),
3158                         old_smb_fname->base_name,
3159                         fsp_get_pathref_fd(dstfsp),
3160                         new_smb_fname->base_name,
3161                         flags);
3162
3163         END_PROFILE(syscall_linkat);
3164         return result;
3165 }
3166
3167 static int vfswrap_mknodat(vfs_handle_struct *handle,
3168                         files_struct *dirfsp,
3169                         const struct smb_filename *smb_fname,
3170                         mode_t mode,
3171                         SMB_DEV_T dev)
3172 {
3173         int result;
3174
3175         START_PROFILE(syscall_mknodat);
3176
3177         result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
3178                         smb_fname->base_name,
3179                         mode,
3180                         dev);
3181
3182         END_PROFILE(syscall_mknodat);
3183         return result;
3184 }
3185
3186 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
3187                         TALLOC_CTX *ctx,
3188                         const struct smb_filename *smb_fname)
3189 {
3190         char *result;
3191         struct smb_filename *result_fname = NULL;
3192
3193         START_PROFILE(syscall_realpath);
3194         result = sys_realpath(smb_fname->base_name);
3195         END_PROFILE(syscall_realpath);
3196         if (result) {
3197                 result_fname = synthetic_smb_fname(ctx,
3198                                                    result,
3199                                                    NULL,
3200                                                    NULL,
3201                                                    0,
3202                                                    0);
3203                 SAFE_FREE(result);
3204         }
3205         return result_fname;
3206 }
3207
3208 static int vfswrap_fchflags(vfs_handle_struct *handle,
3209                         struct files_struct *fsp,
3210                         unsigned int flags)
3211 {
3212 #ifdef HAVE_FCHFLAGS
3213         int fd = fsp_get_pathref_fd(fsp);
3214
3215         if (!fsp->fsp_flags.is_pathref) {
3216                 return fchflags(fd, flags);
3217         }
3218
3219         if (fsp->fsp_flags.have_proc_fds) {
3220                 const char *p = NULL;
3221                 char buf[PATH_MAX];
3222
3223                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3224                 if (p == NULL) {
3225                         return -1;
3226                 }
3227
3228                 return chflags(p, flags);
3229         }
3230
3231         /*
3232          * This is no longer a handle based call.
3233          */
3234         return chflags(fsp->fsp_name->base_name, flags);
3235 #else
3236         errno = ENOSYS;
3237         return -1;
3238 #endif
3239 }
3240
3241 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3242                                              const SMB_STRUCT_STAT *sbuf)
3243 {
3244         struct file_id key;
3245
3246         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3247          * blob */
3248         ZERO_STRUCT(key);
3249
3250         key.devid = sbuf->st_ex_dev;
3251         key.inode = sbuf->st_ex_ino;
3252         /* key.extid is unused by default. */
3253
3254         return key;
3255 }
3256
3257 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3258                                    const SMB_STRUCT_STAT *psbuf)
3259 {
3260         uint64_t file_id;
3261
3262         if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3263                 return psbuf->st_ex_file_id;
3264         }
3265
3266         if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3267                 return (uint64_t)psbuf->st_ex_ino;
3268         }
3269
3270         /* FileIDLow */
3271         file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3272
3273         /* FileIDHigh */
3274         file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3275
3276         return file_id;
3277 }
3278
3279 static NTSTATUS vfswrap_fstreaminfo(vfs_handle_struct *handle,
3280                                    struct files_struct *fsp,
3281                                    TALLOC_CTX *mem_ctx,
3282                                    unsigned int *pnum_streams,
3283                                    struct stream_struct **pstreams)
3284 {
3285         struct stream_struct *tmp_streams = NULL;
3286         unsigned int num_streams = *pnum_streams;
3287         struct stream_struct *streams = *pstreams;
3288         NTSTATUS status;
3289
3290         if (fsp->fsp_flags.is_directory) {
3291                 /*
3292                  * No default streams on directories
3293                  */
3294                 goto done;
3295         }
3296         status = vfs_stat_fsp(fsp);
3297         if (!NT_STATUS_IS_OK(status)) {
3298                 return status;
3299         }
3300
3301         if (num_streams + 1 < 1) {
3302                 /* Integer wrap. */
3303                 return NT_STATUS_INVALID_PARAMETER;
3304         }
3305
3306         tmp_streams = talloc_realloc(mem_ctx,
3307                                         streams,
3308                                         struct stream_struct,
3309                                         num_streams + 1);
3310         if (tmp_streams == NULL) {
3311                 return NT_STATUS_NO_MEMORY;
3312         }
3313         tmp_streams[num_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3314         if (tmp_streams[num_streams].name == NULL) {
3315                 return NT_STATUS_NO_MEMORY;
3316         }
3317         tmp_streams[num_streams].size = fsp->fsp_name->st.st_ex_size;
3318         tmp_streams[num_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(
3319                                                 handle->conn,
3320                                                 fsp,
3321                                                 &fsp->fsp_name->st);
3322         num_streams += 1;
3323
3324         *pnum_streams = num_streams;
3325         *pstreams = tmp_streams;
3326  done:
3327         return NT_STATUS_OK;
3328 }
3329
3330 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3331                                      const struct smb_filename *path,
3332                                      const char *name,
3333                                      TALLOC_CTX *mem_ctx,
3334                                      char **found_name)
3335 {
3336         /*
3337          * Don't fall back to get_real_filename so callers can differentiate
3338          * between a full directory scan and an actual case-insensitive stat.
3339          */
3340         errno = EOPNOTSUPP;
3341         return -1;
3342 }
3343
3344 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3345                                    const struct smb_filename *smb_fname)
3346 {
3347         return handle->conn->connectpath;
3348 }
3349
3350 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3351                                          struct byte_range_lock *br_lck,
3352                                          struct lock_struct *plock)
3353 {
3354         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3355
3356         /* Note: blr is not used in the default implementation. */
3357         return brl_lock_windows_default(br_lck, plock);
3358 }
3359
3360 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3361                                        struct byte_range_lock *br_lck,
3362                                        const struct lock_struct *plock)
3363 {
3364         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3365
3366         return brl_unlock_windows_default(br_lck, plock);
3367 }
3368
3369 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3370                                       files_struct *fsp,
3371                                       struct lock_struct *plock)
3372 {
3373         SMB_ASSERT(plock->lock_type == READ_LOCK ||
3374             plock->lock_type == WRITE_LOCK);
3375
3376         return strict_lock_check_default(fsp, plock);
3377 }
3378
3379 /* NT ACL operations. */
3380
3381 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3382                                     files_struct *fsp,
3383                                     uint32_t security_info,
3384                                     TALLOC_CTX *mem_ctx,
3385                                     struct security_descriptor **ppdesc)
3386 {
3387         NTSTATUS result;
3388
3389         START_PROFILE(fget_nt_acl);
3390         result = posix_fget_nt_acl(fsp, security_info,
3391                                    mem_ctx, ppdesc);
3392         END_PROFILE(fget_nt_acl);
3393         return result;
3394 }
3395
3396 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3397 {
3398         NTSTATUS result;
3399
3400         START_PROFILE(fset_nt_acl);
3401         result = set_nt_acl(fsp, security_info_sent, psd);
3402         END_PROFILE(fset_nt_acl);
3403         return result;
3404 }
3405
3406 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3407                                    struct smb_filename *file,
3408                                    struct security_acl *sacl,
3409                                    uint32_t access_requested,
3410                                    uint32_t access_denied)
3411 {
3412         return NT_STATUS_OK; /* Nothing to do here ... */
3413 }
3414
3415 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3416                                         files_struct *fsp,
3417                                         SMB_ACL_TYPE_T type,
3418                                         TALLOC_CTX *mem_ctx)
3419 {
3420         return sys_acl_get_fd(handle, fsp, type, mem_ctx);
3421 }
3422
3423 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3424                                   files_struct *fsp,
3425                                   SMB_ACL_TYPE_T type,
3426                                   SMB_ACL_T theacl)
3427 {
3428         return sys_acl_set_fd(handle, fsp, type, theacl);
3429 }
3430
3431 static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle,
3432                                          files_struct *fsp)
3433 {
3434         return sys_acl_delete_def_fd(handle, fsp);
3435 }
3436
3437 /****************************************************************
3438  Extended attribute operations.
3439 *****************************************************************/
3440
3441 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3442                                  struct files_struct *fsp,
3443                                  const char *name,
3444                                  void *value,
3445                                  size_t size)
3446 {
3447         int fd = fsp_get_pathref_fd(fsp);
3448
3449         if (!fsp->fsp_flags.is_pathref) {
3450                 return fgetxattr(fd, name, value, size);
3451         }
3452
3453         if (fsp->fsp_flags.have_proc_fds) {
3454                 const char *p = NULL;
3455                 char buf[PATH_MAX];
3456
3457                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3458                 if (p == NULL) {
3459                         return -1;
3460                 }
3461
3462                 return getxattr(p, name, value, size);
3463         }
3464
3465         /*
3466          * This is no longer a handle based call.
3467          */
3468         return getxattr(fsp->fsp_name->base_name, name, value, size);
3469 }
3470
3471 struct vfswrap_getxattrat_state {
3472         struct tevent_context *ev;
3473         struct vfs_handle_struct *handle;
3474         files_struct *dir_fsp;
3475         const struct smb_filename *smb_fname;
3476
3477         /*
3478          * The following variables are talloced off "state" which is protected
3479          * by a destructor and thus are guaranteed to be safe to be used in the
3480          * job function in the worker thread.
3481          */
3482         char *name;
3483         const char *xattr_name;
3484         uint8_t *xattr_value;
3485         struct security_unix_token *token;
3486
3487         ssize_t xattr_size;
3488         struct vfs_aio_state vfs_aio_state;
3489         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3490 };
3491
3492 static int vfswrap_getxattrat_state_destructor(
3493                 struct vfswrap_getxattrat_state *state)
3494 {
3495         return -1;
3496 }
3497
3498 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3499 static void vfswrap_getxattrat_do_async(void *private_data);
3500 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3501
3502 static struct tevent_req *vfswrap_getxattrat_send(
3503                         TALLOC_CTX *mem_ctx,
3504                         struct tevent_context *ev,
3505                         struct vfs_handle_struct *handle,
3506                         files_struct *dir_fsp,
3507                         const struct smb_filename *smb_fname,
3508                         const char *xattr_name,
3509                         size_t alloc_hint)
3510 {
3511         struct tevent_req *req = NULL;
3512         struct tevent_req *subreq = NULL;
3513         struct vfswrap_getxattrat_state *state = NULL;
3514         size_t max_threads = 0;
3515         bool have_per_thread_cwd = false;
3516         bool have_per_thread_creds = false;
3517         bool do_async = false;
3518
3519         req = tevent_req_create(mem_ctx, &state,
3520                                 struct vfswrap_getxattrat_state);
3521         if (req == NULL) {
3522                 return NULL;
3523         }
3524         *state = (struct vfswrap_getxattrat_state) {
3525                 .ev = ev,
3526                 .handle = handle,
3527                 .dir_fsp = dir_fsp,
3528                 .smb_fname = smb_fname,
3529         };
3530
3531         max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3532         if (max_threads >= 1) {
3533                 /*
3534                  * We need a non sync threadpool!
3535                  */
3536                 have_per_thread_cwd = per_thread_cwd_supported();
3537         }
3538 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3539         have_per_thread_creds = true;
3540 #endif
3541         if (have_per_thread_cwd && have_per_thread_creds) {
3542                 do_async = true;
3543         }
3544
3545         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3546                                      state->profile_bytes, 0);
3547
3548         if (fsp_get_pathref_fd(dir_fsp) == -1) {
3549                 DBG_ERR("Need a valid directory fd\n");
3550                 tevent_req_error(req, EINVAL);
3551                 return tevent_req_post(req, ev);
3552         }
3553
3554         if (alloc_hint > 0) {
3555                 state->xattr_value = talloc_zero_array(state,
3556                                                        uint8_t,
3557                                                        alloc_hint);
3558                 if (tevent_req_nomem(state->xattr_value, req)) {
3559                         return tevent_req_post(req, ev);
3560                 }
3561         }
3562
3563         if (!do_async) {
3564                 vfswrap_getxattrat_do_sync(req);
3565                 return tevent_req_post(req, ev);
3566         }
3567
3568         /*
3569          * Now allocate all parameters from a memory context that won't go away
3570          * no matter what. These paremeters will get used in threads and we
3571          * can't reliably cancel threads, so all buffers passed to the threads
3572          * must not be freed before all referencing threads terminate.
3573          */
3574
3575         state->name = talloc_strdup(state, smb_fname->base_name);
3576         if (tevent_req_nomem(state->name, req)) {
3577                 return tevent_req_post(req, ev);
3578         }
3579
3580         state->xattr_name = talloc_strdup(state, xattr_name);
3581         if (tevent_req_nomem(state->xattr_name, req)) {
3582                 return tevent_req_post(req, ev);
3583         }
3584
3585         /*
3586          * This is a hot codepath so at first glance one might think we should
3587          * somehow optimize away the token allocation and do a
3588          * talloc_reference() or similar black magic instead. But due to the
3589          * talloc_stackframe pool per SMB2 request this should be a simple copy
3590          * without a malloc in most cases.
3591          */
3592         if (geteuid() == sec_initial_uid()) {
3593                 state->token = root_unix_token(state);
3594         } else {
3595                 state->token = copy_unix_token(
3596                                         state,
3597                                         dir_fsp->conn->session_info->unix_token);
3598         }
3599         if (tevent_req_nomem(state->token, req)) {
3600                 return tevent_req_post(req, ev);
3601         }
3602
3603         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3604
3605         subreq = pthreadpool_tevent_job_send(
3606                         state,
3607                         ev,
3608                         dir_fsp->conn->sconn->pool,
3609                         vfswrap_getxattrat_do_async,
3610                         state);
3611         if (tevent_req_nomem(subreq, req)) {
3612                 return tevent_req_post(req, ev);
3613         }
3614         tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3615
3616         talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3617
3618         return req;
3619 }
3620
3621 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3622 {
3623         struct vfswrap_getxattrat_state *state = tevent_req_data(
3624                 req, struct vfswrap_getxattrat_state);
3625         struct files_struct *fsp = state->smb_fname->fsp;
3626
3627         if (fsp->base_fsp != NULL) {
3628                 fsp = fsp->base_fsp;
3629         }
3630
3631         state->xattr_size = vfswrap_fgetxattr(state->handle,
3632                                               fsp,
3633                                               state->xattr_name,
3634                                               state->xattr_value,
3635                                               talloc_array_length(state->xattr_value));
3636         if (state->xattr_size == -1) {
3637                 tevent_req_error(req, errno);
3638                 return;
3639         }
3640
3641         tevent_req_done(req);
3642         return;
3643 }
3644
3645 static void vfswrap_getxattrat_do_async(void *private_data)
3646 {
3647         struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3648                 private_data, struct vfswrap_getxattrat_state);
3649         struct timespec start_time;
3650         struct timespec end_time;
3651         int ret;
3652         struct files_struct *fsp = state->smb_fname->fsp;
3653
3654         if (fsp->base_fsp != NULL) {
3655                 fsp = fsp->base_fsp;
3656         }
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