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