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