s3/smbd: remove unneeded flags argument from SMB_VFS_OFFLOAD_WRITE_SEND
[kai/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 err;
742         int fd;
743         void *buf;
744         size_t count;
745         off_t offset;
746
747         struct vfs_aio_state vfs_aio_state;
748         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
749 };
750
751 static void vfs_pread_do(void *private_data);
752 static void vfs_pread_done(struct tevent_req *subreq);
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         return req;
794 }
795
796 static void vfs_pread_do(void *private_data)
797 {
798         struct vfswrap_pread_state *state = talloc_get_type_abort(
799                 private_data, struct vfswrap_pread_state);
800         struct timespec start_time;
801         struct timespec end_time;
802
803         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
804
805         PROFILE_TIMESTAMP(&start_time);
806
807         do {
808                 state->ret = pread(state->fd, state->buf, state->count,
809                                    state->offset);
810         } while ((state->ret == -1) && (errno == EINTR));
811
812         state->err = errno;
813
814         PROFILE_TIMESTAMP(&end_time);
815
816         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
817
818         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
819 }
820
821 static void vfs_pread_done(struct tevent_req *subreq)
822 {
823         struct tevent_req *req = tevent_req_callback_data(
824                 subreq, struct tevent_req);
825 #ifdef WITH_PROFILE
826         struct vfswrap_pread_state *state = tevent_req_data(
827                 req, struct vfswrap_pread_state);
828 #endif
829         int ret;
830
831         ret = pthreadpool_tevent_job_recv(subreq);
832         TALLOC_FREE(subreq);
833         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
834         if (tevent_req_error(req, ret)) {
835                 return;
836         }
837
838         tevent_req_done(req);
839 }
840
841 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
842                                   struct vfs_aio_state *vfs_aio_state)
843 {
844         struct vfswrap_pread_state *state = tevent_req_data(
845                 req, struct vfswrap_pread_state);
846
847         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
848                 return -1;
849         }
850
851         *vfs_aio_state = state->vfs_aio_state;
852         return state->ret;
853 }
854
855 struct vfswrap_pwrite_state {
856         ssize_t ret;
857         int err;
858         int fd;
859         const void *buf;
860         size_t count;
861         off_t offset;
862
863         struct vfs_aio_state vfs_aio_state;
864         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
865 };
866
867 static void vfs_pwrite_do(void *private_data);
868 static void vfs_pwrite_done(struct tevent_req *subreq);
869
870 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
871                                               TALLOC_CTX *mem_ctx,
872                                               struct tevent_context *ev,
873                                               struct files_struct *fsp,
874                                               const void *data,
875                                               size_t n, off_t offset)
876 {
877         struct tevent_req *req, *subreq;
878         struct vfswrap_pwrite_state *state;
879         int ret;
880
881         req = tevent_req_create(mem_ctx, &state, struct vfswrap_pwrite_state);
882         if (req == NULL) {
883                 return NULL;
884         }
885
886         ret = vfswrap_init_pool(handle->conn->sconn);
887         if (tevent_req_error(req, ret)) {
888                 return tevent_req_post(req, ev);
889         }
890
891         state->ret = -1;
892         state->fd = fsp->fh->fd;
893         state->buf = data;
894         state->count = n;
895         state->offset = offset;
896
897         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
898                                      state->profile_bytes, n);
899         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
900
901         subreq = pthreadpool_tevent_job_send(
902                 state, ev, handle->conn->sconn->pool,
903                 vfs_pwrite_do, state);
904         if (tevent_req_nomem(subreq, req)) {
905                 return tevent_req_post(req, ev);
906         }
907         tevent_req_set_callback(subreq, vfs_pwrite_done, req);
908
909         return req;
910 }
911
912 static void vfs_pwrite_do(void *private_data)
913 {
914         struct vfswrap_pwrite_state *state = talloc_get_type_abort(
915                 private_data, struct vfswrap_pwrite_state);
916         struct timespec start_time;
917         struct timespec end_time;
918
919         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
920
921         PROFILE_TIMESTAMP(&start_time);
922
923         do {
924                 state->ret = pwrite(state->fd, state->buf, state->count,
925                                    state->offset);
926         } while ((state->ret == -1) && (errno == EINTR));
927
928         state->err = errno;
929
930         PROFILE_TIMESTAMP(&end_time);
931
932         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
933
934         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
935 }
936
937 static void vfs_pwrite_done(struct tevent_req *subreq)
938 {
939         struct tevent_req *req = tevent_req_callback_data(
940                 subreq, struct tevent_req);
941 #ifdef WITH_PROFILE
942         struct vfswrap_pwrite_state *state = tevent_req_data(
943                 req, struct vfswrap_pwrite_state);
944 #endif
945         int ret;
946
947         ret = pthreadpool_tevent_job_recv(subreq);
948         TALLOC_FREE(subreq);
949         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
950         if (tevent_req_error(req, ret)) {
951                 return;
952         }
953
954         tevent_req_done(req);
955 }
956
957 static ssize_t vfswrap_pwrite_recv(struct tevent_req *req,
958                                    struct vfs_aio_state *vfs_aio_state)
959 {
960         struct vfswrap_pwrite_state *state = tevent_req_data(
961                 req, struct vfswrap_pwrite_state);
962
963         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
964                 return -1;
965         }
966
967         *vfs_aio_state = state->vfs_aio_state;
968         return state->ret;
969 }
970
971 struct vfswrap_fsync_state {
972         ssize_t ret;
973         int err;
974         int fd;
975
976         struct vfs_aio_state vfs_aio_state;
977         SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
978 };
979
980 static void vfs_fsync_do(void *private_data);
981 static void vfs_fsync_done(struct tevent_req *subreq);
982
983 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
984                                              TALLOC_CTX *mem_ctx,
985                                              struct tevent_context *ev,
986                                              struct files_struct *fsp)
987 {
988         struct tevent_req *req, *subreq;
989         struct vfswrap_fsync_state *state;
990         int ret;
991
992         req = tevent_req_create(mem_ctx, &state, struct vfswrap_fsync_state);
993         if (req == NULL) {
994                 return NULL;
995         }
996
997         ret = vfswrap_init_pool(handle->conn->sconn);
998         if (tevent_req_error(req, ret)) {
999                 return tevent_req_post(req, ev);
1000         }
1001
1002         state->ret = -1;
1003         state->fd = fsp->fh->fd;
1004
1005         SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
1006                                      state->profile_basic);
1007
1008         subreq = pthreadpool_tevent_job_send(
1009                 state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
1010         if (tevent_req_nomem(subreq, req)) {
1011                 return tevent_req_post(req, ev);
1012         }
1013         tevent_req_set_callback(subreq, vfs_fsync_done, req);
1014
1015         return req;
1016 }
1017
1018 static void vfs_fsync_do(void *private_data)
1019 {
1020         struct vfswrap_fsync_state *state = talloc_get_type_abort(
1021                 private_data, struct vfswrap_fsync_state);
1022         struct timespec start_time;
1023         struct timespec end_time;
1024
1025         PROFILE_TIMESTAMP(&start_time);
1026
1027         do {
1028                 state->ret = fsync(state->fd);
1029         } while ((state->ret == -1) && (errno == EINTR));
1030
1031         state->err = errno;
1032
1033         PROFILE_TIMESTAMP(&end_time);
1034
1035         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
1036 }
1037
1038 static void vfs_fsync_done(struct tevent_req *subreq)
1039 {
1040         struct tevent_req *req = tevent_req_callback_data(
1041                 subreq, struct tevent_req);
1042 #ifdef WITH_PROFILE
1043         struct vfswrap_fsync_state *state = tevent_req_data(
1044                 req, struct vfswrap_fsync_state);
1045 #endif
1046         int ret;
1047
1048         ret = pthreadpool_tevent_job_recv(subreq);
1049         TALLOC_FREE(subreq);
1050         SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
1051         if (tevent_req_error(req, ret)) {
1052                 return;
1053         }
1054
1055         tevent_req_done(req);
1056 }
1057
1058 static int vfswrap_fsync_recv(struct tevent_req *req,
1059                               struct vfs_aio_state *vfs_aio_state)
1060 {
1061         struct vfswrap_fsync_state *state = tevent_req_data(
1062                 req, struct vfswrap_fsync_state);
1063
1064         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1065                 return -1;
1066         }
1067
1068         *vfs_aio_state = state->vfs_aio_state;
1069         return state->ret;
1070 }
1071
1072 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1073 {
1074         off_t result = 0;
1075
1076         START_PROFILE(syscall_lseek);
1077
1078         /* Cope with 'stat' file opens. */
1079         if (fsp->fh->fd != -1)
1080                 result = lseek(fsp->fh->fd, offset, whence);
1081
1082         /*
1083          * We want to maintain the fiction that we can seek
1084          * on a fifo for file system purposes. This allows
1085          * people to set up UNIX fifo's that feed data to Windows
1086          * applications. JRA.
1087          */
1088
1089         if((result == -1) && (errno == ESPIPE)) {
1090                 result = 0;
1091                 errno = 0;
1092         }
1093
1094         END_PROFILE(syscall_lseek);
1095         return result;
1096 }
1097
1098 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1099                         off_t offset, size_t n)
1100 {
1101         ssize_t result;
1102
1103         START_PROFILE_BYTES(syscall_sendfile, n);
1104         result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1105         END_PROFILE_BYTES(syscall_sendfile);
1106         return result;
1107 }
1108
1109 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1110                         int fromfd,
1111                         files_struct *tofsp,
1112                         off_t offset,
1113                         size_t n)
1114 {
1115         ssize_t result;
1116
1117         START_PROFILE_BYTES(syscall_recvfile, n);
1118         result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1119         END_PROFILE_BYTES(syscall_recvfile);
1120         return result;
1121 }
1122
1123 static int vfswrap_rename(vfs_handle_struct *handle,
1124                           const struct smb_filename *smb_fname_src,
1125                           const struct smb_filename *smb_fname_dst)
1126 {
1127         int result = -1;
1128
1129         START_PROFILE(syscall_rename);
1130
1131         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1132                 errno = ENOENT;
1133                 goto out;
1134         }
1135
1136         result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1137
1138  out:
1139         END_PROFILE(syscall_rename);
1140         return result;
1141 }
1142
1143 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1144 {
1145 #ifdef HAVE_FSYNC
1146         int result;
1147
1148         START_PROFILE(syscall_fsync);
1149         result = fsync(fsp->fh->fd);
1150         END_PROFILE(syscall_fsync);
1151         return result;
1152 #else
1153         return 0;
1154 #endif
1155 }
1156
1157 static int vfswrap_stat(vfs_handle_struct *handle,
1158                         struct smb_filename *smb_fname)
1159 {
1160         int result = -1;
1161
1162         START_PROFILE(syscall_stat);
1163
1164         if (smb_fname->stream_name) {
1165                 errno = ENOENT;
1166                 goto out;
1167         }
1168
1169         result = sys_stat(smb_fname->base_name, &smb_fname->st,
1170                           lp_fake_directory_create_times(SNUM(handle->conn)));
1171  out:
1172         END_PROFILE(syscall_stat);
1173         return result;
1174 }
1175
1176 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1177 {
1178         int result;
1179
1180         START_PROFILE(syscall_fstat);
1181         result = sys_fstat(fsp->fh->fd,
1182                            sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1183         END_PROFILE(syscall_fstat);
1184         return result;
1185 }
1186
1187 static int vfswrap_lstat(vfs_handle_struct *handle,
1188                          struct smb_filename *smb_fname)
1189 {
1190         int result = -1;
1191
1192         START_PROFILE(syscall_lstat);
1193
1194         if (smb_fname->stream_name) {
1195                 errno = ENOENT;
1196                 goto out;
1197         }
1198
1199         result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1200                            lp_fake_directory_create_times(SNUM(handle->conn)));
1201  out:
1202         END_PROFILE(syscall_lstat);
1203         return result;
1204 }
1205
1206 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1207                                        const char *name,
1208                                        enum vfs_translate_direction direction,
1209                                        TALLOC_CTX *mem_ctx,
1210                                        char **mapped_name)
1211 {
1212         return NT_STATUS_NONE_MAPPED;
1213 }
1214
1215 /*
1216  * Implement the default fsctl operation.
1217  */
1218 static bool vfswrap_logged_ioctl_message = false;
1219
1220 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1221                               struct files_struct *fsp,
1222                               TALLOC_CTX *ctx,
1223                               uint32_t function,
1224                               uint16_t req_flags, /* Needed for UNICODE ... */
1225                               const uint8_t *_in_data,
1226                               uint32_t in_len,
1227                               uint8_t **_out_data,
1228                               uint32_t max_out_len,
1229                               uint32_t *out_len)
1230 {
1231         const char *in_data = (const char *)_in_data;
1232         char **out_data = (char **)_out_data;
1233         NTSTATUS status;
1234
1235         switch (function) {
1236         case FSCTL_SET_SPARSE:
1237         {
1238                 bool set_sparse = true;
1239
1240                 if (in_len >= 1 && in_data[0] == 0) {
1241                         set_sparse = false;
1242                 }
1243
1244                 status = file_set_sparse(handle->conn, fsp, set_sparse);
1245
1246                 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1247                       ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1248                        smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1249                        nt_errstr(status)));
1250
1251                 return status;
1252         }
1253
1254         case FSCTL_CREATE_OR_GET_OBJECT_ID:
1255         {
1256                 unsigned char objid[16];
1257                 char *return_data = NULL;
1258
1259                 /* This should return the object-id on this file.
1260                  * I think I'll make this be the inode+dev. JRA.
1261                  */
1262
1263                 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1264                           fsp_fnum_dbg(fsp)));
1265
1266                 *out_len = MIN(max_out_len, 64);
1267
1268                 /* Hmmm, will this cause problems if less data asked for? */
1269                 return_data = talloc_array(ctx, char, 64);
1270                 if (return_data == NULL) {
1271                         return NT_STATUS_NO_MEMORY;
1272                 }
1273
1274                 /* For backwards compatibility only store the dev/inode. */
1275                 push_file_id_16(return_data, &fsp->file_id);
1276                 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1277                 push_file_id_16(return_data+32, &fsp->file_id);
1278                 memset(return_data+48, 0, 16);
1279                 *out_data = return_data;
1280                 return NT_STATUS_OK;
1281         }
1282
1283         case FSCTL_GET_REPARSE_POINT:
1284         {
1285                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1286                 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1287                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1288                 return NT_STATUS_NOT_A_REPARSE_POINT;
1289         }
1290
1291         case FSCTL_SET_REPARSE_POINT:
1292         {
1293                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1294                 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1295                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1296                 return NT_STATUS_NOT_A_REPARSE_POINT;
1297         }
1298
1299         case FSCTL_GET_SHADOW_COPY_DATA:
1300         {
1301                 /*
1302                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1303                  * and return their volume names.  If max_data_count is 16, then it is just
1304                  * asking for the number of volumes and length of the combined names.
1305                  *
1306                  * pdata is the data allocated by our caller, but that uses
1307                  * total_data_count (which is 0 in our case) rather than max_data_count.
1308                  * Allocate the correct amount and return the pointer to let
1309                  * it be deallocated when we return.
1310                  */
1311                 struct shadow_copy_data *shadow_data = NULL;
1312                 bool labels = False;
1313                 uint32_t labels_data_count = 0;
1314                 uint32_t i;
1315                 char *cur_pdata = NULL;
1316
1317                 if (max_out_len < 16) {
1318                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1319                                 max_out_len));
1320                         return NT_STATUS_INVALID_PARAMETER;
1321                 }
1322
1323                 if (max_out_len > 16) {
1324                         labels = True;
1325                 }
1326
1327                 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1328                 if (shadow_data == NULL) {
1329                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
1330                         return NT_STATUS_NO_MEMORY;
1331                 }
1332
1333                 /*
1334                  * Call the VFS routine to actually do the work.
1335                  */
1336                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1337                         int log_lev = 0;
1338                         if (errno == 0) {
1339                                 /* broken module didn't set errno on error */
1340                                 status = NT_STATUS_UNSUCCESSFUL;
1341                         } else {
1342                                 status = map_nt_error_from_unix(errno);
1343                                 if (NT_STATUS_EQUAL(status,
1344                                                     NT_STATUS_NOT_SUPPORTED)) {
1345                                         log_lev = 5;
1346                                 }
1347                         }
1348                         DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1349                                         "connectpath %s, failed - %s.\n",
1350                                         fsp->conn->connectpath,
1351                                         nt_errstr(status)));
1352                         TALLOC_FREE(shadow_data);
1353                         return status;
1354                 }
1355
1356                 labels_data_count = (shadow_data->num_volumes * 2 *
1357                                         sizeof(SHADOW_COPY_LABEL)) + 2;
1358
1359                 if (!labels) {
1360                         *out_len = 16;
1361                 } else {
1362                         *out_len = 12 + labels_data_count;
1363                 }
1364
1365                 if (max_out_len < *out_len) {
1366                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1367                                 max_out_len, *out_len));
1368                         TALLOC_FREE(shadow_data);
1369                         return NT_STATUS_BUFFER_TOO_SMALL;
1370                 }
1371
1372                 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1373                 if (cur_pdata == NULL) {
1374                         TALLOC_FREE(shadow_data);
1375                         return NT_STATUS_NO_MEMORY;
1376                 }
1377
1378                 *out_data = cur_pdata;
1379
1380                 /* num_volumes 4 bytes */
1381                 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1382
1383                 if (labels) {
1384                         /* num_labels 4 bytes */
1385                         SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1386                 }
1387
1388                 /* needed_data_count 4 bytes */
1389                 SIVAL(cur_pdata, 8, labels_data_count);
1390
1391                 cur_pdata += 12;
1392
1393                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1394                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
1395                 if (labels && shadow_data->labels) {
1396                         for (i=0; i<shadow_data->num_volumes; i++) {
1397                                 size_t len = 0;
1398                                 status = srvstr_push(cur_pdata, req_flags,
1399                                             cur_pdata, shadow_data->labels[i],
1400                                             2 * sizeof(SHADOW_COPY_LABEL),
1401                                             STR_UNICODE|STR_TERMINATE, &len);
1402                                 if (!NT_STATUS_IS_OK(status)) {
1403                                         TALLOC_FREE(*out_data);
1404                                         TALLOC_FREE(shadow_data);
1405                                         return status;
1406                                 }
1407                                 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1408                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1409                         }
1410                 }
1411
1412                 TALLOC_FREE(shadow_data);
1413
1414                 return NT_STATUS_OK;
1415         }
1416
1417         case FSCTL_FIND_FILES_BY_SID:
1418         {
1419                 /* pretend this succeeded -
1420                  *
1421                  * we have to send back a list with all files owned by this SID
1422                  *
1423                  * but I have to check that --metze
1424                  */
1425                 struct dom_sid sid;
1426                 uid_t uid;
1427                 size_t sid_len;
1428
1429                 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1430                            fsp_fnum_dbg(fsp)));
1431
1432                 if (in_len < 8) {
1433                         /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1434                         return NT_STATUS_INVALID_PARAMETER;
1435                 }
1436
1437                 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1438
1439                 /* unknown 4 bytes: this is not the length of the sid :-(  */
1440                 /*unknown = IVAL(pdata,0);*/
1441
1442                 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1443                         return NT_STATUS_INVALID_PARAMETER;
1444                 }
1445                 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1446
1447                 if (!sid_to_uid(&sid, &uid)) {
1448                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1449                                  sid_string_dbg(&sid),
1450                                  (unsigned long)sid_len));
1451                         uid = (-1);
1452                 }
1453
1454                 /* we can take a look at the find source :-)
1455                  *
1456                  * find ./ -uid $uid  -name '*'   is what we need here
1457                  *
1458                  *
1459                  * and send 4bytes len and then NULL terminated unicode strings
1460                  * for each file
1461                  *
1462                  * but I don't know how to deal with the paged results
1463                  * (maybe we can hang the result anywhere in the fsp struct)
1464                  *
1465                  * but I don't know how to deal with the paged results
1466                  * (maybe we can hang the result anywhere in the fsp struct)
1467                  *
1468                  * we don't send all files at once
1469                  * and at the next we should *not* start from the beginning,
1470                  * so we have to cache the result
1471                  *
1472                  * --metze
1473                  */
1474
1475                 /* this works for now... */
1476                 return NT_STATUS_OK;
1477         }
1478
1479         case FSCTL_QUERY_ALLOCATED_RANGES:
1480         {
1481                 /* FIXME: This is just a dummy reply, telling that all of the
1482                  * file is allocated. MKS cp needs that.
1483                  * Adding the real allocated ranges via FIEMAP on Linux
1484                  * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1485                  * this FSCTL correct for sparse files.
1486                  */
1487                 uint64_t offset, length;
1488                 char *out_data_tmp = NULL;
1489
1490                 if (in_len != 16) {
1491                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1492                                 in_len));
1493                         return NT_STATUS_INVALID_PARAMETER;
1494                 }
1495
1496                 if (max_out_len < 16) {
1497                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1498                                 max_out_len));
1499                         return NT_STATUS_INVALID_PARAMETER;
1500                 }
1501
1502                 offset = BVAL(in_data,0);
1503                 length = BVAL(in_data,8);
1504
1505                 if (offset + length < offset) {
1506                         /* No 64-bit integer wrap. */
1507                         return NT_STATUS_INVALID_PARAMETER;
1508                 }
1509
1510                 /* Shouldn't this be SMB_VFS_STAT ... ? */
1511                 status = vfs_stat_fsp(fsp);
1512                 if (!NT_STATUS_IS_OK(status)) {
1513                         return status;
1514                 }
1515
1516                 *out_len = 16;
1517                 out_data_tmp = talloc_array(ctx, char, *out_len);
1518                 if (out_data_tmp == NULL) {
1519                         DEBUG(10, ("unable to allocate memory for response\n"));
1520                         return NT_STATUS_NO_MEMORY;
1521                 }
1522
1523                 if (offset > fsp->fsp_name->st.st_ex_size ||
1524                                 fsp->fsp_name->st.st_ex_size == 0 ||
1525                                 length == 0) {
1526                         memset(out_data_tmp, 0, *out_len);
1527                 } else {
1528                         uint64_t end = offset + length;
1529                         end = MIN(end, fsp->fsp_name->st.st_ex_size);
1530                         SBVAL(out_data_tmp, 0, 0);
1531                         SBVAL(out_data_tmp, 8, end);
1532                 }
1533
1534                 *out_data = out_data_tmp;
1535
1536                 return NT_STATUS_OK;
1537         }
1538
1539         case FSCTL_IS_VOLUME_DIRTY:
1540         {
1541                 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1542                           "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1543                 /*
1544                  * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1545                  * says we have to respond with NT_STATUS_INVALID_PARAMETER
1546                  */
1547                 return NT_STATUS_INVALID_PARAMETER;
1548         }
1549
1550         default:
1551                 /*
1552                  * Only print once ... unfortunately there could be lots of
1553                  * different FSCTLs that are called.
1554                  */
1555                 if (!vfswrap_logged_ioctl_message) {
1556                         vfswrap_logged_ioctl_message = true;
1557                         DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1558                         __func__, function));
1559                 }
1560         }
1561
1562         return NT_STATUS_NOT_SUPPORTED;
1563 }
1564
1565 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
1566                                const struct smb_filename *fname,
1567                                SMB_STRUCT_STAT *sbuf);
1568
1569 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1570                                            struct smb_filename *smb_fname,
1571                                            uint32_t *dosmode)
1572 {
1573         bool offline;
1574
1575         offline = vfswrap_is_offline(handle, smb_fname, &smb_fname->st);
1576         if (offline) {
1577                 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1578         }
1579
1580         return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1581 }
1582
1583 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1584                                             struct files_struct *fsp,
1585                                             uint32_t *dosmode)
1586 {
1587         bool offline;
1588
1589         offline = vfswrap_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1590         if (offline) {
1591                 *dosmode |= FILE_ATTRIBUTE_OFFLINE;
1592         }
1593
1594         return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1595 }
1596
1597 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1598                                            const struct smb_filename *smb_fname,
1599                                            uint32_t dosmode)
1600 {
1601         return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1602 }
1603
1604 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1605                                             struct files_struct *fsp,
1606                                             uint32_t dosmode)
1607 {
1608         return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1609 }
1610
1611 static struct vfs_offload_ctx *vfswrap_offload_ctx;
1612
1613 struct vfswrap_offload_read_state {
1614         DATA_BLOB token;
1615 };
1616
1617 static struct tevent_req *vfswrap_offload_read_send(
1618         TALLOC_CTX *mem_ctx,
1619         struct tevent_context *ev,
1620         struct vfs_handle_struct *handle,
1621         struct files_struct *fsp,
1622         uint32_t fsctl,
1623         uint32_t ttl,
1624         off_t offset,
1625         size_t to_copy)
1626 {
1627         struct tevent_req *req = NULL;
1628         struct vfswrap_offload_read_state *state = NULL;
1629         NTSTATUS status;
1630
1631         req = tevent_req_create(mem_ctx, &state,
1632                                 struct vfswrap_offload_read_state);
1633         if (req == NULL) {
1634                 return NULL;
1635         }
1636
1637         status = vfs_offload_token_ctx_init(fsp->conn->sconn->client,
1638                                             &vfswrap_offload_ctx);
1639         if (tevent_req_nterror(req, status)) {
1640                 return tevent_req_post(req, ev);
1641         }
1642
1643         if (fsctl != FSCTL_SRV_REQUEST_RESUME_KEY) {
1644                 tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
1645                 return tevent_req_post(req, ev);
1646         }
1647
1648         status = vfs_offload_token_create_blob(state, fsp, fsctl,
1649                                                &state->token);
1650         if (tevent_req_nterror(req, status)) {
1651                 return tevent_req_post(req, ev);
1652         }
1653
1654         status = vfs_offload_token_db_store_fsp(vfswrap_offload_ctx, fsp,
1655                                                 &state->token);
1656         if (tevent_req_nterror(req, status)) {
1657                 return tevent_req_post(req, ev);
1658         }
1659
1660         tevent_req_done(req);
1661         return tevent_req_post(req, ev);
1662 }
1663
1664 static NTSTATUS vfswrap_offload_read_recv(struct tevent_req *req,
1665                                           struct vfs_handle_struct *handle,
1666                                           TALLOC_CTX *mem_ctx,
1667                                           DATA_BLOB *token)
1668 {
1669         struct vfswrap_offload_read_state *state = tevent_req_data(
1670                 req, struct vfswrap_offload_read_state);
1671         NTSTATUS status;
1672
1673         if (tevent_req_is_nterror(req, &status)) {
1674                 tevent_req_received(req);
1675                 return status;
1676         }
1677
1678         token->length = state->token.length;
1679         token->data = talloc_move(mem_ctx, &state->token.data);
1680
1681         tevent_req_received(req);
1682         return NT_STATUS_OK;
1683 }
1684
1685 struct vfswrap_offload_write_state {
1686         struct tevent_context *ev;
1687         uint8_t *buf;
1688         bool read_lck_locked;
1689         struct lock_struct read_lck;
1690         bool write_lck_locked;
1691         struct lock_struct write_lck;
1692         DATA_BLOB *token;
1693         struct files_struct *src_fsp;
1694         off_t src_off;
1695         struct files_struct *dst_fsp;
1696         off_t dst_off;
1697         off_t to_copy;
1698         off_t remaining;
1699         size_t next_io_size;
1700 };
1701
1702 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req);
1703
1704 static struct tevent_req *vfswrap_offload_write_send(
1705         struct vfs_handle_struct *handle,
1706         TALLOC_CTX *mem_ctx,
1707         struct tevent_context *ev,
1708         uint32_t fsctl,
1709         DATA_BLOB *token,
1710         off_t transfer_offset,
1711         struct files_struct *dest_fsp,
1712         off_t dest_off,
1713         off_t to_copy)
1714 {
1715         struct tevent_req *req;
1716         struct vfswrap_offload_write_state *state = NULL;
1717         size_t num = MIN(to_copy, COPYCHUNK_MAX_TOTAL_LEN);
1718         files_struct *src_fsp = NULL;
1719         NTSTATUS status;
1720
1721         req = tevent_req_create(mem_ctx, &state,
1722                                 struct vfswrap_offload_write_state);
1723         if (req == NULL) {
1724                 return NULL;
1725         }
1726
1727         *state = (struct vfswrap_offload_write_state) {
1728                 .ev = ev,
1729                 .token = token,
1730                 .src_off = transfer_offset,
1731                 .dst_fsp = dest_fsp,
1732                 .dst_off = dest_off,
1733                 .to_copy = to_copy,
1734                 .remaining = to_copy,
1735         };
1736
1737         switch (fsctl) {
1738         case FSCTL_SRV_COPYCHUNK:
1739         case FSCTL_SRV_COPYCHUNK_WRITE:
1740                 break;
1741
1742         case FSCTL_OFFLOAD_WRITE:
1743                 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1744                 return tevent_req_post(req, ev);
1745
1746         case FSCTL_DUP_EXTENTS_TO_FILE:
1747                 DBG_DEBUG("COW clones not supported by vfs_default\n");
1748                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1749                 return tevent_req_post(req, ev);
1750
1751         default:
1752                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1753                 return tevent_req_post(req, ev);
1754         }
1755
1756         /*
1757          * From here on we assume a copy-chunk fsctl
1758          */
1759
1760         if (to_copy == 0) {
1761                 tevent_req_done(req);
1762                 return tevent_req_post(req, ev);
1763         }
1764
1765         status = vfs_offload_token_db_fetch_fsp(vfswrap_offload_ctx,
1766                                                 token, &src_fsp);
1767         if (tevent_req_nterror(req, status)) {
1768                 return tevent_req_post(req, ev);
1769         }
1770         state->src_fsp = src_fsp;
1771
1772         DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1773
1774         status = vfs_offload_token_check_handles(fsctl, src_fsp, dest_fsp);
1775         if (!NT_STATUS_IS_OK(status)) {
1776                 tevent_req_nterror(req, status);
1777                 return tevent_req_post(req, ev);
1778         }
1779
1780         state->buf = talloc_array(state, uint8_t, num);
1781         if (tevent_req_nomem(state->buf, req)) {
1782                 return tevent_req_post(req, ev);
1783         }
1784
1785         status = vfs_stat_fsp(src_fsp);
1786         if (tevent_req_nterror(req, status)) {
1787                 return tevent_req_post(req, ev);
1788         }
1789
1790         if (src_fsp->fsp_name->st.st_ex_size < state->src_off + num) {
1791                 /*
1792                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1793                  *   If the SourceOffset or SourceOffset + Length extends beyond
1794                  *   the end of file, the server SHOULD<240> treat this as a
1795                  *   STATUS_END_OF_FILE error.
1796                  * ...
1797                  *   <240> Section 3.3.5.15.6: Windows servers will return
1798                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1799                  */
1800                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1801                 return tevent_req_post(req, ev);
1802         }
1803
1804         if (src_fsp->op == NULL) {
1805                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1806                 return tevent_req_post(req, ev);
1807         }
1808
1809         if (dest_fsp->op == NULL) {
1810                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1811                 return tevent_req_post(req, ev);
1812         }
1813
1814         status = vfswrap_offload_write_loop(req);
1815         if (!NT_STATUS_IS_OK(status)) {
1816                 tevent_req_nterror(req, status);
1817                 return tevent_req_post(req, ev);
1818         }
1819
1820         return req;
1821 }
1822
1823 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1824
1825 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1826 {
1827         struct vfswrap_offload_write_state *state = tevent_req_data(
1828                 req, struct vfswrap_offload_write_state);
1829         struct tevent_req *subreq = NULL;
1830         bool ok;
1831
1832         state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1833
1834         init_strict_lock_struct(state->src_fsp,
1835                                 state->src_fsp->op->global->open_persistent_id,
1836                                 state->src_off,
1837                                 state->next_io_size,
1838                                 READ_LOCK,
1839                                 &state->read_lck);
1840
1841         ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1842                                  state->src_fsp,
1843                                  &state->read_lck);
1844         if (!ok) {
1845                 return NT_STATUS_FILE_LOCK_CONFLICT;
1846         }
1847
1848         subreq = SMB_VFS_PREAD_SEND(state,
1849                                     state->src_fsp->conn->sconn->ev_ctx,
1850                                     state->src_fsp,
1851                                     state->buf,
1852                                     state->next_io_size,
1853                                     state->src_off);
1854         if (subreq == NULL) {
1855                 return NT_STATUS_NO_MEMORY;
1856         }
1857         tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1858
1859         return NT_STATUS_OK;
1860 }
1861
1862 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1863
1864 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1865 {
1866         struct tevent_req *req = tevent_req_callback_data(
1867                 subreq, struct tevent_req);
1868         struct vfswrap_offload_write_state *state = tevent_req_data(
1869                 req, struct vfswrap_offload_write_state);
1870         struct vfs_aio_state aio_state;
1871         ssize_t nread;
1872         bool ok;
1873
1874         SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1875                               state->src_fsp,
1876                               &state->read_lck);
1877         ZERO_STRUCT(state->read_lck);
1878
1879         nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1880         TALLOC_FREE(subreq);
1881         if (nread == -1) {
1882                 DBG_ERR("read failed: %s\n", strerror(errno));
1883                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1884                 return;
1885         }
1886         if (nread != state->next_io_size) {
1887                 DBG_ERR("Short read, only %zd of %zu\n",
1888                         nread, state->next_io_size);
1889                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1890                 return;
1891         }
1892
1893         state->src_off += nread;
1894
1895         init_strict_lock_struct(state->dst_fsp,
1896                                 state->dst_fsp->op->global->open_persistent_id,
1897                                 state->dst_off,
1898                                 state->next_io_size,
1899                                 WRITE_LOCK,
1900                                 &state->write_lck);
1901
1902         ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1903                                  state->dst_fsp,
1904                                  &state->write_lck);
1905         if (!ok) {
1906                 tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1907                 return;
1908         }
1909
1910         subreq = SMB_VFS_PWRITE_SEND(state,
1911                                      state->ev,
1912                                      state->dst_fsp,
1913                                      state->buf,
1914                                      state->next_io_size,
1915                                      state->dst_off);
1916         if (subreq == NULL) {
1917                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1918                 return;
1919         }
1920         tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1921 }
1922
1923 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1924 {
1925         struct tevent_req *req = tevent_req_callback_data(
1926                 subreq, struct tevent_req);
1927         struct vfswrap_offload_write_state *state = tevent_req_data(
1928                 req, struct vfswrap_offload_write_state);
1929         struct vfs_aio_state aio_state;
1930         ssize_t nwritten;
1931         NTSTATUS status;
1932
1933         SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1934                               state->dst_fsp,
1935                               &state->write_lck);
1936         ZERO_STRUCT(state->write_lck);
1937
1938         nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1939         TALLOC_FREE(subreq);
1940         if (nwritten == -1) {
1941                 DBG_ERR("write failed: %s\n", strerror(errno));
1942                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1943                 return;
1944         }
1945         if (nwritten != state->next_io_size) {
1946                 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1947                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1948                 return;
1949         }
1950
1951         state->dst_off += nwritten;
1952
1953         if (state->remaining < nwritten) {
1954                 /* Paranoia check */
1955                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1956                 return;
1957         }
1958         state->remaining -= nwritten;
1959         if (state->remaining == 0) {
1960                 tevent_req_done(req);
1961                 return;
1962         }
1963
1964         status = vfswrap_offload_write_loop(req);
1965         if (!NT_STATUS_IS_OK(status)) {
1966                 tevent_req_nterror(req, status);
1967                 return;
1968         }
1969
1970         return;
1971 }
1972
1973 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1974                                         struct tevent_req *req,
1975                                         off_t *copied)
1976 {
1977         struct vfswrap_offload_write_state *state = tevent_req_data(
1978                 req, struct vfswrap_offload_write_state);
1979         NTSTATUS status;
1980
1981         if (tevent_req_is_nterror(req, &status)) {
1982                 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1983                 *copied = 0;
1984                 tevent_req_received(req);
1985                 return status;
1986         }
1987
1988         *copied = state->to_copy;
1989         DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1990         tevent_req_received(req);
1991
1992         return NT_STATUS_OK;
1993 }
1994
1995 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1996                                         TALLOC_CTX *mem_ctx,
1997                                         struct files_struct *fsp,
1998                                         struct smb_filename *smb_fname,
1999                                         uint16_t *_compression_fmt)
2000 {
2001         return NT_STATUS_INVALID_DEVICE_REQUEST;
2002 }
2003
2004 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
2005                                         TALLOC_CTX *mem_ctx,
2006                                         struct files_struct *fsp,
2007                                         uint16_t compression_fmt)
2008 {
2009         return NT_STATUS_INVALID_DEVICE_REQUEST;
2010 }
2011
2012 /********************************************************************
2013  Given a stat buffer return the allocated size on disk, taking into
2014  account sparse files.
2015 ********************************************************************/
2016 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
2017                                        struct files_struct *fsp,
2018                                        const SMB_STRUCT_STAT *sbuf)
2019 {
2020         uint64_t result;
2021
2022         START_PROFILE(syscall_get_alloc_size);
2023
2024         if(S_ISDIR(sbuf->st_ex_mode)) {
2025                 result = 0;
2026                 goto out;
2027         }
2028
2029 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2030         /* The type of st_blocksize is blkcnt_t which *MUST* be
2031            signed (according to POSIX) and can be less than 64-bits.
2032            Ensure when we're converting to 64 bits wide we don't
2033            sign extend. */
2034 #if defined(SIZEOF_BLKCNT_T_8)
2035         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2036 #elif defined(SIZEOF_BLKCNT_T_4)
2037         {
2038                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2039                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2040         }
2041 #else
2042 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2043 #endif
2044         if (result == 0) {
2045                 /*
2046                  * Some file systems do not allocate a block for very
2047                  * small files. But for non-empty file should report a
2048                  * positive size.
2049                  */
2050
2051                 uint64_t filesize = get_file_size_stat(sbuf);
2052                 if (filesize > 0) {
2053                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2054                 }
2055         }
2056 #else
2057         result = get_file_size_stat(sbuf);
2058 #endif
2059
2060         if (fsp && fsp->initial_allocation_size)
2061                 result = MAX(result,fsp->initial_allocation_size);
2062
2063         result = smb_roundup(handle->conn, result);
2064
2065  out:
2066         END_PROFILE(syscall_get_alloc_size);
2067         return result;
2068 }
2069
2070 static int vfswrap_unlink(vfs_handle_struct *handle,
2071                           const struct smb_filename *smb_fname)
2072 {
2073         int result = -1;
2074
2075         START_PROFILE(syscall_unlink);
2076
2077         if (smb_fname->stream_name) {
2078                 errno = ENOENT;
2079                 goto out;
2080         }
2081         result = unlink(smb_fname->base_name);
2082
2083  out:
2084         END_PROFILE(syscall_unlink);
2085         return result;
2086 }
2087
2088 static int vfswrap_chmod(vfs_handle_struct *handle,
2089                         const struct smb_filename *smb_fname,
2090                         mode_t mode)
2091 {
2092         int result;
2093
2094         START_PROFILE(syscall_chmod);
2095
2096         /*
2097          * We need to do this due to the fact that the default POSIX ACL
2098          * chmod modifies the ACL *mask* for the group owner, not the
2099          * group owner bits directly. JRA.
2100          */
2101
2102
2103         {
2104                 int saved_errno = errno; /* We might get ENOSYS */
2105                 result = SMB_VFS_CHMOD_ACL(handle->conn,
2106                                 smb_fname,
2107                                 mode);
2108                 if (result == 0) {
2109                         END_PROFILE(syscall_chmod);
2110                         return result;
2111                 }
2112                 /* Error - return the old errno. */
2113                 errno = saved_errno;
2114         }
2115
2116         result = chmod(smb_fname->base_name, mode);
2117         END_PROFILE(syscall_chmod);
2118         return result;
2119 }
2120
2121 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2122 {
2123         int result;
2124
2125         START_PROFILE(syscall_fchmod);
2126
2127         /*
2128          * We need to do this due to the fact that the default POSIX ACL
2129          * chmod modifies the ACL *mask* for the group owner, not the
2130          * group owner bits directly. JRA.
2131          */
2132
2133         {
2134                 int saved_errno = errno; /* We might get ENOSYS */
2135                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2136                         END_PROFILE(syscall_fchmod);
2137                         return result;
2138                 }
2139                 /* Error - return the old errno. */
2140                 errno = saved_errno;
2141         }
2142
2143 #if defined(HAVE_FCHMOD)
2144         result = fchmod(fsp->fh->fd, mode);
2145 #else
2146         result = -1;
2147         errno = ENOSYS;
2148 #endif
2149
2150         END_PROFILE(syscall_fchmod);
2151         return result;
2152 }
2153
2154 static int vfswrap_chown(vfs_handle_struct *handle,
2155                         const struct smb_filename *smb_fname,
2156                         uid_t uid,
2157                         gid_t gid)
2158 {
2159         int result;
2160
2161         START_PROFILE(syscall_chown);
2162         result = chown(smb_fname->base_name, uid, gid);
2163         END_PROFILE(syscall_chown);
2164         return result;
2165 }
2166
2167 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2168 {
2169 #ifdef HAVE_FCHOWN
2170         int result;
2171
2172         START_PROFILE(syscall_fchown);
2173         result = fchown(fsp->fh->fd, uid, gid);
2174         END_PROFILE(syscall_fchown);
2175         return result;
2176 #else
2177         errno = ENOSYS;
2178         return -1;
2179 #endif
2180 }
2181
2182 static int vfswrap_lchown(vfs_handle_struct *handle,
2183                         const struct smb_filename *smb_fname,
2184                         uid_t uid,
2185                         gid_t gid)
2186 {
2187         int result;
2188
2189         START_PROFILE(syscall_lchown);
2190         result = lchown(smb_fname->base_name, uid, gid);
2191         END_PROFILE(syscall_lchown);
2192         return result;
2193 }
2194
2195 static int vfswrap_chdir(vfs_handle_struct *handle,
2196                         const struct smb_filename *smb_fname)
2197 {
2198         int result;
2199
2200         START_PROFILE(syscall_chdir);
2201         result = chdir(smb_fname->base_name);
2202         END_PROFILE(syscall_chdir);
2203         return result;
2204 }
2205
2206 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2207                                 TALLOC_CTX *ctx)
2208 {
2209         char *result;
2210         struct smb_filename *smb_fname = NULL;
2211
2212         START_PROFILE(syscall_getwd);
2213         result = sys_getwd();
2214         END_PROFILE(syscall_getwd);
2215         smb_fname = synthetic_smb_fname(ctx,
2216                                 result,
2217                                 NULL,
2218                                 NULL,
2219                                 0);
2220         if (smb_fname == NULL) {
2221                 SAFE_FREE(result);
2222         }
2223         return smb_fname;
2224 }
2225
2226 /*********************************************************************
2227  nsec timestamp resolution call. Convert down to whatever the underlying
2228  system will support.
2229 **********************************************************************/
2230
2231 static int vfswrap_ntimes(vfs_handle_struct *handle,
2232                           const struct smb_filename *smb_fname,
2233                           struct smb_file_time *ft)
2234 {
2235         int result = -1;
2236
2237         START_PROFILE(syscall_ntimes);
2238
2239         if (smb_fname->stream_name) {
2240                 errno = ENOENT;
2241                 goto out;
2242         }
2243
2244         if (ft != NULL) {
2245                 if (null_timespec(ft->atime)) {
2246                         ft->atime= smb_fname->st.st_ex_atime;
2247                 }
2248
2249                 if (null_timespec(ft->mtime)) {
2250                         ft->mtime = smb_fname->st.st_ex_mtime;
2251                 }
2252
2253                 if (!null_timespec(ft->create_time)) {
2254                         set_create_timespec_ea(handle->conn,
2255                                                smb_fname,
2256                                                ft->create_time);
2257                 }
2258
2259                 if ((timespec_compare(&ft->atime,
2260                                       &smb_fname->st.st_ex_atime) == 0) &&
2261                     (timespec_compare(&ft->mtime,
2262                                       &smb_fname->st.st_ex_mtime) == 0)) {
2263                         return 0;
2264                 }
2265         }
2266
2267 #if defined(HAVE_UTIMENSAT)
2268         if (ft != NULL) {
2269                 struct timespec ts[2];
2270                 ts[0] = ft->atime;
2271                 ts[1] = ft->mtime;
2272                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2273         } else {
2274                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2275         }
2276         if (!((result == -1) && (errno == ENOSYS))) {
2277                 goto out;
2278         }
2279 #endif
2280 #if defined(HAVE_UTIMES)
2281         if (ft != NULL) {
2282                 struct timeval tv[2];
2283                 tv[0] = convert_timespec_to_timeval(ft->atime);
2284                 tv[1] = convert_timespec_to_timeval(ft->mtime);
2285                 result = utimes(smb_fname->base_name, tv);
2286         } else {
2287                 result = utimes(smb_fname->base_name, NULL);
2288         }
2289         if (!((result == -1) && (errno == ENOSYS))) {
2290                 goto out;
2291         }
2292 #endif
2293 #if defined(HAVE_UTIME)
2294         if (ft != NULL) {
2295                 struct utimbuf times;
2296                 times.actime = convert_timespec_to_time_t(ft->atime);
2297                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2298                 result = utime(smb_fname->base_name, &times);
2299         } else {
2300                 result = utime(smb_fname->base_name, NULL);
2301         }
2302         if (!((result == -1) && (errno == ENOSYS))) {
2303                 goto out;
2304         }
2305 #endif
2306         errno = ENOSYS;
2307         result = -1;
2308
2309  out:
2310         END_PROFILE(syscall_ntimes);
2311         return result;
2312 }
2313
2314 /*********************************************************************
2315  A version of ftruncate that will write the space on disk if strict
2316  allocate is set.
2317 **********************************************************************/
2318
2319 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2320 {
2321         off_t space_to_write;
2322         uint64_t space_avail;
2323         uint64_t bsize,dfree,dsize;
2324         int ret;
2325         NTSTATUS status;
2326         SMB_STRUCT_STAT *pst;
2327
2328         status = vfs_stat_fsp(fsp);
2329         if (!NT_STATUS_IS_OK(status)) {
2330                 return -1;
2331         }
2332         pst = &fsp->fsp_name->st;
2333
2334 #ifdef S_ISFIFO
2335         if (S_ISFIFO(pst->st_ex_mode))
2336                 return 0;
2337 #endif
2338
2339         if (pst->st_ex_size == len)
2340                 return 0;
2341
2342         /* Shrink - just ftruncate. */
2343         if (pst->st_ex_size > len)
2344                 return ftruncate(fsp->fh->fd, len);
2345
2346         space_to_write = len - pst->st_ex_size;
2347
2348         /* for allocation try fallocate first. This can fail on some
2349            platforms e.g. when the filesystem doesn't support it and no
2350            emulation is being done by the libc (like on AIX with JFS1). In that
2351            case we do our own emulation. fallocate implementations can
2352            return ENOTSUP or EINVAL in cases like that. */
2353         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2354         if (ret == -1 && errno == ENOSPC) {
2355                 return -1;
2356         }
2357         if (ret == 0) {
2358                 return 0;
2359         }
2360         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2361                 "error %d. Falling back to slow manual allocation\n", errno));
2362
2363         /* available disk space is enough or not? */
2364         space_avail =
2365             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2366         /* space_avail is 1k blocks */
2367         if (space_avail == (uint64_t)-1 ||
2368                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2369                 errno = ENOSPC;
2370                 return -1;
2371         }
2372
2373         /* Write out the real space on disk. */
2374         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2375         if (ret != 0) {
2376                 return -1;
2377         }
2378
2379         return 0;
2380 }
2381
2382 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2383 {
2384         int result = -1;
2385         SMB_STRUCT_STAT *pst;
2386         NTSTATUS status;
2387         char c = 0;
2388
2389         START_PROFILE(syscall_ftruncate);
2390
2391         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2392                 result = strict_allocate_ftruncate(handle, fsp, len);
2393                 END_PROFILE(syscall_ftruncate);
2394                 return result;
2395         }
2396
2397         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2398            ftruncate if the system supports it. Then I discovered that
2399            you can have some filesystems that support ftruncate
2400            expansion and some that don't! On Linux fat can't do
2401            ftruncate extend but ext2 can. */
2402
2403         result = ftruncate(fsp->fh->fd, len);
2404
2405         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2406            extend a file with ftruncate. Provide alternate implementation
2407            for this */
2408
2409         /* Do an fstat to see if the file is longer than the requested
2410            size in which case the ftruncate above should have
2411            succeeded or shorter, in which case seek to len - 1 and
2412            write 1 byte of zero */
2413         status = vfs_stat_fsp(fsp);
2414         if (!NT_STATUS_IS_OK(status)) {
2415                 goto done;
2416         }
2417
2418         /* We need to update the files_struct after successful ftruncate */
2419         if (result == 0) {
2420                 goto done;
2421         }
2422
2423         pst = &fsp->fsp_name->st;
2424
2425 #ifdef S_ISFIFO
2426         if (S_ISFIFO(pst->st_ex_mode)) {
2427                 result = 0;
2428                 goto done;
2429         }
2430 #endif
2431
2432         if (pst->st_ex_size == len) {
2433                 result = 0;
2434                 goto done;
2435         }
2436
2437         if (pst->st_ex_size > len) {
2438                 /* the ftruncate should have worked */
2439                 goto done;
2440         }
2441
2442         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2443                 goto done;
2444         }
2445
2446         result = 0;
2447
2448   done:
2449
2450         END_PROFILE(syscall_ftruncate);
2451         return result;
2452 }
2453
2454 static int vfswrap_fallocate(vfs_handle_struct *handle,
2455                         files_struct *fsp,
2456                         uint32_t mode,
2457                         off_t offset,
2458                         off_t len)
2459 {
2460         int result;
2461
2462         START_PROFILE(syscall_fallocate);
2463         if (mode == 0) {
2464                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2465                 /*
2466                  * posix_fallocate returns 0 on success, errno on error
2467                  * and doesn't set errno. Make it behave like fallocate()
2468                  * which returns -1, and sets errno on failure.
2469                  */
2470                 if (result != 0) {
2471                         errno = result;
2472                         result = -1;
2473                 }
2474         } else {
2475                 /* sys_fallocate handles filtering of unsupported mode flags */
2476                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2477         }
2478         END_PROFILE(syscall_fallocate);
2479         return result;
2480 }
2481
2482 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2483 {
2484         bool result;
2485
2486         START_PROFILE(syscall_fcntl_lock);
2487
2488         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2489                                                 "smbd",
2490                                                 "force process locks",
2491                                                 false)) {
2492                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2493         }
2494
2495         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
2496         END_PROFILE(syscall_fcntl_lock);
2497         return result;
2498 }
2499
2500 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2501                                 uint32_t share_mode, uint32_t access_mask)
2502 {
2503         START_PROFILE(syscall_kernel_flock);
2504         kernel_flock(fsp->fh->fd, share_mode, access_mask);
2505         END_PROFILE(syscall_kernel_flock);
2506         return 0;
2507 }
2508
2509 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2510 {
2511         bool result;
2512         int op = F_GETLK;
2513
2514         START_PROFILE(syscall_fcntl_getlock);
2515
2516         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2517                                                 "smbd",
2518                                                 "force process locks",
2519                                                 false)) {
2520                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2521         }
2522
2523         result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2524         END_PROFILE(syscall_fcntl_getlock);
2525         return result;
2526 }
2527
2528 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2529                                 int leasetype)
2530 {
2531         int result = -1;
2532
2533         START_PROFILE(syscall_linux_setlease);
2534
2535 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2536         result = linux_setlease(fsp->fh->fd, leasetype);
2537 #else
2538         errno = ENOSYS;
2539 #endif
2540         END_PROFILE(syscall_linux_setlease);
2541         return result;
2542 }
2543
2544 static int vfswrap_symlink(vfs_handle_struct *handle,
2545                         const char *link_target,
2546                         const struct smb_filename *new_smb_fname)
2547 {
2548         int result;
2549
2550         START_PROFILE(syscall_symlink);
2551         result = symlink(link_target, new_smb_fname->base_name);
2552         END_PROFILE(syscall_symlink);
2553         return result;
2554 }
2555
2556 static int vfswrap_readlink(vfs_handle_struct *handle,
2557                         const struct smb_filename *smb_fname,
2558                         char *buf,
2559                         size_t bufsiz)
2560 {
2561         int result;
2562
2563         START_PROFILE(syscall_readlink);
2564         result = readlink(smb_fname->base_name, buf, bufsiz);
2565         END_PROFILE(syscall_readlink);
2566         return result;
2567 }
2568
2569 static int vfswrap_link(vfs_handle_struct *handle,
2570                         const struct smb_filename *old_smb_fname,
2571                         const struct smb_filename *new_smb_fname)
2572 {
2573         int result;
2574
2575         START_PROFILE(syscall_link);
2576         result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2577         END_PROFILE(syscall_link);
2578         return result;
2579 }
2580
2581 static int vfswrap_mknod(vfs_handle_struct *handle,
2582                         const struct smb_filename *smb_fname,
2583                         mode_t mode,
2584                         SMB_DEV_T dev)
2585 {
2586         int result;
2587
2588         START_PROFILE(syscall_mknod);
2589         result = sys_mknod(smb_fname->base_name, mode, dev);
2590         END_PROFILE(syscall_mknod);
2591         return result;
2592 }
2593
2594 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2595                         TALLOC_CTX *ctx,
2596                         const struct smb_filename *smb_fname)
2597 {
2598         char *result;
2599         struct smb_filename *result_fname = NULL;
2600
2601         START_PROFILE(syscall_realpath);
2602         result = sys_realpath(smb_fname->base_name);
2603         END_PROFILE(syscall_realpath);
2604         if (result) {
2605                 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2606                 SAFE_FREE(result);
2607         }
2608         return result_fname;
2609 }
2610
2611 static int vfswrap_chflags(vfs_handle_struct *handle,
2612                         const struct smb_filename *smb_fname,
2613                         unsigned int flags)
2614 {
2615 #ifdef HAVE_CHFLAGS
2616         return chflags(smb_fname->base_name, flags);
2617 #else
2618         errno = ENOSYS;
2619         return -1;
2620 #endif
2621 }
2622
2623 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2624                                              const SMB_STRUCT_STAT *sbuf)
2625 {
2626         struct file_id key;
2627
2628         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2629          * blob */
2630         ZERO_STRUCT(key);
2631
2632         key.devid = sbuf->st_ex_dev;
2633         key.inode = sbuf->st_ex_ino;
2634         /* key.extid is unused by default. */
2635
2636         return key;
2637 }
2638
2639 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2640                                    struct files_struct *fsp,
2641                                    const struct smb_filename *smb_fname,
2642                                    TALLOC_CTX *mem_ctx,
2643                                    unsigned int *pnum_streams,
2644                                    struct stream_struct **pstreams)
2645 {
2646         SMB_STRUCT_STAT sbuf;
2647         struct stream_struct *tmp_streams = NULL;
2648         int ret;
2649
2650         if ((fsp != NULL) && (fsp->is_directory)) {
2651                 /*
2652                  * No default streams on directories
2653                  */
2654                 goto done;
2655         }
2656
2657         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2658                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2659         }
2660         else {
2661                 struct smb_filename smb_fname_cp;
2662
2663                 ZERO_STRUCT(smb_fname_cp);
2664                 smb_fname_cp.base_name = discard_const_p(char,
2665                                         smb_fname->base_name);
2666                 smb_fname_cp.flags = smb_fname->flags;
2667
2668                 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2669                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2670                 } else {
2671                         ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2672                 }
2673                 sbuf = smb_fname_cp.st;
2674         }
2675
2676         if (ret == -1) {
2677                 return map_nt_error_from_unix(errno);
2678         }
2679
2680         if (S_ISDIR(sbuf.st_ex_mode)) {
2681                 goto done;
2682         }
2683
2684         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2685                                         (*pnum_streams) + 1);
2686         if (tmp_streams == NULL) {
2687                 return NT_STATUS_NO_MEMORY;
2688         }
2689         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2690         if (tmp_streams[*pnum_streams].name == NULL) {
2691                 return NT_STATUS_NO_MEMORY;
2692         }
2693         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2694         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2695
2696         *pnum_streams += 1;
2697         *pstreams = tmp_streams;
2698  done:
2699         return NT_STATUS_OK;
2700 }
2701
2702 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2703                                      const char *path,
2704                                      const char *name,
2705                                      TALLOC_CTX *mem_ctx,
2706                                      char **found_name)
2707 {
2708         /*
2709          * Don't fall back to get_real_filename so callers can differentiate
2710          * between a full directory scan and an actual case-insensitive stat.
2711          */
2712         errno = EOPNOTSUPP;
2713         return -1;
2714 }
2715
2716 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2717                                    const struct smb_filename *smb_fname)
2718 {
2719         return handle->conn->connectpath;
2720 }
2721
2722 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2723                                          struct byte_range_lock *br_lck,
2724                                          struct lock_struct *plock,
2725                                          bool blocking_lock)
2726 {
2727         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2728
2729         /* Note: blr is not used in the default implementation. */
2730         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2731 }
2732
2733 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2734                                        struct messaging_context *msg_ctx,
2735                                        struct byte_range_lock *br_lck,
2736                                        const struct lock_struct *plock)
2737 {
2738         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2739
2740         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2741 }
2742
2743 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2744                                        struct byte_range_lock *br_lck,
2745                                        struct lock_struct *plock)
2746 {
2747         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2748
2749         /* Note: blr is not used in the default implementation. */
2750         return brl_lock_cancel_default(br_lck, plock);
2751 }
2752
2753 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2754                                 files_struct *fsp,
2755                                 struct lock_struct *plock)
2756 {
2757         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2758             plock->lock_type == WRITE_LOCK);
2759
2760         return strict_lock_default(fsp, plock);
2761 }
2762
2763 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2764                                 files_struct *fsp,
2765                                 struct lock_struct *plock)
2766 {
2767         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2768             plock->lock_type == WRITE_LOCK);
2769
2770         strict_unlock_default(fsp, plock);
2771 }
2772
2773 /* NT ACL operations. */
2774
2775 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2776                                     files_struct *fsp,
2777                                     uint32_t security_info,
2778                                     TALLOC_CTX *mem_ctx,
2779                                     struct security_descriptor **ppdesc)
2780 {
2781         NTSTATUS result;
2782
2783         START_PROFILE(fget_nt_acl);
2784         result = posix_fget_nt_acl(fsp, security_info,
2785                                    mem_ctx, ppdesc);
2786         END_PROFILE(fget_nt_acl);
2787         return result;
2788 }
2789
2790 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2791                                    const struct smb_filename *smb_fname,
2792                                    uint32_t security_info,
2793                                    TALLOC_CTX *mem_ctx,
2794                                    struct security_descriptor **ppdesc)
2795 {
2796         NTSTATUS result;
2797
2798         START_PROFILE(get_nt_acl);
2799         result = posix_get_nt_acl(handle->conn,
2800                                 smb_fname,
2801                                 security_info,
2802                                 mem_ctx,
2803                                 ppdesc);
2804         END_PROFILE(get_nt_acl);
2805         return result;
2806 }
2807
2808 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2809 {
2810         NTSTATUS result;
2811
2812         START_PROFILE(fset_nt_acl);
2813         result = set_nt_acl(fsp, security_info_sent, psd);
2814         END_PROFILE(fset_nt_acl);
2815         return result;
2816 }
2817
2818 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2819                                    struct smb_filename *file,
2820                                    struct security_acl *sacl,
2821                                    uint32_t access_requested,
2822                                    uint32_t access_denied)
2823 {
2824         return NT_STATUS_OK; /* Nothing to do here ... */
2825 }
2826
2827 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2828                                 const struct smb_filename *smb_fname,
2829                                 mode_t mode)
2830 {
2831 #ifdef HAVE_NO_ACL
2832         errno = ENOSYS;
2833         return -1;
2834 #else
2835         int result;
2836
2837         START_PROFILE(chmod_acl);
2838         result = chmod_acl(handle->conn, smb_fname, mode);
2839         END_PROFILE(chmod_acl);
2840         return result;
2841 #endif
2842 }
2843
2844 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2845 {
2846 #ifdef HAVE_NO_ACL
2847         errno = ENOSYS;
2848         return -1;
2849 #else
2850         int result;
2851
2852         START_PROFILE(fchmod_acl);
2853         result = fchmod_acl(fsp, mode);
2854         END_PROFILE(fchmod_acl);
2855         return result;
2856 #endif
2857 }
2858
2859 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2860                                           const struct smb_filename *smb_fname,
2861                                           SMB_ACL_TYPE_T type,
2862                                           TALLOC_CTX *mem_ctx)
2863 {
2864         return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2865 }
2866
2867 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2868                                         files_struct *fsp,
2869                                         TALLOC_CTX *mem_ctx)
2870 {
2871         return sys_acl_get_fd(handle, fsp, mem_ctx);
2872 }
2873
2874 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2875                                 const struct smb_filename *smb_fname,
2876                                 SMB_ACL_TYPE_T acltype,
2877                                 SMB_ACL_T theacl)
2878 {
2879         return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2880 }
2881
2882 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2883 {
2884         return sys_acl_set_fd(handle, fsp, theacl);
2885 }
2886
2887 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2888                         const struct smb_filename *smb_fname)
2889 {
2890         return sys_acl_delete_def_file(handle, smb_fname);
2891 }
2892
2893 /****************************************************************
2894  Extended attribute operations.
2895 *****************************************************************/
2896
2897 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2898                         const struct smb_filename *smb_fname,
2899                         const char *name,
2900                         void *value,
2901                         size_t size)
2902 {
2903         return getxattr(smb_fname->base_name, name, value, size);
2904 }
2905
2906 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2907 {
2908         return fgetxattr(fsp->fh->fd, name, value, size);
2909 }
2910
2911 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2912                         const struct smb_filename *smb_fname,
2913                         char *list,
2914                         size_t size)
2915 {
2916         return listxattr(smb_fname->base_name, list, size);
2917 }
2918
2919 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2920 {
2921         return flistxattr(fsp->fh->fd, list, size);
2922 }
2923
2924 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2925                                 const struct smb_filename *smb_fname,
2926                                 const char *name)
2927 {
2928         return removexattr(smb_fname->base_name, name);
2929 }
2930
2931 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2932 {
2933         return fremovexattr(fsp->fh->fd, name);
2934 }
2935
2936 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2937                                 const struct smb_filename *smb_fname,
2938                                 const char *name,
2939                                 const void *value,
2940                                 size_t size,
2941                                 int flags)
2942 {
2943         return setxattr(smb_fname->base_name, name, value, size, flags);
2944 }
2945
2946 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2947 {
2948         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2949 }
2950
2951 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2952 {
2953         return false;
2954 }
2955
2956 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2957                                const struct smb_filename *fname,
2958                                SMB_STRUCT_STAT *sbuf)
2959 {
2960         NTSTATUS status;
2961         char *path;
2962         bool offline = false;
2963
2964         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2965                 return false;
2966         }
2967
2968         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2969 #if defined(ENOTSUP)
2970                 errno = ENOTSUP;
2971 #endif
2972                 return false;
2973         }
2974
2975         status = get_full_smb_filename(talloc_tos(), fname, &path);
2976         if (!NT_STATUS_IS_OK(status)) {
2977                 errno = map_errno_from_nt_status(status);
2978                 return false;
2979         }
2980
2981         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2982
2983         TALLOC_FREE(path);
2984
2985         return offline;
2986 }
2987
2988 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2989                                        struct files_struct *fsp,
2990                                        TALLOC_CTX *mem_ctx,
2991                                        DATA_BLOB *cookie)
2992 {
2993         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2994 }
2995
2996 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2997                                            struct files_struct *fsp,
2998                                            const DATA_BLOB old_cookie,
2999                                            TALLOC_CTX *mem_ctx,
3000                                            DATA_BLOB *new_cookie)
3001 {
3002         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
3003                                               new_cookie);
3004 }
3005
3006 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
3007                                           struct smb_request *smb1req,
3008                                           struct smbXsrv_open *op,
3009                                           const DATA_BLOB old_cookie,
3010                                           TALLOC_CTX *mem_ctx,
3011                                           struct files_struct **fsp,
3012                                           DATA_BLOB *new_cookie)
3013 {
3014         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
3015                                              old_cookie, mem_ctx,
3016                                              fsp, new_cookie);
3017 }
3018
3019 static struct vfs_fn_pointers vfs_default_fns = {
3020         /* Disk operations */
3021
3022         .connect_fn = vfswrap_connect,
3023         .disconnect_fn = vfswrap_disconnect,
3024         .disk_free_fn = vfswrap_disk_free,
3025         .get_quota_fn = vfswrap_get_quota,
3026         .set_quota_fn = vfswrap_set_quota,
3027         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3028         .statvfs_fn = vfswrap_statvfs,
3029         .fs_capabilities_fn = vfswrap_fs_capabilities,
3030         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3031         .snap_check_path_fn = vfswrap_snap_check_path,
3032         .snap_create_fn = vfswrap_snap_create,
3033         .snap_delete_fn = vfswrap_snap_delete,
3034
3035         /* Directory operations */
3036
3037         .opendir_fn = vfswrap_opendir,
3038         .fdopendir_fn = vfswrap_fdopendir,
3039         .readdir_fn = vfswrap_readdir,
3040         .readdir_attr_fn = vfswrap_readdir_attr,
3041         .seekdir_fn = vfswrap_seekdir,
3042         .telldir_fn = vfswrap_telldir,
3043         .rewind_dir_fn = vfswrap_rewinddir,
3044         .mkdir_fn = vfswrap_mkdir,
3045         .rmdir_fn = vfswrap_rmdir,
3046         .closedir_fn = vfswrap_closedir,
3047         .init_search_op_fn = vfswrap_init_search_op,
3048
3049         /* File operations */
3050
3051         .open_fn = vfswrap_open,
3052         .create_file_fn = vfswrap_create_file,
3053         .close_fn = vfswrap_close,
3054         .read_fn = vfswrap_read,
3055         .pread_fn = vfswrap_pread,
3056         .pread_send_fn = vfswrap_pread_send,
3057         .pread_recv_fn = vfswrap_pread_recv,
3058         .write_fn = vfswrap_write,
3059         .pwrite_fn = vfswrap_pwrite,
3060         .pwrite_send_fn = vfswrap_pwrite_send,
3061         .pwrite_recv_fn = vfswrap_pwrite_recv,
3062         .lseek_fn = vfswrap_lseek,
3063         .sendfile_fn = vfswrap_sendfile,
3064         .recvfile_fn = vfswrap_recvfile,
3065         .rename_fn = vfswrap_rename,
3066         .fsync_fn = vfswrap_fsync,
3067         .fsync_send_fn = vfswrap_fsync_send,
3068         .fsync_recv_fn = vfswrap_fsync_recv,
3069         .stat_fn = vfswrap_stat,
3070         .fstat_fn = vfswrap_fstat,
3071         .lstat_fn = vfswrap_lstat,
3072         .get_alloc_size_fn = vfswrap_get_alloc_size,
3073         .unlink_fn = vfswrap_unlink,
3074         .chmod_fn = vfswrap_chmod,
3075         .fchmod_fn = vfswrap_fchmod,
3076         .chown_fn = vfswrap_chown,
3077         .fchown_fn = vfswrap_fchown,
3078         .lchown_fn = vfswrap_lchown,
3079         .chdir_fn = vfswrap_chdir,
3080         .getwd_fn = vfswrap_getwd,
3081         .ntimes_fn = vfswrap_ntimes,
3082         .ftruncate_fn = vfswrap_ftruncate,
3083         .fallocate_fn = vfswrap_fallocate,
3084         .lock_fn = vfswrap_lock,
3085         .kernel_flock_fn = vfswrap_kernel_flock,
3086         .linux_setlease_fn = vfswrap_linux_setlease,
3087         .getlock_fn = vfswrap_getlock,
3088         .symlink_fn = vfswrap_symlink,
3089         .readlink_fn = vfswrap_readlink,
3090         .link_fn = vfswrap_link,
3091         .mknod_fn = vfswrap_mknod,
3092         .realpath_fn = vfswrap_realpath,
3093         .chflags_fn = vfswrap_chflags,
3094         .file_id_create_fn = vfswrap_file_id_create,
3095         .streaminfo_fn = vfswrap_streaminfo,
3096         .get_real_filename_fn = vfswrap_get_real_filename,
3097         .connectpath_fn = vfswrap_connectpath,
3098         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3099         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3100         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3101         .strict_lock_fn = vfswrap_strict_lock,
3102         .strict_unlock_fn = vfswrap_strict_unlock,
3103         .translate_name_fn = vfswrap_translate_name,
3104         .fsctl_fn = vfswrap_fsctl,
3105         .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3106         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3107         .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3108         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3109         .offload_read_send_fn = vfswrap_offload_read_send,
3110         .offload_read_recv_fn = vfswrap_offload_read_recv,
3111         .offload_write_send_fn = vfswrap_offload_write_send,
3112         .offload_write_recv_fn = vfswrap_offload_write_recv,
3113         .get_compression_fn = vfswrap_get_compression,
3114         .set_compression_fn = vfswrap_set_compression,
3115
3116         /* NT ACL operations. */
3117
3118         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3119         .get_nt_acl_fn = vfswrap_get_nt_acl,
3120         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3121         .audit_file_fn = vfswrap_audit_file,
3122
3123         /* POSIX ACL operations. */
3124
3125         .chmod_acl_fn = vfswrap_chmod_acl,
3126         .fchmod_acl_fn = vfswrap_fchmod_acl,
3127
3128         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3129         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3130         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3131         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3132         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3133         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3134         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3135
3136         /* EA operations. */
3137         .getxattr_fn = vfswrap_getxattr,
3138         .fgetxattr_fn = vfswrap_fgetxattr,
3139         .listxattr_fn = vfswrap_listxattr,
3140         .flistxattr_fn = vfswrap_flistxattr,
3141         .removexattr_fn = vfswrap_removexattr,
3142         .fremovexattr_fn = vfswrap_fremovexattr,
3143         .setxattr_fn = vfswrap_setxattr,
3144         .fsetxattr_fn = vfswrap_fsetxattr,
3145
3146         /* aio operations */
3147         .aio_force_fn = vfswrap_aio_force,
3148
3149         /* durable handle operations */
3150         .durable_cookie_fn = vfswrap_durable_cookie,
3151         .durable_disconnect_fn = vfswrap_durable_disconnect,
3152         .durable_reconnect_fn = vfswrap_durable_reconnect,
3153 };
3154
3155 NTSTATUS vfs_default_init(TALLOC_CTX *);
3156 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3157 {
3158         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3159                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
3160 }
3161
3162