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