vfs_unityed_media: remove handling of init_search_op
[nivanova/samba-autobuild/.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/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
2230         if (result == NULL) {
2231                 return NULL;
2232         }
2233         smb_fname = synthetic_smb_fname(ctx,
2234                                 result,
2235                                 NULL,
2236                                 NULL,
2237                                 0);
2238         if (smb_fname == NULL) {
2239                 SAFE_FREE(result);
2240         }
2241         return smb_fname;
2242 }
2243
2244 /*********************************************************************
2245  nsec timestamp resolution call. Convert down to whatever the underlying
2246  system will support.
2247 **********************************************************************/
2248
2249 static int vfswrap_ntimes(vfs_handle_struct *handle,
2250                           const struct smb_filename *smb_fname,
2251                           struct smb_file_time *ft)
2252 {
2253         int result = -1;
2254
2255         START_PROFILE(syscall_ntimes);
2256
2257         if (smb_fname->stream_name) {
2258                 errno = ENOENT;
2259                 goto out;
2260         }
2261
2262         if (ft != NULL) {
2263                 if (null_timespec(ft->atime)) {
2264                         ft->atime= smb_fname->st.st_ex_atime;
2265                 }
2266
2267                 if (null_timespec(ft->mtime)) {
2268                         ft->mtime = smb_fname->st.st_ex_mtime;
2269                 }
2270
2271                 if (!null_timespec(ft->create_time)) {
2272                         set_create_timespec_ea(handle->conn,
2273                                                smb_fname,
2274                                                ft->create_time);
2275                 }
2276
2277                 if ((timespec_compare(&ft->atime,
2278                                       &smb_fname->st.st_ex_atime) == 0) &&
2279                     (timespec_compare(&ft->mtime,
2280                                       &smb_fname->st.st_ex_mtime) == 0)) {
2281                         return 0;
2282                 }
2283         }
2284
2285 #if defined(HAVE_UTIMENSAT)
2286         if (ft != NULL) {
2287                 struct timespec ts[2];
2288                 ts[0] = ft->atime;
2289                 ts[1] = ft->mtime;
2290                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2291         } else {
2292                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2293         }
2294         if (!((result == -1) && (errno == ENOSYS))) {
2295                 goto out;
2296         }
2297 #endif
2298 #if defined(HAVE_UTIMES)
2299         if (ft != NULL) {
2300                 struct timeval tv[2];
2301                 tv[0] = convert_timespec_to_timeval(ft->atime);
2302                 tv[1] = convert_timespec_to_timeval(ft->mtime);
2303                 result = utimes(smb_fname->base_name, tv);
2304         } else {
2305                 result = utimes(smb_fname->base_name, NULL);
2306         }
2307         if (!((result == -1) && (errno == ENOSYS))) {
2308                 goto out;
2309         }
2310 #endif
2311 #if defined(HAVE_UTIME)
2312         if (ft != NULL) {
2313                 struct utimbuf times;
2314                 times.actime = convert_timespec_to_time_t(ft->atime);
2315                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2316                 result = utime(smb_fname->base_name, &times);
2317         } else {
2318                 result = utime(smb_fname->base_name, NULL);
2319         }
2320         if (!((result == -1) && (errno == ENOSYS))) {
2321                 goto out;
2322         }
2323 #endif
2324         errno = ENOSYS;
2325         result = -1;
2326
2327  out:
2328         END_PROFILE(syscall_ntimes);
2329         return result;
2330 }
2331
2332 /*********************************************************************
2333  A version of ftruncate that will write the space on disk if strict
2334  allocate is set.
2335 **********************************************************************/
2336
2337 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2338 {
2339         off_t space_to_write;
2340         uint64_t space_avail;
2341         uint64_t bsize,dfree,dsize;
2342         int ret;
2343         NTSTATUS status;
2344         SMB_STRUCT_STAT *pst;
2345
2346         status = vfs_stat_fsp(fsp);
2347         if (!NT_STATUS_IS_OK(status)) {
2348                 return -1;
2349         }
2350         pst = &fsp->fsp_name->st;
2351
2352 #ifdef S_ISFIFO
2353         if (S_ISFIFO(pst->st_ex_mode))
2354                 return 0;
2355 #endif
2356
2357         if (pst->st_ex_size == len)
2358                 return 0;
2359
2360         /* Shrink - just ftruncate. */
2361         if (pst->st_ex_size > len)
2362                 return ftruncate(fsp->fh->fd, len);
2363
2364         space_to_write = len - pst->st_ex_size;
2365
2366         /* for allocation try fallocate first. This can fail on some
2367            platforms e.g. when the filesystem doesn't support it and no
2368            emulation is being done by the libc (like on AIX with JFS1). In that
2369            case we do our own emulation. fallocate implementations can
2370            return ENOTSUP or EINVAL in cases like that. */
2371         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2372         if (ret == -1 && errno == ENOSPC) {
2373                 return -1;
2374         }
2375         if (ret == 0) {
2376                 return 0;
2377         }
2378         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2379                 "error %d. Falling back to slow manual allocation\n", errno));
2380
2381         /* available disk space is enough or not? */
2382         space_avail =
2383             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2384         /* space_avail is 1k blocks */
2385         if (space_avail == (uint64_t)-1 ||
2386                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2387                 errno = ENOSPC;
2388                 return -1;
2389         }
2390
2391         /* Write out the real space on disk. */
2392         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2393         if (ret != 0) {
2394                 return -1;
2395         }
2396
2397         return 0;
2398 }
2399
2400 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2401 {
2402         int result = -1;
2403         SMB_STRUCT_STAT *pst;
2404         NTSTATUS status;
2405         char c = 0;
2406
2407         START_PROFILE(syscall_ftruncate);
2408
2409         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2410                 result = strict_allocate_ftruncate(handle, fsp, len);
2411                 END_PROFILE(syscall_ftruncate);
2412                 return result;
2413         }
2414
2415         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2416            ftruncate if the system supports it. Then I discovered that
2417            you can have some filesystems that support ftruncate
2418            expansion and some that don't! On Linux fat can't do
2419            ftruncate extend but ext2 can. */
2420
2421         result = ftruncate(fsp->fh->fd, len);
2422
2423         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2424            extend a file with ftruncate. Provide alternate implementation
2425            for this */
2426
2427         /* Do an fstat to see if the file is longer than the requested
2428            size in which case the ftruncate above should have
2429            succeeded or shorter, in which case seek to len - 1 and
2430            write 1 byte of zero */
2431         status = vfs_stat_fsp(fsp);
2432         if (!NT_STATUS_IS_OK(status)) {
2433                 goto done;
2434         }
2435
2436         /* We need to update the files_struct after successful ftruncate */
2437         if (result == 0) {
2438                 goto done;
2439         }
2440
2441         pst = &fsp->fsp_name->st;
2442
2443 #ifdef S_ISFIFO
2444         if (S_ISFIFO(pst->st_ex_mode)) {
2445                 result = 0;
2446                 goto done;
2447         }
2448 #endif
2449
2450         if (pst->st_ex_size == len) {
2451                 result = 0;
2452                 goto done;
2453         }
2454
2455         if (pst->st_ex_size > len) {
2456                 /* the ftruncate should have worked */
2457                 goto done;
2458         }
2459
2460         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2461                 goto done;
2462         }
2463
2464         result = 0;
2465
2466   done:
2467
2468         END_PROFILE(syscall_ftruncate);
2469         return result;
2470 }
2471
2472 static int vfswrap_fallocate(vfs_handle_struct *handle,
2473                         files_struct *fsp,
2474                         uint32_t mode,
2475                         off_t offset,
2476                         off_t len)
2477 {
2478         int result;
2479
2480         START_PROFILE(syscall_fallocate);
2481         if (mode == 0) {
2482                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2483                 /*
2484                  * posix_fallocate returns 0 on success, errno on error
2485                  * and doesn't set errno. Make it behave like fallocate()
2486                  * which returns -1, and sets errno on failure.
2487                  */
2488                 if (result != 0) {
2489                         errno = result;
2490                         result = -1;
2491                 }
2492         } else {
2493                 /* sys_fallocate handles filtering of unsupported mode flags */
2494                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2495         }
2496         END_PROFILE(syscall_fallocate);
2497         return result;
2498 }
2499
2500 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2501 {
2502         bool result;
2503
2504         START_PROFILE(syscall_fcntl_lock);
2505
2506         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2507                                                 "smbd",
2508                                                 "force process locks",
2509                                                 false)) {
2510                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2511         }
2512
2513         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
2514         END_PROFILE(syscall_fcntl_lock);
2515         return result;
2516 }
2517
2518 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2519                                 uint32_t share_mode, uint32_t access_mask)
2520 {
2521         START_PROFILE(syscall_kernel_flock);
2522         kernel_flock(fsp->fh->fd, share_mode, access_mask);
2523         END_PROFILE(syscall_kernel_flock);
2524         return 0;
2525 }
2526
2527 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2528 {
2529         bool result;
2530         int op = F_GETLK;
2531
2532         START_PROFILE(syscall_fcntl_getlock);
2533
2534         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2535                                                 "smbd",
2536                                                 "force process locks",
2537                                                 false)) {
2538                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2539         }
2540
2541         result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2542         END_PROFILE(syscall_fcntl_getlock);
2543         return result;
2544 }
2545
2546 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2547                                 int leasetype)
2548 {
2549         int result = -1;
2550
2551         START_PROFILE(syscall_linux_setlease);
2552
2553 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2554         result = linux_setlease(fsp->fh->fd, leasetype);
2555 #else
2556         errno = ENOSYS;
2557 #endif
2558         END_PROFILE(syscall_linux_setlease);
2559         return result;
2560 }
2561
2562 static int vfswrap_symlink(vfs_handle_struct *handle,
2563                         const char *link_target,
2564                         const struct smb_filename *new_smb_fname)
2565 {
2566         int result;
2567
2568         START_PROFILE(syscall_symlink);
2569         result = symlink(link_target, new_smb_fname->base_name);
2570         END_PROFILE(syscall_symlink);
2571         return result;
2572 }
2573
2574 static int vfswrap_readlink(vfs_handle_struct *handle,
2575                         const struct smb_filename *smb_fname,
2576                         char *buf,
2577                         size_t bufsiz)
2578 {
2579         int result;
2580
2581         START_PROFILE(syscall_readlink);
2582         result = readlink(smb_fname->base_name, buf, bufsiz);
2583         END_PROFILE(syscall_readlink);
2584         return result;
2585 }
2586
2587 static int vfswrap_link(vfs_handle_struct *handle,
2588                         const struct smb_filename *old_smb_fname,
2589                         const struct smb_filename *new_smb_fname)
2590 {
2591         int result;
2592
2593         START_PROFILE(syscall_link);
2594         result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2595         END_PROFILE(syscall_link);
2596         return result;
2597 }
2598
2599 static int vfswrap_mknod(vfs_handle_struct *handle,
2600                         const struct smb_filename *smb_fname,
2601                         mode_t mode,
2602                         SMB_DEV_T dev)
2603 {
2604         int result;
2605
2606         START_PROFILE(syscall_mknod);
2607         result = sys_mknod(smb_fname->base_name, mode, dev);
2608         END_PROFILE(syscall_mknod);
2609         return result;
2610 }
2611
2612 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2613                         TALLOC_CTX *ctx,
2614                         const struct smb_filename *smb_fname)
2615 {
2616         char *result;
2617         struct smb_filename *result_fname = NULL;
2618
2619         START_PROFILE(syscall_realpath);
2620         result = sys_realpath(smb_fname->base_name);
2621         END_PROFILE(syscall_realpath);
2622         if (result) {
2623                 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2624                 SAFE_FREE(result);
2625         }
2626         return result_fname;
2627 }
2628
2629 static int vfswrap_chflags(vfs_handle_struct *handle,
2630                         const struct smb_filename *smb_fname,
2631                         unsigned int flags)
2632 {
2633 #ifdef HAVE_CHFLAGS
2634         return chflags(smb_fname->base_name, flags);
2635 #else
2636         errno = ENOSYS;
2637         return -1;
2638 #endif
2639 }
2640
2641 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2642                                              const SMB_STRUCT_STAT *sbuf)
2643 {
2644         struct file_id key;
2645
2646         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2647          * blob */
2648         ZERO_STRUCT(key);
2649
2650         key.devid = sbuf->st_ex_dev;
2651         key.inode = sbuf->st_ex_ino;
2652         /* key.extid is unused by default. */
2653
2654         return key;
2655 }
2656
2657 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2658                                    struct files_struct *fsp,
2659                                    const struct smb_filename *smb_fname,
2660                                    TALLOC_CTX *mem_ctx,
2661                                    unsigned int *pnum_streams,
2662                                    struct stream_struct **pstreams)
2663 {
2664         SMB_STRUCT_STAT sbuf;
2665         struct stream_struct *tmp_streams = NULL;
2666         int ret;
2667
2668         if ((fsp != NULL) && (fsp->is_directory)) {
2669                 /*
2670                  * No default streams on directories
2671                  */
2672                 goto done;
2673         }
2674
2675         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2676                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2677         }
2678         else {
2679                 struct smb_filename smb_fname_cp;
2680
2681                 ZERO_STRUCT(smb_fname_cp);
2682                 smb_fname_cp.base_name = discard_const_p(char,
2683                                         smb_fname->base_name);
2684                 smb_fname_cp.flags = smb_fname->flags;
2685
2686                 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2687                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2688                 } else {
2689                         ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2690                 }
2691                 sbuf = smb_fname_cp.st;
2692         }
2693
2694         if (ret == -1) {
2695                 return map_nt_error_from_unix(errno);
2696         }
2697
2698         if (S_ISDIR(sbuf.st_ex_mode)) {
2699                 goto done;
2700         }
2701
2702         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2703                                         (*pnum_streams) + 1);
2704         if (tmp_streams == NULL) {
2705                 return NT_STATUS_NO_MEMORY;
2706         }
2707         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2708         if (tmp_streams[*pnum_streams].name == NULL) {
2709                 return NT_STATUS_NO_MEMORY;
2710         }
2711         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2712         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2713
2714         *pnum_streams += 1;
2715         *pstreams = tmp_streams;
2716  done:
2717         return NT_STATUS_OK;
2718 }
2719
2720 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2721                                      const char *path,
2722                                      const char *name,
2723                                      TALLOC_CTX *mem_ctx,
2724                                      char **found_name)
2725 {
2726         /*
2727          * Don't fall back to get_real_filename so callers can differentiate
2728          * between a full directory scan and an actual case-insensitive stat.
2729          */
2730         errno = EOPNOTSUPP;
2731         return -1;
2732 }
2733
2734 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2735                                    const struct smb_filename *smb_fname)
2736 {
2737         return handle->conn->connectpath;
2738 }
2739
2740 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2741                                          struct byte_range_lock *br_lck,
2742                                          struct lock_struct *plock,
2743                                          bool blocking_lock)
2744 {
2745         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2746
2747         /* Note: blr is not used in the default implementation. */
2748         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2749 }
2750
2751 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2752                                        struct messaging_context *msg_ctx,
2753                                        struct byte_range_lock *br_lck,
2754                                        const struct lock_struct *plock)
2755 {
2756         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2757
2758         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2759 }
2760
2761 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2762                                        struct byte_range_lock *br_lck,
2763                                        struct lock_struct *plock)
2764 {
2765         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2766
2767         /* Note: blr is not used in the default implementation. */
2768         return brl_lock_cancel_default(br_lck, plock);
2769 }
2770
2771 static bool vfswrap_strict_lock_check(struct vfs_handle_struct *handle,
2772                                       files_struct *fsp,
2773                                       struct lock_struct *plock)
2774 {
2775         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2776             plock->lock_type == WRITE_LOCK);
2777
2778         return strict_lock_check_default(fsp, plock);
2779 }
2780
2781 /* NT ACL operations. */
2782
2783 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2784                                     files_struct *fsp,
2785                                     uint32_t security_info,
2786                                     TALLOC_CTX *mem_ctx,
2787                                     struct security_descriptor **ppdesc)
2788 {
2789         NTSTATUS result;
2790
2791         START_PROFILE(fget_nt_acl);
2792         result = posix_fget_nt_acl(fsp, security_info,
2793                                    mem_ctx, ppdesc);
2794         END_PROFILE(fget_nt_acl);
2795         return result;
2796 }
2797
2798 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2799                                    const struct smb_filename *smb_fname,
2800                                    uint32_t security_info,
2801                                    TALLOC_CTX *mem_ctx,
2802                                    struct security_descriptor **ppdesc)
2803 {
2804         NTSTATUS result;
2805
2806         START_PROFILE(get_nt_acl);
2807         result = posix_get_nt_acl(handle->conn,
2808                                 smb_fname,
2809                                 security_info,
2810                                 mem_ctx,
2811                                 ppdesc);
2812         END_PROFILE(get_nt_acl);
2813         return result;
2814 }
2815
2816 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2817 {
2818         NTSTATUS result;
2819
2820         START_PROFILE(fset_nt_acl);
2821         result = set_nt_acl(fsp, security_info_sent, psd);
2822         END_PROFILE(fset_nt_acl);
2823         return result;
2824 }
2825
2826 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2827                                    struct smb_filename *file,
2828                                    struct security_acl *sacl,
2829                                    uint32_t access_requested,
2830                                    uint32_t access_denied)
2831 {
2832         return NT_STATUS_OK; /* Nothing to do here ... */
2833 }
2834
2835 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2836                                 const struct smb_filename *smb_fname,
2837                                 mode_t mode)
2838 {
2839 #ifdef HAVE_NO_ACL
2840         errno = ENOSYS;
2841         return -1;
2842 #else
2843         int result;
2844
2845         START_PROFILE(chmod_acl);
2846         result = chmod_acl(handle->conn, smb_fname, mode);
2847         END_PROFILE(chmod_acl);
2848         return result;
2849 #endif
2850 }
2851
2852 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2853 {
2854 #ifdef HAVE_NO_ACL
2855         errno = ENOSYS;
2856         return -1;
2857 #else
2858         int result;
2859
2860         START_PROFILE(fchmod_acl);
2861         result = fchmod_acl(fsp, mode);
2862         END_PROFILE(fchmod_acl);
2863         return result;
2864 #endif
2865 }
2866
2867 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2868                                           const struct smb_filename *smb_fname,
2869                                           SMB_ACL_TYPE_T type,
2870                                           TALLOC_CTX *mem_ctx)
2871 {
2872         return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2873 }
2874
2875 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2876                                         files_struct *fsp,
2877                                         TALLOC_CTX *mem_ctx)
2878 {
2879         return sys_acl_get_fd(handle, fsp, mem_ctx);
2880 }
2881
2882 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2883                                 const struct smb_filename *smb_fname,
2884                                 SMB_ACL_TYPE_T acltype,
2885                                 SMB_ACL_T theacl)
2886 {
2887         return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2888 }
2889
2890 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2891 {
2892         return sys_acl_set_fd(handle, fsp, theacl);
2893 }
2894
2895 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2896                         const struct smb_filename *smb_fname)
2897 {
2898         return sys_acl_delete_def_file(handle, smb_fname);
2899 }
2900
2901 /****************************************************************
2902  Extended attribute operations.
2903 *****************************************************************/
2904
2905 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2906                         const struct smb_filename *smb_fname,
2907                         const char *name,
2908                         void *value,
2909                         size_t size)
2910 {
2911         return getxattr(smb_fname->base_name, name, value, size);
2912 }
2913
2914 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2915 {
2916         return fgetxattr(fsp->fh->fd, name, value, size);
2917 }
2918
2919 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2920                         const struct smb_filename *smb_fname,
2921                         char *list,
2922                         size_t size)
2923 {
2924         return listxattr(smb_fname->base_name, list, size);
2925 }
2926
2927 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2928 {
2929         return flistxattr(fsp->fh->fd, list, size);
2930 }
2931
2932 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2933                                 const struct smb_filename *smb_fname,
2934                                 const char *name)
2935 {
2936         return removexattr(smb_fname->base_name, name);
2937 }
2938
2939 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2940 {
2941         return fremovexattr(fsp->fh->fd, name);
2942 }
2943
2944 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2945                                 const struct smb_filename *smb_fname,
2946                                 const char *name,
2947                                 const void *value,
2948                                 size_t size,
2949                                 int flags)
2950 {
2951         return setxattr(smb_fname->base_name, name, value, size, flags);
2952 }
2953
2954 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2955 {
2956         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2957 }
2958
2959 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2960 {
2961         return false;
2962 }
2963
2964 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2965                                const struct smb_filename *fname,
2966                                SMB_STRUCT_STAT *sbuf)
2967 {
2968         NTSTATUS status;
2969         char *path;
2970         bool offline = false;
2971
2972         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2973                 return false;
2974         }
2975
2976         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2977 #if defined(ENOTSUP)
2978                 errno = ENOTSUP;
2979 #endif
2980                 return false;
2981         }
2982
2983         status = get_full_smb_filename(talloc_tos(), fname, &path);
2984         if (!NT_STATUS_IS_OK(status)) {
2985                 errno = map_errno_from_nt_status(status);
2986                 return false;
2987         }
2988
2989         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2990
2991         TALLOC_FREE(path);
2992
2993         return offline;
2994 }
2995
2996 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2997                                        struct files_struct *fsp,
2998                                        TALLOC_CTX *mem_ctx,
2999                                        DATA_BLOB *cookie)
3000 {
3001         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
3002 }
3003
3004 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
3005                                            struct files_struct *fsp,
3006                                            const DATA_BLOB old_cookie,
3007                                            TALLOC_CTX *mem_ctx,
3008                                            DATA_BLOB *new_cookie)
3009 {
3010         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3011                                               new_cookie);
3012 }
3013
3014 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3015                                           struct smb_request *smb1req,
3016                                           struct smbXsrv_open *op,
3017                                           const DATA_BLOB old_cookie,
3018                                           TALLOC_CTX *mem_ctx,
3019                                           struct files_struct **fsp,
3020                                           DATA_BLOB *new_cookie)
3021 {
3022         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3023                                              old_cookie, mem_ctx,
3024                                              fsp, new_cookie);
3025 }
3026
3027 static struct vfs_fn_pointers vfs_default_fns = {
3028         /* Disk operations */
3029
3030         .connect_fn = vfswrap_connect,
3031         .disconnect_fn = vfswrap_disconnect,
3032         .disk_free_fn = vfswrap_disk_free,
3033         .get_quota_fn = vfswrap_get_quota,
3034         .set_quota_fn = vfswrap_set_quota,
3035         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3036         .statvfs_fn = vfswrap_statvfs,
3037         .fs_capabilities_fn = vfswrap_fs_capabilities,
3038         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3039         .snap_check_path_fn = vfswrap_snap_check_path,
3040         .snap_create_fn = vfswrap_snap_create,
3041         .snap_delete_fn = vfswrap_snap_delete,
3042
3043         /* Directory operations */
3044
3045         .opendir_fn = vfswrap_opendir,
3046         .fdopendir_fn = vfswrap_fdopendir,
3047         .readdir_fn = vfswrap_readdir,
3048         .readdir_attr_fn = vfswrap_readdir_attr,
3049         .seekdir_fn = vfswrap_seekdir,
3050         .telldir_fn = vfswrap_telldir,
3051         .rewind_dir_fn = vfswrap_rewinddir,
3052         .mkdir_fn = vfswrap_mkdir,
3053         .rmdir_fn = vfswrap_rmdir,
3054         .closedir_fn = vfswrap_closedir,
3055         .init_search_op_fn = vfswrap_init_search_op,
3056
3057         /* File operations */
3058
3059         .open_fn = vfswrap_open,
3060         .create_file_fn = vfswrap_create_file,
3061         .close_fn = vfswrap_close,
3062         .read_fn = vfswrap_read,
3063         .pread_fn = vfswrap_pread,
3064         .pread_send_fn = vfswrap_pread_send,
3065         .pread_recv_fn = vfswrap_pread_recv,
3066         .write_fn = vfswrap_write,
3067         .pwrite_fn = vfswrap_pwrite,
3068         .pwrite_send_fn = vfswrap_pwrite_send,