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