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