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