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