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