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