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