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