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