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