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