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