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