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