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