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