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