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