vfs: Convert vfs_pread_send to pthreadpool_tevent
[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/asys/asys.h"
34 #include "lib/util/tevent_ntstatus.h"
35 #include "lib/util/sys_rw.h"
36 #include "lib/pthreadpool/pthreadpool_tevent.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 void vfswrap_asys_finished(struct tevent_context *ev,
710                                   struct tevent_fd *fde,
711                                   uint16_t flags, void *p);
712
713 static bool vfswrap_init_asys_ctx(struct smbd_server_connection *conn)
714 {
715         struct asys_context *ctx;
716         struct tevent_fd *fde;
717         int ret;
718         int fd;
719
720         if (conn->asys_ctx != NULL) {
721                 return true;
722         }
723
724         ret = asys_context_init(&ctx, lp_aio_max_threads());
725         if (ret != 0) {
726                 DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret)));
727                 return false;
728         }
729
730         fd = asys_signalfd(ctx);
731
732         ret = set_blocking(fd, false);
733         if (ret != 0) {
734                 DBG_WARNING("set_blocking failed: %s\n", strerror(errno));
735                 goto fail;
736         }
737
738         fde = tevent_add_fd(conn->ev_ctx, conn, fd, TEVENT_FD_READ,
739                             vfswrap_asys_finished, ctx);
740         if (fde == NULL) {
741                 DEBUG(1, ("tevent_add_fd failed\n"));
742                 goto fail;
743         }
744
745         conn->asys_ctx = ctx;
746         conn->asys_fde = fde;
747         return true;
748
749 fail:
750         asys_context_destroy(ctx);
751         return false;
752 }
753
754 static int vfswrap_init_pool(struct smbd_server_connection *conn)
755 {
756         int ret;
757
758         if (conn->pool != NULL) {
759                 return 0;
760         }
761
762         ret = pthreadpool_tevent_init(conn, lp_aio_max_threads(),
763                                       &conn->pool);
764         return ret;
765 }
766
767
768 struct vfswrap_asys_state {
769         struct asys_context *asys_ctx;
770         struct tevent_req *req;
771         ssize_t ret;
772         struct vfs_aio_state vfs_aio_state;
773         SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
774         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
775 };
776
777 static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s)
778 {
779         asys_cancel(s->asys_ctx, s->req);
780         return 0;
781 }
782
783 struct vfswrap_pread_state {
784         ssize_t ret;
785         int err;
786         int fd;
787         void *buf;
788         size_t count;
789         off_t offset;
790
791         struct vfs_aio_state vfs_aio_state;
792         SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
793 };
794
795 static void vfs_pread_do(void *private_data);
796 static void vfs_pread_done(struct tevent_req *subreq);
797
798 static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
799                                              TALLOC_CTX *mem_ctx,
800                                              struct tevent_context *ev,
801                                              struct files_struct *fsp,
802                                              void *data,
803                                              size_t n, off_t offset)
804 {
805         struct tevent_req *req, *subreq;
806         struct vfswrap_pread_state *state;
807         int ret;
808
809         req = tevent_req_create(mem_ctx, &state, struct vfswrap_pread_state);
810         if (req == NULL) {
811                 return NULL;
812         }
813
814         ret = vfswrap_init_pool(handle->conn->sconn);
815         if (tevent_req_error(req, ret)) {
816                 return tevent_req_post(req, ev);
817         }
818
819         state->ret = -1;
820         state->fd = fsp->fh->fd;
821         state->buf = data;
822         state->count = n;
823         state->offset = offset;
824
825         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p,
826                                      state->profile_bytes, n);
827         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
828
829         subreq = pthreadpool_tevent_job_send(
830                 state, ev, handle->conn->sconn->pool,
831                 vfs_pread_do, state);
832         if (tevent_req_nomem(subreq, req)) {
833                 return tevent_req_post(req, ev);
834         }
835         tevent_req_set_callback(subreq, vfs_pread_done, req);
836
837         return req;
838 }
839
840 static void vfs_pread_do(void *private_data)
841 {
842         struct vfswrap_pread_state *state = talloc_get_type_abort(
843                 private_data, struct vfswrap_pread_state);
844         struct timespec start_time;
845         struct timespec end_time;
846
847         SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes);
848
849         PROFILE_TIMESTAMP(&start_time);
850
851         do {
852                 state->ret = pread(state->fd, state->buf, state->count,
853                                    state->offset);
854         } while ((state->ret == -1) && (errno == EINTR));
855
856         state->err = errno;
857
858         PROFILE_TIMESTAMP(&end_time);
859
860         state->vfs_aio_state.duration = nsec_time_diff(&end_time, &start_time);
861
862         SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
863 }
864
865 static void vfs_pread_done(struct tevent_req *subreq)
866 {
867         struct tevent_req *req = tevent_req_callback_data(
868                 subreq, struct tevent_req);
869 #ifdef WITH_PROFILE
870         struct vfswrap_pread_state *state = tevent_req_data(
871                 req, struct vfswrap_pread_state);
872 #endif
873         int ret;
874
875         ret = pthreadpool_tevent_job_recv(subreq);
876         TALLOC_FREE(subreq);
877         SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
878         if (tevent_req_error(req, ret)) {
879                 return;
880         }
881
882         tevent_req_done(req);
883 }
884
885 static ssize_t vfswrap_pread_recv(struct tevent_req *req,
886                                   struct vfs_aio_state *vfs_aio_state)
887 {
888         struct vfswrap_pread_state *state = tevent_req_data(
889                 req, struct vfswrap_pread_state);
890
891         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
892                 return -1;
893         }
894
895         *vfs_aio_state = state->vfs_aio_state;
896         return state->ret;
897 }
898
899 static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
900                                               TALLOC_CTX *mem_ctx,
901                                               struct tevent_context *ev,
902                                               struct files_struct *fsp,
903                                               const void *data,
904                                               size_t n, off_t offset)
905 {
906         struct tevent_req *req;
907         struct vfswrap_asys_state *state;
908         int ret;
909
910         req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
911         if (req == NULL) {
912                 return NULL;
913         }
914         if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
915                 tevent_req_oom(req);
916                 return tevent_req_post(req, ev);
917         }
918         state->asys_ctx = handle->conn->sconn->asys_ctx;
919         state->req = req;
920
921         SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p,
922                                      state->profile_bytes, n);
923         ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req);
924         if (ret != 0) {
925                 tevent_req_error(req, ret);
926                 return tevent_req_post(req, ev);
927         }
928         talloc_set_destructor(state, vfswrap_asys_state_destructor);
929
930         return req;
931 }
932
933 static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
934                                              TALLOC_CTX *mem_ctx,
935                                              struct tevent_context *ev,
936                                              struct files_struct *fsp)
937 {
938         struct tevent_req *req;
939         struct vfswrap_asys_state *state;
940         int ret;
941
942         req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state);
943         if (req == NULL) {
944                 return NULL;
945         }
946         if (!vfswrap_init_asys_ctx(handle->conn->sconn)) {
947                 tevent_req_oom(req);
948                 return tevent_req_post(req, ev);
949         }
950         state->asys_ctx = handle->conn->sconn->asys_ctx;
951         state->req = req;
952
953         SMBPROFILE_BASIC_ASYNC_START(syscall_asys_fsync, profile_p,
954                                      state->profile_basic);
955         ret = asys_fsync(state->asys_ctx, fsp->fh->fd, req);
956         if (ret != 0) {
957                 tevent_req_error(req, ret);
958                 return tevent_req_post(req, ev);
959         }
960         talloc_set_destructor(state, vfswrap_asys_state_destructor);
961
962         return req;
963 }
964
965 static void vfswrap_asys_finished(struct tevent_context *ev,
966                                         struct tevent_fd *fde,
967                                         uint16_t flags, void *p)
968 {
969         struct asys_context *asys_ctx = (struct asys_context *)p;
970         struct asys_result results[get_outstanding_aio_calls()];
971         int i, ret;
972
973         if ((flags & TEVENT_FD_READ) == 0) {
974                 return;
975         }
976
977         ret = asys_results(asys_ctx, results, get_outstanding_aio_calls());
978         if (ret < 0) {
979                 DEBUG(1, ("asys_results returned %s\n", strerror(-ret)));
980                 return;
981         }
982
983         for (i=0; i<ret; i++) {
984                 struct asys_result *result = &results[i];
985                 struct tevent_req *req;
986                 struct vfswrap_asys_state *state;
987
988                 if ((result->ret == -1) && (result->err == ECANCELED)) {
989                         continue;
990                 }
991
992                 req = talloc_get_type_abort(result->private_data,
993                                             struct tevent_req);
994                 state = tevent_req_data(req, struct vfswrap_asys_state);
995
996                 talloc_set_destructor(state, NULL);
997
998                 SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
999                 SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
1000                 state->ret = result->ret;
1001                 state->vfs_aio_state.error = result->err;
1002                 state->vfs_aio_state.duration = result->duration;
1003                 tevent_req_defer_callback(req, ev);
1004                 tevent_req_done(req);
1005         }
1006 }
1007
1008 static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
1009                                          struct vfs_aio_state *vfs_aio_state)
1010 {
1011         struct vfswrap_asys_state *state = tevent_req_data(
1012                 req, struct vfswrap_asys_state);
1013
1014         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1015                 return -1;
1016         }
1017         *vfs_aio_state = state->vfs_aio_state;
1018         return state->ret;
1019 }
1020
1021 static int vfswrap_asys_int_recv(struct tevent_req *req,
1022                                  struct vfs_aio_state *vfs_aio_state)
1023 {
1024         struct vfswrap_asys_state *state = tevent_req_data(
1025                 req, struct vfswrap_asys_state);
1026
1027         if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
1028                 return -1;
1029         }
1030         *vfs_aio_state = state->vfs_aio_state;
1031         return state->ret;
1032 }
1033
1034 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
1035 {
1036         off_t result = 0;
1037
1038         START_PROFILE(syscall_lseek);
1039
1040         /* Cope with 'stat' file opens. */
1041         if (fsp->fh->fd != -1)
1042                 result = lseek(fsp->fh->fd, offset, whence);
1043
1044         /*
1045          * We want to maintain the fiction that we can seek
1046          * on a fifo for file system purposes. This allows
1047          * people to set up UNIX fifo's that feed data to Windows
1048          * applications. JRA.
1049          */
1050
1051         if((result == -1) && (errno == ESPIPE)) {
1052                 result = 0;
1053                 errno = 0;
1054         }
1055
1056         END_PROFILE(syscall_lseek);
1057         return result;
1058 }
1059
1060 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
1061                         off_t offset, size_t n)
1062 {
1063         ssize_t result;
1064
1065         START_PROFILE_BYTES(syscall_sendfile, n);
1066         result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
1067         END_PROFILE_BYTES(syscall_sendfile);
1068         return result;
1069 }
1070
1071 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
1072                         int fromfd,
1073                         files_struct *tofsp,
1074                         off_t offset,
1075                         size_t n)
1076 {
1077         ssize_t result;
1078
1079         START_PROFILE_BYTES(syscall_recvfile, n);
1080         result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
1081         END_PROFILE_BYTES(syscall_recvfile);
1082         return result;
1083 }
1084
1085 static int vfswrap_rename(vfs_handle_struct *handle,
1086                           const struct smb_filename *smb_fname_src,
1087                           const struct smb_filename *smb_fname_dst)
1088 {
1089         int result = -1;
1090
1091         START_PROFILE(syscall_rename);
1092
1093         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
1094                 errno = ENOENT;
1095                 goto out;
1096         }
1097
1098         result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
1099
1100  out:
1101         END_PROFILE(syscall_rename);
1102         return result;
1103 }
1104
1105 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
1106 {
1107 #ifdef HAVE_FSYNC
1108         int result;
1109
1110         START_PROFILE(syscall_fsync);
1111         result = fsync(fsp->fh->fd);
1112         END_PROFILE(syscall_fsync);
1113         return result;
1114 #else
1115         return 0;
1116 #endif
1117 }
1118
1119 static int vfswrap_stat(vfs_handle_struct *handle,
1120                         struct smb_filename *smb_fname)
1121 {
1122         int result = -1;
1123
1124         START_PROFILE(syscall_stat);
1125
1126         if (smb_fname->stream_name) {
1127                 errno = ENOENT;
1128                 goto out;
1129         }
1130
1131         result = sys_stat(smb_fname->base_name, &smb_fname->st,
1132                           lp_fake_directory_create_times(SNUM(handle->conn)));
1133  out:
1134         END_PROFILE(syscall_stat);
1135         return result;
1136 }
1137
1138 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1139 {
1140         int result;
1141
1142         START_PROFILE(syscall_fstat);
1143         result = sys_fstat(fsp->fh->fd,
1144                            sbuf, lp_fake_directory_create_times(SNUM(handle->conn)));
1145         END_PROFILE(syscall_fstat);
1146         return result;
1147 }
1148
1149 static int vfswrap_lstat(vfs_handle_struct *handle,
1150                          struct smb_filename *smb_fname)
1151 {
1152         int result = -1;
1153
1154         START_PROFILE(syscall_lstat);
1155
1156         if (smb_fname->stream_name) {
1157                 errno = ENOENT;
1158                 goto out;
1159         }
1160
1161         result = sys_lstat(smb_fname->base_name, &smb_fname->st,
1162                            lp_fake_directory_create_times(SNUM(handle->conn)));
1163  out:
1164         END_PROFILE(syscall_lstat);
1165         return result;
1166 }
1167
1168 static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
1169                                        const char *name,
1170                                        enum vfs_translate_direction direction,
1171                                        TALLOC_CTX *mem_ctx,
1172                                        char **mapped_name)
1173 {
1174         return NT_STATUS_NONE_MAPPED;
1175 }
1176
1177 /*
1178  * Implement the default fsctl operation.
1179  */
1180 static bool vfswrap_logged_ioctl_message = false;
1181
1182 static NTSTATUS vfswrap_fsctl(struct vfs_handle_struct *handle,
1183                               struct files_struct *fsp,
1184                               TALLOC_CTX *ctx,
1185                               uint32_t function,
1186                               uint16_t req_flags, /* Needed for UNICODE ... */
1187                               const uint8_t *_in_data,
1188                               uint32_t in_len,
1189                               uint8_t **_out_data,
1190                               uint32_t max_out_len,
1191                               uint32_t *out_len)
1192 {
1193         const char *in_data = (const char *)_in_data;
1194         char **out_data = (char **)_out_data;
1195         NTSTATUS status;
1196
1197         switch (function) {
1198         case FSCTL_SET_SPARSE:
1199         {
1200                 bool set_sparse = true;
1201
1202                 if (in_len >= 1 && in_data[0] == 0) {
1203                         set_sparse = false;
1204                 }
1205
1206                 status = file_set_sparse(handle->conn, fsp, set_sparse);
1207
1208                 DEBUG(NT_STATUS_IS_OK(status) ? 10 : 9,
1209                       ("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
1210                        smb_fname_str_dbg(fsp->fsp_name), set_sparse,
1211                        nt_errstr(status)));
1212
1213                 return status;
1214         }
1215
1216         case FSCTL_CREATE_OR_GET_OBJECT_ID:
1217         {
1218                 unsigned char objid[16];
1219                 char *return_data = NULL;
1220
1221                 /* This should return the object-id on this file.
1222                  * I think I'll make this be the inode+dev. JRA.
1223                  */
1224
1225                 DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s\n",
1226                           fsp_fnum_dbg(fsp)));
1227
1228                 *out_len = MIN(max_out_len, 64);
1229
1230                 /* Hmmm, will this cause problems if less data asked for? */
1231                 return_data = talloc_array(ctx, char, 64);
1232                 if (return_data == NULL) {
1233                         return NT_STATUS_NO_MEMORY;
1234                 }
1235
1236                 /* For backwards compatibility only store the dev/inode. */
1237                 push_file_id_16(return_data, &fsp->file_id);
1238                 memcpy(return_data+16,create_volume_objectid(fsp->conn,objid),16);
1239                 push_file_id_16(return_data+32, &fsp->file_id);
1240                 memset(return_data+48, 0, 16);
1241                 *out_data = return_data;
1242                 return NT_STATUS_OK;
1243         }
1244
1245         case FSCTL_GET_REPARSE_POINT:
1246         {
1247                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1248                 DEBUG(10, ("FSCTL_GET_REPARSE_POINT: called on %s. "
1249                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1250                 return NT_STATUS_NOT_A_REPARSE_POINT;
1251         }
1252
1253         case FSCTL_SET_REPARSE_POINT:
1254         {
1255                 /* Fail it with STATUS_NOT_A_REPARSE_POINT */
1256                 DEBUG(10, ("FSCTL_SET_REPARSE_POINT: called on %s. "
1257                            "Status: NOT_IMPLEMENTED\n", fsp_fnum_dbg(fsp)));
1258                 return NT_STATUS_NOT_A_REPARSE_POINT;
1259         }
1260
1261         case FSCTL_GET_SHADOW_COPY_DATA:
1262         {
1263                 /*
1264                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
1265                  * and return their volume names.  If max_data_count is 16, then it is just
1266                  * asking for the number of volumes and length of the combined names.
1267                  *
1268                  * pdata is the data allocated by our caller, but that uses
1269                  * total_data_count (which is 0 in our case) rather than max_data_count.
1270                  * Allocate the correct amount and return the pointer to let
1271                  * it be deallocated when we return.
1272                  */
1273                 struct shadow_copy_data *shadow_data = NULL;
1274                 bool labels = False;
1275                 uint32_t labels_data_count = 0;
1276                 uint32_t i;
1277                 char *cur_pdata = NULL;
1278
1279                 if (max_out_len < 16) {
1280                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
1281                                 max_out_len));
1282                         return NT_STATUS_INVALID_PARAMETER;
1283                 }
1284
1285                 if (max_out_len > 16) {
1286                         labels = True;
1287                 }
1288
1289                 shadow_data = talloc_zero(ctx, struct shadow_copy_data);
1290                 if (shadow_data == NULL) {
1291                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
1292                         return NT_STATUS_NO_MEMORY;
1293                 }
1294
1295                 /*
1296                  * Call the VFS routine to actually do the work.
1297                  */
1298                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
1299                         int log_lev = 0;
1300                         if (errno == 0) {
1301                                 /* broken module didn't set errno on error */
1302                                 status = NT_STATUS_UNSUCCESSFUL;
1303                         } else {
1304                                 status = map_nt_error_from_unix(errno);
1305                                 if (NT_STATUS_EQUAL(status,
1306                                                     NT_STATUS_NOT_SUPPORTED)) {
1307                                         log_lev = 5;
1308                                 }
1309                         }
1310                         DEBUG(log_lev, ("FSCTL_GET_SHADOW_COPY_DATA: "
1311                                         "connectpath %s, failed - %s.\n",
1312                                         fsp->conn->connectpath,
1313                                         nt_errstr(status)));
1314                         TALLOC_FREE(shadow_data);
1315                         return status;
1316                 }
1317
1318                 labels_data_count = (shadow_data->num_volumes * 2 *
1319                                         sizeof(SHADOW_COPY_LABEL)) + 2;
1320
1321                 if (!labels) {
1322                         *out_len = 16;
1323                 } else {
1324                         *out_len = 12 + labels_data_count;
1325                 }
1326
1327                 if (max_out_len < *out_len) {
1328                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
1329                                 max_out_len, *out_len));
1330                         TALLOC_FREE(shadow_data);
1331                         return NT_STATUS_BUFFER_TOO_SMALL;
1332                 }
1333
1334                 cur_pdata = talloc_zero_array(ctx, char, *out_len);
1335                 if (cur_pdata == NULL) {
1336                         TALLOC_FREE(shadow_data);
1337                         return NT_STATUS_NO_MEMORY;
1338                 }
1339
1340                 *out_data = cur_pdata;
1341
1342                 /* num_volumes 4 bytes */
1343                 SIVAL(cur_pdata, 0, shadow_data->num_volumes);
1344
1345                 if (labels) {
1346                         /* num_labels 4 bytes */
1347                         SIVAL(cur_pdata, 4, shadow_data->num_volumes);
1348                 }
1349
1350                 /* needed_data_count 4 bytes */
1351                 SIVAL(cur_pdata, 8, labels_data_count);
1352
1353                 cur_pdata += 12;
1354
1355                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
1356                           shadow_data->num_volumes, fsp_str_dbg(fsp)));
1357                 if (labels && shadow_data->labels) {
1358                         for (i=0; i<shadow_data->num_volumes; i++) {
1359                                 size_t len = 0;
1360                                 status = srvstr_push(cur_pdata, req_flags,
1361                                             cur_pdata, shadow_data->labels[i],
1362                                             2 * sizeof(SHADOW_COPY_LABEL),
1363                                             STR_UNICODE|STR_TERMINATE, &len);
1364                                 if (!NT_STATUS_IS_OK(status)) {
1365                                         TALLOC_FREE(*out_data);
1366                                         TALLOC_FREE(shadow_data);
1367                                         return status;
1368                                 }
1369                                 cur_pdata += 2 * sizeof(SHADOW_COPY_LABEL);
1370                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
1371                         }
1372                 }
1373
1374                 TALLOC_FREE(shadow_data);
1375
1376                 return NT_STATUS_OK;
1377         }
1378
1379         case FSCTL_FIND_FILES_BY_SID:
1380         {
1381                 /* pretend this succeeded -
1382                  *
1383                  * we have to send back a list with all files owned by this SID
1384                  *
1385                  * but I have to check that --metze
1386                  */
1387                 struct dom_sid sid;
1388                 uid_t uid;
1389                 size_t sid_len;
1390
1391                 DEBUG(10, ("FSCTL_FIND_FILES_BY_SID: called on %s\n",
1392                            fsp_fnum_dbg(fsp)));
1393
1394                 if (in_len < 8) {
1395                         /* NT_STATUS_BUFFER_TOO_SMALL maybe? */
1396                         return NT_STATUS_INVALID_PARAMETER;
1397                 }
1398
1399                 sid_len = MIN(in_len - 4,SID_MAX_SIZE);
1400
1401                 /* unknown 4 bytes: this is not the length of the sid :-(  */
1402                 /*unknown = IVAL(pdata,0);*/
1403
1404                 if (!sid_parse(_in_data + 4, sid_len, &sid)) {
1405                         return NT_STATUS_INVALID_PARAMETER;
1406                 }
1407                 DEBUGADD(10, ("for SID: %s\n", sid_string_dbg(&sid)));
1408
1409                 if (!sid_to_uid(&sid, &uid)) {
1410                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
1411                                  sid_string_dbg(&sid),
1412                                  (unsigned long)sid_len));
1413                         uid = (-1);
1414                 }
1415
1416                 /* we can take a look at the find source :-)
1417                  *
1418                  * find ./ -uid $uid  -name '*'   is what we need here
1419                  *
1420                  *
1421                  * and send 4bytes len and then NULL terminated unicode strings
1422                  * for each file
1423                  *
1424                  * but I don't know how to deal with the paged results
1425                  * (maybe we can hang the result anywhere in the fsp struct)
1426                  *
1427                  * but I don't know how to deal with the paged results
1428                  * (maybe we can hang the result anywhere in the fsp struct)
1429                  *
1430                  * we don't send all files at once
1431                  * and at the next we should *not* start from the beginning,
1432                  * so we have to cache the result
1433                  *
1434                  * --metze
1435                  */
1436
1437                 /* this works for now... */
1438                 return NT_STATUS_OK;
1439         }
1440
1441         case FSCTL_QUERY_ALLOCATED_RANGES:
1442         {
1443                 /* FIXME: This is just a dummy reply, telling that all of the
1444                  * file is allocated. MKS cp needs that.
1445                  * Adding the real allocated ranges via FIEMAP on Linux
1446                  * and SEEK_DATA/SEEK_HOLE on Solaris is needed to make
1447                  * this FSCTL correct for sparse files.
1448                  */
1449                 uint64_t offset, length;
1450                 char *out_data_tmp = NULL;
1451
1452                 if (in_len != 16) {
1453                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid!\n",
1454                                 in_len));
1455                         return NT_STATUS_INVALID_PARAMETER;
1456                 }
1457
1458                 if (max_out_len < 16) {
1459                         DEBUG(0,("FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid!\n",
1460                                 max_out_len));
1461                         return NT_STATUS_INVALID_PARAMETER;
1462                 }
1463
1464                 offset = BVAL(in_data,0);
1465                 length = BVAL(in_data,8);
1466
1467                 if (offset + length < offset) {
1468                         /* No 64-bit integer wrap. */
1469                         return NT_STATUS_INVALID_PARAMETER;
1470                 }
1471
1472                 /* Shouldn't this be SMB_VFS_STAT ... ? */
1473                 status = vfs_stat_fsp(fsp);
1474                 if (!NT_STATUS_IS_OK(status)) {
1475                         return status;
1476                 }
1477
1478                 *out_len = 16;
1479                 out_data_tmp = talloc_array(ctx, char, *out_len);
1480                 if (out_data_tmp == NULL) {
1481                         DEBUG(10, ("unable to allocate memory for response\n"));
1482                         return NT_STATUS_NO_MEMORY;
1483                 }
1484
1485                 if (offset > fsp->fsp_name->st.st_ex_size ||
1486                                 fsp->fsp_name->st.st_ex_size == 0 ||
1487                                 length == 0) {
1488                         memset(out_data_tmp, 0, *out_len);
1489                 } else {
1490                         uint64_t end = offset + length;
1491                         end = MIN(end, fsp->fsp_name->st.st_ex_size);
1492                         SBVAL(out_data_tmp, 0, 0);
1493                         SBVAL(out_data_tmp, 8, end);
1494                 }
1495
1496                 *out_data = out_data_tmp;
1497
1498                 return NT_STATUS_OK;
1499         }
1500
1501         case FSCTL_IS_VOLUME_DIRTY:
1502         {
1503                 DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on %s "
1504                           "(but remotely not supported)\n", fsp_fnum_dbg(fsp)));
1505                 /*
1506                  * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
1507                  * says we have to respond with NT_STATUS_INVALID_PARAMETER
1508                  */
1509                 return NT_STATUS_INVALID_PARAMETER;
1510         }
1511
1512         default:
1513                 /*
1514                  * Only print once ... unfortunately there could be lots of
1515                  * different FSCTLs that are called.
1516                  */
1517                 if (!vfswrap_logged_ioctl_message) {
1518                         vfswrap_logged_ioctl_message = true;
1519                         DEBUG(2, ("%s (0x%x): Currently not implemented.\n",
1520                         __func__, function));
1521                 }
1522         }
1523
1524         return NT_STATUS_NOT_SUPPORTED;
1525 }
1526
1527 static NTSTATUS vfswrap_get_dos_attributes(struct vfs_handle_struct *handle,
1528                                            struct smb_filename *smb_fname,
1529                                            uint32_t *dosmode)
1530 {
1531         return get_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1532 }
1533
1534 static NTSTATUS vfswrap_fget_dos_attributes(struct vfs_handle_struct *handle,
1535                                             struct files_struct *fsp,
1536                                             uint32_t *dosmode)
1537 {
1538         return get_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1539 }
1540
1541 static NTSTATUS vfswrap_set_dos_attributes(struct vfs_handle_struct *handle,
1542                                            const struct smb_filename *smb_fname,
1543                                            uint32_t dosmode)
1544 {
1545         return set_ea_dos_attribute(handle->conn, smb_fname, dosmode);
1546 }
1547
1548 static NTSTATUS vfswrap_fset_dos_attributes(struct vfs_handle_struct *handle,
1549                                             struct files_struct *fsp,
1550                                             uint32_t dosmode)
1551 {
1552         return set_ea_dos_attribute(handle->conn, fsp->fsp_name, dosmode);
1553 }
1554
1555 struct vfs_cc_state {
1556         off_t copied;
1557         uint8_t *buf;
1558 };
1559
1560 static struct tevent_req *vfswrap_copy_chunk_send(struct vfs_handle_struct *handle,
1561                                                   TALLOC_CTX *mem_ctx,
1562                                                   struct tevent_context *ev,
1563                                                   struct files_struct *src_fsp,
1564                                                   off_t src_off,
1565                                                   struct files_struct *dest_fsp,
1566                                                   off_t dest_off,
1567                                                   off_t num)
1568 {
1569         struct tevent_req *req;
1570         struct vfs_cc_state *vfs_cc_state;
1571         NTSTATUS status;
1572
1573         DEBUG(10, ("performing server side copy chunk of length %lu\n",
1574                    (unsigned long)num));
1575
1576         req = tevent_req_create(mem_ctx, &vfs_cc_state, struct vfs_cc_state);
1577         if (req == NULL) {
1578                 return NULL;
1579         }
1580
1581         vfs_cc_state->buf = talloc_array(vfs_cc_state, uint8_t,
1582                                          MIN(num, 8*1024*1024));
1583         if (tevent_req_nomem(vfs_cc_state->buf, req)) {
1584                 return tevent_req_post(req, ev);
1585         }
1586
1587         status = vfs_stat_fsp(src_fsp);
1588         if (tevent_req_nterror(req, status)) {
1589                 return tevent_req_post(req, ev);
1590         }
1591
1592         if (src_fsp->fsp_name->st.st_ex_size < src_off + num) {
1593                 /*
1594                  * [MS-SMB2] 3.3.5.15.6 Handling a Server-Side Data Copy Request
1595                  *   If the SourceOffset or SourceOffset + Length extends beyond
1596                  *   the end of file, the server SHOULD<240> treat this as a
1597                  *   STATUS_END_OF_FILE error.
1598                  * ...
1599                  *   <240> Section 3.3.5.15.6: Windows servers will return
1600                  *   STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE.
1601                  */
1602                 tevent_req_nterror(req, NT_STATUS_INVALID_VIEW_SIZE);
1603                 return tevent_req_post(req, ev);
1604         }
1605
1606         /* could use 2.6.33+ sendfile here to do this in kernel */
1607         while (vfs_cc_state->copied < num) {
1608                 ssize_t ret;
1609                 struct lock_struct lck;
1610                 int saved_errno;
1611
1612                 off_t this_num = MIN(talloc_array_length(vfs_cc_state->buf),
1613                                      num - vfs_cc_state->copied);
1614
1615                 if (src_fsp->op == NULL) {
1616                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1617                         return tevent_req_post(req, ev);
1618                 }
1619                 init_strict_lock_struct(src_fsp,
1620                                         src_fsp->op->global->open_persistent_id,
1621                                         src_off,
1622                                         this_num,
1623                                         READ_LOCK,
1624                                         &lck);
1625
1626                 if (!SMB_VFS_STRICT_LOCK(src_fsp->conn, src_fsp, &lck)) {
1627                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1628                         return tevent_req_post(req, ev);
1629                 }
1630
1631                 ret = SMB_VFS_PREAD(src_fsp, vfs_cc_state->buf,
1632                                     this_num, src_off);
1633                 if (ret == -1) {
1634                         saved_errno = errno;
1635                 }
1636
1637                 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1638
1639                 if (ret == -1) {
1640                         errno = saved_errno;
1641                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1642                         return tevent_req_post(req, ev);
1643                 }
1644                 if (ret != this_num) {
1645                         /* zero tolerance for short reads */
1646                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1647                         return tevent_req_post(req, ev);
1648                 }
1649
1650                 src_off += ret;
1651
1652                 if (dest_fsp->op == NULL) {
1653                         tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1654                         return tevent_req_post(req, ev);
1655                 }
1656
1657                 init_strict_lock_struct(dest_fsp,
1658                                         dest_fsp->op->global->open_persistent_id,
1659                                         dest_off,
1660                                         this_num,
1661                                         WRITE_LOCK,
1662                                         &lck);
1663
1664                 if (!SMB_VFS_STRICT_LOCK(dest_fsp->conn, dest_fsp, &lck)) {
1665                         tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
1666                         return tevent_req_post(req, ev);
1667                 }
1668
1669                 ret = SMB_VFS_PWRITE(dest_fsp, vfs_cc_state->buf,
1670                                      this_num, dest_off);
1671                 if (ret == -1) {
1672                         saved_errno = errno;
1673                 }
1674
1675                 SMB_VFS_STRICT_UNLOCK(src_fsp->conn, src_fsp, &lck);
1676
1677                 if (ret == -1) {
1678                         errno = saved_errno;
1679                         tevent_req_nterror(req, map_nt_error_from_unix(errno));
1680                         return tevent_req_post(req, ev);
1681                 }
1682                 if (ret != this_num) {
1683                         /* zero tolerance for short writes */
1684                         tevent_req_nterror(req, NT_STATUS_IO_DEVICE_ERROR);
1685                         return tevent_req_post(req, ev);
1686                 }
1687                 dest_off += ret;
1688
1689                 vfs_cc_state->copied += this_num;
1690         }
1691
1692         tevent_req_done(req);
1693         return tevent_req_post(req, ev);
1694 }
1695
1696 static NTSTATUS vfswrap_copy_chunk_recv(struct vfs_handle_struct *handle,
1697                                         struct tevent_req *req,
1698                                         off_t *copied)
1699 {
1700         struct vfs_cc_state *vfs_cc_state = tevent_req_data(req,
1701                                                         struct vfs_cc_state);
1702         NTSTATUS status;
1703
1704         if (tevent_req_is_nterror(req, &status)) {
1705                 DEBUG(2, ("server side copy chunk failed: %s\n",
1706                           nt_errstr(status)));
1707                 *copied = 0;
1708                 tevent_req_received(req);
1709                 return status;
1710         }
1711
1712         *copied = vfs_cc_state->copied;
1713         DEBUG(10, ("server side copy chunk copied %lu\n",
1714                    (unsigned long)*copied));
1715         tevent_req_received(req);
1716
1717         return NT_STATUS_OK;
1718 }
1719
1720 static NTSTATUS vfswrap_get_compression(struct vfs_handle_struct *handle,
1721                                         TALLOC_CTX *mem_ctx,
1722                                         struct files_struct *fsp,
1723                                         struct smb_filename *smb_fname,
1724                                         uint16_t *_compression_fmt)
1725 {
1726         return NT_STATUS_INVALID_DEVICE_REQUEST;
1727 }
1728
1729 static NTSTATUS vfswrap_set_compression(struct vfs_handle_struct *handle,
1730                                         TALLOC_CTX *mem_ctx,
1731                                         struct files_struct *fsp,
1732                                         uint16_t compression_fmt)
1733 {
1734         return NT_STATUS_INVALID_DEVICE_REQUEST;
1735 }
1736
1737 /********************************************************************
1738  Given a stat buffer return the allocated size on disk, taking into
1739  account sparse files.
1740 ********************************************************************/
1741 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
1742                                        struct files_struct *fsp,
1743                                        const SMB_STRUCT_STAT *sbuf)
1744 {
1745         uint64_t result;
1746
1747         START_PROFILE(syscall_get_alloc_size);
1748
1749         if(S_ISDIR(sbuf->st_ex_mode)) {
1750                 result = 0;
1751                 goto out;
1752         }
1753
1754 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
1755         /* The type of st_blocksize is blkcnt_t which *MUST* be
1756            signed (according to POSIX) and can be less than 64-bits.
1757            Ensure when we're converting to 64 bits wide we don't
1758            sign extend. */
1759 #if defined(SIZEOF_BLKCNT_T_8)
1760         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
1761 #elif defined(SIZEOF_BLKCNT_T_4)
1762         {
1763                 uint64_t bs = ((uint64_t)sbuf->st_ex_blocks) & 0xFFFFFFFFLL;
1764                 result = (uint64_t)STAT_ST_BLOCKSIZE * bs;
1765         }
1766 #else
1767 #error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
1768 #endif
1769         if (result == 0) {
1770                 /*
1771                  * Some file systems do not allocate a block for very
1772                  * small files. But for non-empty file should report a
1773                  * positive size.
1774                  */
1775
1776                 uint64_t filesize = get_file_size_stat(sbuf);
1777                 if (filesize > 0) {
1778                         result = MIN((uint64_t)STAT_ST_BLOCKSIZE, filesize);
1779                 }
1780         }
1781 #else
1782         result = get_file_size_stat(sbuf);
1783 #endif
1784
1785         if (fsp && fsp->initial_allocation_size)
1786                 result = MAX(result,fsp->initial_allocation_size);
1787
1788         result = smb_roundup(handle->conn, result);
1789
1790  out:
1791         END_PROFILE(syscall_get_alloc_size);
1792         return result;
1793 }
1794
1795 static int vfswrap_unlink(vfs_handle_struct *handle,
1796                           const struct smb_filename *smb_fname)
1797 {
1798         int result = -1;
1799
1800         START_PROFILE(syscall_unlink);
1801
1802         if (smb_fname->stream_name) {
1803                 errno = ENOENT;
1804                 goto out;
1805         }
1806         result = unlink(smb_fname->base_name);
1807
1808  out:
1809         END_PROFILE(syscall_unlink);
1810         return result;
1811 }
1812
1813 static int vfswrap_chmod(vfs_handle_struct *handle,
1814                         const struct smb_filename *smb_fname,
1815                         mode_t mode)
1816 {
1817         int result;
1818
1819         START_PROFILE(syscall_chmod);
1820
1821         /*
1822          * We need to do this due to the fact that the default POSIX ACL
1823          * chmod modifies the ACL *mask* for the group owner, not the
1824          * group owner bits directly. JRA.
1825          */
1826
1827
1828         {
1829                 int saved_errno = errno; /* We might get ENOSYS */
1830                 result = SMB_VFS_CHMOD_ACL(handle->conn,
1831                                 smb_fname,
1832                                 mode);
1833                 if (result == 0) {
1834                         END_PROFILE(syscall_chmod);
1835                         return result;
1836                 }
1837                 /* Error - return the old errno. */
1838                 errno = saved_errno;
1839         }
1840
1841         result = chmod(smb_fname->base_name, mode);
1842         END_PROFILE(syscall_chmod);
1843         return result;
1844 }
1845
1846 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1847 {
1848         int result;
1849
1850         START_PROFILE(syscall_fchmod);
1851
1852         /*
1853          * We need to do this due to the fact that the default POSIX ACL
1854          * chmod modifies the ACL *mask* for the group owner, not the
1855          * group owner bits directly. JRA.
1856          */
1857
1858         {
1859                 int saved_errno = errno; /* We might get ENOSYS */
1860                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
1861                         END_PROFILE(syscall_fchmod);
1862                         return result;
1863                 }
1864                 /* Error - return the old errno. */
1865                 errno = saved_errno;
1866         }
1867
1868 #if defined(HAVE_FCHMOD)
1869         result = fchmod(fsp->fh->fd, mode);
1870 #else
1871         result = -1;
1872         errno = ENOSYS;
1873 #endif
1874
1875         END_PROFILE(syscall_fchmod);
1876         return result;
1877 }
1878
1879 static int vfswrap_chown(vfs_handle_struct *handle,
1880                         const struct smb_filename *smb_fname,
1881                         uid_t uid,
1882                         gid_t gid)
1883 {
1884         int result;
1885
1886         START_PROFILE(syscall_chown);
1887         result = chown(smb_fname->base_name, uid, gid);
1888         END_PROFILE(syscall_chown);
1889         return result;
1890 }
1891
1892 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
1893 {
1894 #ifdef HAVE_FCHOWN
1895         int result;
1896
1897         START_PROFILE(syscall_fchown);
1898         result = fchown(fsp->fh->fd, uid, gid);
1899         END_PROFILE(syscall_fchown);
1900         return result;
1901 #else
1902         errno = ENOSYS;
1903         return -1;
1904 #endif
1905 }
1906
1907 static int vfswrap_lchown(vfs_handle_struct *handle,
1908                         const struct smb_filename *smb_fname,
1909                         uid_t uid,
1910                         gid_t gid)
1911 {
1912         int result;
1913
1914         START_PROFILE(syscall_lchown);
1915         result = lchown(smb_fname->base_name, uid, gid);
1916         END_PROFILE(syscall_lchown);
1917         return result;
1918 }
1919
1920 static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
1921 {
1922         int result;
1923
1924         START_PROFILE(syscall_chdir);
1925         result = chdir(path);
1926         END_PROFILE(syscall_chdir);
1927         return result;
1928 }
1929
1930 static char *vfswrap_getwd(vfs_handle_struct *handle)
1931 {
1932         char *result;
1933
1934         START_PROFILE(syscall_getwd);
1935         result = sys_getwd();
1936         END_PROFILE(syscall_getwd);
1937         return result;
1938 }
1939
1940 /*********************************************************************
1941  nsec timestamp resolution call. Convert down to whatever the underlying
1942  system will support.
1943 **********************************************************************/
1944
1945 static int vfswrap_ntimes(vfs_handle_struct *handle,
1946                           const struct smb_filename *smb_fname,
1947                           struct smb_file_time *ft)
1948 {
1949         int result = -1;
1950
1951         START_PROFILE(syscall_ntimes);
1952
1953         if (smb_fname->stream_name) {
1954                 errno = ENOENT;
1955                 goto out;
1956         }
1957
1958         if (ft != NULL) {
1959                 if (null_timespec(ft->atime)) {
1960                         ft->atime= smb_fname->st.st_ex_atime;
1961                 }
1962
1963                 if (null_timespec(ft->mtime)) {
1964                         ft->mtime = smb_fname->st.st_ex_mtime;
1965                 }
1966
1967                 if (!null_timespec(ft->create_time)) {
1968                         set_create_timespec_ea(handle->conn,
1969                                                smb_fname,
1970                                                ft->create_time);
1971                 }
1972
1973                 if ((timespec_compare(&ft->atime,
1974                                       &smb_fname->st.st_ex_atime) == 0) &&
1975                     (timespec_compare(&ft->mtime,
1976                                       &smb_fname->st.st_ex_mtime) == 0)) {
1977                         return 0;
1978                 }
1979         }
1980
1981 #if defined(HAVE_UTIMENSAT)
1982         if (ft != NULL) {
1983                 struct timespec ts[2];
1984                 ts[0] = ft->atime;
1985                 ts[1] = ft->mtime;
1986                 result = utimensat(AT_FDCWD, smb_fname->base_name, ts, 0);
1987         } else {
1988                 result = utimensat(AT_FDCWD, smb_fname->base_name, NULL, 0);
1989         }
1990         if (!((result == -1) && (errno == ENOSYS))) {
1991                 goto out;
1992         }
1993 #endif
1994 #if defined(HAVE_UTIMES)
1995         if (ft != NULL) {
1996                 struct timeval tv[2];
1997                 tv[0] = convert_timespec_to_timeval(ft->atime);
1998                 tv[1] = convert_timespec_to_timeval(ft->mtime);
1999                 result = utimes(smb_fname->base_name, tv);
2000         } else {
2001                 result = utimes(smb_fname->base_name, NULL);
2002         }
2003         if (!((result == -1) && (errno == ENOSYS))) {
2004                 goto out;
2005         }
2006 #endif
2007 #if defined(HAVE_UTIME)
2008         if (ft != NULL) {
2009                 struct utimbuf times;
2010                 times.actime = convert_timespec_to_time_t(ft->atime);
2011                 times.modtime = convert_timespec_to_time_t(ft->mtime);
2012                 result = utime(smb_fname->base_name, &times);
2013         } else {
2014                 result = utime(smb_fname->base_name, NULL);
2015         }
2016         if (!((result == -1) && (errno == ENOSYS))) {
2017                 goto out;
2018         }
2019 #endif
2020         errno = ENOSYS;
2021         result = -1;
2022
2023  out:
2024         END_PROFILE(syscall_ntimes);
2025         return result;
2026 }
2027
2028 /*********************************************************************
2029  A version of ftruncate that will write the space on disk if strict
2030  allocate is set.
2031 **********************************************************************/
2032
2033 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2034 {
2035         off_t space_to_write;
2036         uint64_t space_avail;
2037         uint64_t bsize,dfree,dsize;
2038         int ret;
2039         NTSTATUS status;
2040         SMB_STRUCT_STAT *pst;
2041
2042         status = vfs_stat_fsp(fsp);
2043         if (!NT_STATUS_IS_OK(status)) {
2044                 return -1;
2045         }
2046         pst = &fsp->fsp_name->st;
2047
2048 #ifdef S_ISFIFO
2049         if (S_ISFIFO(pst->st_ex_mode))
2050                 return 0;
2051 #endif
2052
2053         if (pst->st_ex_size == len)
2054                 return 0;
2055
2056         /* Shrink - just ftruncate. */
2057         if (pst->st_ex_size > len)
2058                 return ftruncate(fsp->fh->fd, len);
2059
2060         space_to_write = len - pst->st_ex_size;
2061
2062         /* for allocation try fallocate first. This can fail on some
2063            platforms e.g. when the filesystem doesn't support it and no
2064            emulation is being done by the libc (like on AIX with JFS1). In that
2065            case we do our own emulation. fallocate implementations can
2066            return ENOTSUP or EINVAL in cases like that. */
2067         ret = SMB_VFS_FALLOCATE(fsp, 0, pst->st_ex_size, space_to_write);
2068         if (ret == -1 && errno == ENOSPC) {
2069                 return -1;
2070         }
2071         if (ret == 0) {
2072                 return 0;
2073         }
2074         DEBUG(10,("strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2075                 "error %d. Falling back to slow manual allocation\n", errno));
2076
2077         /* available disk space is enough or not? */
2078         space_avail =
2079             get_dfree_info(fsp->conn, fsp->fsp_name, &bsize, &dfree, &dsize);
2080         /* space_avail is 1k blocks */
2081         if (space_avail == (uint64_t)-1 ||
2082                         ((uint64_t)space_to_write/1024 > space_avail) ) {
2083                 errno = ENOSPC;
2084                 return -1;
2085         }
2086
2087         /* Write out the real space on disk. */
2088         ret = vfs_slow_fallocate(fsp, pst->st_ex_size, space_to_write);
2089         if (ret != 0) {
2090                 return -1;
2091         }
2092
2093         return 0;
2094 }
2095
2096 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, off_t len)
2097 {
2098         int result = -1;
2099         SMB_STRUCT_STAT *pst;
2100         NTSTATUS status;
2101         char c = 0;
2102
2103         START_PROFILE(syscall_ftruncate);
2104
2105         if (lp_strict_allocate(SNUM(fsp->conn)) && !fsp->is_sparse) {
2106                 result = strict_allocate_ftruncate(handle, fsp, len);
2107                 END_PROFILE(syscall_ftruncate);
2108                 return result;
2109         }
2110
2111         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2112            ftruncate if the system supports it. Then I discovered that
2113            you can have some filesystems that support ftruncate
2114            expansion and some that don't! On Linux fat can't do
2115            ftruncate extend but ext2 can. */
2116
2117         result = ftruncate(fsp->fh->fd, len);
2118
2119         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2120            extend a file with ftruncate. Provide alternate implementation
2121            for this */
2122
2123         /* Do an fstat to see if the file is longer than the requested
2124            size in which case the ftruncate above should have
2125            succeeded or shorter, in which case seek to len - 1 and
2126            write 1 byte of zero */
2127         status = vfs_stat_fsp(fsp);
2128         if (!NT_STATUS_IS_OK(status)) {
2129                 goto done;
2130         }
2131
2132         /* We need to update the files_struct after successful ftruncate */
2133         if (result == 0) {
2134                 goto done;
2135         }
2136
2137         pst = &fsp->fsp_name->st;
2138
2139 #ifdef S_ISFIFO
2140         if (S_ISFIFO(pst->st_ex_mode)) {
2141                 result = 0;
2142                 goto done;
2143         }
2144 #endif
2145
2146         if (pst->st_ex_size == len) {
2147                 result = 0;
2148                 goto done;
2149         }
2150
2151         if (pst->st_ex_size > len) {
2152                 /* the ftruncate should have worked */
2153                 goto done;
2154         }
2155
2156         if (SMB_VFS_PWRITE(fsp, &c, 1, len-1)!=1) {
2157                 goto done;
2158         }
2159
2160         result = 0;
2161
2162   done:
2163
2164         END_PROFILE(syscall_ftruncate);
2165         return result;
2166 }
2167
2168 static int vfswrap_fallocate(vfs_handle_struct *handle,
2169                         files_struct *fsp,
2170                         uint32_t mode,
2171                         off_t offset,
2172                         off_t len)
2173 {
2174         int result;
2175
2176         START_PROFILE(syscall_fallocate);
2177         if (mode == 0) {
2178                 result = sys_posix_fallocate(fsp->fh->fd, offset, len);
2179                 /*
2180                  * posix_fallocate returns 0 on success, errno on error
2181                  * and doesn't set errno. Make it behave like fallocate()
2182                  * which returns -1, and sets errno on failure.
2183                  */
2184                 if (result != 0) {
2185                         errno = result;
2186                         result = -1;
2187                 }
2188         } else {
2189                 /* sys_fallocate handles filtering of unsupported mode flags */
2190                 result = sys_fallocate(fsp->fh->fd, mode, offset, len);
2191         }
2192         END_PROFILE(syscall_fallocate);
2193         return result;
2194 }
2195
2196 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, off_t offset, off_t count, int type)
2197 {
2198         bool result;
2199
2200         START_PROFILE(syscall_fcntl_lock);
2201
2202         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2203                                                 "smbd",
2204                                                 "force process locks",
2205                                                 false)) {
2206                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2207         }
2208
2209         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
2210         END_PROFILE(syscall_fcntl_lock);
2211         return result;
2212 }
2213
2214 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
2215                                 uint32_t share_mode, uint32_t access_mask)
2216 {
2217         START_PROFILE(syscall_kernel_flock);
2218         kernel_flock(fsp->fh->fd, share_mode, access_mask);
2219         END_PROFILE(syscall_kernel_flock);
2220         return 0;
2221 }
2222
2223 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
2224 {
2225         bool result;
2226         int op = F_GETLK;
2227
2228         START_PROFILE(syscall_fcntl_getlock);
2229
2230         if (fsp->use_ofd_locks || !lp_parm_bool(SNUM(fsp->conn),
2231                                                 "smbd",
2232                                                 "force process locks",
2233                                                 false)) {
2234                 op = map_process_lock_to_ofd_lock(op, &fsp->use_ofd_locks);
2235         }
2236
2237         result = fcntl_getlock(fsp->fh->fd, op, poffset, pcount, ptype, ppid);
2238         END_PROFILE(syscall_fcntl_getlock);
2239         return result;
2240 }
2241
2242 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
2243                                 int leasetype)
2244 {
2245         int result = -1;
2246
2247         START_PROFILE(syscall_linux_setlease);
2248
2249 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
2250         result = linux_setlease(fsp->fh->fd, leasetype);
2251 #else
2252         errno = ENOSYS;
2253 #endif
2254         END_PROFILE(syscall_linux_setlease);
2255         return result;
2256 }
2257
2258 static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2259 {
2260         int result;
2261
2262         START_PROFILE(syscall_symlink);
2263         result = symlink(oldpath, newpath);
2264         END_PROFILE(syscall_symlink);
2265         return result;
2266 }
2267
2268 static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
2269 {
2270         int result;
2271
2272         START_PROFILE(syscall_readlink);
2273         result = readlink(path, buf, bufsiz);
2274         END_PROFILE(syscall_readlink);
2275         return result;
2276 }
2277
2278 static int vfswrap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
2279 {
2280         int result;
2281
2282         START_PROFILE(syscall_link);
2283         result = link(oldpath, newpath);
2284         END_PROFILE(syscall_link);
2285         return result;
2286 }
2287
2288 static int vfswrap_mknod(vfs_handle_struct *handle, const char *pathname, mode_t mode, SMB_DEV_T dev)
2289 {
2290         int result;
2291
2292         START_PROFILE(syscall_mknod);
2293         result = sys_mknod(pathname, mode, dev);
2294         END_PROFILE(syscall_mknod);
2295         return result;
2296 }
2297
2298 static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
2299 {
2300         char *result;
2301
2302         START_PROFILE(syscall_realpath);
2303         result = sys_realpath(path);
2304         END_PROFILE(syscall_realpath);
2305         return result;
2306 }
2307
2308 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
2309                            unsigned int flags)
2310 {
2311 #ifdef HAVE_CHFLAGS
2312         return chflags(path, flags);
2313 #else
2314         errno = ENOSYS;
2315         return -1;
2316 #endif
2317 }
2318
2319 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
2320                                              const SMB_STRUCT_STAT *sbuf)
2321 {
2322         struct file_id key;
2323
2324         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
2325          * blob */
2326         ZERO_STRUCT(key);
2327
2328         key.devid = sbuf->st_ex_dev;
2329         key.inode = sbuf->st_ex_ino;
2330         /* key.extid is unused by default. */
2331
2332         return key;
2333 }
2334
2335 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
2336                                    struct files_struct *fsp,
2337                                    const struct smb_filename *smb_fname,
2338                                    TALLOC_CTX *mem_ctx,
2339                                    unsigned int *pnum_streams,
2340                                    struct stream_struct **pstreams)
2341 {
2342         SMB_STRUCT_STAT sbuf;
2343         struct stream_struct *tmp_streams = NULL;
2344         int ret;
2345
2346         if ((fsp != NULL) && (fsp->is_directory)) {
2347                 /*
2348                  * No default streams on directories
2349                  */
2350                 goto done;
2351         }
2352
2353         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
2354                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
2355         }
2356         else {
2357                 struct smb_filename smb_fname_cp;
2358
2359                 ZERO_STRUCT(smb_fname_cp);
2360                 smb_fname_cp.base_name = discard_const_p(char,
2361                                         smb_fname->base_name);
2362                 smb_fname_cp.flags = smb_fname->flags;
2363
2364                 if (smb_fname_cp.flags & SMB_FILENAME_POSIX_PATH) {
2365                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname_cp);
2366                 } else {
2367                         ret = SMB_VFS_STAT(handle->conn, &smb_fname_cp);
2368                 }
2369                 sbuf = smb_fname_cp.st;
2370         }
2371
2372         if (ret == -1) {
2373                 return map_nt_error_from_unix(errno);
2374         }
2375
2376         if (S_ISDIR(sbuf.st_ex_mode)) {
2377                 goto done;
2378         }
2379
2380         tmp_streams = talloc_realloc(mem_ctx, *pstreams, struct stream_struct,
2381                                         (*pnum_streams) + 1);
2382         if (tmp_streams == NULL) {
2383                 return NT_STATUS_NO_MEMORY;
2384         }
2385         tmp_streams[*pnum_streams].name = talloc_strdup(tmp_streams, "::$DATA");
2386         if (tmp_streams[*pnum_streams].name == NULL) {
2387                 return NT_STATUS_NO_MEMORY;
2388         }
2389         tmp_streams[*pnum_streams].size = sbuf.st_ex_size;
2390         tmp_streams[*pnum_streams].alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
2391
2392         *pnum_streams += 1;
2393         *pstreams = tmp_streams;
2394  done:
2395         return NT_STATUS_OK;
2396 }
2397
2398 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
2399                                      const char *path,
2400                                      const char *name,
2401                                      TALLOC_CTX *mem_ctx,
2402                                      char **found_name)
2403 {
2404         /*
2405          * Don't fall back to get_real_filename so callers can differentiate
2406          * between a full directory scan and an actual case-insensitive stat.
2407          */
2408         errno = EOPNOTSUPP;
2409         return -1;
2410 }
2411
2412 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
2413                                        const char *fname)
2414 {
2415         return handle->conn->connectpath;
2416 }
2417
2418 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
2419                                          struct byte_range_lock *br_lck,
2420                                          struct lock_struct *plock,
2421                                          bool blocking_lock)
2422 {
2423         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2424
2425         /* Note: blr is not used in the default implementation. */
2426         return brl_lock_windows_default(br_lck, plock, blocking_lock);
2427 }
2428
2429 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
2430                                        struct messaging_context *msg_ctx,
2431                                        struct byte_range_lock *br_lck,
2432                                        const struct lock_struct *plock)
2433 {
2434         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2435
2436         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
2437 }
2438
2439 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
2440                                        struct byte_range_lock *br_lck,
2441                                        struct lock_struct *plock)
2442 {
2443         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
2444
2445         /* Note: blr is not used in the default implementation. */
2446         return brl_lock_cancel_default(br_lck, plock);
2447 }
2448
2449 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
2450                                 files_struct *fsp,
2451                                 struct lock_struct *plock)
2452 {
2453         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2454             plock->lock_type == WRITE_LOCK);
2455
2456         return strict_lock_default(fsp, plock);
2457 }
2458
2459 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
2460                                 files_struct *fsp,
2461                                 struct lock_struct *plock)
2462 {
2463         SMB_ASSERT(plock->lock_type == READ_LOCK ||
2464             plock->lock_type == WRITE_LOCK);
2465
2466         strict_unlock_default(fsp, plock);
2467 }
2468
2469 /* NT ACL operations. */
2470
2471 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
2472                                     files_struct *fsp,
2473                                     uint32_t security_info,
2474                                     TALLOC_CTX *mem_ctx,
2475                                     struct security_descriptor **ppdesc)
2476 {
2477         NTSTATUS result;
2478
2479         START_PROFILE(fget_nt_acl);
2480         result = posix_fget_nt_acl(fsp, security_info,
2481                                    mem_ctx, ppdesc);
2482         END_PROFILE(fget_nt_acl);
2483         return result;
2484 }
2485
2486 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
2487                                    const struct smb_filename *smb_fname,
2488                                    uint32_t security_info,
2489                                    TALLOC_CTX *mem_ctx,
2490                                    struct security_descriptor **ppdesc)
2491 {
2492         NTSTATUS result;
2493
2494         START_PROFILE(get_nt_acl);
2495         result = posix_get_nt_acl(handle->conn,
2496                                 smb_fname,
2497                                 security_info,
2498                                 mem_ctx,
2499                                 ppdesc);
2500         END_PROFILE(get_nt_acl);
2501         return result;
2502 }
2503
2504 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd)
2505 {
2506         NTSTATUS result;
2507
2508         START_PROFILE(fset_nt_acl);
2509         result = set_nt_acl(fsp, security_info_sent, psd);
2510         END_PROFILE(fset_nt_acl);
2511         return result;
2512 }
2513
2514 static NTSTATUS vfswrap_audit_file(struct vfs_handle_struct *handle,
2515                                    struct smb_filename *file,
2516                                    struct security_acl *sacl,
2517                                    uint32_t access_requested,
2518                                    uint32_t access_denied)
2519 {
2520         return NT_STATUS_OK; /* Nothing to do here ... */
2521 }
2522
2523 static int vfswrap_chmod_acl(vfs_handle_struct *handle,
2524                                 const struct smb_filename *smb_fname,
2525                                 mode_t mode)
2526 {
2527 #ifdef HAVE_NO_ACL
2528         errno = ENOSYS;
2529         return -1;
2530 #else
2531         int result;
2532
2533         START_PROFILE(chmod_acl);
2534         result = chmod_acl(handle->conn, smb_fname->base_name, mode);
2535         END_PROFILE(chmod_acl);
2536         return result;
2537 #endif
2538 }
2539
2540 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
2541 {
2542 #ifdef HAVE_NO_ACL
2543         errno = ENOSYS;
2544         return -1;
2545 #else
2546         int result;
2547
2548         START_PROFILE(fchmod_acl);
2549         result = fchmod_acl(fsp, mode);
2550         END_PROFILE(fchmod_acl);
2551         return result;
2552 #endif
2553 }
2554
2555 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,
2556                                           const char *path_p,
2557                                           SMB_ACL_TYPE_T type,
2558                                           TALLOC_CTX *mem_ctx)
2559 {
2560         return sys_acl_get_file(handle, path_p, type, mem_ctx);
2561 }
2562
2563 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle,
2564                                         files_struct *fsp,
2565                                         TALLOC_CTX *mem_ctx)
2566 {
2567         return sys_acl_get_fd(handle, fsp, mem_ctx);
2568 }
2569
2570 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
2571 {
2572         return sys_acl_set_file(handle, name, acltype, theacl);
2573 }
2574
2575 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
2576 {
2577         return sys_acl_set_fd(handle, fsp, theacl);
2578 }
2579
2580 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
2581 {
2582         return sys_acl_delete_def_file(handle, path);
2583 }
2584
2585 /****************************************************************
2586  Extended attribute operations.
2587 *****************************************************************/
2588
2589 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
2590 {
2591         return getxattr(path, name, value, size);
2592 }
2593
2594 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
2595 {
2596         return fgetxattr(fsp->fh->fd, name, value, size);
2597 }
2598
2599 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
2600 {
2601         return listxattr(path, list, size);
2602 }
2603
2604 static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
2605 {
2606         return flistxattr(fsp->fh->fd, list, size);
2607 }
2608
2609 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
2610 {
2611         return removexattr(path, name);
2612 }
2613
2614 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
2615 {
2616         return fremovexattr(fsp->fh->fd, name);
2617 }
2618
2619 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
2620 {
2621         return setxattr(path, name, value, size, flags);
2622 }
2623
2624 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
2625 {
2626         return fsetxattr(fsp->fh->fd, name, value, size, flags);
2627 }
2628
2629 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
2630 {
2631         return false;
2632 }
2633
2634 static bool vfswrap_is_offline(struct vfs_handle_struct *handle,
2635                                const struct smb_filename *fname,
2636                                SMB_STRUCT_STAT *sbuf)
2637 {
2638         NTSTATUS status;
2639         char *path;
2640         bool offline = false;
2641
2642         if (ISDOT(fname->base_name) || ISDOTDOT(fname->base_name)) {
2643                 return false;
2644         }
2645
2646         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
2647 #if defined(ENOTSUP)
2648                 errno = ENOTSUP;
2649 #endif
2650                 return false;
2651         }
2652
2653         status = get_full_smb_filename(talloc_tos(), fname, &path);
2654         if (!NT_STATUS_IS_OK(status)) {
2655                 errno = map_errno_from_nt_status(status);
2656                 return false;
2657         }
2658
2659         offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
2660
2661         TALLOC_FREE(path);
2662
2663         return offline;
2664 }
2665
2666 static int vfswrap_set_offline(struct vfs_handle_struct *handle,
2667                                const struct smb_filename *fname)
2668 {
2669         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
2670 #if defined(ENOTSUP)
2671         errno = ENOTSUP;
2672 #endif
2673         return -1;
2674 }
2675
2676 static NTSTATUS vfswrap_durable_cookie(struct vfs_handle_struct *handle,
2677                                        struct files_struct *fsp,
2678                                        TALLOC_CTX *mem_ctx,
2679                                        DATA_BLOB *cookie)
2680 {
2681         return vfs_default_durable_cookie(fsp, mem_ctx, cookie);
2682 }
2683
2684 static NTSTATUS vfswrap_durable_disconnect(struct vfs_handle_struct *handle,
2685                                            struct files_struct *fsp,
2686                                            const DATA_BLOB old_cookie,
2687                                            TALLOC_CTX *mem_ctx,
2688                                            DATA_BLOB *new_cookie)
2689 {
2690         return vfs_default_durable_disconnect(fsp, old_cookie, mem_ctx,
2691                                               new_cookie);
2692 }
2693
2694 static NTSTATUS vfswrap_durable_reconnect(struct vfs_handle_struct *handle,
2695                                           struct smb_request *smb1req,
2696                                           struct smbXsrv_open *op,
2697                                           const DATA_BLOB old_cookie,
2698                                           TALLOC_CTX *mem_ctx,
2699                                           struct files_struct **fsp,
2700                                           DATA_BLOB *new_cookie)
2701 {
2702         return vfs_default_durable_reconnect(handle->conn, smb1req, op,
2703                                              old_cookie, mem_ctx,
2704                                              fsp, new_cookie);
2705 }
2706
2707 static struct vfs_fn_pointers vfs_default_fns = {
2708         /* Disk operations */
2709
2710         .connect_fn = vfswrap_connect,
2711         .disconnect_fn = vfswrap_disconnect,
2712         .disk_free_fn = vfswrap_disk_free,
2713         .get_quota_fn = vfswrap_get_quota,
2714         .set_quota_fn = vfswrap_set_quota,
2715         .get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data,
2716         .statvfs_fn = vfswrap_statvfs,
2717         .fs_capabilities_fn = vfswrap_fs_capabilities,
2718         .get_dfs_referrals_fn = vfswrap_get_dfs_referrals,
2719         .snap_check_path_fn = vfswrap_snap_check_path,
2720         .snap_create_fn = vfswrap_snap_create,
2721         .snap_delete_fn = vfswrap_snap_delete,
2722
2723         /* Directory operations */
2724
2725         .opendir_fn = vfswrap_opendir,
2726         .fdopendir_fn = vfswrap_fdopendir,
2727         .readdir_fn = vfswrap_readdir,
2728         .readdir_attr_fn = vfswrap_readdir_attr,
2729         .seekdir_fn = vfswrap_seekdir,
2730         .telldir_fn = vfswrap_telldir,
2731         .rewind_dir_fn = vfswrap_rewinddir,
2732         .mkdir_fn = vfswrap_mkdir,
2733         .rmdir_fn = vfswrap_rmdir,
2734         .closedir_fn = vfswrap_closedir,
2735         .init_search_op_fn = vfswrap_init_search_op,
2736
2737         /* File operations */
2738
2739         .open_fn = vfswrap_open,
2740         .create_file_fn = vfswrap_create_file,
2741         .close_fn = vfswrap_close,
2742         .read_fn = vfswrap_read,
2743         .pread_fn = vfswrap_pread,
2744         .pread_send_fn = vfswrap_pread_send,
2745         .pread_recv_fn = vfswrap_pread_recv,
2746         .write_fn = vfswrap_write,
2747         .pwrite_fn = vfswrap_pwrite,
2748         .pwrite_send_fn = vfswrap_pwrite_send,
2749         .pwrite_recv_fn = vfswrap_asys_ssize_t_recv,
2750         .lseek_fn = vfswrap_lseek,
2751         .sendfile_fn = vfswrap_sendfile,
2752         .recvfile_fn = vfswrap_recvfile,
2753         .rename_fn = vfswrap_rename,
2754         .fsync_fn = vfswrap_fsync,
2755         .fsync_send_fn = vfswrap_fsync_send,
2756         .fsync_recv_fn = vfswrap_asys_int_recv,
2757         .stat_fn = vfswrap_stat,
2758         .fstat_fn = vfswrap_fstat,
2759         .lstat_fn = vfswrap_lstat,
2760         .get_alloc_size_fn = vfswrap_get_alloc_size,
2761         .unlink_fn = vfswrap_unlink,
2762         .chmod_fn = vfswrap_chmod,
2763         .fchmod_fn = vfswrap_fchmod,
2764         .chown_fn = vfswrap_chown,
2765         .fchown_fn = vfswrap_fchown,
2766         .lchown_fn = vfswrap_lchown,
2767         .chdir_fn = vfswrap_chdir,
2768         .getwd_fn = vfswrap_getwd,
2769         .ntimes_fn = vfswrap_ntimes,
2770         .ftruncate_fn = vfswrap_ftruncate,
2771         .fallocate_fn = vfswrap_fallocate,
2772         .lock_fn = vfswrap_lock,
2773         .kernel_flock_fn = vfswrap_kernel_flock,
2774         .linux_setlease_fn = vfswrap_linux_setlease,
2775         .getlock_fn = vfswrap_getlock,
2776         .symlink_fn = vfswrap_symlink,
2777         .readlink_fn = vfswrap_readlink,
2778         .link_fn = vfswrap_link,
2779         .mknod_fn = vfswrap_mknod,
2780         .realpath_fn = vfswrap_realpath,
2781         .chflags_fn = vfswrap_chflags,
2782         .file_id_create_fn = vfswrap_file_id_create,
2783         .streaminfo_fn = vfswrap_streaminfo,
2784         .get_real_filename_fn = vfswrap_get_real_filename,
2785         .connectpath_fn = vfswrap_connectpath,
2786         .brl_lock_windows_fn = vfswrap_brl_lock_windows,
2787         .brl_unlock_windows_fn = vfswrap_brl_unlock_windows,
2788         .brl_cancel_windows_fn = vfswrap_brl_cancel_windows,
2789         .strict_lock_fn = vfswrap_strict_lock,
2790         .strict_unlock_fn = vfswrap_strict_unlock,
2791         .translate_name_fn = vfswrap_translate_name,
2792         .fsctl_fn = vfswrap_fsctl,
2793         .set_dos_attributes_fn = vfswrap_set_dos_attributes,
2794         .fset_dos_attributes_fn = vfswrap_fset_dos_attributes,
2795         .get_dos_attributes_fn = vfswrap_get_dos_attributes,
2796         .fget_dos_attributes_fn = vfswrap_fget_dos_attributes,
2797         .copy_chunk_send_fn = vfswrap_copy_chunk_send,
2798         .copy_chunk_recv_fn = vfswrap_copy_chunk_recv,
2799         .get_compression_fn = vfswrap_get_compression,
2800         .set_compression_fn = vfswrap_set_compression,
2801
2802         /* NT ACL operations. */
2803
2804         .fget_nt_acl_fn = vfswrap_fget_nt_acl,
2805         .get_nt_acl_fn = vfswrap_get_nt_acl,
2806         .fset_nt_acl_fn = vfswrap_fset_nt_acl,
2807         .audit_file_fn = vfswrap_audit_file,
2808
2809         /* POSIX ACL operations. */
2810
2811         .chmod_acl_fn = vfswrap_chmod_acl,
2812         .fchmod_acl_fn = vfswrap_fchmod_acl,
2813
2814         .sys_acl_get_file_fn = vfswrap_sys_acl_get_file,
2815         .sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd,
2816         .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
2817         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
2818         .sys_acl_set_file_fn = vfswrap_sys_acl_set_file,
2819         .sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd,
2820         .sys_acl_delete_def_file_fn = vfswrap_sys_acl_delete_def_file,
2821
2822         /* EA operations. */
2823         .getxattr_fn = vfswrap_getxattr,
2824         .fgetxattr_fn = vfswrap_fgetxattr,
2825         .listxattr_fn = vfswrap_listxattr,
2826         .flistxattr_fn = vfswrap_flistxattr,
2827         .removexattr_fn = vfswrap_removexattr,
2828         .fremovexattr_fn = vfswrap_fremovexattr,
2829         .setxattr_fn = vfswrap_setxattr,
2830         .fsetxattr_fn = vfswrap_fsetxattr,
2831
2832         /* aio operations */
2833         .aio_force_fn = vfswrap_aio_force,
2834
2835         /* offline operations */
2836         .is_offline_fn = vfswrap_is_offline,
2837         .set_offline_fn = vfswrap_set_offline,
2838
2839         /* durable handle operations */
2840         .durable_cookie_fn = vfswrap_durable_cookie,
2841         .durable_disconnect_fn = vfswrap_durable_disconnect,
2842         .durable_reconnect_fn = vfswrap_durable_reconnect,
2843 };
2844
2845 NTSTATUS vfs_default_init(void);
2846 NTSTATUS vfs_default_init(void)
2847 {
2848         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
2849                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
2850 }
2851
2852