s3/vfs: remove SMB_VFS_STRICT_UNLOCK
[samba.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/tevent_ntstatus.h"
34 #include "lib/util/sys_rw.h"
35 #include "lib/pthreadpool/pthreadpool_tevent.h"
36 #include "librpc/gen_ndr/ndr_ioctl.h"
37 #include "offload_token.h"
38
39 #undef DBGC_CLASS
40 #define DBGC_CLASS DBGC_VFS
41
42 /* Check for NULL pointer parameters in vfswrap_* functions */
43
44 /* We don't want to have NULL function pointers lying around.  Someone
45    is sure to try and execute them.  These stubs are used to prevent
46    this possibility. */
47
48 static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
49 {
50     return 0;    /* Return >= 0 for success */
51 }
52
53 static void vfswrap_disconnect(vfs_handle_struct *handle)
54 {
55 }
56
57 /* Disk operations */
58
59 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,
60                                 const struct smb_filename *smb_fname,
61                                 uint64_t *bsize,
62                                 uint64_t *dfree,
63                                 uint64_t *dsize)
64 {
65         if (sys_fsusage(smb_fname->base_name, dfree, dsize) != 0) {
66                 return (uint64_t)-1;
67         }
68
69         *bsize = 512;
70         return *dfree / 2;
71 }
72
73 static int vfswrap_get_quota(struct vfs_handle_struct *handle,
74                                 const struct smb_filename *smb_fname,
75                                 enum SMB_QUOTA_TYPE qtype,
76                                 unid_t id,
77                                 SMB_DISK_QUOTA *qt)
78 {
79 #ifdef HAVE_SYS_QUOTAS
80         int result;
81
82         START_PROFILE(syscall_get_quota);
83         result = sys_get_quota(smb_fname->base_name, qtype, id, qt);
84         END_PROFILE(syscall_get_quota);
85         return result;
86 #else
87         errno = ENOSYS;
88         return -1;
89 #endif
90 }
91
92 static int vfswrap_set_quota(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
93 {
94 #ifdef HAVE_SYS_QUOTAS
95         int result;
96
97         START_PROFILE(syscall_set_quota);
98         result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
99         END_PROFILE(syscall_set_quota);
100         return result;
101 #else
102         errno = ENOSYS;
103         return -1;
104 #endif
105 }
106
107 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle,
108                                         struct files_struct *fsp,
109                                         struct shadow_copy_data *shadow_copy_data,
110                                         bool labels)
111 {
112         errno = ENOSYS;
113         return -1;  /* Not implemented. */
114 }
115
116 static int vfswrap_statvfs(struct vfs_handle_struct *handle,
117                                 const struct smb_filename *smb_fname,
118                                 vfs_statvfs_struct *statbuf)
119 {
120         return sys_statvfs(smb_fname->base_name, statbuf);
121 }
122
123 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
124                 enum timestamp_set_resolution *p_ts_res)
125 {
126         connection_struct *conn = handle->conn;
127         uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
128         struct smb_filename *smb_fname_cpath = NULL;
129         struct vfs_statvfs_struct statbuf;
130         int ret;
131
132         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         bool write_lck_locked;
1690         DATA_BLOB *token;
1691         struct files_struct *src_fsp;
1692         off_t src_off;
1693         struct files_struct *dst_fsp;
1694         off_t dst_off;
1695         off_t to_copy;
1696         off_t remaining;
1697         size_t next_io_size;
1698 };
1699
1700 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1701
1702 static struct tevent_req *vfswrap_offload_write_send(
1703         struct vfs_handle_struct *handle,
1704         TALLOC_CTX *mem_ctx,
1705         struct tevent_context *ev,
1706         uint32_t fsctl,
1707         DATA_BLOB *token,
1708         off_t transfer_offset,
1709         struct files_struct *dest_fsp,
1710         off_t dest_off,
1711         off_t to_copy)
1712 {
1713         struct tevent_req *req;
1714         struct vfswrap_offload_write_state *state = NULL;
1715         size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1716         files_struct *src_fsp = NULL;
1717         NTSTATUS status;
1718
1719         req = tevent_req_create(mem_ctx, &state,
1720                                 struct vfswrap_offload_write_state);
1721         if (req == NULL) {
1722                 return NULL;
1723         }
1724
1725         *state = (struct vfswrap_offload_write_state) {
1726                 .ev = ev,
1727                 .token = token,
1728                 .src_off = transfer_offset,
1729                 .dst_fsp = dest_fsp,
1730                 .dst_off = dest_off,
1731                 .to_copy = to_copy,
1732                 .remaining = to_copy,
1733         };
1734
1735         switch (fsctl) {
1736         case FSCTL_SRV_COPYCHUNK:
1737         case FSCTL_SRV_COPYCHUNK_WRITE:
1738                 break;
1739
1740         case FSCTL_OFFLOAD_WRITE:
1741                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1742                 return tevent_req_post(req, ev);
1743
1744         case FSCTL_DUP_EXTENTS_TO_FILE:
1745                 DBG_DEBUG("COW clones not supported by vfs_default\n");
1746                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1747                 return tevent_req_post(req, ev);
1748
1749         default:
1750                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1751                 return tevent_req_post(req, ev);
1752         }
1753
1754         /*
1755          * From here on we assume a copy-chunk fsctl
1756          */
1757
1758         if (to_copy == 0) {
1759                 tevent_req_done(req);
1760                 return tevent_req_post(req, ev);
1761         }
1762
1763         status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1764                                                 token, &src_fsp);
1765         if (tevent_req_nterror(req, status)) {
1766                 return tevent_req_post(req, ev);
1767         }
1768         state->src_fsp = src_fsp;
1769
1770         DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1771
1772         status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1773         if (!NT_STATUS_IS_OK(status)) {
1774                 tevent_req_nterror(req, status);
1775                 return tevent_req_post(req, ev);
1776         }
1777
1778         state->buf = talloc_array(state, uint8_t, num);
1779         if (tevent_req_nomem(state->buf, req)) {
1780                 return tevent_req_post(req, ev);
1781         }
1782
1783         status = vfs_stat_fsp(src_fsp);
1784         if (tevent_req_nterror(req, status)) {
1785                 return tevent_req_post(req, ev);
1786         }
1787
1788         if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1789                 /*
1790                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1791                  *   If the SourceOffset or SourceOffset + Length extends beyond
1792                  *   the end of file, the server SHOULD<240> treat this as a
1793                  *   STATUS_END_OF_FILE error.
1794                  * ...
1795                  *   <240> Section 3.3.5.15.6: Windows servers will return
1796                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1797                  */
1798                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1799                 return tevent_req_post(req, ev);
1800         }
1801
1802         if (src_fsp->op == NULL) {
1803                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1804                 return tevent_req_post(req, ev);
1805         }
1806
1807         if (dest_fsp->op == NULL) {
1808                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1809                 return tevent_req_post(req, ev);
1810         }
1811
1812         status = vfswrap_offload_write_loop(req);
1813         if (!NT_STATUS_IS_OK(status)) {
1814                 tevent_req_nterror(req, status);
1815                 return tevent_req_post(req, ev);
1816         }
1817
1818         return req;
1819 }
1820
1821 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1822
1823 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1824 {
1825         struct vfswrap_offload_write_state *state = tevent_req_data(
1826                 req, struct vfswrap_offload_write_state);
1827         struct tevent_req *subreq = NULL;
1828         struct lock_struct read_lck;
1829         bool ok;
1830
1831         state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1832
1833         init_strict_lock_struct(state->src_fsp,
1834                                 state->src_fsp->op->global->open_persistent_id,
1835                                 state->src_off,
1836                                 state->next_io_size,
1837                                 READ_LOCK,
1838                                 &read_lck);
1839
1840         ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1841                                  state->src_fsp,
1842                                  &read_lck);
1843         if (!ok) {
1844                 return NT_STATUS_FILE_LOCK_CONFLICT;
1845         }
1846
1847         subreq = SMB_VFS_PREAD_SEND(state,
1848                                     state->src_fsp->conn->sconn->ev_ctx,
1849                                     state->src_fsp,
1850                                     state->buf,
1851                                     state->next_io_size,
1852                                     state->src_off);
1853         if (subreq == NULL) {
1854                 return NT_STATUS_NO_MEMORY;
1855         }
1856         tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1857
1858         return NT_STATUS_OK;
1859 }
1860
1861 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1862
1863 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1864 {
1865         struct tevent_req *req = tevent_req_callback_data(
1866                 subreq, struct tevent_req);
1867         struct vfswrap_offload_write_state *state = tevent_req_data(
1868                 req, struct vfswrap_offload_write_state);
1869         struct vfs_aio_state aio_state;
1870         struct lock_struct write_lck;
1871         ssize_t nread;
1872         bool ok;
1873
1874         nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1875         TALLOC_FREE(subreq);
1876         if (nread == -1) {
1877                 DBG_ERR("read failed: %s\n", strerror(errno));
1878                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1879                 return;
1880         }
1881         if (nread != state->next_io_size) {
1882                 DBG_ERR("Short read, only %zd of %zu\n",
1883                         nread, state->next_io_size);
1884                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1885                 return;
1886         }
1887
1888         state->src_off += nread;
1889
1890         init_strict_lock_struct(state->dst_fsp,
1891                                 state->dst_fsp->op->global->open_persistent_id,
1892                                 state->dst_off,
1893                                 state->next_io_size,
1894                                 WRITE_LOCK,
1895                                 &write_lck);
1896
1897         ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1898                                  state->dst_fsp,
1899                                  &write_lck);
1900         if (!ok) {
1901                 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1902                 return;
1903         }
1904
1905         subreq = SMB_VFS_PWRITE_SEND(state,
1906                                      state->ev,
1907                                      state->dst_fsp,
1908                                      state->buf,
1909                                      state->next_io_size,
1910                                      state->dst_off);
1911         if (subreq == NULL) {
1912                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1913                 return;
1914         }
1915         tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1916 }
1917
1918 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1919 {
1920         struct tevent_req *req = tevent_req_callback_data(
1921                 subreq, struct tevent_req);
1922         struct vfswrap_offload_write_state *state = tevent_req_data(
1923                 req, struct vfswrap_offload_write_state);
1924         struct vfs_aio_state aio_state;
1925         ssize_t nwritten;
1926         NTSTATUS status;
1927
1928         nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1929         TALLOC_FREE(subreq);
1930         if (nwritten == -1) {
1931                 DBG_ERR("write failed: %s\n", strerror(errno));
1932                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1933                 return;
1934         }
1935         if (nwritten != state->next_io_size) {
1936                 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1937                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1938                 return;
1939         }
1940
1941         state->dst_off += nwritten;
1942
1943         if (state->remaining < nwritten) {
1944                 /* Paranoia check */
1945                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1946                 return;
1947         }
1948         state->remaining -= nwritten;
1949         if (state->remaining == 0) {
1950                 tevent_req_done(req);
1951                 return;
1952         }
1953
1954         status = vfswrap_offload_write_loop(req);
1955         if (!NT_STATUS_IS_OK(status)) {
1956                 tevent_req_nterror(req, status);
1957                 return;
1958         }
1959
1960         return;
1961 }
1962
1963 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1964                                         struct tevent_req *req,
1965                                         off_t *copied)
1966 {
1967         struct vfswrap_offload_write_state *state = tevent_req_data(
1968                 req, struct vfswrap_offload_write_state);
1969         NTSTATUS status;
1970
1971         if (tevent_req_is_nterror(req, &status)) {
1972                 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1973                 *copied = 0;
1974                 tevent_req_received(req);
1975                 return status;
1976         }
1977
1978         *copied = state->to_copy;
1979         DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1980         tevent_req_received(req);
1981
1982         return NT_STATUS_OK;
1983 }
1984
1985 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1986                                         TALLOC_CTX *mem_ctx,
1987                                         struct files_struct *fsp,
1988                                         struct smb_filename *smb_fname,
1989                                         uint16_t *_compression_fmt)
1990 {
1991         return NT_STATUS_INVALID_DEVICE_REQUEST;
1992 }
1993
1994 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1995                                         TALLOC_CTX *mem_ctx,
1996                                         struct files_struct *fsp,
1997                                         uint16_t compression_fmt)
1998 {
1999         return NT_STATUS_INVALID_DEVICE_REQUEST;
2000 }
2001
2002 /********************************************************************
2003  Given a stat buffer return the allocated size on disk, taking into
2004  account sparse files.
2005 ********************************************************************/
2006 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2007                                        struct files_struct *fsp,
2008                                        const SMB_STRUCT_STAT *sbuf)
2009 {
2010         uint64_t result;
2011
2012         START_PROFILE(syscall_get_alloc_size);
2013
2014         if(S_ISDIR(sbuf->st_ex_mode)) {
2015                 result = 0;
2016                 goto out;
2017         }
2018
2019 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2020         /* The type of st_blocksize is blkcnt_t which *MUST* be
2021            signed (according to POSIX) and can be less than 64-bits.
2022            Ensure when we're converting to 64 bits wide we don't
2023            sign extend. */
2024 #if defined(SIZEOF_BLKCNT_T_8)
2025         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2026 #elif defined(SIZEOF_BLKCNT_T_4)
2027         {
2028                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2029                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2030         }
2031 #else
2032 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2033 #endif
2034         if (result == 0) {
2035                 /*
2036                  * Some file systems do not allocate a block for very
2037                  * small files. But for non-empty file should report a
2038                  * positive size.
2039                  */
2040
2041                 uint64_t filesize = get_file_size_stat(sbuf);
2042                 if (filesize > 0) {
2043                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2044                 }
2045         }
2046 #else
2047         result = get_file_size_stat(sbuf);
2048 #endif
2049
2050         if (fsp && fsp->initial_allocation_size)
2051                 result = MAX(result,fsp->initial_allocation_size);
2052
2053         result = smb_roundup(handle->conn, result);
2054
2055  out:
2056         END_PROFILE(syscall_get_alloc_size);
2057         return result;
2058 }
2059
2060 static int vfswrap_unlink(vfs_handle_struct *handle,
2061                           const struct smb_filename *smb_fname)
2062 {
2063         int result = -1;
2064
2065         START_PROFILE(syscall_unlink);
2066
2067         if (smb_fname->stream_name) {
2068                 errno = ENOENT;
2069                 goto out;
2070         }
2071         result = unlink(smb_fname->base_name);
2072
2073  out:
2074         END_PROFILE(syscall_unlink);
2075         return result;
2076 }
2077
2078 static int vfswrap_chmod(vfs_handle_struct *handle,
2079                         const struct smb_filename *smb_fname,
2080                         mode_t mode)
2081 {
2082         int result;
2083
2084         START_PROFILE(syscall_chmod);
2085
2086         /*
2087          * We need to do this due to the fact that the default POSIX ACL
2088          * chmod modifies the ACL *mask* for the group owner, not the
2089          * group owner bits directly. JRA.
2090          */
2091
2092
2093         {
2094                 int saved_errno = errno; /* We might get ENOSYS */
2095                 result = SMB_VFS_CHMOD_ACL(handle->conn,
2096                                 smb_fname,
2097                                 mode);
2098                 if (result == 0) {
2099                         END_PROFILE(syscall_chmod);
2100                         return result;
2101                 }
2102                 /* Error - return the old errno. */
2103                 errno = saved_errno;
2104         }
2105
2106         result = chmod(smb_fname->base_name, mode);
2107         END_PROFILE(syscall_chmod);
2108         return result;
2109 }
2110
2111 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2112 {
2113         int result;
2114
2115         START_PROFILE(syscall_fchmod);
2116
2117         /*
2118          * We need to do this due to the fact that the default POSIX ACL
2119          * chmod modifies the ACL *mask* for the group owner, not the
2120          * group owner bits directly. JRA.
2121          */
2122
2123         {
2124                 int saved_errno = errno; /* We might get ENOSYS */
2125                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2126                         END_PROFILE(syscall_fchmod);
2127                         return result;
2128                 }
2129                 /* Error - return the old errno. */
2130                 errno = saved_errno;
2131         }
2132
2133 #if defined(HAVE_FCHMOD)
2134         result = fchmod(fsp->fh->fd, mode);
2135 #else
2136         result = -1;
2137         errno = ENOSYS;
2138 #endif
2139
2140         END_PROFILE(syscall_fchmod);
2141         return result;
2142 }
2143
2144 static int vfswrap_chown(vfs_handle_struct *handle,
2145                         const struct smb_filename *smb_fname,
2146                         uid_t uid,
2147                         gid_t gid)
2148 {
2149         int result;
2150
2151         START_PROFILE(syscall_chown);
2152         result = chown(smb_fname->base_name, uid, gid);
2153         END_PROFILE(syscall_chown);
2154         return result;
2155 }
2156
2157 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2158 {
2159 #ifdef HAVE_FCHOWN
2160         int result;
2161
2162         START_PROFILE(syscall_fchown);
2163         result = fchown(fsp->fh->fd, uid, gid);
2164         END_PROFILE(syscall_fchown);
2165         return result;
2166 #else
2167         errno = ENOSYS;
2168         return -1;
2169 #endif
2170 }
2171
2172 static int vfswrap_lchown(vfs_handle_struct *handle,
2173                         const struct smb_filename *smb_fname,
2174                         uid_t uid,
2175                         gid_t gid)
2176 {
2177         int result;
2178
2179         START_PROFILE(syscall_lchown);
2180         result = lchown(smb_fname->base_name, uid, gid);
2181         END_PROFILE(syscall_lchown);
2182         return result;
2183 }
2184
2185 static int vfswrap_chdir(vfs_handle_struct *handle,
2186                         const struct smb_filename *smb_fname)
2187 {
2188         int result;
2189
2190         START_PROFILE(syscall_chdir);
2191         result = chdir(smb_fname->base_name);
2192         END_PROFILE(syscall_chdir);
2193         return result;
2194 }
2195
2196 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2197                                 TALLOC_CTX *ctx)
2198 {
2199         char *result;
2200         struct smb_filename *smb_fname = NULL;
2201
2202         START_PROFILE(syscall_getwd);
2203         result = sys_getwd();
2204         END_PROFILE(syscall_getwd);
2205         smb_fname = synthetic_smb_fname(ctx,
2206                                 result,
2207                                 NULL,
2208                                 NULL,
2209                                 0);
2210         if (smb_fname == NULL) {
2211                 SAFE_FREE(result);
2212         }
2213         return smb_fname;
2214 }
2215
2216 /*********************************************************************
2217  nsec timestamp resolution call. Convert down to whatever the underlying
2218  system will support.
2219 **********************************************************************/
2220
2221 static int vfswrap_ntimes(vfs_handle_struct *handle,
2222                           const struct smb_filename *smb_fname,
2223                           struct smb_file_time *ft)
2224 {
2225         int result = -1;
2226
2227         START_PROFILE(syscall_ntimes);
2228
2229         if (smb_fname->stream_name) {
2230                 errno = ENOENT;
2231                 goto out;
2232         }
2233
2234         if (ft != NULL) {
2235                 if (null_timespec(ft->atime)) {
2236                         ft->atime= smb_fname->st.st_ex_atime;
2237                 }
2238
2239                 if (null_timespec(ft->mtime)) {
2240                         ft->mtime = smb_fname->st.st_ex_mtime;
2241                 }
2242
2243                 if (!null_timespec(ft->create_time)) {
2244                         set_create_timespec_ea(handle->conn,
2245                                                smb_fname,
2246                                                ft->create_time);
2247                 }
2248
2249                 if ((timespec_compare(&ft->atime,
2250                                       &smb_fname->st.st_ex_atime) == 0) &&
2251                     (timespec_compare(&ft->mtime,
2252                                       &smb_fname->st.st_ex_mtime) == 0)) {
2253                         return 0;
2254                 }
2255         }
2256
2257 #if defined(HAVE_UTIMENSAT)
2258         if (ft != NULL) {
2259                 struct timespec ts[2];
2260                 ts[0] = ft->atime;
2261                 ts[1] = ft->mtime;
2262                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2263         } else {
2264                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2265         }
2266         if (!((result == -1) && (errno == ENOSYS))) {
2267                 goto out;
2268         }
2269 #endif
2270 #if defined(HAVE_UTIMES)
2271         if (ft != NULL) {
2272                 struct timeval tv[2];
2273                 tv[0] = convert_timespec_to_timeval(ft->atime);
2274                 tv[1] = convert_timespec_to_timeval(ft->mtime);
2275                 result = utimes(smb_fname->base_name, tv);
2276         } else {
2277                 result = utimes(smb_fname->base_name, NULL);
2278         }
2279         if (!((result == -1) && (errno == ENOSYS))) {
2280                 goto out;
2281         }
2282 #endif
2283 #if defined(HAVE_UTIME)
2284         if (ft != NULL) {
2285                 struct utimbuf times;
2286                 times.actime = convert_timespec_to_time_t(ft->atime);
2287                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2288                 result = utime(smb_fname->base_name, &times);
2289         } else {
2290                 result = utime(smb_fname->base_name, NULL);
2291         }
2292         if (!((result == -1) && (errno == ENOSYS))) {
2293                 goto out;
2294         }
2295 #endif
2296         errno = ENOSYS;
2297         result = -1;
2298
2299  out:
2300         END_PROFILE(syscall_ntimes);
2301         return result;
2302 }
2303
2304 /*********************************************************************
2305  A version of ftruncate that will write the space on disk if strict
2306  allocate is set.
2307 **********************************************************************/
2308
2309 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2310 {
2311         off_t space_to_write;
2312         uint64_t space_avail;
2313         uint64_t bsize,dfree,dsize;
2314         int ret;
2315         NTSTATUS status;
2316         SMB_STRUCT_STAT *pst;
2317
2318         status = vfs_stat_fsp(fsp);
2319         if (!NT_STATUS_IS_OK(status)) {
2320                 return -1;
2321         }
2322         pst = &fsp->fsp_name->st;
2323
2324 #ifdef S_ISFIFO
2325         if (S_ISFIFO(pst->st_ex_mode))
2326                 return 0;
2327 #endif
2328
2329         if (pst->st_ex_size == len)
2330                 return 0;
2331
2332         /* Shrink - just ftruncate. */
2333         if (pst->st_ex_size > len)
2334                 return ftruncate(fsp->fh->fd, len);
2335
2336         space_to_write = len - pst->st_ex_size;
2337
2338         /* for allocation try fallocate first. This can fail on some
2339            platforms e.g. when the filesystem doesn't support it and no
2340            emulation is being done by the libc (like on AIX with JFS1). In that
2341            case we do our own emulation. fallocate implementations can
2342            return ENOTSUP or EINVAL in cases like that. */
2343         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2344         if (ret == -1 && errno == ENOSPC) {
2345                 return -1;
2346         }
2347         if (ret == 0) {
2348                 return 0;
2349         }
2350         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2351                 "error %d. Falling back to slow manual allocation\n", errno));
2352
2353         /* available disk space is enough or not? */
2354         space_avail =
2355             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2356         /* space_avail is 1k blocks */
2357         if (space_avail == (uint64_t)-1 ||
2358                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2359                 errno = ENOSPC;
2360                 return -1;
2361         }
2362
2363         /* Write out the real space on disk. */
2364         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2365         if (ret != 0) {
2366                 return -1;
2367         }
2368
2369         return 0;
2370 }
2371
2372 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2373 {
2374         int result = -1;
2375         SMB_STRUCT_STAT *pst;
2376         NTSTATUS status;
2377         char c = 0;
2378
2379         START_PROFILE(syscall_ftruncate);
2380
2381         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2382                 result = strict_allocate_ftruncate(handle, fsp, len);
2383                 END_PROFILE(syscall_ftruncate);
2384                 return result;
2385         }
2386
2387         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2388            ftruncate if the system supports it. Then I discovered that
2389            you can have some filesystems that support ftruncate
2390            expansion and some that don't! On Linux fat can't do
2391            ftruncate extend but ext2 can. */
2392
2393         result = ftruncate(fsp->fh->fd, len);
2394
2395         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2396            extend a file with ftruncate. Provide alternate implementation
2397            for this */
2398
2399         /* Do an fstat to see if the file is longer than the requested
2400            size in which case the ftruncate above should have
2401            succeeded or shorter, in which case seek to len - 1 and
2402            write 1 byte of zero */
2403         status = vfs_stat_fsp(fsp);
2404         if (!NT_STATUS_IS_OK(status)) {
2405                 goto done;
2406         }
2407
2408         /* We need to update the files_struct after successful ftruncate */
2409         if (result == 0) {
2410                 goto done;
2411         }
2412
2413         pst = &fsp->fsp_name->st;
2414
2415 #ifdef S_ISFIFO
2416         if (S_ISFIFO(pst->st_ex_mode)) {
2417                 result = 0;
2418                 goto done;
2419         }
2420 #endif
2421
2422         if (pst->st_ex_size == len) {
2423                 result = 0;
2424                 goto done;
2425         }
2426
2427         if (pst->st_ex_size > len) {
2428                 /* the ftruncate should have worked */
2429                 goto done;
2430         }
2431
2432         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2433                 goto done;
2434         }
2435
2436         result = 0;
2437
2438   done:
2439
2440         END_PROFILE(syscall_ftruncate);
2441         return result;
2442 }
2443
2444 static int vfswrap_fallocate(vfs_handle_struct *handle,
2445                         files_struct *fsp,
2446                         uint32_t mode,
2447                         off_t offset,
2448                         off_t len)
2449 {
2450         int result;
2451
2452         START_PROFILE(syscall_fallocate);
2453         if (mode == 0) {
2454                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2455                 /*
2456                  * posix_fallocate returns 0 on success, errno on error
2457                  * and doesn't set errno. Make it behave like fallocate()
2458                  * which returns -1, and sets errno on failure.
2459                  */
2460                 if (result != 0) {
2461                         errno = result;
2462                         result = -1;
2463                 }
2464         } else {
2465                 /* sys_fallocate handles filtering of unsupported mode flags */
2466                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2467         }
2468         END_PROFILE(syscall_fallocate);
2469         return result;
2470 }
2471
2472 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2473 {
2474         bool result;
2475
2476         START_PROFILE(syscall_fcntl_lock);
2477
2478         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2479                                                 "smbd",
2480                                                 "force process locks",
2481                                                 false)) {
2482                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2483         }
2484
2485         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
2486         END_PROFILE(syscall_fcntl_lock);
2487         return result;
2488 }
2489
2490 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2491                                 uint32_t share_mode, uint32_t access_mask)
2492 {
2493         START_PROFILE(syscall_kernel_flock);
2494         kernel_flock(fsp->fh->fd, share_mode, access_mask);
2495         END_PROFILE(syscall_kernel_flock);
2496         return 0;
2497 }
2498
2499 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2500 {
2501         bool result;
2502         int op = F_GETLK;
2503
2504         START_PROFILE(syscall_fcntl_getlock);
2505
2506         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2507                                                 "smbd",
2508                                                 "force process locks",
2509                                                 false)) {
2510                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2511         }
2512
2513         result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2514         END_PROFILE(syscall_fcntl_getlock);
2515         return result;
2516 }
2517
2518 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2519                                 int leasetype)
2520 {
2521         int result = -1;
2522
2523         START_PROFILE(syscall_linux_setlease);
2524
2525 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2526         result = linux_setlease(fsp->fh->fd, leasetype);
2527 #else
2528         errno = ENOSYS;
2529 #endif
2530         END_PROFILE(syscall_linux_setlease);
2531         return result;
2532 }
2533
2534 static int vfswrap_symlink(vfs_handle_struct *handle,
2535                         const char *link_target,
2536                         const struct smb_filename *new_smb_fname)
2537 {
2538         int result;
2539
2540         START_PROFILE(syscall_symlink);
2541         result = symlink(link_target, new_smb_fname->base_name);
2542         END_PROFILE(syscall_symlink);
2543         return result;
2544 }
2545
2546 static int vfswrap_readlink(vfs_handle_struct *handle,
2547                         const struct smb_filename *smb_fname,
2548                         char *buf,
2549                         size_t bufsiz)
2550 {
2551         int result;
2552
2553         START_PROFILE(syscall_readlink);
2554         result = readlink(smb_fname->base_name, buf, bufsiz);
2555         END_PROFILE(syscall_readlink);
2556         return result;
2557 }
2558
2559 static int vfswrap_link(vfs_handle_struct *handle,
2560                         const struct smb_filename *old_smb_fname,
2561                         const struct smb_filename *new_smb_fname)
2562 {
2563         int result;
2564
2565         START_PROFILE(syscall_link);
2566         result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2567         END_PROFILE(syscall_link);
2568         return result;
2569 }
2570
2571 static int vfswrap_mknod(vfs_handle_struct *handle,
2572                         const struct smb_filename *smb_fname,
2573                         mode_t mode,
2574                         SMB_DEV_T dev)
2575 {
2576         int result;
2577
2578         START_PROFILE(syscall_mknod);
2579         result = sys_mknod(smb_fname->base_name, mode, dev);
2580         END_PROFILE(syscall_mknod);
2581         return result;
2582 }
2583
2584 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2585                         TALLOC_CTX *ctx,
2586                         const struct smb_filename *smb_fname)
2587 {
2588         char *result;
2589         struct smb_filename *result_fname = NULL;
2590
2591         START_PROFILE(syscall_realpath);
2592         result = sys_realpath(smb_fname->base_name);
2593         END_PROFILE(syscall_realpath);
2594         if (result) {
2595                 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2596                 SAFE_FREE(result);
2597         }
2598         return result_fname;
2599 }
2600
2601 static int vfswrap_chflags(vfs_handle_struct *handle,
2602                         const struct smb_filename *smb_fname,
2603                         unsigned int flags)
2604 {
2605 #ifdef HAVE_CHFLAGS
2606         return chflags(smb_fname->base_name, flags);
2607 #else
2608         errno = ENOSYS;
2609         return -1;
2610 #endif
2611 }
2612
2613 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2614                                              const SMB_STRUCT_STAT *sbuf)
2615 {
2616         struct file_id key;
2617
2618         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2619          * blob */
2620         ZERO_STRUCT(key);
2621
2622         key.devid = sbuf->st_ex_dev;
2623         key.inode = sbuf->st_ex_ino;
2624         /* key.extid is unused by default. */
2625
2626         return key;
2627 }
2628
2629 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2630                                    struct files_struct *fsp,
2631                                    const struct smb_filename *smb_fname,
2632                                    TALLOC_CTX *mem_ctx,
2633                                    unsigned int *pnum_streams,
2634                                    struct stream_struct **pstreams)
2635 {
2636         SMB_STRUCT_STAT sbuf;
2637         struct stream_struct *tmp_streams = NULL;
2638         int ret;
2639
2640         if ((fsp != NULL) && (fsp->is_directory)) {
2641                 /*
2642                  * No default streams on directories
2643                  */
2644                 goto done;
2645         }
2646
2647         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2648                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2649         }
2650         else {
2651                 struct smb_filename smb_fname_cp;
2652
2653                 ZERO_STRUCT(smb_fname_cp);
2654                 smb_fname_cp.base_name = discard_const_p(char,
2655                                         smb_fname->base_name);
2656                 smb_fname_cp.flags = smb_fname->flags;
2657
2658                 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2659                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2660                 } else {
2661                         ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2662                 }
2663                 sbuf = smb_fname_cp.st;
2664         }
2665
2666         if (ret == -1) {
2667                 return map_nt_error_from_unix(errno);
2668         }
2669
2670         if (S_ISDIR(sbuf.st_ex_mode)) {
2671                 goto done;
2672         }
2673
2674         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2675                                         (*pnum_streams) + 1);
2676         if (tmp_streams == NULL) {
2677                 return NT_STATUS_NO_MEMORY;
2678         }
2679         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2680         if (tmp_streams[*pnum_streams].name == NULL) {
2681                 return NT_STATUS_NO_MEMORY;
2682         }
2683         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2684         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2685
2686         *pnum_streams += 1;
2687         *pstreams = tmp_streams;
2688  done:
2689         return NT_STATUS_OK;
2690 }
2691
2692 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2693                                      const char *path,
2694                                      const char *name,
2695                                      TALLOC_CTX *mem_ctx,
2696                                      char **found_name)
2697 {
2698         /*
2699          * Don't fall back to get_real_filename so callers can differentiate
2700          * between a full directory scan and an actual case-insensitive stat.
2701          */
2702         errno = EOPNOTSUPP;
2703         return -1;
2704 }
2705
2706 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2707                                    const struct smb_filename *smb_fname)
2708 {
2709         return handle->conn->connectpath;
2710 }
2711
2712 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2713                                          struct byte_range_lock *br_lck,
2714                                          struct lock_struct *plock,
2715                                          bool blocking_lock)
2716 {
2717         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2718
2719         /* Note: blr is not used in the default implementation. */
2720         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2721 }
2722
2723 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2724                                        struct messaging_context *msg_ctx,
2725                                        struct byte_range_lock *br_lck,
2726                                        const struct lock_struct *plock)
2727 {
2728         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2729
2730         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2731 }
2732
2733 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2734                                        struct byte_range_lock *br_lck,
2735                                        struct lock_struct *plock)
2736 {
2737         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2738
2739         /* Note: blr is not used in the default implementation. */
2740         return brl_lock_cancel_default(br_lck, plock);
2741 }
2742
2743 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2744                                 files_struct *fsp,
2745                                 struct lock_struct *plock)
2746 {
2747         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2748             plock->lock_type == WRITE_LOCK);
2749
2750         return strict_lock_default(fsp, plock);
2751 }
2752
2753 /* NT ACL operations. */
2754
2755 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2756                                     files_struct *fsp,
2757                                     uint32_t security_info,
2758                                     TALLOC_CTX *mem_ctx,
2759                                     struct security_descriptor **ppdesc)
2760 {
2761         NTSTATUS result;
2762
2763         START_PROFILE(fget_nt_acl);
2764         result = posix_fget_nt_acl(fsp, security_info,
2765                                    mem_ctx, ppdesc);
2766         END_PROFILE(fget_nt_acl);
2767         return result;
2768 }
2769
2770 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2771                                    const struct smb_filename *smb_fname,
2772                                    uint32_t security_info,
2773                                    TALLOC_CTX *mem_ctx,
2774                                    struct security_descriptor **ppdesc)
2775 {
2776         NTSTATUS result;
2777
2778         START_PROFILE(get_nt_acl);
2779         result = posix_get_nt_acl(handle->conn,
2780                                 smb_fname,
2781                                 security_info,
2782                                 mem_ctx,
2783                                 ppdesc);
2784         END_PROFILE(get_nt_acl);
2785         return result;
2786 }
2787
2788 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2789 {
2790         NTSTATUS result;
2791
2792         START_PROFILE(fset_nt_acl);
2793         result = set_nt_acl(fsp, security_info_sent, psd);
2794         END_PROFILE(fset_nt_acl);
2795         return result;
2796 }
2797
2798 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2799                                    struct smb_filename *file,
2800                                    struct security_acl *sacl,
2801                                    uint32_t access_requested,
2802                                    uint32_t access_denied)
2803 {
2804         return NT_STATUS_OK; /* Nothing to do here ... */
2805 }
2806
2807 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2808                                 const struct smb_filename *smb_fname,
2809                                 mode_t mode)
2810 {
2811 #ifdef HAVE_NO_ACL
2812         errno = ENOSYS;
2813         return -1;
2814 #else
2815         int result;
2816
2817         START_PROFILE(chmod_acl);
2818         result = chmod_acl(handle->conn, smb_fname, mode);
2819         END_PROFILE(chmod_acl);
2820         return result;
2821 #endif
2822 }
2823
2824 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2825 {
2826 #ifdef HAVE_NO_ACL
2827         errno = ENOSYS;
2828         return -1;
2829 #else
2830         int result;
2831
2832         START_PROFILE(fchmod_acl);
2833         result = fchmod_acl(fsp, mode);
2834         END_PROFILE(fchmod_acl);
2835         return result;
2836 #endif
2837 }
2838
2839 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2840                                           const struct smb_filename *smb_fname,
2841                                           SMB_ACL_TYPE_T type,
2842                                           TALLOC_CTX *mem_ctx)
2843 {
2844         return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2845 }
2846
2847 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2848                                         files_struct *fsp,
2849                                         TALLOC_CTX *mem_ctx)
2850 {
2851         return sys_acl_get_fd(handle, fsp, mem_ctx);
2852 }
2853
2854 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2855                                 const struct smb_filename *smb_fname,
2856                                 SMB_ACL_TYPE_T acltype,
2857                                 SMB_ACL_T theacl)
2858 {
2859         return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2860 }
2861
2862 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2863 {
2864         return sys_acl_set_fd(handle, fsp, theacl);
2865 }
2866
2867 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2868                         const struct smb_filename *smb_fname)
2869 {
2870         return sys_acl_delete_def_file(handle, smb_fname);
2871 }
2872
2873 /****************************************************************
2874  Extended attribute operations.
2875 *****************************************************************/
2876
2877 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2878                         const struct smb_filename *smb_fname,
2879                         const char *name,
2880                         void *value,
2881                         size_t size)
2882 {
2883         return getxattr(smb_fname->base_name, name, value, size);
2884 }
2885
2886 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2887 {
2888         return fgetxattr(fsp->fh->fd, name, value, size);
2889 }
2890
2891 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2892                         const struct smb_filename *smb_fname,
2893                         char *list,
2894                         size_t size)
2895 {
2896         return listxattr(smb_fname->base_name, list, size);
2897 }
2898
2899 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2900 {
2901         return flistxattr(fsp->fh->fd, list, size);
2902 }
2903
2904 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2905                                 const struct smb_filename *smb_fname,
2906                                 const char *name)
2907 {
2908         return removexattr(smb_fname->base_name, name);
2909 }
2910
2911 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2912 {
2913         return fremovexattr(fsp->fh->fd, name);
2914 }
2915
2916 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2917                                 const struct smb_filename *smb_fname,
2918                                 const char *name,
2919                                 const void *value,
2920                                 size_t size,
2921                                 int flags)
2922 {
2923         return setxattr(smb_fname->base_name, name, value, size, flags);
2924 }
2925
2926 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2927 {
2928         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2929 }
2930
2931 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2932 {
2933         return false;
2934 }
2935
2936 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2937                                const struct smb_filename *fname,
2938                                SMB_STRUCT_STAT *sbuf)
2939 {
2940         NTSTATUS status;
2941         char *path;
2942         bool offline = false;
2943
2944         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2945                 return false;
2946         }
2947
2948         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2949 #if defined(ENOTSUP)
2950                 errno = ENOTSUP;
2951 #endif
2952                 return false;
2953         }
2954
2955         status = get_full_smb_filename(talloc_tos(), fname, &path);
2956         if (!NT_STATUS_IS_OK(status)) {
2957                 errno = map_errno_from_nt_status(status);
2958                 return false;
2959         }
2960
2961         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2962
2963         TALLOC_FREE(path);
2964
2965         return offline;
2966 }
2967
2968 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2969                                        struct files_struct *fsp,
2970                                        TALLOC_CTX *mem_ctx,
2971                                        DATA_BLOB *cookie)
2972 {
2973         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2974 }
2975
2976 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2977                                            struct files_struct *fsp,
2978                                            const DATA_BLOB old_cookie,
2979                                            TALLOC_CTX *mem_ctx,
2980                                            DATA_BLOB *new_cookie)
2981 {
2982         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2983                                               new_cookie);
2984 }
2985
2986 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2987                                           struct smb_request *smb1req,
2988                                           struct smbXsrv_open *op,
2989                                           const DATA_BLOB old_cookie,
2990                                           TALLOC_CTX *mem_ctx,
2991                                           struct files_struct **fsp,
2992                                           DATA_BLOB *new_cookie)
2993 {
2994         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2995                                              old_cookie, mem_ctx,
2996                                              fsp, new_cookie);
2997 }
2998
2999 static struct vfs_fn_pointers vfs_default_fns = {
3000         /* Disk operations */
3001
3002         .connect_fn = vfswrap_connect,
3003         .disconnect_fn = vfswrap_disconnect,
3004         .disk_free_fn = vfswrap_disk_free,
3005         .get_quota_fn = vfswrap_get_quota,
3006         .set_quota_fn = vfswrap_set_quota,
3007         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3008         .statvfs_fn = vfswrap_statvfs,
3009         .fs_capabilities_fn = vfswrap_fs_capabilities,
3010         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3011         .snap_check_path_fn = vfswrap_snap_check_path,
3012         .snap_create_fn = vfswrap_snap_create,
3013         .snap_delete_fn = vfswrap_snap_delete,
3014
3015         /* Directory operations */
3016
3017         .opendir_fn = vfswrap_opendir,
3018         .fdopendir_fn = vfswrap_fdopendir,
3019         .readdir_fn = vfswrap_readdir,
3020         .readdir_attr_fn = vfswrap_readdir_attr,
3021         .seekdir_fn = vfswrap_seekdir,
3022         .telldir_fn = vfswrap_telldir,
3023         .rewind_dir_fn = vfswrap_rewinddir,
3024         .mkdir_fn = vfswrap_mkdir,
3025         .rmdir_fn = vfswrap_rmdir,
3026         .closedir_fn = vfswrap_closedir,
3027         .init_search_op_fn = vfswrap_init_search_op,
3028
3029         /* File operations */
3030
3031         .open_fn = vfswrap_open,
3032         .create_file_fn = vfswrap_create_file,
3033         .close_fn = vfswrap_close,
3034         .read_fn = vfswrap_read,
3035         .pread_fn = vfswrap_pread,
3036         .pread_send_fn = vfswrap_pread_send,
3037         .pread_recv_fn = vfswrap_pread_recv,
3038         .write_fn = vfswrap_write,
3039         .pwrite_fn = vfswrap_pwrite,
3040         .pwrite_send_fn = vfswrap_pwrite_send,
3041         .pwrite_recv_fn = vfswrap_pwrite_recv,
3042         .lseek_fn = vfswrap_lseek,
3043         .sendfile_fn = vfswrap_sendfile,
3044         .recvfile_fn = vfswrap_recvfile,
3045         .rename_fn = vfswrap_rename,
3046         .fsync_fn = vfswrap_fsync,
3047         .fsync_send_fn = vfswrap_fsync_send,
3048         .fsync_recv_fn = vfswrap_fsync_recv,
3049         .stat_fn = vfswrap_stat,
3050         .fstat_fn = vfswrap_fstat,
3051         .lstat_fn = vfswrap_lstat,
3052         .get_alloc_size_fn = vfswrap_get_alloc_size,
3053         .unlink_fn = vfswrap_unlink,
3054         .chmod_fn = vfswrap_chmod,
3055         .fchmod_fn = vfswrap_fchmod,
3056         .chown_fn = vfswrap_chown,
3057         .fchown_fn = vfswrap_fchown,
3058         .lchown_fn = vfswrap_lchown,
3059         .chdir_fn = vfswrap_chdir,
3060         .getwd_fn = vfswrap_getwd,
3061         .ntimes_fn = vfswrap_ntimes,
3062         .ftruncate_fn = vfswrap_ftruncate,
3063         .fallocate_fn = vfswrap_fallocate,
3064         .lock_fn = vfswrap_lock,
3065         .kernel_flock_fn = vfswrap_kernel_flock,
3066         .linux_setlease_fn = vfswrap_linux_setlease,
3067         .getlock_fn = vfswrap_getlock,
3068         .symlink_fn = vfswrap_symlink,
3069         .readlink_fn = vfswrap_readlink,
3070         .link_fn = vfswrap_link,
3071         .mknod_fn = vfswrap_mknod,
3072         .realpath_fn = vfswrap_realpath,
3073         .chflags_fn = vfswrap_chflags,
3074         .file_id_create_fn = vfswrap_file_id_create,
3075         .streaminfo_fn = vfswrap_streaminfo,
3076         .get_real_filename_fn = vfswrap_get_real_filename,
3077         .connectpath_fn = vfswrap_connectpath,
3078         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3079         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3080         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3081         .strict_lock_fn = vfswrap_strict_lock,
3082         .translate_name_fn = vfswrap_translate_name,
3083         .fsctl_fn = vfswrap_fsctl,
3084         .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3085         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3086         .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3087         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3088         .offload_read_send_fn = vfswrap_offload_read_send,
3089         .offload_read_recv_fn = vfswrap_offload_read_recv,
3090         .offload_write_send_fn = vfswrap_offload_write_send,
3091         .offload_write_recv_fn = vfswrap_offload_write_recv,
3092         .get_compression_fn = vfswrap_get_compression,
3093         .set_compression_fn = vfswrap_set_compression,
3094
3095         /* NT ACL operations. */
3096
3097         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3098         .get_nt_acl_fn = vfswrap_get_nt_acl,
3099         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3100         .audit_file_fn = vfswrap_audit_file,
3101
3102         /* POSIX ACL operations. */
3103
3104         .chmod_acl_fn = vfswrap_chmod_acl,
3105         .fchmod_acl_fn = vfswrap_fchmod_acl,
3106
3107         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3108         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3109         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3110         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3111         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3112         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3113         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3114
3115         /* EA operations. */
3116         .getxattr_fn = vfswrap_getxattr,
3117         .fgetxattr_fn = vfswrap_fgetxattr,
3118         .listxattr_fn = vfswrap_listxattr,
3119         .flistxattr_fn = vfswrap_flistxattr,
3120         .removexattr_fn = vfswrap_removexattr,
3121         .fremovexattr_fn = vfswrap_fremovexattr,
3122         .setxattr_fn = vfswrap_setxattr,
3123         .fsetxattr_fn = vfswrap_fsetxattr,
3124
3125         /* aio operations */
3126         .aio_force_fn = vfswrap_aio_force,
3127
3128         /* durable handle operations */
3129         .durable_cookie_fn = vfswrap_durable_cookie,
3130         .durable_disconnect_fn = vfswrap_durable_disconnect,
3131         .durable_reconnect_fn = vfswrap_durable_reconnect,
3132 };
3133
3134 NTSTATUS vfs_default_init(TALLOC_CTX *);
3135 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3136 {
3137         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3138                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
3139 }
3140
3141