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