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