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