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