VFS: Remove SMB_VFS_LISTXATTR, no longer used
[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         if (is_named_stream(smb_fname)) {
2408                 errno = ENOENT;
2409                 goto out;
2410         }
2411         result = unlinkat(fsp_get_pathref_fd(dirfsp),
2412                         smb_fname->base_name,
2413                         flags);
2414
2415  out:
2416         END_PROFILE(syscall_unlinkat);
2417         return result;
2418 }
2419
2420 static int vfswrap_chmod(vfs_handle_struct *handle,
2421                         const struct smb_filename *smb_fname,
2422                         mode_t mode)
2423 {
2424         int result;
2425
2426         START_PROFILE(syscall_chmod);
2427         result = chmod(smb_fname->base_name, mode);
2428         END_PROFILE(syscall_chmod);
2429         return result;
2430 }
2431
2432 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2433 {
2434         int result;
2435
2436         START_PROFILE(syscall_fchmod);
2437 #if defined(HAVE_FCHMOD)
2438         result = fchmod(fsp_get_io_fd(fsp), mode);
2439 #else
2440         result = -1;
2441         errno = ENOSYS;
2442 #endif
2443
2444         END_PROFILE(syscall_fchmod);
2445         return result;
2446 }
2447
2448 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2449 {
2450 #ifdef HAVE_FCHOWN
2451         int result;
2452
2453         START_PROFILE(syscall_fchown);
2454         result = fchown(fsp_get_io_fd(fsp), uid, gid);
2455         END_PROFILE(syscall_fchown);
2456         return result;
2457 #else
2458         errno = ENOSYS;
2459         return -1;
2460 #endif
2461 }
2462
2463 static int vfswrap_lchown(vfs_handle_struct *handle,
2464                         const struct smb_filename *smb_fname,
2465                         uid_t uid,
2466                         gid_t gid)
2467 {
2468         int result;
2469
2470         START_PROFILE(syscall_lchown);
2471         result = lchown(smb_fname->base_name, uid, gid);
2472         END_PROFILE(syscall_lchown);
2473         return result;
2474 }
2475
2476 static int vfswrap_chdir(vfs_handle_struct *handle,
2477                         const struct smb_filename *smb_fname)
2478 {
2479         int result;
2480
2481         START_PROFILE(syscall_chdir);
2482         result = chdir(smb_fname->base_name);
2483         END_PROFILE(syscall_chdir);
2484         return result;
2485 }
2486
2487 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2488                                 TALLOC_CTX *ctx)
2489 {
2490         char *result;
2491         struct smb_filename *smb_fname = NULL;
2492
2493         START_PROFILE(syscall_getwd);
2494         result = sys_getwd();
2495         END_PROFILE(syscall_getwd);
2496
2497         if (result == NULL) {
2498                 return NULL;
2499         }
2500         smb_fname = synthetic_smb_fname(ctx,
2501                                 result,
2502                                 NULL,
2503                                 NULL,
2504                                 0,
2505                                 0);
2506         /*
2507          * sys_getwd() *always* returns malloced memory.
2508          * We must free here to avoid leaks:
2509          * BUG:https://bugzilla.samba.org/show_bug.cgi?id=13372
2510          */
2511         SAFE_FREE(result);
2512         return smb_fname;
2513 }
2514
2515 /*********************************************************************
2516  nsec timestamp resolution call. Convert down to whatever the underlying
2517  system will support.
2518 **********************************************************************/
2519
2520 static int vfswrap_ntimes(vfs_handle_struct *handle,
2521                           const struct smb_filename *smb_fname,
2522                           struct smb_file_time *ft)
2523 {
2524         int result = -1;
2525
2526         START_PROFILE(syscall_ntimes);
2527
2528         if (is_named_stream(smb_fname)) {
2529                 errno = ENOENT;
2530                 goto out;
2531         }
2532
2533         if (ft != NULL) {
2534                 if (is_omit_timespec(&ft->atime)) {
2535                         ft->atime= smb_fname->st.st_ex_atime;
2536                 }
2537
2538                 if (is_omit_timespec(&ft->mtime)) {
2539                         ft->mtime = smb_fname->st.st_ex_mtime;
2540                 }
2541
2542                 if (!is_omit_timespec(&ft->create_time)) {
2543                         set_create_timespec_ea(handle->conn,
2544                                                smb_fname,
2545                                                ft->create_time);
2546                 }
2547
2548                 if ((timespec_compare(&ft->atime,
2549                                       &smb_fname->st.st_ex_atime) == 0) &&
2550                     (timespec_compare(&ft->mtime,
2551                                       &smb_fname->st.st_ex_mtime) == 0)) {
2552                         return 0;
2553                 }
2554         }
2555
2556 #if defined(HAVE_UTIMENSAT)
2557         if (ft != NULL) {
2558                 struct timespec ts[2];
2559                 ts[0] = ft->atime;
2560                 ts[1] = ft->mtime;
2561                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2562         } else {
2563                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2564         }
2565         if (!((result == -1) && (errno == ENOSYS))) {
2566                 goto out;
2567         }
2568 #endif
2569 #if defined(HAVE_UTIMES)
2570         if (ft != NULL) {
2571                 struct timeval tv[2];
2572                 tv[0] = convert_timespec_to_timeval(ft->atime);
2573                 tv[1] = convert_timespec_to_timeval(ft->mtime);
2574                 result = utimes(smb_fname->base_name, tv);
2575         } else {
2576                 result = utimes(smb_fname->base_name, NULL);
2577         }
2578         if (!((result == -1) && (errno == ENOSYS))) {
2579                 goto out;
2580         }
2581 #endif
2582 #if defined(HAVE_UTIME)
2583         if (ft != NULL) {
2584                 struct utimbuf times;
2585                 times.actime = convert_timespec_to_time_t(ft->atime);
2586                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2587                 result = utime(smb_fname->base_name, &times);
2588         } else {
2589                 result = utime(smb_fname->base_name, NULL);
2590         }
2591         if (!((result == -1) && (errno == ENOSYS))) {
2592                 goto out;
2593         }
2594 #endif
2595         errno = ENOSYS;
2596         result = -1;
2597
2598  out:
2599         END_PROFILE(syscall_ntimes);
2600         return result;
2601 }
2602
2603 /*********************************************************************
2604  A version of ftruncate that will write the space on disk if strict
2605  allocate is set.
2606 **********************************************************************/
2607
2608 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2609 {
2610         off_t space_to_write;
2611         uint64_t space_avail;
2612         uint64_t bsize,dfree,dsize;
2613         int ret;
2614         NTSTATUS status;
2615         SMB_STRUCT_STAT *pst;
2616         bool ok;
2617
2618         ok = vfs_valid_pwrite_range(len, 0);
2619         if (!ok) {
2620                 errno = EINVAL;
2621                 return -1;
2622         }
2623
2624         status = vfs_stat_fsp(fsp);
2625         if (!NT_STATUS_IS_OK(status)) {
2626                 return -1;
2627         }
2628         pst = &fsp->fsp_name->st;
2629
2630 #ifdef S_ISFIFO
2631         if (S_ISFIFO(pst->st_ex_mode))
2632                 return 0;
2633 #endif
2634
2635         if (pst->st_ex_size == len)
2636                 return 0;
2637
2638         /* Shrink - just ftruncate. */
2639         if (pst->st_ex_size > len)
2640                 return ftruncate(fsp_get_io_fd(fsp), len);
2641
2642         space_to_write = len - pst->st_ex_size;
2643
2644         /* for allocation try fallocate first. This can fail on some
2645            platforms e.g. when the filesystem doesn't support it and no
2646            emulation is being done by the libc (like on AIX with JFS1). In that
2647            case we do our own emulation. fallocate implementations can
2648            return ENOTSUP or EINVAL in cases like that. */
2649         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2650         if (ret == -1 && errno == ENOSPC) {
2651                 return -1;
2652         }
2653         if (ret == 0) {
2654                 return 0;
2655         }
2656         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2657                 "error %d. Falling back to slow manual allocation\n", errno));
2658
2659         /* available disk space is enough or not? */
2660         space_avail =
2661             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2662         /* space_avail is 1k blocks */
2663         if (space_avail == (uint64_t)-1 ||
2664                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2665                 errno = ENOSPC;
2666                 return -1;
2667         }
2668
2669         /* Write out the real space on disk. */
2670         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2671         if (ret != 0) {
2672                 return -1;
2673         }
2674
2675         return 0;
2676 }
2677
2678 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2679 {
2680         int result = -1;
2681         SMB_STRUCT_STAT *pst;
2682         NTSTATUS status;
2683         char c = 0;
2684
2685         START_PROFILE(syscall_ftruncate);
2686
2687         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->fsp_flags.is_sparse) {
2688                 result = strict_allocate_ftruncate(handle, fsp, len);
2689                 END_PROFILE(syscall_ftruncate);
2690                 return result;
2691         }
2692
2693         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2694            ftruncate if the system supports it. Then I discovered that
2695            you can have some filesystems that support ftruncate
2696            expansion and some that don't! On Linux fat can't do
2697            ftruncate extend but ext2 can. */
2698
2699         result = ftruncate(fsp_get_io_fd(fsp), len);
2700
2701         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2702            extend a file with ftruncate. Provide alternate implementation
2703            for this */
2704
2705         /* Do an fstat to see if the file is longer than the requested
2706            size in which case the ftruncate above should have
2707            succeeded or shorter, in which case seek to len - 1 and
2708            write 1 byte of zero */
2709         status = vfs_stat_fsp(fsp);
2710         if (!NT_STATUS_IS_OK(status)) {
2711                 goto done;
2712         }
2713
2714         /* We need to update the files_struct after successful ftruncate */
2715         if (result == 0) {
2716                 goto done;
2717         }
2718
2719         pst = &fsp->fsp_name->st;
2720
2721 #ifdef S_ISFIFO
2722         if (S_ISFIFO(pst->st_ex_mode)) {
2723                 result = 0;
2724                 goto done;
2725         }
2726 #endif
2727
2728         if (pst->st_ex_size == len) {
2729                 result = 0;
2730                 goto done;
2731         }
2732
2733         if (pst->st_ex_size > len) {
2734                 /* the ftruncate should have worked */
2735                 goto done;
2736         }
2737
2738         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2739                 goto done;
2740         }
2741
2742         result = 0;
2743
2744   done:
2745
2746         END_PROFILE(syscall_ftruncate);
2747         return result;
2748 }
2749
2750 static int vfswrap_fallocate(vfs_handle_struct *handle,
2751                         files_struct *fsp,
2752                         uint32_t mode,
2753                         off_t offset,
2754                         off_t len)
2755 {
2756         int result;
2757
2758         START_PROFILE(syscall_fallocate);
2759         if (mode == 0) {
2760                 result = sys_posix_fallocate(fsp_get_io_fd(fsp), offset, len);
2761                 /*
2762                  * posix_fallocate returns 0 on success, errno on error
2763                  * and doesn't set errno. Make it behave like fallocate()
2764                  * which returns -1, and sets errno on failure.
2765                  */
2766                 if (result != 0) {
2767                         errno = result;
2768                         result = -1;
2769                 }
2770         } else {
2771                 /* sys_fallocate handles filtering of unsupported mode flags */
2772                 result = sys_fallocate(fsp_get_io_fd(fsp), mode, offset, len);
2773         }
2774         END_PROFILE(syscall_fallocate);
2775         return result;
2776 }
2777
2778 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2779 {
2780         bool result;
2781
2782         START_PROFILE(syscall_fcntl_lock);
2783
2784         if (fsp->fsp_flags.use_ofd_locks) {
2785                 op = map_process_lock_to_ofd_lock(op);
2786         }
2787
2788         result =  fcntl_lock(fsp_get_io_fd(fsp), op, offset, count, type);
2789         END_PROFILE(syscall_fcntl_lock);
2790         return result;
2791 }
2792
2793 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2794                                 uint32_t share_access, uint32_t access_mask)
2795 {
2796         START_PROFILE(syscall_kernel_flock);
2797         kernel_flock(fsp_get_io_fd(fsp), share_access, access_mask);
2798         END_PROFILE(syscall_kernel_flock);
2799         return 0;
2800 }
2801
2802 static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
2803                          va_list cmd_arg)
2804 {
2805         void *argp;
2806         va_list dup_cmd_arg;
2807         int result;
2808         int val;
2809
2810         START_PROFILE(syscall_fcntl);
2811
2812         va_copy(dup_cmd_arg, cmd_arg);
2813
2814         switch(cmd) {
2815         case F_SETLK:
2816         case F_SETLKW:
2817         case F_GETLK:
2818 #if defined(HAVE_OFD_LOCKS)
2819         case F_OFD_SETLK:
2820         case F_OFD_SETLKW:
2821         case F_OFD_GETLK:
2822 #endif
2823 #if defined(HAVE_F_OWNER_EX)
2824         case F_GETOWN_EX:
2825         case F_SETOWN_EX:
2826 #endif
2827 #if defined(HAVE_RW_HINTS)
2828         case F_GET_RW_HINT:
2829         case F_SET_RW_HINT:
2830         case F_GET_FILE_RW_HINT:
2831         case F_SET_FILE_RW_HINT:
2832 #endif
2833                 argp = va_arg(dup_cmd_arg, void *);
2834                 result = sys_fcntl_ptr(fsp_get_io_fd(fsp), cmd, argp);
2835                 break;
2836         default:
2837                 val = va_arg(dup_cmd_arg, int);
2838                 result = sys_fcntl_int(fsp_get_io_fd(fsp), cmd, val);
2839         }
2840
2841         va_end(dup_cmd_arg);
2842
2843         END_PROFILE(syscall_fcntl);
2844         return result;
2845 }
2846
2847 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2848 {
2849         bool result;
2850         int op = F_GETLK;
2851
2852         START_PROFILE(syscall_fcntl_getlock);
2853
2854         if (fsp->fsp_flags.use_ofd_locks) {
2855                 op = map_process_lock_to_ofd_lock(op);
2856         }
2857
2858         result = fcntl_getlock(fsp_get_io_fd(fsp), op, poffset, pcount, ptype, ppid);
2859         END_PROFILE(syscall_fcntl_getlock);
2860         return result;
2861 }
2862
2863 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2864                                 int leasetype)
2865 {
2866         int result = -1;
2867
2868         START_PROFILE(syscall_linux_setlease);
2869
2870 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2871         result = linux_setlease(fsp_get_io_fd(fsp), leasetype);
2872 #else
2873         errno = ENOSYS;
2874 #endif
2875         END_PROFILE(syscall_linux_setlease);
2876         return result;
2877 }
2878
2879 static int vfswrap_symlinkat(vfs_handle_struct *handle,
2880                         const struct smb_filename *link_target,
2881                         struct files_struct *dirfsp,
2882                         const struct smb_filename *new_smb_fname)
2883 {
2884         int result;
2885
2886         START_PROFILE(syscall_symlinkat);
2887
2888         result = symlinkat(link_target->base_name,
2889                         fsp_get_pathref_fd(dirfsp),
2890                         new_smb_fname->base_name);
2891         END_PROFILE(syscall_symlinkat);
2892         return result;
2893 }
2894
2895 static int vfswrap_readlinkat(vfs_handle_struct *handle,
2896                         const struct files_struct *dirfsp,
2897                         const struct smb_filename *smb_fname,
2898                         char *buf,
2899                         size_t bufsiz)
2900 {
2901         int result;
2902
2903         START_PROFILE(syscall_readlinkat);
2904
2905         result = readlinkat(fsp_get_pathref_fd(dirfsp),
2906                         smb_fname->base_name,
2907                         buf,
2908                         bufsiz);
2909
2910         END_PROFILE(syscall_readlinkat);
2911         return result;
2912 }
2913
2914 static int vfswrap_linkat(vfs_handle_struct *handle,
2915                         files_struct *srcfsp,
2916                         const struct smb_filename *old_smb_fname,
2917                         files_struct *dstfsp,
2918                         const struct smb_filename *new_smb_fname,
2919                         int flags)
2920 {
2921         int result;
2922
2923         START_PROFILE(syscall_linkat);
2924
2925         result = linkat(fsp_get_pathref_fd(srcfsp),
2926                         old_smb_fname->base_name,
2927                         fsp_get_pathref_fd(dstfsp),
2928                         new_smb_fname->base_name,
2929                         flags);
2930
2931         END_PROFILE(syscall_linkat);
2932         return result;
2933 }
2934
2935 static int vfswrap_mknodat(vfs_handle_struct *handle,
2936                         files_struct *dirfsp,
2937                         const struct smb_filename *smb_fname,
2938                         mode_t mode,
2939                         SMB_DEV_T dev)
2940 {
2941         int result;
2942
2943         START_PROFILE(syscall_mknodat);
2944
2945         result = sys_mknodat(fsp_get_pathref_fd(dirfsp),
2946                         smb_fname->base_name,
2947                         mode,
2948                         dev);
2949
2950         END_PROFILE(syscall_mknodat);
2951         return result;
2952 }
2953
2954 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2955                         TALLOC_CTX *ctx,
2956                         const struct smb_filename *smb_fname)
2957 {
2958         char *result;
2959         struct smb_filename *result_fname = NULL;
2960
2961         START_PROFILE(syscall_realpath);
2962         result = sys_realpath(smb_fname->base_name);
2963         END_PROFILE(syscall_realpath);
2964         if (result) {
2965                 result_fname = synthetic_smb_fname(ctx,
2966                                                    result,
2967                                                    NULL,
2968                                                    NULL,
2969                                                    0,
2970                                                    0);
2971                 SAFE_FREE(result);
2972         }
2973         return result_fname;
2974 }
2975
2976 static int vfswrap_chflags(vfs_handle_struct *handle,
2977                         const struct smb_filename *smb_fname,
2978                         unsigned int flags)
2979 {
2980 #ifdef HAVE_CHFLAGS
2981         return chflags(smb_fname->base_name, flags);
2982 #else
2983         errno = ENOSYS;
2984         return -1;
2985 #endif
2986 }
2987
2988 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2989                                              const SMB_STRUCT_STAT *sbuf)
2990 {
2991         struct file_id key;
2992
2993         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2994          * blob */
2995         ZERO_STRUCT(key);
2996
2997         key.devid = sbuf->st_ex_dev;
2998         key.inode = sbuf->st_ex_ino;
2999         /* key.extid is unused by default. */
3000
3001         return key;
3002 }
3003
3004 static uint64_t vfswrap_fs_file_id(struct vfs_handle_struct *handle,
3005                                    const SMB_STRUCT_STAT *psbuf)
3006 {
3007         uint64_t file_id;
3008
3009         if (!(psbuf->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
3010                 return psbuf->st_ex_file_id;
3011         }
3012
3013         if (handle->conn->base_share_dev == psbuf->st_ex_dev) {
3014                 return (uint64_t)psbuf->st_ex_ino;
3015         }
3016
3017         /* FileIDLow */
3018         file_id = ((psbuf->st_ex_ino) & UINT32_MAX);
3019
3020         /* FileIDHigh */
3021         file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32;
3022
3023         return file_id;
3024 }
3025
3026 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
3027                                    struct files_struct *fsp,
3028                                    const struct smb_filename *smb_fname,
3029                                    TALLOC_CTX *mem_ctx,
3030                                    unsigned int *pnum_streams,
3031                                    struct stream_struct **pstreams)
3032 {
3033         SMB_STRUCT_STAT sbuf;
3034         struct stream_struct *tmp_streams = NULL;
3035         int ret;
3036
3037         if ((fsp != NULL) && (fsp->fsp_flags.is_directory)) {
3038                 /*
3039                  * No default streams on directories
3040                  */
3041                 goto done;
3042         }
3043
3044         if ((fsp != NULL) && (fsp_get_pathref_fd(fsp) != -1)) {
3045                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
3046         }
3047         else {
3048                 struct smb_filename *smb_fname_cp = NULL;
3049
3050                 smb_fname_cp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
3051                 if (smb_fname_cp == NULL) {
3052                         return NT_STATUS_NO_MEMORY;
3053                 }
3054
3055                 ret = vfs_stat(handle->conn, smb_fname_cp);
3056                 sbuf = smb_fname_cp->st;
3057                 TALLOC_FREE(smb_fname_cp);
3058         }
3059
3060         if (ret == -1) {
3061                 return map_nt_error_from_unix(errno);
3062         }
3063
3064         if (S_ISDIR(sbuf.st_ex_mode)) {
3065                 goto done;
3066         }
3067
3068         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
3069                                         (*pnum_streams) + 1);
3070         if (tmp_streams == NULL) {
3071                 return NT_STATUS_NO_MEMORY;
3072         }
3073         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
3074         if (tmp_streams[*pnum_streams].name == NULL) {
3075                 return NT_STATUS_NO_MEMORY;
3076         }
3077         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
3078         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
3079
3080         *pnum_streams += 1;
3081         *pstreams = tmp_streams;
3082  done:
3083         return NT_STATUS_OK;
3084 }
3085
3086 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
3087                                      const struct smb_filename *path,
3088                                      const char *name,
3089                                      TALLOC_CTX *mem_ctx,
3090                                      char **found_name)
3091 {
3092         /*
3093          * Don't fall back to get_real_filename so callers can differentiate
3094          * between a full directory scan and an actual case-insensitive stat.
3095          */
3096         errno = EOPNOTSUPP;
3097         return -1;
3098 }
3099
3100 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
3101                                    const struct smb_filename *smb_fname)
3102 {
3103         return handle->conn->connectpath;
3104 }
3105
3106 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
3107                                          struct byte_range_lock *br_lck,
3108                                          struct lock_struct *plock)
3109 {
3110         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3111
3112         /* Note: blr is not used in the default implementation. */
3113         return brl_lock_windows_default(br_lck, plock);
3114 }
3115
3116 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
3117                                        struct byte_range_lock *br_lck,
3118                                        const struct lock_struct *plock)
3119 {
3120         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
3121
3122         return brl_unlock_windows_default(br_lck, plock);
3123 }
3124
3125 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
3126                                       files_struct *fsp,
3127                                       struct lock_struct *plock)
3128 {
3129         SMB_ASSERT(plock->lock_type == READ_LOCK ||
3130             plock->lock_type == WRITE_LOCK);
3131
3132         return strict_lock_check_default(fsp, plock);
3133 }
3134
3135 /* NT ACL operations. */
3136
3137 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
3138                                     files_struct *fsp,
3139                                     uint32_t security_info,
3140                                     TALLOC_CTX *mem_ctx,
3141                                     struct security_descriptor **ppdesc)
3142 {
3143         NTSTATUS result;
3144
3145         START_PROFILE(fget_nt_acl);
3146         result = posix_fget_nt_acl(fsp, security_info,
3147                                    mem_ctx, ppdesc);
3148         END_PROFILE(fget_nt_acl);
3149         return result;
3150 }
3151
3152 static NTSTATUS vfswrap_get_nt_acl_at(vfs_handle_struct *handle,
3153                         struct files_struct *dirfsp,
3154                         const struct smb_filename *smb_fname,
3155                         uint32_t security_info,
3156                         TALLOC_CTX *mem_ctx,
3157                         struct security_descriptor **ppdesc)
3158 {
3159         NTSTATUS result;
3160
3161         START_PROFILE(get_nt_acl_at);
3162
3163         SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
3164
3165         result = posix_get_nt_acl(handle->conn,
3166                                 smb_fname,
3167                                 security_info,
3168                                 mem_ctx,
3169                                 ppdesc);
3170         END_PROFILE(get_nt_acl_at);
3171         return result;
3172 }
3173
3174 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
3175 {
3176         NTSTATUS result;
3177
3178         START_PROFILE(fset_nt_acl);
3179         result = set_nt_acl(fsp, security_info_sent, psd);
3180         END_PROFILE(fset_nt_acl);
3181         return result;
3182 }
3183
3184 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
3185                                    struct smb_filename *file,
3186                                    struct security_acl *sacl,
3187                                    uint32_t access_requested,
3188                                    uint32_t access_denied)
3189 {
3190         return NT_STATUS_OK; /* Nothing to do here ... */
3191 }
3192
3193 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
3194                                           const struct smb_filename *smb_fname,
3195                                           SMB_ACL_TYPE_T type,
3196                                           TALLOC_CTX *mem_ctx)
3197 {
3198         return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
3199 }
3200
3201 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
3202                                         files_struct *fsp,
3203                                         TALLOC_CTX *mem_ctx)
3204 {
3205         return sys_acl_get_fd(handle, fsp, mem_ctx);
3206 }
3207
3208 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle,
3209                                   files_struct *fsp,
3210                                   SMB_ACL_TYPE_T type,
3211                                   SMB_ACL_T theacl)
3212 {
3213         if (!fsp->fsp_flags.is_pathref &&
3214             type == SMB_ACL_TYPE_ACCESS)
3215         {
3216                 return sys_acl_set_fd(handle, fsp, theacl);
3217         }
3218
3219         if (fsp->fsp_flags.have_proc_fds) {
3220                 int fd = fsp_get_pathref_fd(fsp);
3221                 struct smb_filename smb_fname;
3222                 const char *p = NULL;
3223                 char buf[PATH_MAX];
3224
3225                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3226                 if (p == NULL) {
3227                         return -1;
3228                 }
3229
3230                 smb_fname = (struct smb_filename) {
3231                         .base_name = buf,
3232                 };
3233
3234                 return sys_acl_set_file(handle,
3235                                         &smb_fname,
3236                                         type,
3237                                         theacl);
3238         }
3239
3240         /*
3241          * This is no longer a handle based call.
3242          */
3243         return sys_acl_set_file(handle,
3244                                 fsp->fsp_name,
3245                                 type,
3246                                 theacl);
3247 }
3248
3249 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
3250                         const struct smb_filename *smb_fname)
3251 {
3252         return sys_acl_delete_def_file(handle, smb_fname);
3253 }
3254
3255 /****************************************************************
3256  Extended attribute operations.
3257 *****************************************************************/
3258
3259 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
3260                         const struct smb_filename *smb_fname,
3261                         const char *name,
3262                         void *value,
3263                         size_t size)
3264 {
3265         return getxattr(smb_fname->base_name, name, value, size);
3266 }
3267
3268 struct vfswrap_getxattrat_state {
3269         struct tevent_context *ev;
3270         files_struct *dir_fsp;
3271         const struct smb_filename *smb_fname;
3272
3273         /*
3274          * The following variables are talloced off "state" which is protected
3275          * by a destructor and thus are guaranteed to be safe to be used in the
3276          * job function in the worker thread.
3277          */
3278         char *name;
3279         const char *xattr_name;
3280         uint8_t *xattr_value;
3281         struct security_unix_token *token;
3282
3283         ssize_t xattr_size;
3284         struct vfs_aio_state vfs_aio_state;
3285         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
3286 };
3287
3288 static int vfswrap_getxattrat_state_destructor(
3289                 struct vfswrap_getxattrat_state *state)
3290 {
3291         return -1;
3292 }
3293
3294 static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
3295 static void vfswrap_getxattrat_do_async(void *private_data);
3296 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
3297
3298 static struct tevent_req *vfswrap_getxattrat_send(
3299                         TALLOC_CTX *mem_ctx,
3300                         struct tevent_context *ev,
3301                         struct vfs_handle_struct *handle,
3302                         files_struct *dir_fsp,
3303                         const struct smb_filename *smb_fname,
3304                         const char *xattr_name,
3305                         size_t alloc_hint)
3306 {
3307         struct tevent_req *req = NULL;
3308         struct tevent_req *subreq = NULL;
3309         struct vfswrap_getxattrat_state *state = NULL;
3310         size_t max_threads = 0;
3311         bool have_per_thread_cwd = false;
3312         bool have_per_thread_creds = false;
3313         bool do_async = false;
3314
3315         req = tevent_req_create(mem_ctx, &state,
3316                                 struct vfswrap_getxattrat_state);
3317         if (req == NULL) {
3318                 return NULL;
3319         }
3320         *state = (struct vfswrap_getxattrat_state) {
3321                 .ev = ev,
3322                 .dir_fsp = dir_fsp,
3323                 .smb_fname = smb_fname,
3324         };
3325
3326         max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
3327         if (max_threads >= 1) {
3328                 /*
3329                  * We need a non sync threadpool!
3330                  */
3331                 have_per_thread_cwd = per_thread_cwd_supported();
3332         }
3333 #ifdef HAVE_LINUX_THREAD_CREDENTIALS
3334         have_per_thread_creds = true;
3335 #endif
3336         if (have_per_thread_cwd && have_per_thread_creds) {
3337                 do_async = true;
3338         }
3339
3340         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
3341                                      state->profile_bytes, 0);
3342
3343         if (fsp_get_pathref_fd(dir_fsp) == -1) {
3344                 DBG_ERR("Need a valid directory fd\n");
3345                 tevent_req_error(req, EINVAL);
3346                 return tevent_req_post(req, ev);
3347         }
3348
3349         if (alloc_hint > 0) {
3350                 state->xattr_value = talloc_zero_array(state,
3351                                                        uint8_t,
3352                                                        alloc_hint);
3353                 if (tevent_req_nomem(state->xattr_value, req)) {
3354                         return tevent_req_post(req, ev);
3355                 }
3356         }
3357
3358         if (!do_async) {
3359                 vfswrap_getxattrat_do_sync(req);
3360                 return tevent_req_post(req, ev);
3361         }
3362
3363         /*
3364          * Now allocate all parameters from a memory context that won't go away
3365          * no matter what. These paremeters will get used in threads and we
3366          * can't reliably cancel threads, so all buffers passed to the threads
3367          * must not be freed before all referencing threads terminate.
3368          */
3369
3370         state->name = talloc_strdup(state, smb_fname->base_name);
3371         if (tevent_req_nomem(state->name, req)) {
3372                 return tevent_req_post(req, ev);
3373         }
3374
3375         state->xattr_name = talloc_strdup(state, xattr_name);
3376         if (tevent_req_nomem(state->xattr_name, req)) {
3377                 return tevent_req_post(req, ev);
3378         }
3379
3380         /*
3381          * This is a hot codepath so at first glance one might think we should
3382          * somehow optimize away the token allocation and do a
3383          * talloc_reference() or similar black magic instead. But due to the
3384          * talloc_stackframe pool per SMB2 request this should be a simple copy
3385          * without a malloc in most cases.
3386          */
3387         if (geteuid() == sec_initial_uid()) {
3388                 state->token = root_unix_token(state);
3389         } else {
3390                 state->token = copy_unix_token(
3391                                         state,
3392                                         dir_fsp->conn->session_info->unix_token);
3393         }
3394         if (tevent_req_nomem(state->token, req)) {
3395                 return tevent_req_post(req, ev);
3396         }
3397
3398         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3399
3400         subreq = pthreadpool_tevent_job_send(
3401                         state,
3402                         ev,
3403                         dir_fsp->conn->sconn->pool,
3404                         vfswrap_getxattrat_do_async,
3405                         state);
3406         if (tevent_req_nomem(subreq, req)) {
3407                 return tevent_req_post(req, ev);
3408         }
3409         tevent_req_set_callback(subreq, vfswrap_getxattrat_done, req);
3410
3411         talloc_set_destructor(state, vfswrap_getxattrat_state_destructor);
3412
3413         return req;
3414 }
3415
3416 static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
3417 {
3418         struct vfswrap_getxattrat_state *state = tevent_req_data(
3419                 req, struct vfswrap_getxattrat_state);
3420         char *path = NULL;
3421         char *tofree = NULL;
3422         char pathbuf[PATH_MAX+1];
3423         ssize_t pathlen;
3424         int err;
3425
3426         pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
3427                                 state->smb_fname->base_name,
3428                                 pathbuf,
3429                                 sizeof(pathbuf),
3430                                 &path,
3431                                 &tofree);
3432         if (pathlen == -1) {
3433                 tevent_req_error(req, ENOMEM);
3434                 return;
3435         }
3436
3437         state->xattr_size = getxattr(path,
3438                                      state->xattr_name,
3439                                      state->xattr_value,
3440                                      talloc_array_length(state->xattr_value));
3441         err = errno;
3442         TALLOC_FREE(tofree);
3443         if (state->xattr_size == -1) {
3444                 tevent_req_error(req, err);
3445                 return;
3446         }
3447
3448         tevent_req_done(req);
3449         return;
3450 }
3451
3452 static void vfswrap_getxattrat_do_async(void *private_data)
3453 {
3454         struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
3455                 private_data, struct vfswrap_getxattrat_state);
3456         struct timespec start_time;
3457         struct timespec end_time;
3458         int ret;
3459
3460         PROFILE_TIMESTAMP(&start_time);
3461         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
3462
3463         /*
3464          * Here we simulate a getxattrat()
3465          * call using fchdir();getxattr()
3466          */
3467
3468         per_thread_cwd_activate();
3469
3470         /* Become the correct credential on this thread. */
3471         ret = set_thread_credentials(state->token->uid,
3472                                      state->token->gid,
3473                                      (size_t)state->token->ngroups,
3474                                      state->token->groups);
3475         if (ret != 0) {
3476                 state->xattr_size = -1;
3477                 state->vfs_aio_state.error = errno;
3478                 goto end_profile;
3479         }
3480
3481         ret = fchdir(fsp_get_pathref_fd(state->dir_fsp));
3482         if (ret == -1) {
3483                 state->xattr_size = -1;
3484                 state->vfs_aio_state.error = errno;
3485                 goto end_profile;
3486         }
3487
3488         state->xattr_size = getxattr(state->name,
3489                                      state->xattr_name,
3490                                      state->xattr_value,
3491                                      talloc_array_length(state->xattr_value));
3492         if (state->xattr_size == -1) {
3493                 state->vfs_aio_state.error = errno;
3494         }
3495
3496 end_profile:
3497         PROFILE_TIMESTAMP(&end_time);
3498         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
3499         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
3500 }
3501
3502 static void vfswrap_getxattrat_done(struct tevent_req *subreq)
3503 {
3504         struct tevent_req *req = tevent_req_callback_data(
3505                 subreq, struct tevent_req);
3506         struct vfswrap_getxattrat_state *state = tevent_req_data(
3507                 req, struct vfswrap_getxattrat_state);
3508         int ret;
3509         bool ok;
3510
3511         /*
3512          * Make sure we run as the user again
3513          */
3514         ok = change_to_user_and_service_by_fsp(state->dir_fsp);
3515         SMB_ASSERT(ok);
3516
3517         ret = pthreadpool_tevent_job_recv(subreq);
3518         TALLOC_FREE(subreq);
3519         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
3520         talloc_set_destructor(state, NULL);
3521         if (ret != 0) {
3522                 if (ret != EAGAIN) {
3523                         tevent_req_error(req, ret);
3524                         return;
3525                 }
3526                 /*
3527                  * If we get EAGAIN from pthreadpool_tevent_job_recv() this
3528                  * means the lower level pthreadpool failed to create a new
3529                  * thread. Fallback to sync processing in that case to allow
3530                  * some progress for the client.
3531                  */
3532                 vfswrap_getxattrat_do_sync(req);
3533                 return;
3534         }
3535
3536         if (state->xattr_size == -1) {
3537                 tevent_req_error(req, state->vfs_aio_state.error);
3538                 return;
3539         }
3540
3541         if (state->xattr_value == NULL) {
3542                 /*
3543                  * The caller only wanted the size.
3544                  */
3545                 tevent_req_done(req);
3546                 return;
3547         }
3548
3549         /*
3550          * shrink the buffer to the returned size.
3551          * (can't fail). It means NULL if size is 0.
3552          */
3553         state->xattr_value = talloc_realloc(state,
3554                                             state->xattr_value,
3555                                             uint8_t,
3556                                             state->xattr_size);
3557
3558         tevent_req_done(req);
3559 }
3560
3561 static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req,
3562                                        struct vfs_aio_state *aio_state,
3563                                        TALLOC_CTX *mem_ctx,
3564                                        uint8_t **xattr_value)
3565 {
3566         struct vfswrap_getxattrat_state *state = tevent_req_data(
3567                 req, struct vfswrap_getxattrat_state);
3568         ssize_t xattr_size;
3569
3570         if (tevent_req_is_unix_error(req, &aio_state->error)) {
3571                 tevent_req_received(req);
3572                 return -1;
3573         }
3574
3575         *aio_state = state->vfs_aio_state;
3576         xattr_size = state->xattr_size;
3577         if (xattr_value != NULL) {
3578                 *xattr_value = talloc_move(mem_ctx, &state->xattr_value);
3579         }
3580
3581         tevent_req_received(req);
3582         return xattr_size;
3583 }
3584
3585 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle,
3586                                  struct files_struct *fsp,
3587                                  const char *name,
3588                                  void *value,
3589                                  size_t size)
3590 {
3591         int fd = fsp_get_pathref_fd(fsp);
3592
3593         if (!fsp->fsp_flags.is_pathref) {
3594                 return fgetxattr(fd, name, value, size);
3595         }
3596
3597         if (fsp->fsp_flags.have_proc_fds) {
3598                 const char *p = NULL;
3599                 char buf[PATH_MAX];
3600
3601                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3602                 if (p == NULL) {
3603                         return -1;
3604                 }
3605
3606                 return getxattr(p, name, value, size);
3607         }
3608
3609         /*
3610          * This is no longer a handle based call.
3611          */
3612         return getxattr(fsp->fsp_name->base_name, name, value, size);
3613 }
3614
3615 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
3616 {
3617         int fd = fsp_get_pathref_fd(fsp);
3618
3619         if (!fsp->fsp_flags.is_pathref) {
3620                 return flistxattr(fd, list, size);
3621         }
3622
3623         if (fsp->fsp_flags.have_proc_fds) {
3624                 const char *p = NULL;
3625                 char buf[PATH_MAX];
3626
3627                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3628                 if (p == NULL) {
3629                         return -1;
3630                 }
3631
3632                 return listxattr(p, list, size);
3633         }
3634
3635         /*
3636          * This is no longer a handle based call.
3637          */
3638         return listxattr(fsp->fsp_name->base_name, list, size);
3639 }
3640
3641 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
3642                                 const struct smb_filename *smb_fname,
3643                                 const char *name)
3644 {
3645         return removexattr(smb_fname->base_name, name);
3646 }
3647
3648 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
3649 {
3650         int fd = fsp_get_pathref_fd(fsp);
3651
3652         if (!fsp->fsp_flags.is_pathref) {
3653                 return fremovexattr(fd, name);
3654         }
3655
3656         if (fsp->fsp_flags.have_proc_fds) {
3657                 const char *p = NULL;
3658                 char buf[PATH_MAX];
3659
3660                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3661                 if (p == NULL) {
3662                         return -1;
3663                 }
3664
3665                 return removexattr(p, name);
3666         }
3667
3668         /*
3669          * This is no longer a handle based call.
3670          */
3671         return removexattr(fsp->fsp_name->base_name, name);
3672 }
3673
3674 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
3675                                 const struct smb_filename *smb_fname,
3676                                 const char *name,
3677                                 const void *value,
3678                                 size_t size,
3679                                 int flags)
3680 {
3681         return setxattr(smb_fname->base_name, name, value, size, flags);
3682 }
3683
3684 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
3685 {
3686         int fd = fsp_get_pathref_fd(fsp);
3687
3688         if (!fsp->fsp_flags.is_pathref) {
3689                 return fsetxattr(fd, name, value, size, flags);
3690         }
3691
3692         if (fsp->fsp_flags.have_proc_fds) {
3693                 const char *p = NULL;
3694                 char buf[PATH_MAX];
3695
3696                 p = sys_proc_fd_path(fd, buf, sizeof(buf));
3697                 if (p == NULL) {
3698                         return -1;
3699                 }
3700
3701                 return setxattr(p, name, value, size, flags);
3702         }
3703
3704         /*
3705          * This is no longer a handle based call.
3706          */
3707         return setxattr(fsp->fsp_name->base_name, name, value, size, flags);
3708 }
3709
3710 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
3711 {
3712         return false;
3713 }
3714
3715 static bool vfswrap_is_offline(struct connection_struct *conn,
3716                                const struct smb_filename *fname)
3717 {
3718         NTSTATUS status;
3719         char *path;
3720         bool offline = false;
3721
3722         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
3723                 return false;
3724         }
3725
3726         if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
3727 #if defined(ENOTSUP)
3728                 errno = ENOTSUP;
3729 #endif
3730                 return false;
3731         }
3732
3733         status = get_full_smb_filename(talloc_tos(), fname, &path);
3734         if (!NT_STATUS_IS_OK(status)) {
3735                 errno = map_errno_from_nt_status(status);
3736                 return false;
3737         }
3738
3739         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
3740
3741         TALLOC_FREE(path);
3742
3743         return offline;
3744 }
3745
3746 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
3747                                        struct files_struct *fsp,
3748                                        TALLOC_CTX *mem_ctx,
3749                                        DATA_BLOB *cookie)
3750 {
3751         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3752 }
3753
3754 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3755                                            struct files_struct *fsp,
3756                                            const DATA_BLOB old_cookie,
3757                                            TALLOC_CTX *mem_ctx,
3758                                            DATA_BLOB *new_cookie)
3759 {
3760         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3761                                               new_cookie);
3762 }
3763
3764 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3765                                           struct smb_request *smb1req,
3766                                           struct smbXsrv_open *op,
3767                                           const DATA_BLOB old_cookie,
3768                                           TALLOC_CTX *mem_ctx,
3769                                           struct files_struct **fsp,
3770                                           DATA_BLOB *new_cookie)
3771 {
3772         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3773                                              old_cookie, mem_ctx,
3774                                              fsp, new_cookie);
3775 }
3776
3777 static struct vfs_fn_pointers vfs_default_fns = {
3778         /* Disk operations */
3779
3780         .connect_fn = vfswrap_connect,
3781         .disconnect_fn = vfswrap_disconnect,
3782         .disk_free_fn = vfswrap_disk_free,
3783         .get_quota_fn = vfswrap_get_quota,
3784         .set_quota_fn = vfswrap_set_quota,
3785         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3786         .statvfs_fn = vfswrap_statvfs,
3787         .fs_capabilities_fn = vfswrap_fs_capabilities,
3788         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3789         .create_dfs_pathat_fn = vfswrap_create_dfs_pathat,
3790         .read_dfs_pathat_fn = vfswrap_read_dfs_pathat,
3791         .snap_check_path_fn = vfswrap_snap_check_path,
3792         .snap_create_fn = vfswrap_snap_create,
3793         .snap_delete_fn = vfswrap_snap_delete,
3794
3795         /* Directory operations */
3796
3797         .fdopendir_fn = vfswrap_fdopendir,
3798         .readdir_fn = vfswrap_readdir,
3799         .readdir_attr_fn = vfswrap_readdir_attr,
3800         .seekdir_fn = vfswrap_seekdir,
3801         .telldir_fn = vfswrap_telldir,
3802         .rewind_dir_fn = vfswrap_rewinddir,
3803         .mkdirat_fn = vfswrap_mkdirat,
3804         .closedir_fn = vfswrap_closedir,
3805
3806         /* File operations */
3807
3808         .openat_fn = vfswrap_openat,
3809         .create_file_fn = vfswrap_create_file,
3810         .close_fn = vfswrap_close,
3811         .pread_fn = vfswrap_pread,
3812         .pread_send_fn = vfswrap_pread_send,
3813         .pread_recv_fn = vfswrap_pread_recv,
3814         .pwrite_fn = vfswrap_pwrite,
3815         .pwrite_send_fn = vfswrap_pwrite_send,
3816         .pwrite_recv_fn = vfswrap_pwrite_recv,
3817         .lseek_fn = vfswrap_lseek,
3818         .sendfile_fn = vfswrap_sendfile,
3819         .recvfile_fn = vfswrap_recvfile,
3820         .renameat_fn = vfswrap_renameat,
3821         .fsync_send_fn = vfswrap_fsync_send,
3822         .fsync_recv_fn = vfswrap_fsync_recv,
3823         .stat_fn = vfswrap_stat,
3824         .fstat_fn = vfswrap_fstat,
3825         .lstat_fn = vfswrap_lstat,
3826         .get_alloc_size_fn = vfswrap_get_alloc_size,
3827         .unlinkat_fn = vfswrap_unlinkat,
3828         .chmod_fn = vfswrap_chmod,
3829         .fchmod_fn = vfswrap_fchmod,
3830         .fchown_fn = vfswrap_fchown,
3831         .lchown_fn = vfswrap_lchown,
3832         .chdir_fn = vfswrap_chdir,
3833         .getwd_fn = vfswrap_getwd,
3834         .ntimes_fn = vfswrap_ntimes,
3835         .ftruncate_fn = vfswrap_ftruncate,
3836         .fallocate_fn = vfswrap_fallocate,
3837         .lock_fn = vfswrap_lock,
3838         .kernel_flock_fn = vfswrap_kernel_flock,
3839         .fcntl_fn = vfswrap_fcntl,
3840         .linux_setlease_fn = vfswrap_linux_setlease,
3841         .getlock_fn = vfswrap_getlock,
3842         .symlinkat_fn = vfswrap_symlinkat,
3843         .readlinkat_fn = vfswrap_readlinkat,
3844         .linkat_fn = vfswrap_linkat,
3845         .mknodat_fn = vfswrap_mknodat,
3846         .realpath_fn = vfswrap_realpath,
3847         .chflags_fn = vfswrap_chflags,
3848         .file_id_create_fn = vfswrap_file_id_create,
3849         .fs_file_id_fn = vfswrap_fs_file_id,
3850         .streaminfo_fn = vfswrap_streaminfo,
3851         .get_real_filename_fn = vfswrap_get_real_filename,
3852         .connectpath_fn = vfswrap_connectpath,
3853         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3854         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3855         .strict_lock_check_fn = vfswrap_strict_lock_check,
3856         .translate_name_fn = vfswrap_translate_name,
3857         .fsctl_fn = vfswrap_fsctl,
3858         .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3859         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3860         .get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send,
3861         .get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv,
3862         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3863         .offload_read_send_fn = vfswrap_offload_read_send,
3864         .offload_read_recv_fn = vfswrap_offload_read_recv,
3865         .offload_write_send_fn = vfswrap_offload_write_send,
3866         .offload_write_recv_fn = vfswrap_offload_write_recv,
3867         .fget_compression_fn = vfswrap_fget_compression,
3868         .set_compression_fn = vfswrap_set_compression,
3869
3870         /* NT ACL operations. */
3871
3872         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3873         .get_nt_acl_at_fn = vfswrap_get_nt_acl_at,
3874         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3875         .audit_file_fn = vfswrap_audit_file,
3876
3877         /* POSIX ACL operations. */
3878
3879         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3880         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3881         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3882         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3883         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3884         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3885
3886         /* EA operations. */
3887         .getxattr_fn = vfswrap_getxattr,
3888         .getxattrat_send_fn = vfswrap_getxattrat_send,
3889         .getxattrat_recv_fn = vfswrap_getxattrat_recv,
3890         .fgetxattr_fn = vfswrap_fgetxattr,
3891         .flistxattr_fn = vfswrap_flistxattr,
3892         .removexattr_fn = vfswrap_removexattr,
3893         .fremovexattr_fn = vfswrap_fremovexattr,
3894         .setxattr_fn = vfswrap_setxattr,
3895         .fsetxattr_fn = vfswrap_fsetxattr,
3896
3897         /* aio operations */
3898         .aio_force_fn = vfswrap_aio_force,
3899
3900         /* durable handle operations */
3901         .durable_cookie_fn = vfswrap_durable_cookie,
3902         .durable_disconnect_fn = vfswrap_durable_disconnect,
3903         .durable_reconnect_fn = vfswrap_durable_reconnect,
3904 };
3905
3906 static_decl_vfs;
3907 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3908 {
3909         /*
3910          * Here we need to implement every call!
3911          *
3912          * As this is the end of the vfs module chain.
3913          */
3914         smb_vfs_assert_all_fns(&vfs_default_fns, DEFAULT_VFS_MODULE_NAME);
3915         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3916                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
3917 }
3918
3919