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