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