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