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