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