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