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