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