vfs_default: Protect vfs_getxattrat_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         struct tevent_req *req;
933         ssize_t ret;
934         int fd;
935         const void *buf;
936         size_t count;
937         off_t offset;
938
939         struct vfs_aio_state vfs_aio_state;
940         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
941 };
942
943 static void vfs_pwrite_do(void *private_data);
944 static void vfs_pwrite_done(struct tevent_req *subreq);
945 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state);
946
947 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
948                                               TALLOC_CTX *mem_ctx,
949                                               struct tevent_context *ev,
950                                               struct files_struct *fsp,
951                                               const void *data,
952                                               size_t n, off_t offset)
953 {
954         struct tevent_req *req, *subreq;
955         struct vfswrap_pwrite_state *state;
956
957         req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
958         if (req == NULL) {
959                 return NULL;
960         }
961
962         state->req = req;
963         state->ret = -1;
964         state->fd = fsp->fh->fd;
965         state->buf = data;
966         state->count = n;
967         state->offset = offset;
968
969         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
970                                      state->profile_bytes, n);
971         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
972
973         subreq = pthreadpool_tevent_job_send(
974                 state, ev, handle->conn->sconn->pool,
975                 vfs_pwrite_do, state);
976         if (tevent_req_nomem(subreq, req)) {
977                 return tevent_req_post(req, ev);
978         }
979         tevent_req_set_callback(subreq, vfs_pwrite_done, state);
980
981         talloc_set_destructor(state, vfs_pwrite_state_destructor);
982
983         return req;
984 }
985
986 static void vfs_pwrite_do(void *private_data)
987 {
988         struct vfswrap_pwrite_state *state = talloc_get_type_abort(
989                 private_data, struct vfswrap_pwrite_state);
990         struct timespec start_time;
991         struct timespec end_time;
992
993         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
994
995         PROFILE_TIMESTAMP(&start_time);
996
997         do {
998                 state->ret = pwrite(state->fd, state->buf, state->count,
999                                    state->offset);
1000         } while ((state->ret == -1) && (errno == EINTR));
1001
1002         if (state->ret == -1) {
1003                 state->vfs_aio_state.error = errno;
1004         }
1005
1006         PROFILE_TIMESTAMP(&end_time);
1007
1008         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1009
1010         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1011 }
1012
1013 static int vfs_pwrite_state_destructor(struct vfswrap_pwrite_state *state)
1014 {
1015         /*
1016          * This destructor only gets called if the request is still
1017          * in flight, which is why we deny it by returning -1. We
1018          * also set the req pointer to NULL so the _done function
1019          * can detect the caller doesn't want the result anymore.
1020          *
1021          * Forcing the fsp closed by a SHUTDOWN_CLOSE can cause this.
1022          */
1023         state->req = NULL;
1024         return -1;
1025 }
1026
1027 static void vfs_pwrite_done(struct tevent_req *subreq)
1028 {
1029         struct vfswrap_pwrite_state *state = tevent_req_callback_data(
1030                 subreq, struct vfswrap_pwrite_state);
1031         struct tevent_req *req = state->req;
1032         int ret;
1033
1034         ret = pthreadpool_tevent_job_recv(subreq);
1035         TALLOC_FREE(subreq);
1036         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1037         talloc_set_destructor(state, NULL);
1038         if (req == NULL) {
1039                 /*
1040                  * We were shutdown closed in flight. No one
1041                  * wants the result, and state has been reparented
1042                  * to the NULL context, so just free it so we
1043                  * don't leak memory.
1044                  */
1045                 DBG_NOTICE("pwrite request abandoned in flight\n");
1046                 TALLOC_FREE(state);
1047                 return;
1048         }
1049         if (ret != 0) {
1050                 if (ret != EAGAIN) {
1051                         tevent_req_error(req, ret);
1052                         return;
1053                 }
1054                 /*
1055                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1056                  * means the lower level pthreadpool failed to create a new
1057                  * thread. Fallback to sync processing in that case to allow
1058                  * some progress for the client.
1059                  */
1060                 vfs_pwrite_do(state);
1061         }
1062
1063         tevent_req_done(req);
1064 }
1065
1066 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
1067                                    struct vfs_aio_state *vfs_aio_state)
1068 {
1069         struct vfswrap_pwrite_state *state = tevent_req_data(
1070                 req, struct vfswrap_pwrite_state);
1071
1072         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1073                 return -1;
1074         }
1075
1076         *vfs_aio_state = state->vfs_aio_state;
1077         return state->ret;
1078 }
1079
1080 struct vfswrap_fsync_state {
1081         struct tevent_req *req;
1082         ssize_t ret;
1083         int fd;
1084
1085         struct vfs_aio_state vfs_aio_state;
1086         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
1087 };
1088
1089 static void vfs_fsync_do(void *private_data);
1090 static void vfs_fsync_done(struct tevent_req *subreq);
1091 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state);
1092
1093 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
1094                                              TALLOC_CTX *mem_ctx,
1095                                              struct tevent_context *ev,
1096                                              struct files_struct *fsp)
1097 {
1098         struct tevent_req *req, *subreq;
1099         struct vfswrap_fsync_state *state;
1100
1101         req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
1102         if (req == NULL) {
1103                 return NULL;
1104         }
1105
1106         state->req = req;
1107         state->ret = -1;
1108         state->fd = fsp->fh->fd;
1109
1110         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p,
1111                                      state->profile_bytes, 0);
1112         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1113
1114         subreq = pthreadpool_tevent_job_send(
1115                 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1116         if (tevent_req_nomem(subreq, req)) {
1117                 return tevent_req_post(req, ev);
1118         }
1119         tevent_req_set_callback(subreq, vfs_fsync_done, state);
1120
1121         talloc_set_destructor(state, vfs_fsync_state_destructor);
1122
1123         return req;
1124 }
1125
1126 static void vfs_fsync_do(void *private_data)
1127 {
1128         struct vfswrap_fsync_state *state = talloc_get_type_abort(
1129                 private_data, struct vfswrap_fsync_state);
1130         struct timespec start_time;
1131         struct timespec end_time;
1132
1133         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
1134
1135         PROFILE_TIMESTAMP(&start_time);
1136
1137         do {
1138                 state->ret = fsync(state->fd);
1139         } while ((state->ret == -1) && (errno == EINTR));
1140
1141         if (state->ret == -1) {
1142                 state->vfs_aio_state.error = errno;
1143         }
1144
1145         PROFILE_TIMESTAMP(&end_time);
1146
1147         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1148
1149         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
1150 }
1151
1152 static int vfs_fsync_state_destructor(struct vfswrap_fsync_state *state)
1153 {
1154         /*
1155          * This destructor only gets called if the request is still
1156          * in flight, which is why we deny it by returning -1. We
1157          * also set the req pointer to NULL so the _done function
1158          * can detect the caller doesn't want the result anymore.
1159          *
1160          * Forcing the fsp closed by a SHUTDOWN_CLOSE can cause this.
1161          */
1162         state->req = NULL;
1163         return -1;
1164 }
1165
1166 static void vfs_fsync_done(struct tevent_req *subreq)
1167 {
1168         struct vfswrap_fsync_state *state = tevent_req_callback_data(
1169                 subreq, struct vfswrap_fsync_state);
1170         struct tevent_req *req = state->req;
1171         int ret;
1172
1173         ret = pthreadpool_tevent_job_recv(subreq);
1174         TALLOC_FREE(subreq);
1175         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1176         talloc_set_destructor(state, NULL);
1177         if (req == NULL) {
1178                 /*
1179                  * We were shutdown closed in flight. No one
1180                  * wants the result, and state has been reparented
1181                  * to the NULL context, so just free it so we
1182                  * don't leak memory.
1183                  */
1184                 DBG_NOTICE("fsync request abandoned in flight\n");
1185                 TALLOC_FREE(state);
1186                 return;
1187         }
1188         if (ret != 0) {
1189                 if (ret != EAGAIN) {
1190                         tevent_req_error(req, ret);
1191                         return;
1192                 }
1193                 /*
1194                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
1195                  * means the lower level pthreadpool failed to create a new
1196                  * thread. Fallback to sync processing in that case to allow
1197                  * some progress for the client.
1198                  */
1199                 vfs_fsync_do(state);
1200         }
1201
1202         tevent_req_done(req);
1203 }
1204
1205 static int vfswrap_fsync_recv(struct tevent_req *req,
1206                               struct vfs_aio_state *vfs_aio_state)
1207 {
1208         struct vfswrap_fsync_state *state = tevent_req_data(
1209                 req, struct vfswrap_fsync_state);
1210
1211         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1212                 return -1;
1213         }
1214
1215         *vfs_aio_state = state->vfs_aio_state;
1216         return state->ret;
1217 }
1218
1219 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1220 {
1221         off_t result = 0;
1222
1223         START_PROFILE(syscall_lseek);
1224
1225         result = lseek(fsp->fh->fd, offset, whence);
1226         /*
1227          * We want to maintain the fiction that we can seek
1228          * on a fifo for file system purposes. This allows
1229          * people to set up UNIX fifo's that feed data to Windows
1230          * applications. JRA.
1231          */
1232
1233         if((result == -1) && (errno == ESPIPE)) {
1234                 result = 0;
1235                 errno = 0;
1236         }
1237
1238         END_PROFILE(syscall_lseek);
1239         return result;
1240 }
1241
1242 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1243                         off_t offset, size_t n)
1244 {
1245         ssize_t result;
1246
1247         START_PROFILE_BYTES(syscall_sendfile, n);
1248         result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1249         END_PROFILE_BYTES(syscall_sendfile);
1250         return result;
1251 }
1252
1253 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1254                         int fromfd,
1255                         files_struct *tofsp,
1256                         off_t offset,
1257                         size_t n)
1258 {
1259         ssize_t result;
1260
1261         START_PROFILE_BYTES(syscall_recvfile, n);
1262         result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1263         END_PROFILE_BYTES(syscall_recvfile);
1264         return result;
1265 }
1266
1267 static int vfswrap_renameat(vfs_handle_struct *handle,
1268                           files_struct *srcfsp,
1269                           const struct smb_filename *smb_fname_src,
1270                           files_struct *dstfsp,
1271                           const struct smb_filename *smb_fname_dst)
1272 {
1273         int result = -1;
1274
1275         START_PROFILE(syscall_renameat);
1276
1277         if (is_named_stream(smb_fname_src) || is_named_stream(smb_fname_dst)) {
1278                 errno = ENOENT;
1279                 goto out;
1280         }
1281
1282         result = renameat(srcfsp->fh->fd,
1283                         smb_fname_src->base_name,
1284                         dstfsp->fh->fd,
1285                         smb_fname_dst->base_name);
1286
1287  out:
1288         END_PROFILE(syscall_renameat);
1289         return result;
1290 }
1291
1292 static int vfswrap_stat(vfs_handle_struct *handle,
1293                         struct smb_filename *smb_fname)
1294 {
1295         int result = -1;
1296
1297         START_PROFILE(syscall_stat);
1298
1299         if (is_named_stream(smb_fname)) {
1300                 errno = ENOENT;
1301                 goto out;
1302         }
1303
1304         result = sys_stat(smb_fname->base_name, &smb_fname->st,
1305                           lp_fake_directory_create_times(SNUM(handle->conn)));
1306  out:
1307         END_PROFILE(syscall_stat);
1308         return result;
1309 }
1310
1311 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1312 {
1313         int result;
1314
1315         START_PROFILE(syscall_fstat);
1316         result = sys_fstat(fsp->fh->fd,
1317                            sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1318         END_PROFILE(syscall_fstat);
1319         return result;
1320 }
1321
1322 static int vfswrap_lstat(vfs_handle_struct *handle,
1323                          struct smb_filename *smb_fname)
1324 {
1325         int result = -1;
1326
1327         START_PROFILE(syscall_lstat);
1328
1329         if (is_named_stream(smb_fname)) {
1330                 errno = ENOENT;
1331                 goto out;
1332         }
1333
1334         result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1335                            lp_fake_directory_create_times(SNUM(handle->conn)));
1336  out:
1337         END_PROFILE(syscall_lstat);
1338         return result;
1339 }
1340
1341 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1342                                        const char *name,
1343                                        enum vfs_translate_direction direction,
1344                                        TALLOC_CTX *mem_ctx,
1345                                        char **mapped_name)
1346 {
1347         return NT_STATUS_NONE_MAPPED;
1348 }
1349
1350 /*
1351  * Implement the default fsctl operation.
1352  */
1353 static bool vfswrap_logged_ioctl_message = false;
1354
1355 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1356                               struct files_struct *fsp,
1357                               TALLOC_CTX *ctx,
1358                               uint32_t function,
1359                               uint16_t req_flags, /* Needed for UNICODE ... */
1360                               const uint8_t *_in_data,
1361                               uint32_t in_len,
1362                               uint8_t **_out_data,
1363                               uint32_t max_out_len,
1364                               uint32_t *out_len)
1365 {
1366         const char *in_data = (const char *)_in_data;
1367         char **out_data = (char **)_out_data;
1368         NTSTATUS status;
1369
1370         switch (function) {
1371         case FSCTL_SET_SPARSE:
1372         {
1373                 bool set_sparse = true;
1374
1375                 if (in_len >= 1 && in_data[0] == 0) {
1376                         set_sparse = false;
1377                 }
1378
1379                 status = file_set_sparse(handle->conn, fsp, set_sparse);
1380
1381                 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1382                       ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1383                        smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1384                        nt_errstr(status)));
1385
1386                 return status;
1387         }
1388
1389         case FSCTL_CREATE_OR_GET_OBJECT_ID:
1390         {
1391                 unsigned char objid[16];
1392                 char *return_data = NULL;
1393
1394                 /* This should return the object-id on this file.
1395                  * I think I'll make this be the inode+dev. JRA.
1396                  */
1397
1398                 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1399                           fsp_fnum_dbg(fsp)));
1400
1401                 *out_len = MIN(max_out_len, 64);
1402
1403                 /* Hmmm, will this cause problems if less data asked for? */
1404                 return_data = talloc_array(ctx, char, 64);
1405                 if (return_data == NULL) {
1406                         return NT_STATUS_NO_MEMORY;
1407                 }
1408
1409                 /* For backwards compatibility only store the dev/inode. */
1410                 push_file_id_16(return_data, &fsp->file_id);
1411                 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1412                 push_file_id_16(return_data+32, &fsp->file_id);
1413                 memset(return_data+48, 0, 16);
1414                 *out_data = return_data;
1415                 return NT_STATUS_OK;
1416         }
1417
1418         case FSCTL_GET_REPARSE_POINT:
1419         {
1420                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1421                 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1422                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1423                 return NT_STATUS_NOT_A_REPARSE_POINT;
1424         }
1425
1426         case FSCTL_SET_REPARSE_POINT:
1427         {
1428                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1429                 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1430                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1431                 return NT_STATUS_NOT_A_REPARSE_POINT;
1432         }
1433
1434         case FSCTL_GET_SHADOW_COPY_DATA:
1435         {
1436                 /*
1437                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1438                  * and return their volume names.  If max_data_count is 16, then it is just
1439                  * asking for the number of volumes and length of the combined names.
1440                  *
1441                  * pdata is the data allocated by our caller, but that uses
1442                  * total_data_count (which is 0 in our case) rather than max_data_count.
1443                  * Allocate the correct amount and return the pointer to let
1444                  * it be deallocated when we return.
1445                  */
1446                 struct shadow_copy_data *shadow_data = NULL;
1447                 bool labels = False;
1448                 uint32_t labels_data_count = 0;
1449                 uint32_t i;
1450                 char *cur_pdata = NULL;
1451
1452                 if (max_out_len < 16) {
1453                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1454                                 max_out_len));
1455                         return NT_STATUS_INVALID_PARAMETER;
1456                 }
1457
1458                 if (max_out_len > 16) {
1459                         labels = True;
1460                 }
1461
1462                 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1463                 if (shadow_data == NULL) {
1464                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
1465                         return NT_STATUS_NO_MEMORY;
1466                 }
1467
1468                 /*
1469                  * Call the VFS routine to actually do the work.
1470                  */
1471                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1472                         int log_lev = 0;
1473                         if (errno == 0) {
1474                                 /* broken module didn't set errno on error */
1475                                 status = NT_STATUS_UNSUCCESSFUL;
1476                         } else {
1477                                 status = map_nt_error_from_unix(errno);
1478                                 if (NT_STATUS_EQUAL(status,
1479                                                     NT_STATUS_NOT_SUPPORTED)) {
1480                                         log_lev = 5;
1481                                 }
1482                         }
1483                         DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1484                                         "connectpath %s, failed - %s.\n",
1485                                         fsp->conn->connectpath,
1486                                         nt_errstr(status)));
1487                         TALLOC_FREE(shadow_data);
1488                         return status;
1489                 }
1490
1491                 labels_data_count = (shadow_data->num_volumes * 2 *
1492                                         sizeof(SHADOW_COPY_LABEL)) + 2;
1493
1494                 if (!labels) {
1495                         *out_len = 16;
1496                 } else {
1497                         *out_len = 12 + labels_data_count;
1498                 }
1499
1500                 if (max_out_len < *out_len) {
1501                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1502                                 max_out_len, *out_len));
1503                         TALLOC_FREE(shadow_data);
1504                         return NT_STATUS_BUFFER_TOO_SMALL;
1505                 }
1506
1507                 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1508                 if (cur_pdata == NULL) {
1509                         TALLOC_FREE(shadow_data);
1510                         return NT_STATUS_NO_MEMORY;
1511                 }
1512
1513                 *out_data = cur_pdata;
1514
1515                 /* num_volumes 4 bytes */
1516                 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1517
1518                 if (labels) {
1519                         /* num_labels 4 bytes */
1520                         SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1521                 }
1522
1523                 /* needed_data_count 4 bytes */
1524                 SIVAL(cur_pdata, 8, labels_data_count);
1525
1526                 cur_pdata += 12;
1527
1528                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1529                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
1530                 if (labels && shadow_data->labels) {
1531                         for (i=0; i<shadow_data->num_volumes; i++) {
1532                                 size_t len = 0;
1533                                 status = srvstr_push(cur_pdata, req_flags,
1534                                             cur_pdata, shadow_data->labels[i],
1535                                             2 * sizeof(SHADOW_COPY_LABEL),
1536                                             STR_UNICODE|STR_TERMINATE, &len);
1537                                 if (!NT_STATUS_IS_OK(status)) {
1538                                         TALLOC_FREE(*out_data);
1539                                         TALLOC_FREE(shadow_data);
1540                                         return status;
1541                                 }
1542                                 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1543                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1544                         }
1545                 }
1546
1547                 TALLOC_FREE(shadow_data);
1548
1549                 return NT_STATUS_OK;
1550         }
1551
1552         case FSCTL_FIND_FILES_BY_SID:
1553         {
1554                 /* pretend this succeeded -
1555                  *
1556                  * we have to send back a list with all files owned by this SID
1557                  *
1558                  * but I have to check that --metze
1559                  */
1560                 ssize_t ret;
1561                 struct dom_sid sid;
1562                 struct dom_sid_buf buf;
1563                 uid_t uid;
1564                 size_t sid_len;
1565
1566                 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1567                            fsp_fnum_dbg(fsp)));
1568
1569                 if (in_len < 8) {
1570                         /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1571                         return NT_STATUS_INVALID_PARAMETER;
1572                 }
1573
1574                 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1575
1576                 /* unknown 4 bytes: this is not the length of the sid :-(  */
1577                 /*unknown = IVAL(pdata,0);*/
1578
1579                 ret = sid_parse(_in_data + 4, sid_len, &sid);
1580                 if (ret == -1) {
1581                         return NT_STATUS_INVALID_PARAMETER;
1582                 }
1583                 DEBUGADD(10, ("for SID: %s\n",
1584                               dom_sid_str_buf(&sid, &buf)));
1585
1586                 if (!sid_to_uid(&sid, &uid)) {
1587                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1588                                  dom_sid_str_buf(&sid, &buf),
1589                                  (unsigned long)sid_len));
1590                         uid = (-1);
1591                 }
1592
1593                 /* we can take a look at the find source :-)
1594                  *
1595                  * find ./ -uid $uid  -name '*'   is what we need here
1596                  *
1597                  *
1598                  * and send 4bytes len and then NULL terminated unicode strings
1599                  * for each file
1600                  *
1601                  * but I don't know how to deal with the paged results
1602                  * (maybe we can hang the result anywhere in the fsp struct)
1603                  *
1604                  * but I don't know how to deal with the paged results
1605                  * (maybe we can hang the result anywhere in the fsp struct)
1606                  *
1607                  * we don't send all files at once
1608                  * and at the next we should *not* start from the beginning,
1609                  * so we have to cache the result
1610                  *
1611                  * --metze
1612                  */
1613
1614                 /* this works for now... */
1615                 return NT_STATUS_OK;
1616         }
1617
1618         case FSCTL_QUERY_ALLOCATED_RANGES:
1619         {
1620                 /* FIXME: This is just a dummy reply, telling that all of the
1621                  * file is allocated. MKS cp needs that.
1622                  * Adding the real allocated ranges via FIEMAP on Linux
1623                  * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1624                  * this FSCTL correct for sparse files.
1625                  */
1626                 uint64_t offset, length;
1627                 char *out_data_tmp = NULL;
1628
1629                 if (in_len != 16) {
1630                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1631                                 in_len));
1632                         return NT_STATUS_INVALID_PARAMETER;
1633                 }
1634
1635                 if (max_out_len < 16) {
1636                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1637                                 max_out_len));
1638                         return NT_STATUS_INVALID_PARAMETER;
1639                 }
1640
1641                 offset = BVAL(in_data,0);
1642                 length = BVAL(in_data,8);
1643
1644                 if (offset + length < offset) {
1645                         /* No 64-bit integer wrap. */
1646                         return NT_STATUS_INVALID_PARAMETER;
1647                 }
1648
1649                 /* Shouldn't this be SMB_VFS_STAT ... ? */
1650                 status = vfs_stat_fsp(fsp);
1651                 if (!NT_STATUS_IS_OK(status)) {
1652                         return status;
1653                 }
1654
1655                 *out_len = 16;
1656                 out_data_tmp = talloc_array(ctx, char, *out_len);
1657                 if (out_data_tmp == NULL) {
1658                         DEBUG(10, ("unable to allocate memory for response\n"));
1659                         return NT_STATUS_NO_MEMORY;
1660                 }
1661
1662                 if (offset > fsp->fsp_name->st.st_ex_size ||
1663                                 fsp->fsp_name->st.st_ex_size == 0 ||
1664                                 length == 0) {
1665                         memset(out_data_tmp, 0, *out_len);
1666                 } else {
1667                         uint64_t end = offset + length;
1668                         end = MIN(end, fsp->fsp_name->st.st_ex_size);
1669                         SBVAL(out_data_tmp, 0, 0);
1670                         SBVAL(out_data_tmp, 8, end);
1671                 }
1672
1673                 *out_data = out_data_tmp;
1674
1675                 return NT_STATUS_OK;
1676         }
1677
1678         case FSCTL_IS_VOLUME_DIRTY:
1679         {
1680                 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1681                           "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1682                 /*
1683                  * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1684                  * says we have to respond with NT_STATUS_INVALID_PARAMETER
1685                  */
1686                 return NT_STATUS_INVALID_PARAMETER;
1687         }
1688
1689         default:
1690                 /*
1691                  * Only print once ... unfortunately there could be lots of
1692                  * different FSCTLs that are called.
1693                  */
1694                 if (!vfswrap_logged_ioctl_message) {
1695                         vfswrap_logged_ioctl_message = true;
1696                         DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1697                         __func__, function));
1698                 }
1699         }
1700
1701         return NT_STATUS_NOT_SUPPORTED;
1702 }
1703
1704 static bool vfswrap_is_offline(struct connection_struct *conn,
1705                                const struct smb_filename *fname);
1706
1707 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1708                                            struct smb_filename *smb_fname,
1709                                            uint32_t *dosmode)
1710 {
1711         bool offline;
1712
1713         offline = vfswrap_is_offline(handle->conn, smb_fname);
1714         if (offline) {
1715                 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1716         }
1717
1718         return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1719 }
1720
1721 struct vfswrap_get_dos_attributes_state {
1722         struct vfs_aio_state aio_state;
1723         connection_struct *conn;
1724         TALLOC_CTX *mem_ctx;
1725         struct tevent_context *ev;
1726         files_struct *dir_fsp;
1727         struct smb_filename *smb_fname;
1728         uint32_t dosmode;
1729         bool as_root;
1730 };
1731
1732 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
1733
1734 static struct tevent_req *vfswrap_get_dos_attributes_send(
1735                         TALLOC_CTX *mem_ctx,
1736                         struct tevent_context *ev,
1737                         struct vfs_handle_struct *handle,
1738                         files_struct *dir_fsp,
1739                         struct smb_filename *smb_fname)
1740 {
1741         struct tevent_req *req = NULL;
1742         struct tevent_req *subreq = NULL;
1743         struct vfswrap_get_dos_attributes_state *state = NULL;
1744
1745         req = tevent_req_create(mem_ctx, &state,
1746                                 struct vfswrap_get_dos_attributes_state);
1747         if (req == NULL) {
1748                 return NULL;
1749         }
1750
1751         *state = (struct vfswrap_get_dos_attributes_state) {
1752                 .conn = dir_fsp->conn,
1753                 .mem_ctx = mem_ctx,
1754                 .ev = ev,
1755                 .dir_fsp = dir_fsp,
1756                 .smb_fname = smb_fname,
1757         };
1758
1759         subreq = SMB_VFS_GETXATTRAT_SEND(state,
1760                                          ev,
1761                                          dir_fsp,
1762                                          smb_fname,
1763                                          SAMBA_XATTR_DOS_ATTRIB,
1764                                          sizeof(fstring));
1765         if (tevent_req_nomem(subreq, req)) {
1766                 return tevent_req_post(req, ev);
1767         }
1768         tevent_req_set_callback(subreq,
1769                                 vfswrap_get_dos_attributes_getxattr_done,
1770                                 req);
1771
1772         return req;
1773 }
1774
1775 static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
1776 {
1777         struct tevent_req *req =
1778                 tevent_req_callback_data(subreq,
1779                 struct tevent_req);
1780         struct vfswrap_get_dos_attributes_state *state =
1781                 tevent_req_data(req,
1782                 struct vfswrap_get_dos_attributes_state);
1783         ssize_t xattr_size;
1784         DATA_BLOB blob = {0};
1785         char *path = NULL;
1786         char *tofree = NULL;
1787         char pathbuf[PATH_MAX+1];
1788         ssize_t pathlen;
1789         struct smb_filename smb_fname;
1790         bool offline;
1791         NTSTATUS status;
1792
1793         xattr_size = SMB_VFS_GETXATTRAT_RECV(subreq,
1794                                              &state->aio_state,
1795                                              state,
1796                                              &blob.data);
1797         TALLOC_FREE(subreq);
1798         if (xattr_size == -1) {
1799                 status = map_nt_error_from_unix(state->aio_state.error);
1800
1801                 if (state->as_root) {
1802                         tevent_req_nterror(req, status);
1803                         return;
1804                 }
1805                 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1806                         tevent_req_nterror(req, status);
1807                         return;
1808                 }
1809
1810                 state->as_root = true;
1811
1812                 become_root();
1813                 subreq = SMB_VFS_GETXATTRAT_SEND(state,
1814                                                  state->ev,
1815                                                  state->dir_fsp,
1816                                                  state->smb_fname,
1817                                                  SAMBA_XATTR_DOS_ATTRIB,
1818                                                  sizeof(fstring));
1819                 unbecome_root();
1820                 if (tevent_req_nomem(subreq, req)) {
1821                         return;
1822                 }
1823                 tevent_req_set_callback(subreq,
1824                                         vfswrap_get_dos_attributes_getxattr_done,
1825                                         req);
1826                 return;
1827         }
1828
1829         blob.length = xattr_size;
1830
1831         status = parse_dos_attribute_blob(state->smb_fname,
1832                                           blob,
1833                                           &state->dosmode);
1834         if (!NT_STATUS_IS_OK(status)) {
1835                 tevent_req_nterror(req, status);
1836                 return;
1837         }
1838
1839         pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
1840                                 state->smb_fname->base_name,
1841                                 pathbuf,
1842                                 sizeof(pathbuf),
1843                                 &path,
1844                                 &tofree);
1845         if (pathlen == -1) {
1846                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1847                 return;
1848         }
1849
1850         smb_fname = (struct smb_filename) {
1851                 .base_name = path,
1852                 .st = state->smb_fname->st,
1853                 .flags = state->smb_fname->flags,
1854         };
1855
1856         offline = vfswrap_is_offline(state->conn, &smb_fname);
1857         if (offline) {
1858                 state->dosmode |= FILE_ATTRIBUTE_OFFLINE;
1859         }
1860         TALLOC_FREE(tofree);
1861
1862         tevent_req_done(req);
1863         return;
1864 }
1865
1866 static NTSTATUS vfswrap_get_dos_attributes_recv(struct tevent_req *req,
1867                                                 struct vfs_aio_state *aio_state,
1868                                                 uint32_t *dosmode)
1869 {
1870         struct vfswrap_get_dos_attributes_state *state =
1871                 tevent_req_data(req,
1872                 struct vfswrap_get_dos_attributes_state);
1873         NTSTATUS status;
1874
1875         if (tevent_req_is_nterror(req, &status)) {
1876                 tevent_req_received(req);
1877                 return status;
1878         }
1879
1880         *aio_state = state->aio_state;
1881         *dosmode = state->dosmode;
1882         tevent_req_received(req);
1883         return NT_STATUS_OK;
1884 }
1885
1886 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1887                                             struct files_struct *fsp,
1888                                             uint32_t *dosmode)
1889 {
1890         bool offline;
1891
1892         offline = vfswrap_is_offline(handle->conn, fsp->fsp_name);
1893         if (offline) {
1894                 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1895         }
1896
1897         return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1898 }
1899
1900 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1901                                            const struct smb_filename *smb_fname,
1902                                            uint32_t dosmode)
1903 {
1904         return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1905 }
1906
1907 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1908                                             struct files_struct *fsp,
1909                                             uint32_t dosmode)
1910 {
1911         return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1912 }
1913
1914 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1915
1916 struct vfswrap_offload_read_state {
1917         DATA_BLOB token;
1918 };
1919
1920 static struct tevent_req *vfswrap_offload_read_send(
1921         TALLOC_CTX *mem_ctx,
1922         struct tevent_context *ev,
1923         struct vfs_handle_struct *handle,
1924         struct files_struct *fsp,
1925         uint32_t fsctl,
1926         uint32_t ttl,
1927         off_t offset,
1928         size_t to_copy)
1929 {
1930         struct tevent_req *req = NULL;
1931         struct vfswrap_offload_read_state *state = NULL;
1932         NTSTATUS status;
1933
1934         req = tevent_req_create(mem_ctx, &state,
1935                                 struct vfswrap_offload_read_state);
1936         if (req == NULL) {
1937                 return NULL;
1938         }
1939
1940         status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1941                                             &vfswrap_offload_ctx);
1942         if (tevent_req_nterror(req, status)) {
1943                 return tevent_req_post(req, ev);
1944         }
1945
1946         if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1947                 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1948                 return tevent_req_post(req, ev);
1949         }
1950
1951         status = vfs_offload_token_create_blob(state, fsp, fsctl,
1952                                                &state->token);
1953         if (tevent_req_nterror(req, status)) {
1954                 return tevent_req_post(req, ev);
1955         }
1956
1957         status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1958                                                 &state->token);
1959         if (tevent_req_nterror(req, status)) {
1960                 return tevent_req_post(req, ev);
1961         }
1962
1963         tevent_req_done(req);
1964         return tevent_req_post(req, ev);
1965 }
1966
1967 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1968                                           struct vfs_handle_struct *handle,
1969                                           TALLOC_CTX *mem_ctx,
1970                                           DATA_BLOB *token)
1971 {
1972         struct vfswrap_offload_read_state *state = tevent_req_data(
1973                 req, struct vfswrap_offload_read_state);
1974         NTSTATUS status;
1975
1976         if (tevent_req_is_nterror(req, &status)) {
1977                 tevent_req_received(req);
1978                 return status;
1979         }
1980
1981         token->length = state->token.length;
1982         token->data = talloc_move(mem_ctx, &state->token.data);
1983
1984         tevent_req_received(req);
1985         return NT_STATUS_OK;
1986 }
1987
1988 struct vfswrap_offload_write_state {
1989         uint8_t *buf;
1990         bool read_lck_locked;
1991         bool write_lck_locked;
1992         DATA_BLOB *token;
1993         struct tevent_context *src_ev;
1994         struct files_struct *src_fsp;
1995         off_t src_off;
1996         struct tevent_context *dst_ev;
1997         struct files_struct *dst_fsp;
1998         off_t dst_off;
1999         off_t to_copy;
2000         off_t remaining;
2001         size_t next_io_size;
2002 };
2003
2004 static void vfswrap_offload_write_cleanup(struct tevent_req *req,
2005                                           enum tevent_req_state req_state)
2006 {
2007         struct vfswrap_offload_write_state *state = tevent_req_data(
2008                 req, struct vfswrap_offload_write_state);
2009         bool ok;
2010
2011         if (state->dst_fsp == NULL) {
2012                 return;
2013         }
2014
2015         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2016         SMB_ASSERT(ok);
2017         state->dst_fsp = NULL;
2018 }
2019
2020 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
2021
2022 static struct tevent_req *vfswrap_offload_write_send(
2023         struct vfs_handle_struct *handle,
2024         TALLOC_CTX *mem_ctx,
2025         struct tevent_context *ev,
2026         uint32_t fsctl,
2027         DATA_BLOB *token,
2028         off_t transfer_offset,
2029         struct files_struct *dest_fsp,
2030         off_t dest_off,
2031         off_t to_copy)
2032 {
2033         struct tevent_req *req;
2034         struct vfswrap_offload_write_state *state = NULL;
2035         /* off_t is signed! */
2036         off_t max_offset = INT64_MAX - to_copy;
2037         size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
2038         files_struct *src_fsp = NULL;
2039         NTSTATUS status;
2040         bool ok;
2041
2042         req = tevent_req_create(mem_ctx, &state,
2043                                 struct vfswrap_offload_write_state);
2044         if (req == NULL) {
2045                 return NULL;
2046         }
2047
2048         *state = (struct vfswrap_offload_write_state) {
2049                 .token = token,
2050                 .src_off = transfer_offset,
2051                 .dst_ev = ev,
2052                 .dst_fsp = dest_fsp,
2053                 .dst_off = dest_off,
2054                 .to_copy = to_copy,
2055                 .remaining = to_copy,
2056         };
2057
2058         tevent_req_set_cleanup_fn(req, vfswrap_offload_write_cleanup);
2059
2060         switch (fsctl) {
2061         case FSCTL_SRV_COPYCHUNK:
2062         case FSCTL_SRV_COPYCHUNK_WRITE:
2063                 break;
2064
2065         case FSCTL_OFFLOAD_WRITE:
2066                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2067                 return tevent_req_post(req, ev);
2068
2069         case FSCTL_DUP_EXTENTS_TO_FILE:
2070                 DBG_DEBUG("COW clones not supported by vfs_default\n");
2071                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2072                 return tevent_req_post(req, ev);
2073
2074         default:
2075                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2076                 return tevent_req_post(req, ev);
2077         }
2078
2079         /*
2080          * From here on we assume a copy-chunk fsctl
2081          */
2082
2083         if (to_copy == 0) {
2084                 tevent_req_done(req);
2085                 return tevent_req_post(req, ev);
2086         }
2087
2088         if (state->src_off > max_offset) {
2089                 /*
2090                  * Protect integer checks below.
2091                  */
2092                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2093                 return tevent_req_post(req, ev);
2094         }
2095         if (state->src_off < 0) {
2096                 /*
2097                  * Protect integer checks below.
2098                  */
2099                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2100                 return tevent_req_post(req, ev);
2101         }
2102         if (state->dst_off > max_offset) {
2103                 /*
2104                  * Protect integer checks below.
2105                  */
2106                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2107                 return tevent_req_post(req, ev);
2108         }
2109         if (state->dst_off < 0) {
2110                 /*
2111                  * Protect integer checks below.
2112                  */
2113                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
2114                 return tevent_req_post(req, ev);
2115         }
2116
2117         status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
2118                                                 token, &src_fsp);
2119         if (tevent_req_nterror(req, status)) {
2120                 return tevent_req_post(req, ev);
2121         }
2122
2123         DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
2124
2125         status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
2126         if (!NT_STATUS_IS_OK(status)) {
2127                 tevent_req_nterror(req, status);
2128                 return tevent_req_post(req, ev);
2129         }
2130
2131         ok = change_to_user_and_service_by_fsp(src_fsp);
2132         if (!ok) {
2133                 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
2134                 return tevent_req_post(req, ev);
2135         }
2136
2137         state->src_ev = src_fsp->conn->sconn->ev_ctx;
2138         state->src_fsp = src_fsp;
2139
2140         status = vfs_stat_fsp(src_fsp);
2141         if (tevent_req_nterror(req, status)) {
2142                 return tevent_req_post(req, ev);
2143         }
2144
2145         if (src_fsp->fsp_name->st.st_ex_size < state->src_off + to_copy) {
2146                 /*
2147                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
2148                  *   If the SourceOffset or SourceOffset + Length extends beyond
2149                  *   the end of file, the server SHOULD<240> treat this as a
2150                  *   STATUS_END_OF_FILE error.
2151                  * ...
2152                  *   <240> Section 3.3.5.15.6: Windows servers will return
2153                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
2154                  */
2155                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
2156                 return tevent_req_post(req, ev);
2157         }
2158
2159         state->buf = talloc_array(state, uint8_t, num);
2160         if (tevent_req_nomem(state->buf, req)) {
2161                 return tevent_req_post(req, ev);
2162         }
2163
2164         status = vfswrap_offload_write_loop(req);
2165         if (!NT_STATUS_IS_OK(status)) {
2166                 tevent_req_nterror(req, status);
2167                 return tevent_req_post(req, ev);
2168         }
2169
2170         return req;
2171 }
2172
2173 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
2174
2175 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
2176 {
2177         struct vfswrap_offload_write_state *state = tevent_req_data(
2178                 req, struct vfswrap_offload_write_state);
2179         struct tevent_req *subreq = NULL;
2180         struct lock_struct read_lck;
2181         bool ok;
2182
2183         /*
2184          * This is called under the context of state->src_fsp.
2185          */
2186
2187         state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
2188
2189         init_strict_lock_struct(state->src_fsp,
2190                                 state->src_fsp->op->global->open_persistent_id,
2191                                 state->src_off,
2192                                 state->next_io_size,
2193                                 READ_LOCK,
2194                                 &read_lck);
2195
2196         ok = SMB_VFS_STRICT_LOCK_CHECK(state->src_fsp->conn,
2197                                  state->src_fsp,
2198                                  &read_lck);
2199         if (!ok) {
2200                 return NT_STATUS_FILE_LOCK_CONFLICT;
2201         }
2202
2203         subreq = SMB_VFS_PREAD_SEND(state,
2204                                     state->src_ev,
2205                                     state->src_fsp,
2206                                     state->buf,
2207                                     state->next_io_size,
2208                                     state->src_off);
2209         if (subreq == NULL) {
2210                 return NT_STATUS_NO_MEMORY;
2211         }
2212         tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
2213
2214         return NT_STATUS_OK;
2215 }
2216
2217 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
2218
2219 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
2220 {
2221         struct tevent_req *req = tevent_req_callback_data(
2222                 subreq, struct tevent_req);
2223         struct vfswrap_offload_write_state *state = tevent_req_data(
2224                 req, struct vfswrap_offload_write_state);
2225         struct vfs_aio_state aio_state;
2226         struct lock_struct write_lck;
2227         ssize_t nread;
2228         bool ok;
2229
2230         nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
2231         TALLOC_FREE(subreq);
2232         if (nread == -1) {
2233                 DBG_ERR("read failed: %s\n", strerror(aio_state.error));
2234                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2235                 return;
2236         }
2237         if (nread != state->next_io_size) {
2238                 DBG_ERR("Short read, only %zd of %zu\n",
2239                         nread, state->next_io_size);
2240                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2241                 return;
2242         }
2243
2244         state->src_off += nread;
2245
2246         ok = change_to_user_and_service_by_fsp(state->dst_fsp);
2247         if (!ok) {
2248                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2249                 return;
2250         }
2251
2252         init_strict_lock_struct(state->dst_fsp,
2253                                 state->dst_fsp->op->global->open_persistent_id,
2254                                 state->dst_off,
2255                                 state->next_io_size,
2256                                 WRITE_LOCK,
2257                                 &write_lck);
2258
2259         ok = SMB_VFS_STRICT_LOCK_CHECK(state->dst_fsp->conn,
2260                                  state->dst_fsp,
2261                                  &write_lck);
2262         if (!ok) {
2263                 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2264                 return;
2265         }
2266
2267         subreq = SMB_VFS_PWRITE_SEND(state,
2268                                      state->dst_ev,
2269                                      state->dst_fsp,
2270                                      state->buf,
2271                                      state->next_io_size,
2272                                      state->dst_off);
2273         if (subreq == NULL) {
2274                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
2275                 return;
2276         }
2277         tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
2278 }
2279
2280 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
2281 {
2282         struct tevent_req *req = tevent_req_callback_data(
2283                 subreq, struct tevent_req);
2284         struct vfswrap_offload_write_state *state = tevent_req_data(
2285                 req, struct vfswrap_offload_write_state);
2286         struct vfs_aio_state aio_state;
2287         ssize_t nwritten;
2288         NTSTATUS status;
2289         bool ok;
2290
2291         nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
2292         TALLOC_FREE(subreq);
2293         if (nwritten == -1) {
2294                 DBG_ERR("write failed: %s\n", strerror(aio_state.error));
2295                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
2296                 return;
2297         }
2298         if (nwritten != state->next_io_size) {
2299                 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
2300                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
2301                 return;
2302         }
2303
2304         state->dst_off += nwritten;
2305
2306         if (state->remaining < nwritten) {
2307                 /* Paranoia check */
2308                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2309                 return;
2310         }
2311         state->remaining -= nwritten;
2312         if (state->remaining == 0) {
2313                 tevent_req_done(req);
2314                 return;
2315         }
2316
2317         ok = change_to_user_and_service_by_fsp(state->src_fsp);
2318         if (!ok) {
2319                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2320                 return;
2321         }
2322
2323         status = vfswrap_offload_write_loop(req);
2324         if (!NT_STATUS_IS_OK(status)) {
2325                 tevent_req_nterror(req, status);
2326                 return;
2327         }
2328
2329         return;
2330 }
2331
2332 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
2333                                         struct tevent_req *req,
2334                                         off_t *copied)
2335 {
2336         struct vfswrap_offload_write_state *state = tevent_req_data(
2337                 req, struct vfswrap_offload_write_state);
2338         NTSTATUS status;
2339
2340         if (tevent_req_is_nterror(req, &status)) {
2341                 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
2342                 *copied = 0;
2343                 tevent_req_received(req);
2344                 return status;
2345         }
2346
2347         *copied = state->to_copy;
2348         DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
2349         tevent_req_received(req);
2350
2351         return NT_STATUS_OK;
2352 }
2353
2354 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
2355                                         TALLOC_CTX *mem_ctx,
2356                                         struct files_struct *fsp,
2357                                         struct smb_filename *smb_fname,
2358                                         uint16_t *_compression_fmt)
2359 {
2360         return NT_STATUS_INVALID_DEVICE_REQUEST;
2361 }
2362
2363 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2364                                         TALLOC_CTX *mem_ctx,
2365                                         struct files_struct *fsp,
2366                                         uint16_t compression_fmt)
2367 {
2368         return NT_STATUS_INVALID_DEVICE_REQUEST;
2369 }
2370
2371 /********************************************************************
2372  Given a stat buffer return the allocated size on disk, taking into
2373  account sparse files.
2374 ********************************************************************/
2375 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2376                                        struct files_struct *fsp,
2377                                        const SMB_STRUCT_STAT *sbuf)
2378 {
2379         uint64_t result;
2380
2381         START_PROFILE(syscall_get_alloc_size);
2382
2383         if(S_ISDIR(sbuf->st_ex_mode)) {
2384                 result = 0;
2385                 goto out;
2386         }
2387
2388 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2389         /* The type of st_blocksize is blkcnt_t which *MUST* be
2390            signed (according to POSIX) and can be less than 64-bits.
2391            Ensure when we're converting to 64 bits wide we don't
2392            sign extend. */
2393 #if defined(SIZEOF_BLKCNT_T_8)
2394         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2395 #elif defined(SIZEOF_BLKCNT_T_4)
2396         {
2397                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2398                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2399         }
2400 #else
2401 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2402 #endif
2403         if (result == 0) {
2404                 /*
2405                  * Some file systems do not allocate a block for very
2406                  * small files. But for non-empty file should report a
2407                  * positive size.
2408                  */
2409
2410                 uint64_t filesize = get_file_size_stat(sbuf);
2411                 if (filesize > 0) {
2412                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2413                 }
2414         }
2415 #else
2416         result = get_file_size_stat(sbuf);
2417 #endif
2418
2419         if (fsp && fsp->initial_allocation_size)
2420                 result = MAX(result,fsp->initial_allocation_size);
2421
2422         result = smb_roundup(handle->conn, result);
2423
2424  out:
2425         END_PROFILE(syscall_get_alloc_size);
2426         return result;
2427 }
2428
2429 static int vfswrap_unlinkat(vfs_handle_struct *handle,
2430                         struct files_struct *dirfsp,
2431                         const struct smb_filename *smb_fname,
2432                         int flags)
2433 {
2434         int result = -1;
2435
2436         START_PROFILE(syscall_unlinkat);
2437
2438         SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2439
2440         if (is_named_stream(smb_fname)) {
2441                 errno = ENOENT;
2442                 goto out;
2443         }
2444         result = unlinkat(dirfsp->fh->fd,
2445                         smb_fname->base_name,
2446                         flags);
2447
2448  out:
2449         END_PROFILE(syscall_unlinkat);
2450         return result;
2451 }
2452
2453 static int vfswrap_chmod(vfs_handle_struct *handle,
2454                         const struct smb_filename *smb_fname,
2455                         mode_t mode)
2456 {
2457         int result;
2458
2459         START_PROFILE(syscall_chmod);
2460         result = chmod(smb_fname->base_name, mode);
2461         END_PROFILE(syscall_chmod);
2462         return result;
2463 }
2464
2465 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2466 {
2467         int result;
2468
2469         START_PROFILE(syscall_fchmod);
2470 #if defined(HAVE_FCHMOD)
2471         result = fchmod(fsp->fh->fd, mode);
2472 #else
2473         result = -1;
2474         errno = ENOSYS;
2475 #endif
2476
2477         END_PROFILE(syscall_fchmod);
2478         return result;
2479 }
2480
2481 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2482 {
2483 #ifdef HAVE_FCHOWN
2484         int result;
2485
2486         START_PROFILE(syscall_fchown);
2487         result = fchown(fsp->fh->fd, uid, gid);
2488         END_PROFILE(syscall_fchown);
2489         return result;
2490 #else
2491         errno = ENOSYS;
2492         return -1;
2493 #endif
2494 }
2495
2496 static int vfswrap_lchown(vfs_handle_struct *handle,
2497                         const struct smb_filename *smb_fname,
2498                         uid_t uid,
2499                         gid_t gid)
2500 {
2501         int result;
2502
2503         START_PROFILE(syscall_lchown);
2504         result = lchown(smb_fname->base_name, uid, gid);
2505         END_PROFILE(syscall_lchown);
2506         return result;
2507 }
2508
2509 static int vfswrap_chdir(vfs_handle_struct *handle,
2510                         const struct smb_filename *smb_fname)
2511 {
2512         int result;
2513
2514         START_PROFILE(syscall_chdir);
2515         result = chdir(smb_fname->base_name);
2516         END_PROFILE(syscall_chdir);
2517         return result;
2518 }
2519
2520 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2521                                 TALLOC_CTX *ctx)
2522 {
2523         char *result;
2524         struct smb_filename *smb_fname = NULL;
2525
2526         START_PROFILE(syscall_getwd);
2527         result = sys_getwd();
2528         END_PROFILE(syscall_getwd);
2529
2530         if (result == NULL) {
2531                 return NULL;
2532         }
2533         smb_fname = synthetic_smb_fname(ctx,
2534                                 result,
2535                                 NULL,
2536                                 NULL,
2537                                 0);
2538         /*
2539          * sys_getwd() *always* returns malloced memory.
2540          * We must free here to avoid leaks:
2541          * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2542          */
2543         SAFE_FREE(result);
2544         return smb_fname;
2545 }
2546
2547 /*********************************************************************
2548  nsec timestamp resolution call. Convert down to whatever the underlying
2549  system will support.
2550 **********************************************************************/
2551
2552 static int vfswrap_ntimes(vfs_handle_struct *handle,
2553                           const struct smb_filename *smb_fname,
2554                           struct smb_file_time *ft)
2555 {
2556         int result = -1;
2557
2558         START_PROFILE(syscall_ntimes);
2559
2560         if (is_named_stream(smb_fname)) {
2561                 errno = ENOENT;
2562                 goto out;
2563         }
2564
2565         if (ft != NULL) {
2566                 if (is_omit_timespec(&ft->atime)) {
2567                         ft->atime= smb_fname->st.st_ex_atime;
2568                 }
2569
2570                 if (is_omit_timespec(&ft->mtime)) {
2571                         ft->mtime = smb_fname->st.st_ex_mtime;
2572                 }
2573
2574                 if (!is_omit_timespec(&ft->create_time)) {
2575                         set_create_timespec_ea(handle->conn,
2576                                                smb_fname,
2577                                                ft->create_time);
2578                 }
2579
2580                 if ((timespec_compare(&ft->atime,
2581                                       &smb_fname->st.st_ex_atime) == 0) &&
2582                     (timespec_compare(&ft->mtime,
2583                                       &smb_fname->st.st_ex_mtime) == 0)) {
2584                         return 0;
2585                 }
2586         }
2587
2588 #if defined(HAVE_UTIMENSAT)
2589         if (ft != NULL) {
2590                 struct timespec ts[2];
2591                 ts[0] = ft->atime;
2592                 ts[1] = ft->mtime;
2593                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2594         } else {
2595                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2596         }
2597         if (!((result == -1) && (errno == ENOSYS))) {
2598                 goto out;
2599         }
2600 #endif
2601 #if defined(HAVE_UTIMES)
2602         if (ft != NULL) {
2603                 struct timeval tv[2];
2604                 tv[0] = convert_timespec_to_timeval(ft->atime);
2605                 tv[1] = convert_timespec_to_timeval(ft->mtime);
2606                 result = utimes(smb_fname->base_name, tv);
2607         } else {
2608                 result = utimes(smb_fname->base_name, NULL);
2609         }
2610         if (!((result == -1) && (errno == ENOSYS))) {
2611                 goto out;
2612         }
2613 #endif
2614 #if defined(HAVE_UTIME)
2615         if (ft != NULL) {
2616                 struct utimbuf times;
2617                 times.actime = convert_timespec_to_time_t(ft->atime);
2618                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2619                 result = utime(smb_fname->base_name, &times);
2620         } else {
2621                 result = utime(smb_fname->base_name, NULL);
2622         }
2623         if (!((result == -1) && (errno == ENOSYS))) {
2624                 goto out;
2625         }
2626 #endif
2627         errno = ENOSYS;
2628         result = -1;
2629
2630  out:
2631         END_PROFILE(syscall_ntimes);
2632         return result;
2633 }
2634
2635 /*********************************************************************
2636  A version of ftruncate that will write the space on disk if strict
2637  allocate is set.
2638 **********************************************************************/
2639
2640 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2641 {
2642         off_t space_to_write;
2643         uint64_t space_avail;
2644         uint64_t bsize,dfree,dsize;
2645         int ret;
2646         NTSTATUS status;
2647         SMB_STRUCT_STAT *pst;
2648
2649         status = vfs_stat_fsp(fsp);
2650         if (!NT_STATUS_IS_OK(status)) {
2651                 return -1;
2652         }
2653         pst = &fsp->fsp_name->st;
2654
2655 #ifdef S_ISFIFO
2656         if (S_ISFIFO(pst->st_ex_mode))
2657                 return 0;
2658 #endif
2659
2660         if (pst->st_ex_size == len)
2661                 return 0;
2662
2663         /* Shrink - just ftruncate. */
2664         if (pst->st_ex_size > len)
2665                 return ftruncate(fsp->fh->fd, len);
2666
2667         space_to_write = len - pst->st_ex_size;
2668
2669         /* for allocation try fallocate first. This can fail on some
2670            platforms e.g. when the filesystem doesn't support it and no
2671            emulation is being done by the libc (like on AIX with JFS1). In that
2672            case we do our own emulation. fallocate implementations can
2673            return ENOTSUP or EINVAL in cases like that. */
2674         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2675         if (ret == -1 && errno == ENOSPC) {
2676                 return -1;
2677         }
2678         if (ret == 0) {
2679                 return 0;
2680         }
2681         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2682                 "error %d. Falling back to slow manual allocation\n", errno));
2683
2684         /* available disk space is enough or not? */
2685         space_avail =
2686             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2687         /* space_avail is 1k blocks */
2688         if (space_avail == (uint64_t)-1 ||
2689                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2690                 errno = ENOSPC;
2691                 return -1;
2692         }
2693
2694         /* Write out the real space on disk. */
2695         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2696         if (ret != 0) {
2697                 return -1;
2698         }
2699
2700         return 0;
2701 }
2702
2703 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2704 {
2705         int result = -1;
2706         SMB_STRUCT_STAT *pst;
2707         NTSTATUS status;
2708         char c = 0;
2709
2710         START_PROFILE(syscall_ftruncate);
2711
2712         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2713                 result = strict_allocate_ftruncate(handle, fsp, len);
2714                 END_PROFILE(syscall_ftruncate);
2715                 return result;
2716         }
2717
2718         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2719            ftruncate if the system supports it. Then I discovered that
2720            you can have some filesystems that support ftruncate
2721            expansion and some that don't! On Linux fat can't do
2722            ftruncate extend but ext2 can. */
2723
2724         result = ftruncate(fsp->fh->fd, len);
2725
2726         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2727            extend a file with ftruncate. Provide alternate implementation
2728            for this */
2729
2730         /* Do an fstat to see if the file is longer than the requested
2731            size in which case the ftruncate above should have
2732            succeeded or shorter, in which case seek to len - 1 and
2733            write 1 byte of zero */
2734         status = vfs_stat_fsp(fsp);
2735         if (!NT_STATUS_IS_OK(status)) {
2736                 goto done;
2737         }
2738
2739         /* We need to update the files_struct after successful ftruncate */
2740         if (result == 0) {
2741                 goto done;
2742         }
2743
2744         pst = &fsp->fsp_name->st;
2745
2746 #ifdef S_ISFIFO
2747         if (S_ISFIFO(pst->st_ex_mode)) {
2748                 result = 0;
2749                 goto done;
2750         }
2751 #endif
2752
2753         if (pst->st_ex_size == len) {
2754                 result = 0;
2755                 goto done;
2756         }
2757
2758         if (pst->st_ex_size > len) {
2759                 /* the ftruncate should have worked */
2760                 goto done;
2761         }
2762
2763         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2764                 goto done;
2765         }
2766
2767         result = 0;
2768
2769   done:
2770
2771         END_PROFILE(syscall_ftruncate);
2772         return result;
2773 }
2774
2775 static int vfswrap_fallocate(vfs_handle_struct *handle,
2776                         files_struct *fsp,
2777                         uint32_t mode,
2778                         off_t offset,
2779                         off_t len)
2780 {
2781         int result;
2782
2783         START_PROFILE(syscall_fallocate);
2784         if (mode == 0) {
2785                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2786                 /*
2787                  * posix_fallocate returns 0 on success, errno on error
2788                  * and doesn't set errno. Make it behave like fallocate()
2789                  * which returns -1, and sets errno on failure.
2790                  */
2791                 if (result != 0) {
2792                         errno = result;
2793                         result = -1;
2794                 }
2795         } else {
2796                 /* sys_fallocate handles filtering of unsupported mode flags */
2797                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2798         }
2799         END_PROFILE(syscall_fallocate);
2800         return result;
2801 }
2802
2803 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2804 {
2805         bool result;
2806
2807         START_PROFILE(syscall_fcntl_lock);
2808
2809         if (fsp->use_ofd_locks) {
2810                 op = map_process_lock_to_ofd_lock(op);
2811         }
2812
2813         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
2814         END_PROFILE(syscall_fcntl_lock);
2815         return result;
2816 }
2817
2818 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2819                                 uint32_t share_access, uint32_t access_mask)
2820 {
2821         START_PROFILE(syscall_kernel_flock);
2822         kernel_flock(fsp->fh->fd, share_access, access_mask);
2823         END_PROFILE(syscall_kernel_flock);
2824         return 0;
2825 }
2826
2827 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2828                          va_list cmd_arg)
2829 {
2830         void *argp;
2831         va_list dup_cmd_arg;
2832         int result;
2833         int val;
2834
2835         START_PROFILE(syscall_fcntl);
2836
2837         va_copy(dup_cmd_arg, cmd_arg);
2838
2839         switch(cmd) {
2840         case F_SETLK:
2841         case F_SETLKW:
2842         case F_GETLK:
2843 #if defined(HAVE_OFD_LOCKS)
2844         case F_OFD_SETLK:
2845         case F_OFD_SETLKW:
2846         case F_OFD_GETLK:
2847 #endif
2848 #if defined(HAVE_F_OWNER_EX)
2849         case F_GETOWN_EX:
2850         case F_SETOWN_EX:
2851 #endif
2852 #if defined(HAVE_RW_HINTS)
2853         case F_GET_RW_HINT:
2854         case F_SET_RW_HINT:
2855         case F_GET_FILE_RW_HINT:
2856         case F_SET_FILE_RW_HINT:
2857 #endif
2858                 argp = va_arg(dup_cmd_arg, void *);
2859                 result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
2860                 break;
2861         default:
2862                 val = va_arg(dup_cmd_arg, int);
2863                 result = sys_fcntl_int(fsp->fh->fd, cmd, val);
2864         }
2865
2866         va_end(dup_cmd_arg);
2867
2868         END_PROFILE(syscall_fcntl);
2869         return result;
2870 }
2871
2872 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2873 {
2874         bool result;
2875         int op = F_GETLK;
2876
2877         START_PROFILE(syscall_fcntl_getlock);
2878
2879         if (fsp->use_ofd_locks) {
2880                 op = map_process_lock_to_ofd_lock(op);
2881         }
2882
2883         result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2884         END_PROFILE(syscall_fcntl_getlock);
2885         return result;
2886 }
2887
2888 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2889                                 int leasetype)
2890 {
2891         int result = -1;
2892
2893         START_PROFILE(syscall_linux_setlease);
2894
2895 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2896         result = linux_setlease(fsp->fh->fd, leasetype);
2897 #else
2898         errno = ENOSYS;
2899 #endif
2900         END_PROFILE(syscall_linux_setlease);
2901         return result;
2902 }
2903
2904 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2905                         const char *link_target,
2906                         struct files_struct *dirfsp,
2907                         const struct smb_filename *new_smb_fname)
2908 {
2909         int result;
2910
2911         START_PROFILE(syscall_symlinkat);
2912
2913         SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2914
2915         result = symlinkat(link_target,
2916                         dirfsp->fh->fd,
2917                         new_smb_fname->base_name);
2918         END_PROFILE(syscall_symlinkat);
2919         return result;
2920 }
2921
2922 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2923                         files_struct *dirfsp,
2924                         const struct smb_filename *smb_fname,
2925                         char *buf,
2926                         size_t bufsiz)
2927 {
2928         int result;
2929
2930         START_PROFILE(syscall_readlinkat);
2931
2932         SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2933
2934         result = readlinkat(dirfsp->fh->fd,
2935                         smb_fname->base_name,
2936                         buf,
2937                         bufsiz);
2938
2939         END_PROFILE(syscall_readlinkat);
2940         return result;
2941 }
2942
2943 static int vfswrap_linkat(vfs_handle_struct *handle,
2944                         files_struct *srcfsp,
2945                         const struct smb_filename *old_smb_fname,
2946                         files_struct *dstfsp,
2947                         const struct smb_filename *new_smb_fname,
2948                         int flags)
2949 {
2950         int result;
2951
2952         START_PROFILE(syscall_linkat);
2953
2954         SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
2955         SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
2956
2957         result = linkat(srcfsp->fh->fd,
2958                         old_smb_fname->base_name,
2959                         dstfsp->fh->fd,
2960                         new_smb_fname->base_name,
2961                         flags);
2962
2963         END_PROFILE(syscall_linkat);
2964         return result;
2965 }
2966
2967 static int vfswrap_mknodat(vfs_handle_struct *handle,
2968                         files_struct *dirfsp,
2969                         const struct smb_filename *smb_fname,
2970                         mode_t mode,
2971                         SMB_DEV_T dev)
2972 {
2973         int result;
2974
2975         START_PROFILE(syscall_mknodat);
2976
2977         SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
2978
2979         result = sys_mknodat(dirfsp->fh->fd,
2980                         smb_fname->base_name,
2981                         mode,
2982                         dev);
2983
2984         END_PROFILE(syscall_mknodat);
2985         return result;
2986 }
2987
2988 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2989                         TALLOC_CTX *ctx,
2990                         const struct smb_filename *smb_fname)
2991 {
2992         char *result;
2993         struct smb_filename *result_fname = NULL;
2994
2995         START_PROFILE(syscall_realpath);
2996         result = sys_realpath(smb_fname->base_name);
2997         END_PROFILE(syscall_realpath);
2998         if (result) {
2999                 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
3000                 SAFE_FREE(result);
3001         }
3002         return result_fname;
3003 }
3004
3005 static int vfswrap_chflags(vfs_handle_struct *handle,
3006                         const struct smb_filename *smb_fname,
3007                         unsigned int flags)
3008 {
3009 #ifdef HAVE_CHFLAGS
3010         return chflags(smb_fname->base_name, flags);
3011 #else
3012         errno = ENOSYS;
3013         return -1;
3014 #endif
3015 }
3016
3017 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
3018                                              const SMB_STRUCT_STAT *sbuf)
3019 {
3020         struct file_id key;
3021
3022         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
3023          * blob */
3024         ZERO_STRUCT(key);
3025
3026         key.devid = sbuf->st_ex_dev;
3027         key.inode = sbuf->st_ex_ino;
3028         /* key.extid is unused by default. */
3029
3030         return key;
3031 }
3032
3033 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3034                                    const SMB_STRUCT_STAT *psbuf)
3035 {
3036         uint64_t file_id;
3037
3038         if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3039                 return psbuf->st_ex_file_id;
3040         }
3041
3042         if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3043                 return (uint64_t)psbuf->st_ex_ino;
3044         }
3045
3046         /* FileIDLow */
3047         file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3048
3049         /* FileIDHigh */
3050         file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3051
3052         return file_id;
3053 }
3054
3055 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3056                                    struct files_struct *fsp,
3057                                    const struct smb_filename *smb_fname,
3058                                    TALLOC_CTX *mem_ctx,
3059                                    unsigned int *pnum_streams,
3060                                    struct stream_struct **pstreams)
3061 {
3062         SMB_STRUCT_STAT sbuf;
3063         struct stream_struct *tmp_streams = NULL;
3064         int ret;
3065
3066         if ((fsp != NULL) && (fsp->is_directory)) {
3067                 /*
3068                  * No default streams on directories
3069                  */
3070                 goto done;
3071         }
3072
3073         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
3074                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3075         }
3076         else {
3077                 struct smb_filename smb_fname_cp;
3078
3079                 ZERO_STRUCT(smb_fname_cp);
3080                 smb_fname_cp.base_name = discard_const_p(char,
3081                                         smb_fname->base_name);
3082                 smb_fname_cp.flags = smb_fname->flags;
3083
3084                 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
3085                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
3086                 } else {
3087                         ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
3088                 }
3089                 sbuf = smb_fname_cp.st;
3090         }
3091
3092         if (ret == -1) {
3093                 return map_nt_error_from_unix(errno);
3094         }
3095
3096         if (S_ISDIR(sbuf.st_ex_mode)) {
3097                 goto done;
3098         }
3099
3100         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3101                                         (*pnum_streams) + 1);
3102         if (tmp_streams == NULL) {
3103                 return NT_STATUS_NO_MEMORY;
3104         }
3105         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3106         if (tmp_streams[*pnum_streams].name == NULL) {
3107                 return NT_STATUS_NO_MEMORY;
3108         }
3109         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3110         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3111
3112         *pnum_streams += 1;
3113         *pstreams = tmp_streams;
3114  done:
3115         return NT_STATUS_OK;
3116 }
3117
3118 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3119                                      const char *path,
3120                                      const char *name,
3121                                      TALLOC_CTX *mem_ctx,
3122                                      char **found_name)
3123 {
3124         /*
3125          * Don't fall back to get_real_filename so callers can differentiate
3126          * between a full directory scan and an actual case-insensitive stat.
3127          */
3128         errno = EOPNOTSUPP;
3129         return -1;
3130 }
3131
3132 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3133                                    const struct smb_filename *smb_fname)
3134 {
3135         return handle->conn->connectpath;
3136 }
3137
3138 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3139                                          struct byte_range_lock *br_lck,
3140                                          struct lock_struct *plock)
3141 {
3142         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3143
3144         /* Note: blr is not used in the default implementation. */
3145         return brl_lock_windows_default(br_lck, plock);
3146 }
3147
3148 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3149                                        struct byte_range_lock *br_lck,
3150                                        const struct lock_struct *plock)
3151 {
3152         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3153
3154         return brl_unlock_windows_default(br_lck, plock);
3155 }
3156
3157 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3158                                       files_struct *fsp,
3159                                       struct lock_struct *plock)
3160 {
3161         SMB_ASSERT(plock->lock_type == READ_LOCK ||
3162             plock->lock_type == WRITE_LOCK);
3163
3164         return strict_lock_check_default(fsp, plock);
3165 }
3166
3167 /* NT ACL operations. */
3168
3169 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3170                                     files_struct *fsp,
3171                                     uint32_t security_info,
3172                                     TALLOC_CTX *mem_ctx,
3173                                     struct security_descriptor **ppdesc)
3174 {
3175         NTSTATUS result;
3176
3177         START_PROFILE(fget_nt_acl);
3178         result = posix_fget_nt_acl(fsp, security_info,
3179                                    mem_ctx, ppdesc);
3180         END_PROFILE(fget_nt_acl);
3181         return result;
3182 }
3183
3184 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
3185                                    const struct smb_filename *smb_fname,
3186                                    uint32_t security_info,
3187                                    TALLOC_CTX *mem_ctx,
3188                                    struct security_descriptor **ppdesc)
3189 {
3190         NTSTATUS result;
3191
3192         START_PROFILE(get_nt_acl);
3193         result = posix_get_nt_acl(handle->conn,
3194                                 smb_fname,
3195                                 security_info,
3196                                 mem_ctx,
3197                                 ppdesc);
3198         END_PROFILE(get_nt_acl);
3199         return result;
3200 }
3201
3202 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3203 {
3204         NTSTATUS result;
3205
3206         START_PROFILE(fset_nt_acl);
3207         result = set_nt_acl(fsp, security_info_sent, psd);
3208         END_PROFILE(fset_nt_acl);
3209         return result;
3210 }
3211
3212 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3213                                    struct smb_filename *file,
3214                                    struct security_acl *sacl,
3215                                    uint32_t access_requested,
3216                                    uint32_t access_denied)
3217 {
3218         return NT_STATUS_OK; /* Nothing to do here ... */
3219 }
3220
3221 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3222                                           const struct smb_filename *smb_fname,
3223                                           SMB_ACL_TYPE_T type,
3224                                           TALLOC_CTX *mem_ctx)
3225 {
3226         return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3227 }
3228
3229 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3230                                         files_struct *fsp,
3231                                         TALLOC_CTX *mem_ctx)
3232 {
3233         return sys_acl_get_fd(handle, fsp, mem_ctx);
3234 }
3235
3236 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
3237                                 const struct smb_filename *smb_fname,
3238                                 SMB_ACL_TYPE_T acltype,
3239                                 SMB_ACL_T theacl)
3240 {
3241         return sys_acl_set_file(handle, smb_fname, acltype, theacl);
3242 }
3243
3244 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
3245 {
3246         return sys_acl_set_fd(handle, fsp, theacl);
3247 }
3248
3249 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3250                         const struct smb_filename *smb_fname)
3251 {
3252         return sys_acl_delete_def_file(handle, smb_fname);
3253 }
3254
3255 /****************************************************************
3256  Extended attribute operations.
3257 *****************************************************************/
3258
3259 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3260                         const struct smb_filename *smb_fname,
3261                         const char *name,
3262                         void *value,
3263                         size_t size)
3264 {
3265         return getxattr(smb_fname->base_name, name, value, size);
3266 }
3267
3268 struct vfswrap_getxattrat_state {
3269         struct tevent_context *ev;
3270         files_struct *dir_fsp;
3271         const struct smb_filename *smb_fname;
3272         struct tevent_req *req;
3273
3274         /*
3275          * The following variables are talloced off "state" which is protected
3276          * by a destructor and thus are guaranteed to be safe to be used in the
3277          * job function in the worker thread.
3278          */
3279         char *name;
3280         const char *xattr_name;
3281         uint8_t *xattr_value;
3282         struct security_unix_token *token;
3283
3284         ssize_t xattr_size;
3285         struct vfs_aio_state vfs_aio_state;
3286         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3287 };
3288
3289 static int vfswrap_getxattrat_state_destructor(
3290                 struct vfswrap_getxattrat_state *state)
3291 {
3292         /*
3293          * This destructor only gets called if the request is still
3294          * in flight, which is why we deny it by returning -1. We
3295          * also set the req pointer to NULL so the _done function
3296          * can detect the caller doesn't want the result anymore.
3297          *
3298          * Forcing the fsp closed by a SHUTDOWN_CLOSE can cause this.
3299          */
3300         state->req = NULL;
3301         return -1;
3302 }
3303
3304 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3305 static void vfswrap_getxattrat_do_async(void *private_data);
3306 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3307
3308 static struct tevent_req *vfswrap_getxattrat_send(
3309                         TALLOC_CTX *mem_ctx,
3310                         struct tevent_context *ev,
3311                         struct vfs_handle_struct *handle,
3312                         files_struct *dir_fsp,
3313                         const struct smb_filename *smb_fname,
3314                         const char *xattr_name,
3315                         size_t alloc_hint)
3316 {
3317         struct tevent_req *req = NULL;
3318         struct tevent_req *subreq = NULL;
3319         struct vfswrap_getxattrat_state *state = NULL;
3320         size_t max_threads = 0;
3321         bool have_per_thread_cwd = false;
3322         bool have_per_thread_creds = false;
3323         bool do_async = false;
3324
3325         req = tevent_req_create(mem_ctx, &state,
3326                                 struct vfswrap_getxattrat_state);
3327         if (req == NULL) {
3328                 return NULL;
3329         }
3330         *state = (struct vfswrap_getxattrat_state) {
3331                 .ev = ev,
3332                 .dir_fsp = dir_fsp,
3333                 .smb_fname = smb_fname,
3334                 .req = req,
3335         };
3336
3337         max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3338         if (max_threads >= 1) {
3339                 /*
3340                  * We need a non sync threadpool!
3341                  */
3342                 have_per_thread_cwd = per_thread_cwd_supported();
3343         }
3344 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3345         have_per_thread_creds = true;
3346 #endif
3347         if (have_per_thread_cwd && have_per_thread_creds) {
3348                 do_async = true;
3349         }
3350
3351         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3352                                      state->profile_bytes, 0);
3353
3354         if (dir_fsp->fh->fd == -1) {
3355                 DBG_ERR("Need a valid directory fd\n");
3356                 tevent_req_error(req, EINVAL);
3357                 return tevent_req_post(req, ev);
3358         }
3359
3360         if (alloc_hint > 0) {
3361                 state->xattr_value = talloc_zero_array(state,
3362                                                        uint8_t,
3363                                                        alloc_hint);
3364                 if (tevent_req_nomem(state->xattr_value, req)) {
3365                         return tevent_req_post(req, ev);
3366                 }
3367         }
3368
3369         if (!do_async) {
3370                 vfswrap_getxattrat_do_sync(req);
3371                 return tevent_req_post(req, ev);
3372         }
3373
3374         /*
3375          * Now allocate all parameters from a memory context that won't go away
3376          * no matter what. These paremeters will get used in threads and we
3377          * can't reliably cancel threads, so all buffers passed to the threads
3378          * must not be freed before all referencing threads terminate.
3379          */
3380
3381         state->name = talloc_strdup(state, smb_fname->base_name);
3382         if (tevent_req_nomem(state->name, req)) {
3383                 return tevent_req_post(req, ev);
3384         }
3385
3386         state->xattr_name = talloc_strdup(state, xattr_name);
3387         if (tevent_req_nomem(state->xattr_name, req)) {
3388                 return tevent_req_post(req, ev);
3389         }
3390
3391         /*
3392          * This is a hot codepath so at first glance one might think we should
3393          * somehow optimize away the token allocation and do a
3394          * talloc_reference() or similar black magic instead. But due to the
3395          * talloc_stackframe pool per SMB2 request this should be a simple copy
3396          * without a malloc in most cases.
3397          */
3398         if (geteuid() == sec_initial_uid()) {
3399                 state->token = root_unix_token(state);
3400         } else {
3401                 state->token = copy_unix_token(
3402                                         state,
3403                                         dir_fsp->conn->session_info->unix_token);
3404         }
3405         if (tevent_req_nomem(state->token, req)) {
3406                 return tevent_req_post(req, ev);
3407         }
3408
3409         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3410
3411         subreq = pthreadpool_tevent_job_send(
3412                         state,
3413                         ev,
3414                         dir_fsp->conn->sconn->pool,
3415                         vfswrap_getxattrat_do_async,
3416                         state);
3417         if (tevent_req_nomem(subreq, req)) {
3418                 return tevent_req_post(req, ev);
3419         }
3420         tevent_req_set_callback(subreq, vfswrap_getxattrat_done, state);
3421
3422         talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3423
3424         return req;
3425 }
3426
3427 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3428 {
3429         struct vfswrap_getxattrat_state *state = tevent_req_data(
3430                 req, struct vfswrap_getxattrat_state);
3431         char *path = NULL;
3432         char *tofree = NULL;
3433         char pathbuf[PATH_MAX+1];
3434         ssize_t pathlen;
3435         int err;
3436
3437         pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3438                                 state->smb_fname->base_name,
3439                                 pathbuf,
3440                                 sizeof(pathbuf),
3441                                 &path,
3442                                 &tofree);
3443         if (pathlen == -1) {
3444                 tevent_req_error(req, ENOMEM);
3445                 return;
3446         }
3447
3448         state->xattr_size = getxattr(path,
3449                                      state->xattr_name,
3450                                      state->xattr_value,
3451                                      talloc_array_length(state->xattr_value));
3452         err = errno;
3453         TALLOC_FREE(tofree);
3454         if (state->xattr_size == -1) {
3455                 tevent_req_error(req, err);
3456                 return;
3457         }
3458
3459         tevent_req_done(req);
3460         return;
3461 }
3462
3463 static void vfswrap_getxattrat_do_async(void *private_data)
3464 {
3465         struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3466                 private_data, struct vfswrap_getxattrat_state);
3467         struct timespec start_time;
3468         struct timespec end_time;
3469         int ret;
3470
3471         PROFILE_TIMESTAMP(&start_time);
3472         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3473
3474         /*
3475          * Here we simulate a getxattrat()
3476          * call using fchdir();getxattr()
3477          */
3478
3479         per_thread_cwd_activate();
3480
3481         /* Become the correct credential on this thread. */
3482         ret = set_thread_credentials(state->token->uid,
3483                                      state->token->gid,
3484                                      (size_t)state->token->ngroups,
3485                                      state->token->groups);
3486         if (ret != 0) {
3487                 state->xattr_size = -1;
3488                 state->vfs_aio_state.error = errno;
3489                 goto end_profile;
3490         }
3491
3492         ret = fchdir(state->dir_fsp->fh->fd);
3493         if (ret == -1) {
3494                 state->xattr_size = -1;
3495                 state->vfs_aio_state.error = errno;
3496                 goto end_profile;
3497         }
3498
3499         state->xattr_size = getxattr(state->name,
3500                                      state->xattr_name,
3501                                      state->xattr_value,
3502                                      talloc_array_length(state->xattr_value));
3503         if (state->xattr_size == -1) {
3504                 state->vfs_aio_state.error = errno;
3505         }
3506
3507 end_profile:
3508         PROFILE_TIMESTAMP(&end_time);
3509         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3510         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3511 }
3512
3513 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3514 {
3515         struct vfswrap_getxattrat_state *state = tevent_req_callback_data(
3516                 subreq, struct vfswrap_getxattrat_state);
3517         struct tevent_req *req = state->req;
3518         int ret;
3519         bool ok;
3520
3521         /*
3522          * Make sure we run as the user again
3523          */
3524         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3525         SMB_ASSERT(ok);
3526
3527         ret = pthreadpool_tevent_job_recv(subreq);
3528         TALLOC_FREE(subreq);
3529         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3530         talloc_set_destructor(state, NULL);
3531         if (req == NULL) {
3532                 /*
3533                  * We were shutdown closed in flight. No one wants the result,
3534                  * and state has been reparented to the NULL context, so just
3535                  * free it so we don't leak memory.
3536                  */
3537                 DBG_NOTICE("getxattr request abandoned in flight\n");
3538                 TALLOC_FREE(state);
3539                 return;
3540         }
3541         if (ret != 0) {
3542                 if (ret != EAGAIN) {
3543                         tevent_req_error(req, ret);
3544                         return;
3545                 }
3546                 /*
3547                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3548                  * means the lower level pthreadpool failed to create a new
3549                  * thread. Fallback to sync processing in that case to allow
3550                  * some progress for the client.
3551                  */
3552                 vfswrap_getxattrat_do_sync(req);
3553                 return;
3554         }
3555
3556         if (state->xattr_size == -1) {
3557                 tevent_req_error(req, state->vfs_aio_state.error);
3558                 return;
3559         }
3560
3561         if (state->xattr_value == NULL) {
3562                 /*
3563                  * The caller only wanted the size.
3564                  */
3565                 tevent_req_done(req);
3566                 return;
3567         }
3568
3569         /*
3570          * shrink the buffer to the returned size.
3571          * (can't fail). It means NULL if size is 0.
3572          */
3573         state->xattr_value = talloc_realloc(state,
3574                                             state->xattr_value,
3575                                             uint8_t,
3576                                             state->xattr_size);
3577
3578         tevent_req_done(req);
3579 }
3580
3581 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3582                                        struct vfs_aio_state *aio_state,
3583                                        TALLOC_CTX *mem_ctx,
3584                                        uint8_t **xattr_value)
3585 {
3586         struct vfswrap_getxattrat_state *state = tevent_req_data(
3587                 req, struct vfswrap_getxattrat_state);
3588         ssize_t xattr_size;
3589
3590         if (tevent_req_is_unix_error(req, &aio_state->error)) {
3591                 tevent_req_received(req);
3592                 return -1;
3593         }
3594
3595         *aio_state = state->vfs_aio_state;
3596         xattr_size = state->xattr_size;
3597         if (xattr_value != NULL) {
3598                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3599         }
3600
3601         tevent_req_received(req);
3602         return xattr_size;
3603 }
3604
3605 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
3606 {
3607         return fgetxattr(fsp->fh->fd, name, value, size);
3608 }
3609
3610 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
3611                         const struct smb_filename *smb_fname,
3612                         char *list,
3613                         size_t size)
3614 {
3615         return listxattr(smb_fname->base_name, list, size);
3616 }
3617
3618 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3619 {
3620         return flistxattr(fsp->fh->fd, list, size);
3621 }
3622
3623 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3624                                 const struct smb_filename *smb_fname,
3625                                 const char *name)
3626 {
3627         return removexattr(smb_fname->base_name, name);
3628 }
3629
3630 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3631 {
3632         return fremovexattr(fsp->fh->fd, name);
3633 }
3634
3635 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3636                                 const struct smb_filename *smb_fname,
3637                                 const char *name,
3638                                 const void *value,
3639                                 size_t size,
3640                                 int flags)
3641 {
3642         return setxattr(smb_fname->base_name, name, value, size, flags);
3643 }
3644
3645 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3646 {
3647         return fsetxattr(fsp->fh->fd, name, value, size, flags);
3648 }
3649
3650 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3651 {
3652         return false;
3653 }
3654
3655 static bool vfswrap_is_offline(struct connection_struct *conn,
3656                                const struct smb_filename *fname)
3657 {
3658         NTSTATUS status;
3659         char *path;
3660         bool offline = false;
3661
3662         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3663                 return false;
3664         }
3665
3666         if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3667 #if defined(ENOTSUP)
3668                 errno = ENOTSUP;
3669 #endif
3670                 return false;
3671         }
3672
3673         status = get_full_smb_filename(talloc_tos(), fname, &path);
3674         if (!NT_STATUS_IS_OK(status)) {
3675                 errno = map_errno_from_nt_status(status);
3676                 return false;
3677         }
3678
3679         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3680
3681         TALLOC_FREE(path);
3682
3683         return offline;
3684 }
3685
3686 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3687                                        struct files_struct *fsp,
3688                                        TALLOC_CTX *mem_ctx,
3689                                        DATA_BLOB *cookie)
3690 {
3691         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3692 }
3693
3694 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3695                                            struct files_struct *fsp,
3696                                            const DATA_BLOB old_cookie,
3697                                            TALLOC_CTX *mem_ctx,
3698                                            DATA_BLOB *new_cookie)
3699 {
3700         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3701                                               new_cookie);
3702 }
3703
3704 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3705                                           struct smb_request *smb1req,
3706                                           struct smbXsrv_open *op,
3707                                           const DATA_BLOB old_cookie,
3708                                           TALLOC_CTX *mem_ctx,
3709                                           struct files_struct **fsp,
3710                                           DATA_BLOB *new_cookie)
3711 {
3712         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3713                                              old_cookie, mem_ctx,
3714                                              fsp, new_cookie);
3715 }
3716
3717 static struct vfs_fn_pointers vfs_default_fns = {
3718         /* Disk operations */
3719
3720         .connect_fn = vfswrap_connect,
3721         .disconnect_fn = vfswrap_disconnect,
3722         .disk_free_fn = vfswrap_disk_free,
3723         .get_quota_fn = vfswrap_get_quota,
3724         .set_quota_fn = vfswrap_set_quota,
3725         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3726         .statvfs_fn = vfswrap_statvfs,
3727         .fs_capabilities_fn = vfswrap_fs_capabilities,
3728         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3729         .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3730         .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3731         .snap_check_path_fn = vfswrap_snap_check_path,
3732         .snap_create_fn = vfswrap_snap_create,
3733         .snap_delete_fn = vfswrap_snap_delete,
3734
3735         /* Directory operations */
3736
3737         .opendir_fn = vfswrap_opendir,
3738         .fdopendir_fn = vfswrap_fdopendir,
3739         .readdir_fn = vfswrap_readdir,
3740         .readdir_attr_fn = vfswrap_readdir_attr,
3741         .seekdir_fn = vfswrap_seekdir,
3742         .telldir_fn = vfswrap_telldir,
3743         .rewind_dir_fn = vfswrap_rewinddir,
3744         .mkdirat_fn = vfswrap_mkdirat,
3745         .closedir_fn = vfswrap_closedir,
3746
3747         /* File operations */
3748
3749         .open_fn = vfswrap_open,
3750         .create_file_fn = vfswrap_create_file,
3751         .close_fn = vfswrap_close,
3752         .pread_fn = vfswrap_pread,
3753         .pread_send_fn = vfswrap_pread_send,
3754         .pread_recv_fn = vfswrap_pread_recv,
3755         .pwrite_fn = vfswrap_pwrite,
3756         .pwrite_send_fn = vfswrap_pwrite_send,
3757         .pwrite_recv_fn = vfswrap_pwrite_recv,
3758         .lseek_fn = vfswrap_lseek,
3759         .sendfile_fn = vfswrap_sendfile,
3760         .recvfile_fn = vfswrap_recvfile,
3761         .renameat_fn = vfswrap_renameat,
3762         .fsync_send_fn = vfswrap_fsync_send,
3763         .fsync_recv_fn = vfswrap_fsync_recv,
3764         .stat_fn = vfswrap_stat,
3765         .fstat_fn = vfswrap_fstat,
3766         .lstat_fn = vfswrap_lstat,
3767         .get_alloc_size_fn = vfswrap_get_alloc_size,
3768         .unlinkat_fn = vfswrap_unlinkat,
3769         .chmod_fn = vfswrap_chmod,
3770         .fchmod_fn = vfswrap_fchmod,
3771         .fchown_fn = vfswrap_fchown,
3772         .lchown_fn = vfswrap_lchown,
3773         .chdir_fn = vfswrap_chdir,
3774         .getwd_fn = vfswrap_getwd,
3775         .ntimes_fn = vfswrap_ntimes,
3776         .ftruncate_fn = vfswrap_ftruncate,
3777         .fallocate_fn = vfswrap_fallocate,
3778         .lock_fn = vfswrap_lock,
3779         .kernel_flock_fn = vfswrap_kernel_flock,
3780         .fcntl_fn = vfswrap_fcntl,
3781         .linux_setlease_fn = vfswrap_linux_setlease,
3782         .getlock_fn = vfswrap_getlock,
3783         .symlinkat_fn = vfswrap_symlinkat,
3784         .readlinkat_fn = vfswrap_readlinkat,
3785         .linkat_fn = vfswrap_linkat,
3786         .mknodat_fn = vfswrap_mknodat,
3787         .realpath_fn = vfswrap_realpath,
3788         .chflags_fn = vfswrap_chflags,
3789         .file_id_create_fn = vfswrap_file_id_create,
3790         .fs_file_id_fn = vfswrap_fs_file_id,
3791         .streaminfo_fn = vfswrap_streaminfo,
3792         .get_real_filename_fn = vfswrap_get_real_filename,
3793         .connectpath_fn = vfswrap_connectpath,
3794         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3795         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3796         .strict_lock_check_fn = vfswrap_strict_lock_check,
3797         .translate_name_fn = vfswrap_translate_name,
3798         .fsctl_fn = vfswrap_fsctl,
3799         .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3800         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3801         .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3802         .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3803         .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3804         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3805         .offload_read_send_fn = vfswrap_offload_read_send,
3806         .offload_read_recv_fn = vfswrap_offload_read_recv,
3807         .offload_write_send_fn = vfswrap_offload_write_send,
3808         .offload_write_recv_fn = vfswrap_offload_write_recv,
3809         .get_compression_fn = vfswrap_get_compression,
3810         .set_compression_fn = vfswrap_set_compression,
3811
3812         /* NT ACL operations. */
3813
3814         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3815         .get_nt_acl_fn = vfswrap_get_nt_acl,
3816         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3817         .audit_file_fn = vfswrap_audit_file,
3818
3819         /* POSIX ACL operations. */
3820
3821         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3822         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3823         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3824         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3825         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3826         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3827         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3828
3829         /* EA operations. */
3830         .getxattr_fn = vfswrap_getxattr,
3831         .getxattrat_send_fn = vfswrap_getxattrat_send,
3832         .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3833         .fgetxattr_fn = vfswrap_fgetxattr,
3834         .listxattr_fn = vfswrap_listxattr,
3835         .flistxattr_fn = vfswrap_flistxattr,
3836         .removexattr_fn = vfswrap_removexattr,
3837         .fremovexattr_fn = vfswrap_fremovexattr,
3838         .setxattr_fn = vfswrap_setxattr,
3839         .fsetxattr_fn = vfswrap_fsetxattr,
3840
3841         /* aio operations */
3842         .aio_force_fn = vfswrap_aio_force,
3843
3844         /* durable handle operations */
3845         .durable_cookie_fn = vfswrap_durable_cookie,
3846         .durable_disconnect_fn = vfswrap_durable_disconnect,
3847         .durable_reconnect_fn = vfswrap_durable_reconnect,
3848 };
3849
3850 static_decl_vfs;
3851 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3852 {
3853         /*
3854          * Here we need to implement every call!
3855          *
3856          * As this is the end of the vfs module chain.
3857          */
3858         smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3859         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3860                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
3861 }
3862
3863