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