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