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