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