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