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