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