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