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