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