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