vfs_default: let copy_chunk_send use const from IDL
[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         off_t copied;
1596         uint8_t *buf;
1597 };
1598
1599 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1600                                                   TALLOC_CTX *mem_ctx,
1601                                                   struct tevent_context *ev,
1602                                                   struct files_struct *src_fsp,
1603                                                   off_t src_off,
1604                                                   struct files_struct *dest_fsp,
1605                                                   off_t dest_off,
1606                                                   off_t num)
1607 {
1608         struct tevent_req *req;
1609         struct vfs_cc_state *vfs_cc_state;
1610         NTSTATUS status;
1611
1612         DEBUG(10, ("performing server side copy chunk of length %lu\n",
1613                    (unsigned long)num));
1614
1615         req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1616         if (req == NULL) {
1617                 return NULL;
1618         }
1619
1620         vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1621                                          MIN(num, COPYCHUNK_MAX_TOTAL_LEN));
1622         if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1623                 return tevent_req_post(req, ev);
1624         }
1625
1626         status = vfs_stat_fsp(src_fsp);
1627         if (tevent_req_nterror(req, status)) {
1628                 return tevent_req_post(req, ev);
1629         }
1630
1631         if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1632                 /*
1633                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1634                  *   If the SourceOffset or SourceOffset + Length extends beyond
1635                  *   the end of file, the server SHOULD<240> treat this as a
1636                  *   STATUS_END_OF_FILE error.
1637                  * ...
1638                  *   <240> Section 3.3.5.15.6: Windows servers will return
1639                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1640                  */
1641                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1642                 return tevent_req_post(req, ev);
1643         }
1644
1645         /* could use 2.6.33+ sendfile here to do this in kernel */
1646         while (vfs_cc_state->copied < num) {
1647                 ssize_t ret;
1648                 struct lock_struct lck;
1649                 int saved_errno;
1650
1651                 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1652                                      num - vfs_cc_state->copied);
1653
1654                 if (src_fsp->op == NULL) {
1655                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1656                         return tevent_req_post(req, ev);
1657                 }
1658                 init_strict_lock_struct(src_fsp,
1659                                         src_fsp->op->global->open_persistent_id,
1660                                         src_off,
1661                                         this_num,
1662                                         READ_LOCK,
1663                                         &lck);
1664
1665                 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1666                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1667                         return tevent_req_post(req, ev);
1668                 }
1669
1670                 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1671                                     this_num, src_off);
1672                 if (ret == -1) {
1673                         saved_errno = errno;
1674                 }
1675
1676                 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1677
1678                 if (ret == -1) {
1679                         errno = saved_errno;
1680                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1681                         return tevent_req_post(req, ev);
1682                 }
1683                 if (ret != this_num) {
1684                         /* zero tolerance for short reads */
1685                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1686                         return tevent_req_post(req, ev);
1687                 }
1688
1689                 src_off += ret;
1690
1691                 if (dest_fsp->op == NULL) {
1692                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1693                         return tevent_req_post(req, ev);
1694                 }
1695
1696                 init_strict_lock_struct(dest_fsp,
1697                                         dest_fsp->op->global->open_persistent_id,
1698                                         dest_off,
1699                                         this_num,
1700                                         WRITE_LOCK,
1701                                         &lck);
1702
1703                 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1704                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1705                         return tevent_req_post(req, ev);
1706                 }
1707
1708                 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1709                                      this_num, dest_off);
1710                 if (ret == -1) {
1711                         saved_errno = errno;
1712                 }
1713
1714                 SMB_VFS_STRICT_UNLOCK(dest_fsp->conn, dest_fsp, &lck);
1715
1716                 if (ret == -1) {
1717                         errno = saved_errno;
1718                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1719                         return tevent_req_post(req, ev);
1720                 }
1721                 if (ret != this_num) {
1722                         /* zero tolerance for short writes */
1723                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1724                         return tevent_req_post(req, ev);
1725                 }
1726                 dest_off += ret;
1727
1728                 vfs_cc_state->copied += this_num;
1729         }
1730
1731         tevent_req_done(req);
1732         return tevent_req_post(req, ev);
1733 }
1734
1735 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1736                                         struct tevent_req *req,
1737                                         off_t *copied)
1738 {
1739         struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1740                                                         struct vfs_cc_state);
1741         NTSTATUS status;
1742
1743         if (tevent_req_is_nterror(req, &status)) {
1744                 DEBUG(2, ("server side copy chunk failed: %s\n",
1745                           nt_errstr(status)));
1746                 *copied = 0;
1747                 tevent_req_received(req);
1748                 return status;
1749         }
1750
1751         *copied = vfs_cc_state->copied;
1752         DEBUG(10, ("server side copy chunk copied %lu\n",
1753                    (unsigned long)*copied));
1754         tevent_req_received(req);
1755
1756         return NT_STATUS_OK;
1757 }
1758
1759 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1760                                         TALLOC_CTX *mem_ctx,
1761                                         struct files_struct *fsp,
1762                                         struct smb_filename *smb_fname,
1763                                         uint16_t *_compression_fmt)
1764 {
1765         return NT_STATUS_INVALID_DEVICE_REQUEST;
1766 }
1767
1768 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1769                                         TALLOC_CTX *mem_ctx,
1770                                         struct files_struct *fsp,
1771                                         uint16_t compression_fmt)
1772 {
1773         return NT_STATUS_INVALID_DEVICE_REQUEST;
1774 }
1775
1776 /********************************************************************
1777  Given a stat buffer return the allocated size on disk, taking into
1778  account sparse files.
1779 ********************************************************************/
1780 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1781                                        struct files_struct *fsp,
1782                                        const SMB_STRUCT_STAT *sbuf)
1783 {
1784         uint64_t result;
1785
1786         START_PROFILE(syscall_get_alloc_size);
1787
1788         if(S_ISDIR(sbuf->st_ex_mode)) {
1789                 result = 0;
1790                 goto out;
1791         }
1792
1793 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1794         /* The type of st_blocksize is blkcnt_t which *MUST* be
1795            signed (according to POSIX) and can be less than 64-bits.
1796            Ensure when we're converting to 64 bits wide we don't
1797            sign extend. */
1798 #if defined(SIZEOF_BLKCNT_T_8)
1799         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1800 #elif defined(SIZEOF_BLKCNT_T_4)
1801         {
1802                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1803                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1804         }
1805 #else
1806 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1807 #endif
1808         if (result == 0) {
1809                 /*
1810                  * Some file systems do not allocate a block for very
1811                  * small files. But for non-empty file should report a
1812                  * positive size.
1813                  */
1814
1815                 uint64_t filesize = get_file_size_stat(sbuf);
1816                 if (filesize > 0) {
1817                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1818                 }
1819         }
1820 #else
1821         result = get_file_size_stat(sbuf);
1822 #endif
1823
1824         if (fsp && fsp->initial_allocation_size)
1825                 result = MAX(result,fsp->initial_allocation_size);
1826
1827         result = smb_roundup(handle->conn, result);
1828
1829  out:
1830         END_PROFILE(syscall_get_alloc_size);
1831         return result;
1832 }
1833
1834 static int vfswrap_unlink(vfs_handle_struct *handle,
1835                           const struct smb_filename *smb_fname)
1836 {
1837         int result = -1;
1838
1839         START_PROFILE(syscall_unlink);
1840
1841         if (smb_fname->stream_name) {
1842                 errno = ENOENT;
1843                 goto out;
1844         }
1845         result = unlink(smb_fname->base_name);
1846
1847  out:
1848         END_PROFILE(syscall_unlink);
1849         return result;
1850 }
1851
1852 static int vfswrap_chmod(vfs_handle_struct *handle,
1853                         const struct smb_filename *smb_fname,
1854                         mode_t mode)
1855 {
1856         int result;
1857
1858         START_PROFILE(syscall_chmod);
1859
1860         /*
1861          * We need to do this due to the fact that the default POSIX ACL
1862          * chmod modifies the ACL *mask* for the group owner, not the
1863          * group owner bits directly. JRA.
1864          */
1865
1866
1867         {
1868                 int saved_errno = errno; /* We might get ENOSYS */
1869                 result = SMB_VFS_CHMOD_ACL(handle->conn,
1870                                 smb_fname,
1871                                 mode);
1872                 if (result == 0) {
1873                         END_PROFILE(syscall_chmod);
1874                         return result;
1875                 }
1876                 /* Error - return the old errno. */
1877                 errno = saved_errno;
1878         }
1879
1880         result = chmod(smb_fname->base_name, mode);
1881         END_PROFILE(syscall_chmod);
1882         return result;
1883 }
1884
1885 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1886 {
1887         int result;
1888
1889         START_PROFILE(syscall_fchmod);
1890
1891         /*
1892          * We need to do this due to the fact that the default POSIX ACL
1893          * chmod modifies the ACL *mask* for the group owner, not the
1894          * group owner bits directly. JRA.
1895          */
1896
1897         {
1898                 int saved_errno = errno; /* We might get ENOSYS */
1899                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1900                         END_PROFILE(syscall_fchmod);
1901                         return result;
1902                 }
1903                 /* Error - return the old errno. */
1904                 errno = saved_errno;
1905         }
1906
1907 #if defined(HAVE_FCHMOD)
1908         result = fchmod(fsp->fh->fd, mode);
1909 #else
1910         result = -1;
1911         errno = ENOSYS;
1912 #endif
1913
1914         END_PROFILE(syscall_fchmod);
1915         return result;
1916 }
1917
1918 static int vfswrap_chown(vfs_handle_struct *handle,
1919                         const struct smb_filename *smb_fname,
1920                         uid_t uid,
1921                         gid_t gid)
1922 {
1923         int result;
1924
1925         START_PROFILE(syscall_chown);
1926         result = chown(smb_fname->base_name, uid, gid);
1927         END_PROFILE(syscall_chown);
1928         return result;
1929 }
1930
1931 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1932 {
1933 #ifdef HAVE_FCHOWN
1934         int result;
1935
1936         START_PROFILE(syscall_fchown);
1937         result = fchown(fsp->fh->fd, uid, gid);
1938         END_PROFILE(syscall_fchown);
1939         return result;
1940 #else
1941         errno = ENOSYS;
1942         return -1;
1943 #endif
1944 }
1945
1946 static int vfswrap_lchown(vfs_handle_struct *handle,
1947                         const struct smb_filename *smb_fname,
1948                         uid_t uid,
1949                         gid_t gid)
1950 {
1951         int result;
1952
1953         START_PROFILE(syscall_lchown);
1954         result = lchown(smb_fname->base_name, uid, gid);
1955         END_PROFILE(syscall_lchown);
1956         return result;
1957 }
1958
1959 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1960 {
1961         int result;
1962
1963         START_PROFILE(syscall_chdir);
1964         result = chdir(path);
1965         END_PROFILE(syscall_chdir);
1966         return result;
1967 }
1968
1969 static char *vfswrap_getwd(vfs_handle_struct *handle)
1970 {
1971         char *result;
1972
1973         START_PROFILE(syscall_getwd);
1974         result = sys_getwd();
1975         END_PROFILE(syscall_getwd);
1976         return result;
1977 }
1978
1979 /*********************************************************************
1980  nsec timestamp resolution call. Convert down to whatever the underlying
1981  system will support.
1982 **********************************************************************/
1983
1984 static int vfswrap_ntimes(vfs_handle_struct *handle,
1985                           const struct smb_filename *smb_fname,
1986                           struct smb_file_time *ft)
1987 {
1988         int result = -1;
1989
1990         START_PROFILE(syscall_ntimes);
1991
1992         if (smb_fname->stream_name) {
1993                 errno = ENOENT;
1994                 goto out;
1995         }
1996
1997         if (ft != NULL) {
1998                 if (null_timespec(ft->atime)) {
1999                         ft->atime= smb_fname->st.st_ex_atime;
2000                 }
2001
2002                 if (null_timespec(ft->mtime)) {
2003                         ft->mtime = smb_fname->st.st_ex_mtime;
2004                 }
2005
2006                 if (!null_timespec(ft->create_time)) {
2007                         set_create_timespec_ea(handle->conn,
2008                                                smb_fname,
2009                                                ft->create_time);
2010                 }
2011
2012                 if ((timespec_compare(&ft->atime,
2013                                       &smb_fname->st.st_ex_atime) == 0) &&
2014                     (timespec_compare(&ft->mtime,
2015                                       &smb_fname->st.st_ex_mtime) == 0)) {
2016                         return 0;
2017                 }
2018         }
2019
2020 #if defined(HAVE_UTIMENSAT)
2021         if (ft != NULL) {
2022                 struct timespec ts[2];
2023                 ts[0] = ft->atime;
2024                 ts[1] = ft->mtime;
2025                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
2026         } else {
2027                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
2028         }
2029         if (!((result == -1) && (errno == ENOSYS))) {
2030                 goto out;
2031         }
2032 #endif
2033 #if defined(HAVE_UTIMES)
2034         if (ft != NULL) {
2035                 struct timeval tv[2];
2036                 tv[0] = convert_timespec_to_timeval(ft->atime);
2037                 tv[1] = convert_timespec_to_timeval(ft->mtime);
2038                 result = utimes(smb_fname->base_name, tv);
2039         } else {
2040                 result = utimes(smb_fname->base_name, NULL);
2041         }
2042         if (!((result == -1) && (errno == ENOSYS))) {
2043                 goto out;
2044         }
2045 #endif
2046 #if defined(HAVE_UTIME)
2047         if (ft != NULL) {
2048                 struct utimbuf times;
2049                 times.actime = convert_timespec_to_time_t(ft->atime);
2050                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2051                 result = utime(smb_fname->base_name, &times);
2052         } else {
2053                 result = utime(smb_fname->base_name, NULL);
2054         }
2055         if (!((result == -1) && (errno == ENOSYS))) {
2056                 goto out;
2057         }
2058 #endif
2059         errno = ENOSYS;
2060         result = -1;
2061
2062  out:
2063         END_PROFILE(syscall_ntimes);
2064         return result;
2065 }
2066
2067 /*********************************************************************
2068  A version of ftruncate that will write the space on disk if strict
2069  allocate is set.
2070 **********************************************************************/
2071
2072 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2073 {
2074         off_t space_to_write;
2075         uint64_t space_avail;
2076         uint64_t bsize,dfree,dsize;
2077         int ret;
2078         NTSTATUS status;
2079         SMB_STRUCT_STAT *pst;
2080
2081         status = vfs_stat_fsp(fsp);
2082         if (!NT_STATUS_IS_OK(status)) {
2083                 return -1;
2084         }
2085         pst = &fsp->fsp_name->st;
2086
2087 #ifdef S_ISFIFO
2088         if (S_ISFIFO(pst->st_ex_mode))
2089                 return 0;
2090 #endif
2091
2092         if (pst->st_ex_size == len)
2093                 return 0;
2094
2095         /* Shrink - just ftruncate. */
2096         if (pst->st_ex_size > len)
2097                 return ftruncate(fsp->fh->fd, len);
2098
2099         space_to_write = len - pst->st_ex_size;
2100
2101         /* for allocation try fallocate first. This can fail on some
2102            platforms e.g. when the filesystem doesn't support it and no
2103            emulation is being done by the libc (like on AIX with JFS1). In that
2104            case we do our own emulation. fallocate implementations can
2105            return ENOTSUP or EINVAL in cases like that. */
2106         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2107         if (ret == -1 && errno == ENOSPC) {
2108                 return -1;
2109         }
2110         if (ret == 0) {
2111                 return 0;
2112         }
2113         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2114                 "error %d. Falling back to slow manual allocation\n", errno));
2115
2116         /* available disk space is enough or not? */
2117         space_avail =
2118             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2119         /* space_avail is 1k blocks */
2120         if (space_avail == (uint64_t)-1 ||
2121                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2122                 errno = ENOSPC;
2123                 return -1;
2124         }
2125
2126         /* Write out the real space on disk. */
2127         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2128         if (ret != 0) {
2129                 return -1;
2130         }
2131
2132         return 0;
2133 }
2134
2135 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2136 {
2137         int result = -1;
2138         SMB_STRUCT_STAT *pst;
2139         NTSTATUS status;
2140         char c = 0;
2141
2142         START_PROFILE(syscall_ftruncate);
2143
2144         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2145                 result = strict_allocate_ftruncate(handle, fsp, len);
2146                 END_PROFILE(syscall_ftruncate);
2147                 return result;
2148         }
2149
2150         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2151            ftruncate if the system supports it. Then I discovered that
2152            you can have some filesystems that support ftruncate
2153            expansion and some that don't! On Linux fat can't do
2154            ftruncate extend but ext2 can. */
2155
2156         result = ftruncate(fsp->fh->fd, len);
2157
2158         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2159            extend a file with ftruncate. Provide alternate implementation
2160            for this */
2161
2162         /* Do an fstat to see if the file is longer than the requested
2163            size in which case the ftruncate above should have
2164            succeeded or shorter, in which case seek to len - 1 and
2165            write 1 byte of zero */
2166         status = vfs_stat_fsp(fsp);
2167         if (!NT_STATUS_IS_OK(status)) {
2168                 goto done;
2169         }
2170
2171         /* We need to update the files_struct after successful ftruncate */
2172         if (result == 0) {
2173                 goto done;
2174         }
2175
2176         pst = &fsp->fsp_name->st;
2177
2178 #ifdef S_ISFIFO
2179         if (S_ISFIFO(pst->st_ex_mode)) {
2180                 result = 0;
2181                 goto done;
2182         }
2183 #endif
2184
2185         if (pst->st_ex_size == len) {
2186                 result = 0;
2187                 goto done;
2188         }
2189
2190         if (pst->st_ex_size > len) {
2191                 /* the ftruncate should have worked */
2192                 goto done;
2193         }
2194
2195         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2196                 goto done;
2197         }
2198
2199         result = 0;
2200
2201   done:
2202
2203         END_PROFILE(syscall_ftruncate);
2204         return result;
2205 }
2206
2207 static int vfswrap_fallocate(vfs_handle_struct *handle,
2208                         files_struct *fsp,
2209                         uint32_t mode,
2210                         off_t offset,
2211                         off_t len)
2212 {
2213         int result;
2214
2215         START_PROFILE(syscall_fallocate);
2216         if (mode == 0) {
2217                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2218                 /*
2219                  * posix_fallocate returns 0 on success, errno on error
2220                  * and doesn't set errno. Make it behave like fallocate()
2221                  * which returns -1, and sets errno on failure.
2222                  */
2223                 if (result != 0) {
2224                         errno = result;
2225                         result = -1;
2226                 }
2227         } else {
2228                 /* sys_fallocate handles filtering of unsupported mode flags */
2229                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2230         }
2231         END_PROFILE(syscall_fallocate);
2232         return result;
2233 }
2234
2235 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2236 {
2237         bool result;
2238
2239         START_PROFILE(syscall_fcntl_lock);
2240
2241         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2242                                                 "smbd",
2243                                                 "force process locks",
2244                                                 false)) {
2245                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2246         }
2247
2248         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
2249         END_PROFILE(syscall_fcntl_lock);
2250         return result;
2251 }
2252
2253 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2254                                 uint32_t share_mode, uint32_t access_mask)
2255 {
2256         START_PROFILE(syscall_kernel_flock);
2257         kernel_flock(fsp->fh->fd, share_mode, access_mask);
2258         END_PROFILE(syscall_kernel_flock);
2259         return 0;
2260 }
2261
2262 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2263 {
2264         bool result;
2265         int op = F_GETLK;
2266
2267         START_PROFILE(syscall_fcntl_getlock);
2268
2269         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2270                                                 "smbd",
2271                                                 "force process locks",
2272                                                 false)) {
2273                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2274         }
2275
2276         result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2277         END_PROFILE(syscall_fcntl_getlock);
2278         return result;
2279 }
2280
2281 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2282                                 int leasetype)
2283 {
2284         int result = -1;
2285
2286         START_PROFILE(syscall_linux_setlease);
2287
2288 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2289         result = linux_setlease(fsp->fh->fd, leasetype);
2290 #else
2291         errno = ENOSYS;
2292 #endif
2293         END_PROFILE(syscall_linux_setlease);
2294         return result;
2295 }
2296
2297 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2298 {
2299         int result;
2300
2301         START_PROFILE(syscall_symlink);
2302         result = symlink(oldpath, newpath);
2303         END_PROFILE(syscall_symlink);
2304         return result;
2305 }
2306
2307 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2308 {
2309         int result;
2310
2311         START_PROFILE(syscall_readlink);
2312         result = readlink(path, buf, bufsiz);
2313         END_PROFILE(syscall_readlink);
2314         return result;
2315 }
2316
2317 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2318 {
2319         int result;
2320
2321         START_PROFILE(syscall_link);
2322         result = link(oldpath, newpath);
2323         END_PROFILE(syscall_link);
2324         return result;
2325 }
2326
2327 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2328 {
2329         int result;
2330
2331         START_PROFILE(syscall_mknod);
2332         result = sys_mknod(pathname, mode, dev);
2333         END_PROFILE(syscall_mknod);
2334         return result;
2335 }
2336
2337 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2338 {
2339         char *result;
2340
2341         START_PROFILE(syscall_realpath);
2342         result = sys_realpath(path);
2343         END_PROFILE(syscall_realpath);
2344         return result;
2345 }
2346
2347 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2348                            unsigned int flags)
2349 {
2350 #ifdef HAVE_CHFLAGS
2351         return chflags(path, flags);
2352 #else
2353         errno = ENOSYS;
2354         return -1;
2355 #endif
2356 }
2357
2358 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2359                                              const SMB_STRUCT_STAT *sbuf)
2360 {
2361         struct file_id key;
2362
2363         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2364          * blob */
2365         ZERO_STRUCT(key);
2366
2367         key.devid = sbuf->st_ex_dev;
2368         key.inode = sbuf->st_ex_ino;
2369         /* key.extid is unused by default. */
2370
2371         return key;
2372 }
2373
2374 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2375                                    struct files_struct *fsp,
2376                                    const struct smb_filename *smb_fname,
2377                                    TALLOC_CTX *mem_ctx,
2378                                    unsigned int *pnum_streams,
2379                                    struct stream_struct **pstreams)
2380 {
2381         SMB_STRUCT_STAT sbuf;
2382         struct stream_struct *tmp_streams = NULL;
2383         int ret;
2384
2385         if ((fsp != NULL) && (fsp->is_directory)) {
2386                 /*
2387                  * No default streams on directories
2388                  */
2389                 goto done;
2390         }
2391
2392         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2393                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2394         }
2395         else {
2396                 struct smb_filename smb_fname_cp;
2397
2398                 ZERO_STRUCT(smb_fname_cp);
2399                 smb_fname_cp.base_name = discard_const_p(char,
2400                                         smb_fname->base_name);
2401                 smb_fname_cp.flags = smb_fname->flags;
2402
2403                 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2404                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2405                 } else {
2406                         ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2407                 }
2408                 sbuf = smb_fname_cp.st;
2409         }
2410
2411         if (ret == -1) {
2412                 return map_nt_error_from_unix(errno);
2413         }
2414
2415         if (S_ISDIR(sbuf.st_ex_mode)) {
2416                 goto done;
2417         }
2418
2419         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2420                                         (*pnum_streams) + 1);
2421         if (tmp_streams == NULL) {
2422                 return NT_STATUS_NO_MEMORY;
2423         }
2424         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2425         if (tmp_streams[*pnum_streams].name == NULL) {
2426                 return NT_STATUS_NO_MEMORY;
2427         }
2428         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2429         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2430
2431         *pnum_streams += 1;
2432         *pstreams = tmp_streams;
2433  done:
2434         return NT_STATUS_OK;
2435 }
2436
2437 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2438                                      const char *path,
2439                                      const char *name,
2440                                      TALLOC_CTX *mem_ctx,
2441                                      char **found_name)
2442 {
2443         /*
2444          * Don't fall back to get_real_filename so callers can differentiate
2445          * between a full directory scan and an actual case-insensitive stat.
2446          */
2447         errno = EOPNOTSUPP;
2448         return -1;
2449 }
2450
2451 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2452                                        const char *fname)
2453 {
2454         return handle->conn->connectpath;
2455 }
2456
2457 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2458                                          struct byte_range_lock *br_lck,
2459                                          struct lock_struct *plock,
2460                                          bool blocking_lock)
2461 {
2462         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2463
2464         /* Note: blr is not used in the default implementation. */
2465         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2466 }
2467
2468 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2469                                        struct messaging_context *msg_ctx,
2470                                        struct byte_range_lock *br_lck,
2471                                        const struct lock_struct *plock)
2472 {
2473         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2474
2475         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2476 }
2477
2478 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2479                                        struct byte_range_lock *br_lck,
2480                                        struct lock_struct *plock)
2481 {
2482         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2483
2484         /* Note: blr is not used in the default implementation. */
2485         return brl_lock_cancel_default(br_lck, plock);
2486 }
2487
2488 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2489                                 files_struct *fsp,
2490                                 struct lock_struct *plock)
2491 {
2492         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2493             plock->lock_type == WRITE_LOCK);
2494
2495         return strict_lock_default(fsp, plock);
2496 }
2497
2498 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2499                                 files_struct *fsp,
2500                                 struct lock_struct *plock)
2501 {
2502         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2503             plock->lock_type == WRITE_LOCK);
2504
2505         strict_unlock_default(fsp, plock);
2506 }
2507
2508 /* NT ACL operations. */
2509
2510 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2511                                     files_struct *fsp,
2512                                     uint32_t security_info,
2513                                     TALLOC_CTX *mem_ctx,
2514                                     struct security_descriptor **ppdesc)
2515 {
2516         NTSTATUS result;
2517
2518         START_PROFILE(fget_nt_acl);
2519         result = posix_fget_nt_acl(fsp, security_info,
2520                                    mem_ctx, ppdesc);
2521         END_PROFILE(fget_nt_acl);
2522         return result;
2523 }
2524
2525 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2526                                    const struct smb_filename *smb_fname,
2527                                    uint32_t security_info,
2528                                    TALLOC_CTX *mem_ctx,
2529                                    struct security_descriptor **ppdesc)
2530 {
2531         NTSTATUS result;
2532
2533         START_PROFILE(get_nt_acl);
2534         result = posix_get_nt_acl(handle->conn,
2535                                 smb_fname,
2536                                 security_info,
2537                                 mem_ctx,
2538                                 ppdesc);
2539         END_PROFILE(get_nt_acl);
2540         return result;
2541 }
2542
2543 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2544 {
2545         NTSTATUS result;
2546
2547         START_PROFILE(fset_nt_acl);
2548         result = set_nt_acl(fsp, security_info_sent, psd);
2549         END_PROFILE(fset_nt_acl);
2550         return result;
2551 }
2552
2553 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2554                                    struct smb_filename *file,
2555                                    struct security_acl *sacl,
2556                                    uint32_t access_requested,
2557                                    uint32_t access_denied)
2558 {
2559         return NT_STATUS_OK; /* Nothing to do here ... */
2560 }
2561
2562 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2563                                 const struct smb_filename *smb_fname,
2564                                 mode_t mode)
2565 {
2566 #ifdef HAVE_NO_ACL
2567         errno = ENOSYS;
2568         return -1;
2569 #else
2570         int result;
2571
2572         START_PROFILE(chmod_acl);
2573         result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2574         END_PROFILE(chmod_acl);
2575         return result;
2576 #endif
2577 }
2578
2579 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2580 {
2581 #ifdef HAVE_NO_ACL
2582         errno = ENOSYS;
2583         return -1;
2584 #else
2585         int result;
2586
2587         START_PROFILE(fchmod_acl);
2588         result = fchmod_acl(fsp, mode);
2589         END_PROFILE(fchmod_acl);
2590         return result;
2591 #endif
2592 }
2593
2594 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2595                                           const char *path_p,
2596                                           SMB_ACL_TYPE_T type,
2597                                           TALLOC_CTX *mem_ctx)
2598 {
2599         return sys_acl_get_file(handle, path_p, type, mem_ctx);
2600 }
2601
2602 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2603                                         files_struct *fsp,
2604                                         TALLOC_CTX *mem_ctx)
2605 {
2606         return sys_acl_get_fd(handle, fsp, mem_ctx);
2607 }
2608
2609 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2610 {
2611         return sys_acl_set_file(handle, name, acltype, theacl);
2612 }
2613
2614 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2615 {
2616         return sys_acl_set_fd(handle, fsp, theacl);
2617 }
2618
2619 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2620 {
2621         return sys_acl_delete_def_file(handle, path);
2622 }
2623
2624 /****************************************************************
2625  Extended attribute operations.
2626 *****************************************************************/
2627
2628 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2629 {
2630         return getxattr(path, name, value, size);
2631 }
2632
2633 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2634 {
2635         return fgetxattr(fsp->fh->fd, name, value, size);
2636 }
2637
2638 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2639 {
2640         return listxattr(path, list, size);
2641 }
2642
2643 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2644 {
2645         return flistxattr(fsp->fh->fd, list, size);
2646 }
2647
2648 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2649 {
2650         return removexattr(path, name);
2651 }
2652
2653 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2654 {
2655         return fremovexattr(fsp->fh->fd, name);
2656 }
2657
2658 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2659 {
2660         return setxattr(path, name, value, size, flags);
2661 }
2662
2663 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2664 {
2665         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2666 }
2667
2668 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2669 {
2670         return false;
2671 }
2672
2673 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2674                                const struct smb_filename *fname,
2675                                SMB_STRUCT_STAT *sbuf)
2676 {
2677         NTSTATUS status;
2678         char *path;
2679         bool offline = false;
2680
2681         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2682                 return false;
2683         }
2684
2685         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2686 #if defined(ENOTSUP)
2687                 errno = ENOTSUP;
2688 #endif
2689                 return false;
2690         }
2691
2692         status = get_full_smb_filename(talloc_tos(), fname, &path);
2693         if (!NT_STATUS_IS_OK(status)) {
2694                 errno = map_errno_from_nt_status(status);
2695                 return false;
2696         }
2697
2698         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2699
2700         TALLOC_FREE(path);
2701
2702         return offline;
2703 }
2704
2705 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2706                                        struct files_struct *fsp,
2707                                        TALLOC_CTX *mem_ctx,
2708                                        DATA_BLOB *cookie)
2709 {
2710         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2711 }
2712
2713 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2714                                            struct files_struct *fsp,
2715                                            const DATA_BLOB old_cookie,
2716                                            TALLOC_CTX *mem_ctx,
2717                                            DATA_BLOB *new_cookie)
2718 {
2719         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2720                                               new_cookie);
2721 }
2722
2723 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2724                                           struct smb_request *smb1req,
2725                                           struct smbXsrv_open *op,
2726                                           const DATA_BLOB old_cookie,
2727                                           TALLOC_CTX *mem_ctx,
2728                                           struct files_struct **fsp,
2729                                           DATA_BLOB *new_cookie)
2730 {
2731         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2732                                              old_cookie, mem_ctx,
2733                                              fsp, new_cookie);
2734 }
2735
2736 static struct vfs_fn_pointers vfs_default_fns = {
2737         /* Disk operations */
2738
2739         .connect_fn = vfswrap_connect,
2740         .disconnect_fn = vfswrap_disconnect,
2741         .disk_free_fn = vfswrap_disk_free,
2742         .get_quota_fn = vfswrap_get_quota,
2743         .set_quota_fn = vfswrap_set_quota,
2744         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2745         .statvfs_fn = vfswrap_statvfs,
2746         .fs_capabilities_fn = vfswrap_fs_capabilities,
2747         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2748         .snap_check_path_fn = vfswrap_snap_check_path,
2749         .snap_create_fn = vfswrap_snap_create,
2750         .snap_delete_fn = vfswrap_snap_delete,
2751
2752         /* Directory operations */
2753
2754         .opendir_fn = vfswrap_opendir,
2755         .fdopendir_fn = vfswrap_fdopendir,
2756         .readdir_fn = vfswrap_readdir,
2757         .readdir_attr_fn = vfswrap_readdir_attr,
2758         .seekdir_fn = vfswrap_seekdir,
2759         .telldir_fn = vfswrap_telldir,
2760         .rewind_dir_fn = vfswrap_rewinddir,
2761         .mkdir_fn = vfswrap_mkdir,
2762         .rmdir_fn = vfswrap_rmdir,
2763         .closedir_fn = vfswrap_closedir,
2764         .init_search_op_fn = vfswrap_init_search_op,
2765
2766         /* File operations */
2767
2768         .open_fn = vfswrap_open,
2769         .create_file_fn = vfswrap_create_file,
2770         .close_fn = vfswrap_close,
2771         .read_fn = vfswrap_read,
2772         .pread_fn = vfswrap_pread,
2773         .pread_send_fn = vfswrap_pread_send,
2774         .pread_recv_fn = vfswrap_pread_recv,
2775         .write_fn = vfswrap_write,
2776         .pwrite_fn = vfswrap_pwrite,
2777         .pwrite_send_fn = vfswrap_pwrite_send,
2778         .pwrite_recv_fn = vfswrap_pwrite_recv,
2779         .lseek_fn = vfswrap_lseek,
2780         .sendfile_fn = vfswrap_sendfile,
2781         .recvfile_fn = vfswrap_recvfile,
2782         .rename_fn = vfswrap_rename,
2783         .fsync_fn = vfswrap_fsync,
2784         .fsync_send_fn = vfswrap_fsync_send,
2785         .fsync_recv_fn = vfswrap_fsync_recv,
2786         .stat_fn = vfswrap_stat,
2787         .fstat_fn = vfswrap_fstat,
2788         .lstat_fn = vfswrap_lstat,
2789         .get_alloc_size_fn = vfswrap_get_alloc_size,
2790         .unlink_fn = vfswrap_unlink,
2791         .chmod_fn = vfswrap_chmod,
2792         .fchmod_fn = vfswrap_fchmod,
2793         .chown_fn = vfswrap_chown,
2794         .fchown_fn = vfswrap_fchown,
2795         .lchown_fn = vfswrap_lchown,
2796         .chdir_fn = vfswrap_chdir,
2797         .getwd_fn = vfswrap_getwd,
2798         .ntimes_fn = vfswrap_ntimes,
2799         .ftruncate_fn = vfswrap_ftruncate,
2800         .fallocate_fn = vfswrap_fallocate,
2801         .lock_fn = vfswrap_lock,
2802         .kernel_flock_fn = vfswrap_kernel_flock,
2803         .linux_setlease_fn = vfswrap_linux_setlease,
2804         .getlock_fn = vfswrap_getlock,
2805         .symlink_fn = vfswrap_symlink,
2806         .readlink_fn = vfswrap_readlink,
2807         .link_fn = vfswrap_link,
2808         .mknod_fn = vfswrap_mknod,
2809         .realpath_fn = vfswrap_realpath,
2810         .chflags_fn = vfswrap_chflags,
2811         .file_id_create_fn = vfswrap_file_id_create,
2812         .streaminfo_fn = vfswrap_streaminfo,
2813         .get_real_filename_fn = vfswrap_get_real_filename,
2814         .connectpath_fn = vfswrap_connectpath,
2815         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2816         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2817         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2818         .strict_lock_fn = vfswrap_strict_lock,
2819         .strict_unlock_fn = vfswrap_strict_unlock,
2820         .translate_name_fn = vfswrap_translate_name,
2821         .fsctl_fn = vfswrap_fsctl,
2822         .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2823         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2824         .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2825         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2826         .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2827         .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2828         .get_compression_fn = vfswrap_get_compression,
2829         .set_compression_fn = vfswrap_set_compression,
2830
2831         /* NT ACL operations. */
2832
2833         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2834         .get_nt_acl_fn = vfswrap_get_nt_acl,
2835         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2836         .audit_file_fn = vfswrap_audit_file,
2837
2838         /* POSIX ACL operations. */
2839
2840         .chmod_acl_fn = vfswrap_chmod_acl,
2841         .fchmod_acl_fn = vfswrap_fchmod_acl,
2842
2843         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2844         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2845         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2846         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2847         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2848         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2849         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2850
2851         /* EA operations. */
2852         .getxattr_fn = vfswrap_getxattr,
2853         .fgetxattr_fn = vfswrap_fgetxattr,
2854         .listxattr_fn = vfswrap_listxattr,
2855         .flistxattr_fn = vfswrap_flistxattr,
2856         .removexattr_fn = vfswrap_removexattr,
2857         .fremovexattr_fn = vfswrap_fremovexattr,
2858         .setxattr_fn = vfswrap_setxattr,
2859         .fsetxattr_fn = vfswrap_fsetxattr,
2860
2861         /* aio operations */
2862         .aio_force_fn = vfswrap_aio_force,
2863
2864         /* durable handle operations */
2865         .durable_cookie_fn = vfswrap_durable_cookie,
2866         .durable_disconnect_fn = vfswrap_durable_disconnect,
2867         .durable_reconnect_fn = vfswrap_durable_reconnect,
2868 };
2869
2870 NTSTATUS vfs_default_init(void);
2871 NTSTATUS vfs_default_init(void)
2872 {
2873         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2874                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
2875 }
2876
2877