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