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