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