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