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