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