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