s3/vfs: rename SMB_VFS_COPY_CHUNK_SEND/RECV to SMB_VFS_OFFLOAD_WRITE_SEND/RECV
[samba.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/time.h"
23 #include "system/filesys.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "ntioctl.h"
27 #include "smbprofile.h"
28 #include "../libcli/security/security.h"
29 #include "passdb/lookup_sid.h"
30 #include "source3/include/msdfs.h"
31 #include "librpc/gen_ndr/ndr_dfsblobs.h"
32 #include "lib/util/tevent_unix.h"
33 #include "lib/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         struct files_struct *src_fsp;
1693         off_t src_off;
1694         struct files_struct *dst_fsp;
1695         off_t dst_off;
1696         off_t to_copy;
1697         off_t remaining;
1698         size_t next_io_size;
1699         uint32_t flags;
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         struct files_struct *src_fsp,
1709         off_t src_off,
1710         struct files_struct *dest_fsp,
1711         off_t dest_off,
1712         off_t to_copy,
1713         uint32_t flags)
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         NTSTATUS status;
1719
1720         DBG_DEBUG("server side copy chunk of length %" PRIu64 "\n", to_copy);
1721
1722         req = tevent_req_create(mem_ctx, &state,
1723                                 struct vfswrap_offload_write_state);
1724         if (req == NULL) {
1725                 return NULL;
1726         }
1727
1728         if (flags & ~VFS_OFFLOAD_WRITE_FL_MASK_ALL) {
1729                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1730                 return tevent_req_post(req, ev);
1731         }
1732
1733         if (flags & VFS_OFFLOAD_WRITE_FL_MUST_CLONE) {
1734                 DEBUG(10, ("COW clones not supported by vfs_default\n"));
1735                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1736                 return tevent_req_post(req, ev);
1737         }
1738
1739         *state = (struct vfswrap_offload_write_state) {
1740                 .ev = ev,
1741                 .src_fsp = src_fsp,
1742                 .src_off = src_off,
1743                 .dst_fsp = dest_fsp,
1744                 .dst_off = dest_off,
1745                 .to_copy = to_copy,
1746                 .remaining = to_copy,
1747                 .flags = flags,
1748         };
1749         state->buf = talloc_array(state, uint8_t, num);
1750         if (tevent_req_nomem(state->buf, req)) {
1751                 return tevent_req_post(req, ev);
1752         }
1753
1754         status = vfs_stat_fsp(src_fsp);
1755         if (tevent_req_nterror(req, status)) {
1756                 return tevent_req_post(req, ev);
1757         }
1758
1759         if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1760                 /*
1761                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1762                  *   If the SourceOffset or SourceOffset + Length extends beyond
1763                  *   the end of file, the server SHOULD<240> treat this as a
1764                  *   STATUS_END_OF_FILE error.
1765                  * ...
1766                  *   <240> Section 3.3.5.15.6: Windows servers will return
1767                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1768                  */
1769                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1770                 return tevent_req_post(req, ev);
1771         }
1772
1773         if (src_fsp->op == NULL) {
1774                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1775                 return tevent_req_post(req, ev);
1776         }
1777
1778         if (dest_fsp->op == NULL) {
1779                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1780                 return tevent_req_post(req, ev);
1781         }
1782
1783         status = vfswrap_offload_write_loop(req);
1784         if (!NT_STATUS_IS_OK(status)) {
1785                 tevent_req_nterror(req, status);
1786                 return tevent_req_post(req, ev);
1787         }
1788
1789         return req;
1790 }
1791
1792 static void vfswrap_offload_write_read_done(struct tevent_req *subreq);
1793
1794 static NTSTATUS vfswrap_offload_write_loop(struct tevent_req *req)
1795 {
1796         struct vfswrap_offload_write_state *state = tevent_req_data(
1797                 req, struct vfswrap_offload_write_state);
1798         struct tevent_req *subreq = NULL;
1799         bool ok;
1800
1801         state->next_io_size = MIN(state->remaining, talloc_array_length(state->buf));
1802
1803         if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1804                 init_strict_lock_struct(state->src_fsp,
1805                                 state->src_fsp->op->global->open_persistent_id,
1806                                         state->src_off,
1807                                         state->next_io_size,
1808                                         READ_LOCK,
1809                                         &state->read_lck);
1810
1811                 ok = SMB_VFS_STRICT_LOCK(state->src_fsp->conn,
1812                                          state->src_fsp,
1813                                          &state->read_lck);
1814                 if (!ok) {
1815                         return NT_STATUS_FILE_LOCK_CONFLICT;
1816                 }
1817         }
1818
1819         subreq = SMB_VFS_PREAD_SEND(state,
1820                                     state->src_fsp->conn->sconn->ev_ctx,
1821                                     state->src_fsp,
1822                                     state->buf,
1823                                     state->next_io_size,
1824                                     state->src_off);
1825         if (subreq == NULL) {
1826                 return NT_STATUS_NO_MEMORY;
1827         }
1828         tevent_req_set_callback(subreq, vfswrap_offload_write_read_done, req);
1829
1830         return NT_STATUS_OK;
1831 }
1832
1833 static void vfswrap_offload_write_write_done(struct tevent_req *subreq);
1834
1835 static void vfswrap_offload_write_read_done(struct tevent_req *subreq)
1836 {
1837         struct tevent_req *req = tevent_req_callback_data(
1838                 subreq, struct tevent_req);
1839         struct vfswrap_offload_write_state *state = tevent_req_data(
1840                 req, struct vfswrap_offload_write_state);
1841         struct vfs_aio_state aio_state;
1842         ssize_t nread;
1843         bool ok;
1844
1845         if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1846                 SMB_VFS_STRICT_UNLOCK(state->src_fsp->conn,
1847                                       state->src_fsp,
1848                                       &state->read_lck);
1849                 ZERO_STRUCT(state->read_lck);
1850         }
1851
1852         nread = SMB_VFS_PREAD_RECV(subreq, &aio_state);
1853         TALLOC_FREE(subreq);
1854         if (nread == -1) {
1855                 DBG_ERR("read failed: %s\n", strerror(errno));
1856                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1857                 return;
1858         }
1859         if (nread != state->next_io_size) {
1860                 DBG_ERR("Short read, only %zd of %zu\n",
1861                         nread, state->next_io_size);
1862                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1863                 return;
1864         }
1865
1866         state->src_off += nread;
1867
1868         if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1869                 init_strict_lock_struct(state->dst_fsp,
1870                                 state->dst_fsp->op->global->open_persistent_id,
1871                                         state->dst_off,
1872                                         state->next_io_size,
1873                                         WRITE_LOCK,
1874                                         &state->write_lck);
1875
1876                 ok = SMB_VFS_STRICT_LOCK(state->dst_fsp->conn,
1877                                          state->dst_fsp,
1878                                          &state->write_lck);
1879                 if (!ok) {
1880                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1881                         return;
1882                 }
1883         }
1884
1885         subreq = SMB_VFS_PWRITE_SEND(state,
1886                                      state->ev,
1887                                      state->dst_fsp,
1888                                      state->buf,
1889                                      state->next_io_size,
1890                                      state->dst_off);
1891         if (subreq == NULL) {
1892                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
1893                 return;
1894         }
1895         tevent_req_set_callback(subreq, vfswrap_offload_write_write_done, req);
1896 }
1897
1898 static void vfswrap_offload_write_write_done(struct tevent_req *subreq)
1899 {
1900         struct tevent_req *req = tevent_req_callback_data(
1901                 subreq, struct tevent_req);
1902         struct vfswrap_offload_write_state *state = tevent_req_data(
1903                 req, struct vfswrap_offload_write_state);
1904         struct vfs_aio_state aio_state;
1905         ssize_t nwritten;
1906         NTSTATUS status;
1907
1908         if (!(state->flags & VFS_OFFLOAD_WRITE_FL_IGNORE_LOCKS)) {
1909                 SMB_VFS_STRICT_UNLOCK(state->dst_fsp->conn,
1910                                       state->dst_fsp,
1911                                       &state->write_lck);
1912                 ZERO_STRUCT(state->write_lck);
1913         }
1914
1915         nwritten = SMB_VFS_PWRITE_RECV(subreq, &aio_state);
1916         TALLOC_FREE(subreq);
1917         if (nwritten == -1) {
1918                 DBG_ERR("write failed: %s\n", strerror(errno));
1919                 tevent_req_nterror(req, map_nt_error_from_unix(aio_state.error));
1920                 return;
1921         }
1922         if (nwritten != state->next_io_size) {
1923                 DBG_ERR("Short write, only %zd of %zu\n", nwritten, state->next_io_size);
1924                 tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1925                 return;
1926         }
1927
1928         state->dst_off += nwritten;
1929
1930         if (state->remaining < nwritten) {
1931                 /* Paranoia check */
1932                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1933                 return;
1934         }
1935         state->remaining -= nwritten;
1936         if (state->remaining == 0) {
1937                 tevent_req_done(req);
1938                 return;
1939         }
1940
1941         status = vfswrap_offload_write_loop(req);
1942         if (!NT_STATUS_IS_OK(status)) {
1943                 tevent_req_nterror(req, status);
1944                 return;
1945         }
1946
1947         return;
1948 }
1949
1950 static NTSTATUS vfswrap_offload_write_recv(struct vfs_handle_struct *handle,
1951                                         struct tevent_req *req,
1952                                         off_t *copied)
1953 {
1954         struct vfswrap_offload_write_state *state = tevent_req_data(
1955                 req, struct vfswrap_offload_write_state);
1956         NTSTATUS status;
1957
1958         if (tevent_req_is_nterror(req, &status)) {
1959                 DBG_DEBUG("copy chunk failed: %s\n", nt_errstr(status));
1960                 *copied = 0;
1961                 tevent_req_received(req);
1962                 return status;
1963         }
1964
1965         *copied = state->to_copy;
1966         DBG_DEBUG("copy chunk copied %lu\n", (unsigned long)*copied);
1967         tevent_req_received(req);
1968
1969         return NT_STATUS_OK;
1970 }
1971
1972 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1973                                         TALLOC_CTX *mem_ctx,
1974                                         struct files_struct *fsp,
1975                                         struct smb_filename *smb_fname,
1976                                         uint16_t *_compression_fmt)
1977 {
1978         return NT_STATUS_INVALID_DEVICE_REQUEST;
1979 }
1980
1981 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1982                                         TALLOC_CTX *mem_ctx,
1983                                         struct files_struct *fsp,
1984                                         uint16_t compression_fmt)
1985 {
1986         return NT_STATUS_INVALID_DEVICE_REQUEST;
1987 }
1988
1989 /********************************************************************
1990  Given a stat buffer return the allocated size on disk, taking into
1991  account sparse files.
1992 ********************************************************************/
1993 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1994                                        struct files_struct *fsp,
1995                                        const SMB_STRUCT_STAT *sbuf)
1996 {
1997         uint64_t result;
1998
1999         START_PROFILE(syscall_get_alloc_size);
2000
2001         if(S_ISDIR(sbuf->st_ex_mode)) {
2002                 result = 0;
2003                 goto out;
2004         }
2005
2006 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2007         /* The type of st_blocksize is blkcnt_t which *MUST* be
2008            signed (according to POSIX) and can be less than 64-bits.
2009            Ensure when we're converting to 64 bits wide we don't
2010            sign extend. */
2011 #if defined(SIZEOF_BLKCNT_T_8)
2012         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
2013 #elif defined(SIZEOF_BLKCNT_T_4)
2014         {
2015                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
2016                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
2017         }
2018 #else
2019 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
2020 #endif
2021         if (result == 0) {
2022                 /*
2023                  * Some file systems do not allocate a block for very
2024                  * small files. But for non-empty file should report a
2025                  * positive size.
2026                  */
2027
2028                 uint64_t filesize = get_file_size_stat(sbuf);
2029                 if (filesize > 0) {
2030                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
2031                 }
2032         }
2033 #else
2034         result = get_file_size_stat(sbuf);
2035 #endif
2036
2037         if (fsp && fsp->initial_allocation_size)
2038                 result = MAX(result,fsp->initial_allocation_size);
2039
2040         result = smb_roundup(handle->conn, result);
2041
2042  out:
2043         END_PROFILE(syscall_get_alloc_size);
2044         return result;
2045 }
2046
2047 static int vfswrap_unlink(vfs_handle_struct *handle,
2048                           const struct smb_filename *smb_fname)
2049 {
2050         int result = -1;
2051
2052         START_PROFILE(syscall_unlink);
2053
2054         if (smb_fname->stream_name) {
2055                 errno = ENOENT;
2056                 goto out;
2057         }
2058         result = unlink(smb_fname->base_name);
2059
2060  out:
2061         END_PROFILE(syscall_unlink);
2062         return result;
2063 }
2064
2065 static int vfswrap_chmod(vfs_handle_struct *handle,
2066                         const struct smb_filename *smb_fname,
2067                         mode_t mode)
2068 {
2069         int result;
2070
2071         START_PROFILE(syscall_chmod);
2072
2073         /*
2074          * We need to do this due to the fact that the default POSIX ACL
2075          * chmod modifies the ACL *mask* for the group owner, not the
2076          * group owner bits directly. JRA.
2077          */
2078
2079
2080         {
2081                 int saved_errno = errno; /* We might get ENOSYS */
2082                 result = SMB_VFS_CHMOD_ACL(handle->conn,
2083                                 smb_fname,
2084                                 mode);
2085                 if (result == 0) {
2086                         END_PROFILE(syscall_chmod);
2087                         return result;
2088                 }
2089                 /* Error - return the old errno. */
2090                 errno = saved_errno;
2091         }
2092
2093         result = chmod(smb_fname->base_name, mode);
2094         END_PROFILE(syscall_chmod);
2095         return result;
2096 }
2097
2098 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2099 {
2100         int result;
2101
2102         START_PROFILE(syscall_fchmod);
2103
2104         /*
2105          * We need to do this due to the fact that the default POSIX ACL
2106          * chmod modifies the ACL *mask* for the group owner, not the
2107          * group owner bits directly. JRA.
2108          */
2109
2110         {
2111                 int saved_errno = errno; /* We might get ENOSYS */
2112                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
2113                         END_PROFILE(syscall_fchmod);
2114                         return result;
2115                 }
2116                 /* Error - return the old errno. */
2117                 errno = saved_errno;
2118         }
2119
2120 #if defined(HAVE_FCHMOD)
2121         result = fchmod(fsp->fh->fd, mode);
2122 #else
2123         result = -1;
2124         errno = ENOSYS;
2125 #endif
2126
2127         END_PROFILE(syscall_fchmod);
2128         return result;
2129 }
2130
2131 static int vfswrap_chown(vfs_handle_struct *handle,
2132                         const struct smb_filename *smb_fname,
2133                         uid_t uid,
2134                         gid_t gid)
2135 {
2136         int result;
2137
2138         START_PROFILE(syscall_chown);
2139         result = chown(smb_fname->base_name, uid, gid);
2140         END_PROFILE(syscall_chown);
2141         return result;
2142 }
2143
2144 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
2145 {
2146 #ifdef HAVE_FCHOWN
2147         int result;
2148
2149         START_PROFILE(syscall_fchown);
2150         result = fchown(fsp->fh->fd, uid, gid);
2151         END_PROFILE(syscall_fchown);
2152         return result;
2153 #else
2154         errno = ENOSYS;
2155         return -1;
2156 #endif
2157 }
2158
2159 static int vfswrap_lchown(vfs_handle_struct *handle,
2160                         const struct smb_filename *smb_fname,
2161                         uid_t uid,
2162                         gid_t gid)
2163 {
2164         int result;
2165
2166         START_PROFILE(syscall_lchown);
2167         result = lchown(smb_fname->base_name, uid, gid);
2168         END_PROFILE(syscall_lchown);
2169         return result;
2170 }
2171
2172 static int vfswrap_chdir(vfs_handle_struct *handle,
2173                         const struct smb_filename *smb_fname)
2174 {
2175         int result;
2176
2177         START_PROFILE(syscall_chdir);
2178         result = chdir(smb_fname->base_name);
2179         END_PROFILE(syscall_chdir);
2180         return result;
2181 }
2182
2183 static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
2184                                 TALLOC_CTX *ctx)
2185 {
2186         char *result;
2187         struct smb_filename *smb_fname = NULL;
2188
2189         START_PROFILE(syscall_getwd);
2190         result = sys_getwd();
2191         END_PROFILE(syscall_getwd);
2192         smb_fname = synthetic_smb_fname(ctx,
2193                                 result,
2194                                 NULL,
2195                                 NULL,
2196                                 0);
2197         if (smb_fname == NULL) {
2198                 SAFE_FREE(result);
2199         }
2200         return smb_fname;
2201 }
2202
2203 /*********************************************************************
2204  nsec timestamp resolution call. Convert down to whatever the underlying
2205  system will support.
2206 **********************************************************************/
2207
2208 static int vfswrap_ntimes(vfs_handle_struct *handle,
2209                           const struct smb_filename *smb_fname,
2210                           struct smb_file_time *ft)
2211 {
2212         int result = -1;
2213
2214         START_PROFILE(syscall_ntimes);
2215
2216         if (smb_fname->stream_name) {
2217                 errno = ENOENT;
2218                 goto out;
2219         }
2220
2221         if (ft != NULL) {
2222                 if (null_timespec(ft->atime)) {
2223                         ft->atime= smb_fname->st.st_ex_atime;
2224                 }
2225
2226                 if (null_timespec(ft->mtime)) {
2227                         ft->mtime = smb_fname->st.st_ex_mtime;
2228                 }
2229
2230                 if (!null_timespec(ft->create_time)) {
2231                         set_create_timespec_ea(handle->conn,
2232                                                smb_fname,
2233                                                ft->create_time);
2234                 }
2235
2236                 if ((timespec_compare(&ft->atime,
2237                                       &smb_fname->st.st_ex_atime) == 0) &&
2238                     (timespec_compare(&ft->mtime,
2239                                       &smb_fname->st.st_ex_mtime) == 0)) {
2240                         return 0;
2241                 }
2242         }
2243
2244 #if defined(HAVE_UTIMENSAT)
2245         if (ft != NULL) {
2246                 struct timespec ts[2];
2247                 ts[0] = ft->atime;
2248                 ts[1] = ft->mtime;
2249                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2250         } else {
2251                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2252         }
2253         if (!((result == -1) && (errno == ENOSYS))) {
2254                 goto out;
2255         }
2256 #endif
2257 #if defined(HAVE_UTIMES)
2258         if (ft != NULL) {
2259                 struct timeval tv[2];
2260                 tv[0] = convert_timespec_to_timeval(ft->atime);
2261                 tv[1] = convert_timespec_to_timeval(ft->mtime);
2262                 result = utimes(smb_fname->base_name, tv);
2263         } else {
2264                 result = utimes(smb_fname->base_name, NULL);
2265         }
2266         if (!((result == -1) && (errno == ENOSYS))) {
2267                 goto out;
2268         }
2269 #endif
2270 #if defined(HAVE_UTIME)
2271         if (ft != NULL) {
2272                 struct utimbuf times;
2273                 times.actime = convert_timespec_to_time_t(ft->atime);
2274                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2275                 result = utime(smb_fname->base_name, &times);
2276         } else {
2277                 result = utime(smb_fname->base_name, NULL);
2278         }
2279         if (!((result == -1) && (errno == ENOSYS))) {
2280                 goto out;
2281         }
2282 #endif
2283         errno = ENOSYS;
2284         result = -1;
2285
2286  out:
2287         END_PROFILE(syscall_ntimes);
2288         return result;
2289 }
2290
2291 /*********************************************************************
2292  A version of ftruncate that will write the space on disk if strict
2293  allocate is set.
2294 **********************************************************************/
2295
2296 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2297 {
2298         off_t space_to_write;
2299         uint64_t space_avail;
2300         uint64_t bsize,dfree,dsize;
2301         int ret;
2302         NTSTATUS status;
2303         SMB_STRUCT_STAT *pst;
2304
2305         status = vfs_stat_fsp(fsp);
2306         if (!NT_STATUS_IS_OK(status)) {
2307                 return -1;
2308         }
2309         pst = &fsp->fsp_name->st;
2310
2311 #ifdef S_ISFIFO
2312         if (S_ISFIFO(pst->st_ex_mode))
2313                 return 0;
2314 #endif
2315
2316         if (pst->st_ex_size == len)
2317                 return 0;
2318
2319         /* Shrink - just ftruncate. */
2320         if (pst->st_ex_size > len)
2321                 return ftruncate(fsp->fh->fd, len);
2322
2323         space_to_write = len - pst->st_ex_size;
2324
2325         /* for allocation try fallocate first. This can fail on some
2326            platforms e.g. when the filesystem doesn't support it and no
2327            emulation is being done by the libc (like on AIX with JFS1). In that
2328            case we do our own emulation. fallocate implementations can
2329            return ENOTSUP or EINVAL in cases like that. */
2330         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2331         if (ret == -1 && errno == ENOSPC) {
2332                 return -1;
2333         }
2334         if (ret == 0) {
2335                 return 0;
2336         }
2337         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2338                 "error %d. Falling back to slow manual allocation\n", errno));
2339
2340         /* available disk space is enough or not? */
2341         space_avail =
2342             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2343         /* space_avail is 1k blocks */
2344         if (space_avail == (uint64_t)-1 ||
2345                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2346                 errno = ENOSPC;
2347                 return -1;
2348         }
2349
2350         /* Write out the real space on disk. */
2351         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2352         if (ret != 0) {
2353                 return -1;
2354         }
2355
2356         return 0;
2357 }
2358
2359 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2360 {
2361         int result = -1;
2362         SMB_STRUCT_STAT *pst;
2363         NTSTATUS status;
2364         char c = 0;
2365
2366         START_PROFILE(syscall_ftruncate);
2367
2368         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2369                 result = strict_allocate_ftruncate(handle, fsp, len);
2370                 END_PROFILE(syscall_ftruncate);
2371                 return result;
2372         }
2373
2374         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2375            ftruncate if the system supports it. Then I discovered that
2376            you can have some filesystems that support ftruncate
2377            expansion and some that don't! On Linux fat can't do
2378            ftruncate extend but ext2 can. */
2379
2380         result = ftruncate(fsp->fh->fd, len);
2381
2382         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2383            extend a file with ftruncate. Provide alternate implementation
2384            for this */
2385
2386         /* Do an fstat to see if the file is longer than the requested
2387            size in which case the ftruncate above should have
2388            succeeded or shorter, in which case seek to len - 1 and
2389            write 1 byte of zero */
2390         status = vfs_stat_fsp(fsp);
2391         if (!NT_STATUS_IS_OK(status)) {
2392                 goto done;
2393         }
2394
2395         /* We need to update the files_struct after successful ftruncate */
2396         if (result == 0) {
2397                 goto done;
2398         }
2399
2400         pst = &fsp->fsp_name->st;
2401
2402 #ifdef S_ISFIFO
2403         if (S_ISFIFO(pst->st_ex_mode)) {
2404                 result = 0;
2405                 goto done;
2406         }
2407 #endif
2408
2409         if (pst->st_ex_size == len) {
2410                 result = 0;
2411                 goto done;
2412         }
2413
2414         if (pst->st_ex_size > len) {
2415                 /* the ftruncate should have worked */
2416                 goto done;
2417         }
2418
2419         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2420                 goto done;
2421         }
2422
2423         result = 0;
2424
2425   done:
2426
2427         END_PROFILE(syscall_ftruncate);
2428         return result;
2429 }
2430
2431 static int vfswrap_fallocate(vfs_handle_struct *handle,
2432                         files_struct *fsp,
2433                         uint32_t mode,
2434                         off_t offset,
2435                         off_t len)
2436 {
2437         int result;
2438
2439         START_PROFILE(syscall_fallocate);
2440         if (mode == 0) {
2441                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2442                 /*
2443                  * posix_fallocate returns 0 on success, errno on error
2444                  * and doesn't set errno. Make it behave like fallocate()
2445                  * which returns -1, and sets errno on failure.
2446                  */
2447                 if (result != 0) {
2448                         errno = result;
2449                         result = -1;
2450                 }
2451         } else {
2452                 /* sys_fallocate handles filtering of unsupported mode flags */
2453                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2454         }
2455         END_PROFILE(syscall_fallocate);
2456         return result;
2457 }
2458
2459 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2460 {
2461         bool result;
2462
2463         START_PROFILE(syscall_fcntl_lock);
2464
2465         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2466                                                 "smbd",
2467                                                 "force process locks",
2468                                                 false)) {
2469                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2470         }
2471
2472         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
2473         END_PROFILE(syscall_fcntl_lock);
2474         return result;
2475 }
2476
2477 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2478                                 uint32_t share_mode, uint32_t access_mask)
2479 {
2480         START_PROFILE(syscall_kernel_flock);
2481         kernel_flock(fsp->fh->fd, share_mode, access_mask);
2482         END_PROFILE(syscall_kernel_flock);
2483         return 0;
2484 }
2485
2486 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2487 {
2488         bool result;
2489         int op = F_GETLK;
2490
2491         START_PROFILE(syscall_fcntl_getlock);
2492
2493         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2494                                                 "smbd",
2495                                                 "force process locks",
2496                                                 false)) {
2497                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2498         }
2499
2500         result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2501         END_PROFILE(syscall_fcntl_getlock);
2502         return result;
2503 }
2504
2505 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2506                                 int leasetype)
2507 {
2508         int result = -1;
2509
2510         START_PROFILE(syscall_linux_setlease);
2511
2512 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2513         result = linux_setlease(fsp->fh->fd, leasetype);
2514 #else
2515         errno = ENOSYS;
2516 #endif
2517         END_PROFILE(syscall_linux_setlease);
2518         return result;
2519 }
2520
2521 static int vfswrap_symlink(vfs_handle_struct *handle,
2522                         const char *link_target,
2523                         const struct smb_filename *new_smb_fname)
2524 {
2525         int result;
2526
2527         START_PROFILE(syscall_symlink);
2528         result = symlink(link_target, new_smb_fname->base_name);
2529         END_PROFILE(syscall_symlink);
2530         return result;
2531 }
2532
2533 static int vfswrap_readlink(vfs_handle_struct *handle,
2534                         const struct smb_filename *smb_fname,
2535                         char *buf,
2536                         size_t bufsiz)
2537 {
2538         int result;
2539
2540         START_PROFILE(syscall_readlink);
2541         result = readlink(smb_fname->base_name, buf, bufsiz);
2542         END_PROFILE(syscall_readlink);
2543         return result;
2544 }
2545
2546 static int vfswrap_link(vfs_handle_struct *handle,
2547                         const struct smb_filename *old_smb_fname,
2548                         const struct smb_filename *new_smb_fname)
2549 {
2550         int result;
2551
2552         START_PROFILE(syscall_link);
2553         result = link(old_smb_fname->base_name, new_smb_fname->base_name);
2554         END_PROFILE(syscall_link);
2555         return result;
2556 }
2557
2558 static int vfswrap_mknod(vfs_handle_struct *handle,
2559                         const struct smb_filename *smb_fname,
2560                         mode_t mode,
2561                         SMB_DEV_T dev)
2562 {
2563         int result;
2564
2565         START_PROFILE(syscall_mknod);
2566         result = sys_mknod(smb_fname->base_name, mode, dev);
2567         END_PROFILE(syscall_mknod);
2568         return result;
2569 }
2570
2571 static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
2572                         TALLOC_CTX *ctx,
2573                         const struct smb_filename *smb_fname)
2574 {
2575         char *result;
2576         struct smb_filename *result_fname = NULL;
2577
2578         START_PROFILE(syscall_realpath);
2579         result = sys_realpath(smb_fname->base_name);
2580         END_PROFILE(syscall_realpath);
2581         if (result) {
2582                 result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
2583                 SAFE_FREE(result);
2584         }
2585         return result_fname;
2586 }
2587
2588 static int vfswrap_chflags(vfs_handle_struct *handle,
2589                         const struct smb_filename *smb_fname,
2590                         unsigned int flags)
2591 {
2592 #ifdef HAVE_CHFLAGS
2593         return chflags(smb_fname->base_name, flags);
2594 #else
2595         errno = ENOSYS;
2596         return -1;
2597 #endif
2598 }
2599
2600 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2601                                              const SMB_STRUCT_STAT *sbuf)
2602 {
2603         struct file_id key;
2604
2605         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2606          * blob */
2607         ZERO_STRUCT(key);
2608
2609         key.devid = sbuf->st_ex_dev;
2610         key.inode = sbuf->st_ex_ino;
2611         /* key.extid is unused by default. */
2612
2613         return key;
2614 }
2615
2616 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2617                                    struct files_struct *fsp,
2618                                    const struct smb_filename *smb_fname,
2619                                    TALLOC_CTX *mem_ctx,
2620                                    unsigned int *pnum_streams,
2621                                    struct stream_struct **pstreams)
2622 {
2623         SMB_STRUCT_STAT sbuf;
2624         struct stream_struct *tmp_streams = NULL;
2625         int ret;
2626
2627         if ((fsp != NULL) && (fsp->is_directory)) {
2628                 /*
2629                  * No default streams on directories
2630                  */
2631                 goto done;
2632         }
2633
2634         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2635                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2636         }
2637         else {
2638                 struct smb_filename smb_fname_cp;
2639
2640                 ZERO_STRUCT(smb_fname_cp);
2641                 smb_fname_cp.base_name = discard_const_p(char,
2642                                         smb_fname->base_name);
2643                 smb_fname_cp.flags = smb_fname->flags;
2644
2645                 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2646                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2647                 } else {
2648                         ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2649                 }
2650                 sbuf = smb_fname_cp.st;
2651         }
2652
2653         if (ret == -1) {
2654                 return map_nt_error_from_unix(errno);
2655         }
2656
2657         if (S_ISDIR(sbuf.st_ex_mode)) {
2658                 goto done;
2659         }
2660
2661         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2662                                         (*pnum_streams) + 1);
2663         if (tmp_streams == NULL) {
2664                 return NT_STATUS_NO_MEMORY;
2665         }
2666         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2667         if (tmp_streams[*pnum_streams].name == NULL) {
2668                 return NT_STATUS_NO_MEMORY;
2669         }
2670         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2671         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2672
2673         *pnum_streams += 1;
2674         *pstreams = tmp_streams;
2675  done:
2676         return NT_STATUS_OK;
2677 }
2678
2679 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2680                                      const char *path,
2681                                      const char *name,
2682                                      TALLOC_CTX *mem_ctx,
2683                                      char **found_name)
2684 {
2685         /*
2686          * Don't fall back to get_real_filename so callers can differentiate
2687          * between a full directory scan and an actual case-insensitive stat.
2688          */
2689         errno = EOPNOTSUPP;
2690         return -1;
2691 }
2692
2693 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2694                                    const struct smb_filename *smb_fname)
2695 {
2696         return handle->conn->connectpath;
2697 }
2698
2699 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2700                                          struct byte_range_lock *br_lck,
2701                                          struct lock_struct *plock,
2702                                          bool blocking_lock)
2703 {
2704         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2705
2706         /* Note: blr is not used in the default implementation. */
2707         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2708 }
2709
2710 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2711                                        struct messaging_context *msg_ctx,
2712                                        struct byte_range_lock *br_lck,
2713                                        const struct lock_struct *plock)
2714 {
2715         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2716
2717         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2718 }
2719
2720 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2721                                        struct byte_range_lock *br_lck,
2722                                        struct lock_struct *plock)
2723 {
2724         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2725
2726         /* Note: blr is not used in the default implementation. */
2727         return brl_lock_cancel_default(br_lck, plock);
2728 }
2729
2730 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2731                                 files_struct *fsp,
2732                                 struct lock_struct *plock)
2733 {
2734         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2735             plock->lock_type == WRITE_LOCK);
2736
2737         return strict_lock_default(fsp, plock);
2738 }
2739
2740 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2741                                 files_struct *fsp,
2742                                 struct lock_struct *plock)
2743 {
2744         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2745             plock->lock_type == WRITE_LOCK);
2746
2747         strict_unlock_default(fsp, plock);
2748 }
2749
2750 /* NT ACL operations. */
2751
2752 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2753                                     files_struct *fsp,
2754                                     uint32_t security_info,
2755                                     TALLOC_CTX *mem_ctx,
2756                                     struct security_descriptor **ppdesc)
2757 {
2758         NTSTATUS result;
2759
2760         START_PROFILE(fget_nt_acl);
2761         result = posix_fget_nt_acl(fsp, security_info,
2762                                    mem_ctx, ppdesc);
2763         END_PROFILE(fget_nt_acl);
2764         return result;
2765 }
2766
2767 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2768                                    const struct smb_filename *smb_fname,
2769                                    uint32_t security_info,
2770                                    TALLOC_CTX *mem_ctx,
2771                                    struct security_descriptor **ppdesc)
2772 {
2773         NTSTATUS result;
2774
2775         START_PROFILE(get_nt_acl);
2776         result = posix_get_nt_acl(handle->conn,
2777                                 smb_fname,
2778                                 security_info,
2779                                 mem_ctx,
2780                                 ppdesc);
2781         END_PROFILE(get_nt_acl);
2782         return result;
2783 }
2784
2785 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2786 {
2787         NTSTATUS result;
2788
2789         START_PROFILE(fset_nt_acl);
2790         result = set_nt_acl(fsp, security_info_sent, psd);
2791         END_PROFILE(fset_nt_acl);
2792         return result;
2793 }
2794
2795 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2796                                    struct smb_filename *file,
2797                                    struct security_acl *sacl,
2798                                    uint32_t access_requested,
2799                                    uint32_t access_denied)
2800 {
2801         return NT_STATUS_OK; /* Nothing to do here ... */
2802 }
2803
2804 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2805                                 const struct smb_filename *smb_fname,
2806                                 mode_t mode)
2807 {
2808 #ifdef HAVE_NO_ACL
2809         errno = ENOSYS;
2810         return -1;
2811 #else
2812         int result;
2813
2814         START_PROFILE(chmod_acl);
2815         result = chmod_acl(handle->conn, smb_fname, mode);
2816         END_PROFILE(chmod_acl);
2817         return result;
2818 #endif
2819 }
2820
2821 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2822 {
2823 #ifdef HAVE_NO_ACL
2824         errno = ENOSYS;
2825         return -1;
2826 #else
2827         int result;
2828
2829         START_PROFILE(fchmod_acl);
2830         result = fchmod_acl(fsp, mode);
2831         END_PROFILE(fchmod_acl);
2832         return result;
2833 #endif
2834 }
2835
2836 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2837                                           const struct smb_filename *smb_fname,
2838                                           SMB_ACL_TYPE_T type,
2839                                           TALLOC_CTX *mem_ctx)
2840 {
2841         return sys_acl_get_file(handle, smb_fname, type, mem_ctx);
2842 }
2843
2844 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2845                                         files_struct *fsp,
2846                                         TALLOC_CTX *mem_ctx)
2847 {
2848         return sys_acl_get_fd(handle, fsp, mem_ctx);
2849 }
2850
2851 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,
2852                                 const struct smb_filename *smb_fname,
2853                                 SMB_ACL_TYPE_T acltype,
2854                                 SMB_ACL_T theacl)
2855 {
2856         return sys_acl_set_file(handle, smb_fname, acltype, theacl);
2857 }
2858
2859 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2860 {
2861         return sys_acl_set_fd(handle, fsp, theacl);
2862 }
2863
2864 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,
2865                         const struct smb_filename *smb_fname)
2866 {
2867         return sys_acl_delete_def_file(handle, smb_fname);
2868 }
2869
2870 /****************************************************************
2871  Extended attribute operations.
2872 *****************************************************************/
2873
2874 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
2875                         const struct smb_filename *smb_fname,
2876                         const char *name,
2877                         void *value,
2878                         size_t size)
2879 {
2880         return getxattr(smb_fname->base_name, name, value, size);
2881 }
2882
2883 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2884 {
2885         return fgetxattr(fsp->fh->fd, name, value, size);
2886 }
2887
2888 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle,
2889                         const struct smb_filename *smb_fname,
2890                         char *list,
2891                         size_t size)
2892 {
2893         return listxattr(smb_fname->base_name, list, size);
2894 }
2895
2896 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2897 {
2898         return flistxattr(fsp->fh->fd, list, size);
2899 }
2900
2901 static int vfswrap_removexattr(struct vfs_handle_struct *handle,
2902                                 const struct smb_filename *smb_fname,
2903                                 const char *name)
2904 {
2905         return removexattr(smb_fname->base_name, name);
2906 }
2907
2908 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2909 {
2910         return fremovexattr(fsp->fh->fd, name);
2911 }
2912
2913 static int vfswrap_setxattr(struct vfs_handle_struct *handle,
2914                                 const struct smb_filename *smb_fname,
2915                                 const char *name,
2916                                 const void *value,
2917                                 size_t size,
2918                                 int flags)
2919 {
2920         return setxattr(smb_fname->base_name, name, value, size, flags);
2921 }
2922
2923 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2924 {
2925         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2926 }
2927
2928 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2929 {
2930         return false;
2931 }
2932
2933 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2934                                const struct smb_filename *fname,
2935                                SMB_STRUCT_STAT *sbuf)
2936 {
2937         NTSTATUS status;
2938         char *path;
2939         bool offline = false;
2940
2941         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2942                 return false;
2943         }
2944
2945         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2946 #if defined(ENOTSUP)
2947                 errno = ENOTSUP;
2948 #endif
2949                 return false;
2950         }
2951
2952         status = get_full_smb_filename(talloc_tos(), fname, &path);
2953         if (!NT_STATUS_IS_OK(status)) {
2954                 errno = map_errno_from_nt_status(status);
2955                 return false;
2956         }
2957
2958         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2959
2960         TALLOC_FREE(path);
2961
2962         return offline;
2963 }
2964
2965 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2966                                        struct files_struct *fsp,
2967                                        TALLOC_CTX *mem_ctx,
2968                                        DATA_BLOB *cookie)
2969 {
2970         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2971 }
2972
2973 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2974                                            struct files_struct *fsp,
2975                                            const DATA_BLOB old_cookie,
2976                                            TALLOC_CTX *mem_ctx,
2977                                            DATA_BLOB *new_cookie)
2978 {
2979         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2980                                               new_cookie);
2981 }
2982
2983 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2984                                           struct smb_request *smb1req,
2985                                           struct smbXsrv_open *op,
2986                                           const DATA_BLOB old_cookie,
2987                                           TALLOC_CTX *mem_ctx,
2988                                           struct files_struct **fsp,
2989                                           DATA_BLOB *new_cookie)
2990 {
2991         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2992                                              old_cookie, mem_ctx,
2993                                              fsp, new_cookie);
2994 }
2995
2996 static struct vfs_fn_pointers vfs_default_fns = {
2997         /* Disk operations */
2998
2999         .connect_fn = vfswrap_connect,
3000         .disconnect_fn = vfswrap_disconnect,
3001         .disk_free_fn = vfswrap_disk_free,
3002         .get_quota_fn = vfswrap_get_quota,
3003         .set_quota_fn = vfswrap_set_quota,
3004         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
3005         .statvfs_fn = vfswrap_statvfs,
3006         .fs_capabilities_fn = vfswrap_fs_capabilities,
3007         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
3008         .snap_check_path_fn = vfswrap_snap_check_path,
3009         .snap_create_fn = vfswrap_snap_create,
3010         .snap_delete_fn = vfswrap_snap_delete,
3011
3012         /* Directory operations */
3013
3014         .opendir_fn = vfswrap_opendir,
3015         .fdopendir_fn = vfswrap_fdopendir,
3016         .readdir_fn = vfswrap_readdir,
3017         .readdir_attr_fn = vfswrap_readdir_attr,
3018         .seekdir_fn = vfswrap_seekdir,
3019         .telldir_fn = vfswrap_telldir,
3020         .rewind_dir_fn = vfswrap_rewinddir,
3021         .mkdir_fn = vfswrap_mkdir,
3022         .rmdir_fn = vfswrap_rmdir,
3023         .closedir_fn = vfswrap_closedir,
3024         .init_search_op_fn = vfswrap_init_search_op,
3025
3026         /* File operations */
3027
3028         .open_fn = vfswrap_open,
3029         .create_file_fn = vfswrap_create_file,
3030         .close_fn = vfswrap_close,
3031         .read_fn = vfswrap_read,
3032         .pread_fn = vfswrap_pread,
3033         .pread_send_fn = vfswrap_pread_send,
3034         .pread_recv_fn = vfswrap_pread_recv,
3035         .write_fn = vfswrap_write,
3036         .pwrite_fn = vfswrap_pwrite,
3037         .pwrite_send_fn = vfswrap_pwrite_send,
3038         .pwrite_recv_fn = vfswrap_pwrite_recv,
3039         .lseek_fn = vfswrap_lseek,
3040         .sendfile_fn = vfswrap_sendfile,
3041         .recvfile_fn = vfswrap_recvfile,
3042         .rename_fn = vfswrap_rename,
3043         .fsync_fn = vfswrap_fsync,
3044         .fsync_send_fn = vfswrap_fsync_send,
3045         .fsync_recv_fn = vfswrap_fsync_recv,
3046         .stat_fn = vfswrap_stat,
3047         .fstat_fn = vfswrap_fstat,
3048         .lstat_fn = vfswrap_lstat,
3049         .get_alloc_size_fn = vfswrap_get_alloc_size,
3050         .unlink_fn = vfswrap_unlink,
3051         .chmod_fn = vfswrap_chmod,
3052         .fchmod_fn = vfswrap_fchmod,
3053         .chown_fn = vfswrap_chown,
3054         .fchown_fn = vfswrap_fchown,
3055         .lchown_fn = vfswrap_lchown,
3056         .chdir_fn = vfswrap_chdir,
3057         .getwd_fn = vfswrap_getwd,
3058         .ntimes_fn = vfswrap_ntimes,
3059         .ftruncate_fn = vfswrap_ftruncate,
3060         .fallocate_fn = vfswrap_fallocate,
3061         .lock_fn = vfswrap_lock,
3062         .kernel_flock_fn = vfswrap_kernel_flock,
3063         .linux_setlease_fn = vfswrap_linux_setlease,
3064         .getlock_fn = vfswrap_getlock,
3065         .symlink_fn = vfswrap_symlink,
3066         .readlink_fn = vfswrap_readlink,
3067         .link_fn = vfswrap_link,
3068         .mknod_fn = vfswrap_mknod,
3069         .realpath_fn = vfswrap_realpath,
3070         .chflags_fn = vfswrap_chflags,
3071         .file_id_create_fn = vfswrap_file_id_create,
3072         .streaminfo_fn = vfswrap_streaminfo,
3073         .get_real_filename_fn = vfswrap_get_real_filename,
3074         .connectpath_fn = vfswrap_connectpath,
3075         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
3076         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
3077         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
3078         .strict_lock_fn = vfswrap_strict_lock,
3079         .strict_unlock_fn = vfswrap_strict_unlock,
3080         .translate_name_fn = vfswrap_translate_name,
3081         .fsctl_fn = vfswrap_fsctl,
3082         .set_dos_attributes_fn = vfswrap_set_dos_attributes,
3083         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
3084         .get_dos_attributes_fn = vfswrap_get_dos_attributes,
3085         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
3086         .offload_read_send_fn = vfswrap_offload_read_send,
3087         .offload_read_recv_fn = vfswrap_offload_read_recv,
3088         .offload_write_send_fn = vfswrap_offload_write_send,
3089         .offload_write_recv_fn = vfswrap_offload_write_recv,
3090         .get_compression_fn = vfswrap_get_compression,
3091         .set_compression_fn = vfswrap_set_compression,
3092
3093         /* NT ACL operations. */
3094
3095         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
3096         .get_nt_acl_fn = vfswrap_get_nt_acl,
3097         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
3098         .audit_file_fn = vfswrap_audit_file,
3099
3100         /* POSIX ACL operations. */
3101
3102         .chmod_acl_fn = vfswrap_chmod_acl,
3103         .fchmod_acl_fn = vfswrap_fchmod_acl,
3104
3105         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
3106         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
3107         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
3108         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
3109         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
3110         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
3111         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
3112
3113         /* EA operations. */
3114         .getxattr_fn = vfswrap_getxattr,
3115         .fgetxattr_fn = vfswrap_fgetxattr,
3116         .listxattr_fn = vfswrap_listxattr,
3117         .flistxattr_fn = vfswrap_flistxattr,
3118         .removexattr_fn = vfswrap_removexattr,
3119         .fremovexattr_fn = vfswrap_fremovexattr,
3120         .setxattr_fn = vfswrap_setxattr,
3121         .fsetxattr_fn = vfswrap_fsetxattr,
3122
3123         /* aio operations */
3124         .aio_force_fn = vfswrap_aio_force,
3125
3126         /* durable handle operations */
3127         .durable_cookie_fn = vfswrap_durable_cookie,
3128         .durable_disconnect_fn = vfswrap_durable_disconnect,
3129         .durable_reconnect_fn = vfswrap_durable_reconnect,
3130 };
3131
3132 NTSTATUS vfs_default_init(TALLOC_CTX *);
3133 NTSTATUS vfs_default_init(TALLOC_CTX *ctx)
3134 {
3135         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
3136                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
3137 }
3138
3139