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