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