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