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