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