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