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