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