cd792aba3245c08d5cffa43259321934b1f23499
[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
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_VFS
25
26 /* Check for NULL pointer parameters in vfswrap_* functions */
27
28 /* We don't want to have NULL function pointers lying around.  Someone
29    is sure to try and execute them.  These stubs are used to prevent
30    this possibility. */
31
32 static int vfswrap_connect(vfs_handle_struct *handle,  const char *service, const char *user)
33 {
34     return 0;    /* Return >= 0 for success */
35 }
36
37 static void vfswrap_disconnect(vfs_handle_struct *handle)
38 {
39 }
40
41 /* Disk operations */
42
43 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,  const char *path, bool small_query, uint64_t *bsize,
44                                uint64_t *dfree, uint64_t *dsize)
45 {
46         uint64_t result;
47
48         result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
49         return result;
50 }
51
52 static int vfswrap_get_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
53 {
54 #ifdef HAVE_SYS_QUOTAS
55         int result;
56
57         START_PROFILE(syscall_get_quota);
58         result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
59         END_PROFILE(syscall_get_quota);
60         return result;
61 #else
62         errno = ENOSYS;
63         return -1;
64 #endif
65 }
66
67 static int vfswrap_set_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_set_quota);
73         result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
74         END_PROFILE(syscall_set_quota);
75         return result;
76 #else
77         errno = ENOSYS;
78         return -1;
79 #endif
80 }
81
82 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, bool labels)
83 {
84         errno = ENOSYS;
85         return -1;  /* Not implemented. */
86 }
87
88 static int vfswrap_statvfs(struct vfs_handle_struct *handle,  const char *path, vfs_statvfs_struct *statbuf)
89 {
90         return sys_statvfs(path, statbuf);
91 }
92
93 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle)
94 {
95 #if defined(DARWINOS)
96         struct vfs_statvfs_struct statbuf;
97         ZERO_STRUCT(statbuf);
98         sys_statvfs(handle->conn->connectpath, &statbuf);
99         return statbuf.FsCapabilities;
100 #endif
101         return FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
102 }
103
104 /* Directory operations */
105
106 static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
107 {
108         SMB_STRUCT_DIR *result;
109
110         START_PROFILE(syscall_opendir);
111         result = sys_opendir(fname);
112         END_PROFILE(syscall_opendir);
113         return result;
114 }
115
116 static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,
117                                           SMB_STRUCT_DIR *dirp,
118                                           SMB_STRUCT_STAT *sbuf)
119 {
120         SMB_STRUCT_DIRENT *result;
121
122         START_PROFILE(syscall_readdir);
123         result = sys_readdir(dirp);
124         /* Default Posix readdir() does not give us stat info.
125          * Set to invalid to indicate we didn't return this info. */
126         if (sbuf)
127                 SET_STAT_INVALID(*sbuf);
128         END_PROFILE(syscall_readdir);
129         return result;
130 }
131
132 static void vfswrap_seekdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp, long offset)
133 {
134         START_PROFILE(syscall_seekdir);
135         sys_seekdir(dirp, offset);
136         END_PROFILE(syscall_seekdir);
137 }
138
139 static long vfswrap_telldir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
140 {
141         long result;
142         START_PROFILE(syscall_telldir);
143         result = sys_telldir(dirp);
144         END_PROFILE(syscall_telldir);
145         return result;
146 }
147
148 static void vfswrap_rewinddir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
149 {
150         START_PROFILE(syscall_rewinddir);
151         sys_rewinddir(dirp);
152         END_PROFILE(syscall_rewinddir);
153 }
154
155 static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mode)
156 {
157         int result;
158         bool has_dacl = False;
159         char *parent = NULL;
160
161         START_PROFILE(syscall_mkdir);
162
163         if (lp_inherit_acls(SNUM(handle->conn))
164             && parent_dirname(talloc_tos(), path, &parent, NULL)
165             && (has_dacl = directory_has_default_acl(handle->conn, parent)))
166                 mode = 0777;
167
168         TALLOC_FREE(parent);
169
170         result = mkdir(path, mode);
171
172         if (result == 0 && !has_dacl) {
173                 /*
174                  * We need to do this as the default behavior of POSIX ACLs
175                  * is to set the mask to be the requested group permission
176                  * bits, not the group permission bits to be the requested
177                  * group permission bits. This is not what we want, as it will
178                  * mess up any inherited ACL bits that were set. JRA.
179                  */
180                 int saved_errno = errno; /* We may get ENOSYS */
181                 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
182                         errno = saved_errno;
183         }
184
185         END_PROFILE(syscall_mkdir);
186         return result;
187 }
188
189 static int vfswrap_rmdir(vfs_handle_struct *handle,  const char *path)
190 {
191         int result;
192
193         START_PROFILE(syscall_rmdir);
194         result = rmdir(path);
195         END_PROFILE(syscall_rmdir);
196         return result;
197 }
198
199 static int vfswrap_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
200 {
201         int result;
202
203         START_PROFILE(syscall_closedir);
204         result = sys_closedir(dirp);
205         END_PROFILE(syscall_closedir);
206         return result;
207 }
208
209 static void vfswrap_init_search_op(vfs_handle_struct *handle,
210                                    SMB_STRUCT_DIR *dirp)
211 {
212         /* Default behavior is a NOOP */
213 }
214
215 /* File operations */
216
217 static int vfswrap_open(vfs_handle_struct *handle,
218                         struct smb_filename *smb_fname,
219                         files_struct *fsp, int flags, mode_t mode)
220 {
221         int result;
222         NTSTATUS status;
223         char *fname = NULL;
224
225         START_PROFILE(syscall_open);
226
227         /*
228          * XXX: Should an error be returned if there is a stream rather than
229          * trying to open a filename with a ':'?
230          */
231         status = get_full_smb_filename(talloc_tos(), smb_fname,
232                                        &fname);
233         if (!NT_STATUS_IS_OK(status)) {
234                 errno = map_errno_from_nt_status(status);
235                 return -1;
236         }
237
238         result = sys_open(fname, flags, mode);
239
240         TALLOC_FREE(fname);
241
242         END_PROFILE(syscall_open);
243         return result;
244 }
245
246 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
247                                     struct smb_request *req,
248                                     uint16_t root_dir_fid,
249                                     struct smb_filename *smb_fname,
250                                     uint32_t access_mask,
251                                     uint32_t share_access,
252                                     uint32_t create_disposition,
253                                     uint32_t create_options,
254                                     uint32_t file_attributes,
255                                     uint32_t oplock_request,
256                                     uint64_t allocation_size,
257                                     struct security_descriptor *sd,
258                                     struct ea_list *ea_list,
259                                     files_struct **result,
260                                     int *pinfo)
261 {
262         return create_file_default(handle->conn, req, root_dir_fid, smb_fname,
263                                    access_mask, share_access,
264                                    create_disposition, create_options,
265                                    file_attributes, oplock_request,
266                                    allocation_size, sd, ea_list, result,
267                                    pinfo);
268 }
269
270 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp)
271 {
272         int result;
273
274         START_PROFILE(syscall_close);
275         result = fd_close_posix(fsp);
276         END_PROFILE(syscall_close);
277         return result;
278 }
279
280 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
281 {
282         ssize_t result;
283
284         START_PROFILE_BYTES(syscall_read, n);
285         result = sys_read(fsp->fh->fd, data, n);
286         END_PROFILE(syscall_read);
287         return result;
288 }
289
290 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
291                         size_t n, SMB_OFF_T offset)
292 {
293         ssize_t result;
294
295 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
296         START_PROFILE_BYTES(syscall_pread, n);
297         result = sys_pread(fsp->fh->fd, data, n, offset);
298         END_PROFILE(syscall_pread);
299
300         if (result == -1 && errno == ESPIPE) {
301                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
302                 result = SMB_VFS_READ(fsp, data, n);
303                 fsp->fh->pos = 0;
304         }
305
306 #else /* HAVE_PREAD */
307         SMB_OFF_T   curr;
308         int lerrno;
309
310         curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
311         if (curr == -1 && errno == ESPIPE) {
312                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
313                 result = SMB_VFS_READ(fsp, data, n);
314                 fsp->fh->pos = 0;
315                 return result;
316         }
317
318         if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
319                 return -1;
320         }
321
322         errno = 0;
323         result = SMB_VFS_READ(fsp, data, n);
324         lerrno = errno;
325
326         SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
327         errno = lerrno;
328
329 #endif /* HAVE_PREAD */
330
331         return result;
332 }
333
334 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
335 {
336         ssize_t result;
337
338         START_PROFILE_BYTES(syscall_write, n);
339         result = sys_write(fsp->fh->fd, data, n);
340         END_PROFILE(syscall_write);
341         return result;
342 }
343
344 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
345                         size_t n, SMB_OFF_T offset)
346 {
347         ssize_t result;
348
349 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
350         START_PROFILE_BYTES(syscall_pwrite, n);
351         result = sys_pwrite(fsp->fh->fd, data, n, offset);
352         END_PROFILE(syscall_pwrite);
353
354         if (result == -1 && errno == ESPIPE) {
355                 /* Maintain the fiction that pipes can be sought on. */
356                 result = SMB_VFS_WRITE(fsp, data, n);
357         }
358
359 #else /* HAVE_PWRITE */
360         SMB_OFF_T   curr;
361         int         lerrno;
362
363         curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
364         if (curr == -1) {
365                 return -1;
366         }
367
368         if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
369                 return -1;
370         }
371
372         result = SMB_VFS_WRITE(fsp, data, n);
373         lerrno = errno;
374
375         SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
376         errno = lerrno;
377
378 #endif /* HAVE_PWRITE */
379
380         return result;
381 }
382
383 static SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T offset, int whence)
384 {
385         SMB_OFF_T result = 0;
386
387         START_PROFILE(syscall_lseek);
388
389         /* Cope with 'stat' file opens. */
390         if (fsp->fh->fd != -1)
391                 result = sys_lseek(fsp->fh->fd, offset, whence);
392
393         /*
394          * We want to maintain the fiction that we can seek
395          * on a fifo for file system purposes. This allows
396          * people to set up UNIX fifo's that feed data to Windows
397          * applications. JRA.
398          */
399
400         if((result == -1) && (errno == ESPIPE)) {
401                 result = 0;
402                 errno = 0;
403         }
404
405         END_PROFILE(syscall_lseek);
406         return result;
407 }
408
409 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
410                         SMB_OFF_T offset, size_t n)
411 {
412         ssize_t result;
413
414         START_PROFILE_BYTES(syscall_sendfile, n);
415         result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
416         END_PROFILE(syscall_sendfile);
417         return result;
418 }
419
420 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
421                         int fromfd,
422                         files_struct *tofsp,
423                         SMB_OFF_T offset,
424                         size_t n)
425 {
426         ssize_t result;
427
428         START_PROFILE_BYTES(syscall_recvfile, n);
429         result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
430         END_PROFILE(syscall_recvfile);
431         return result;
432 }
433
434 /*********************************************************
435  For rename across filesystems Patch from Warren Birnbaum
436  <warrenb@hpcvscdp.cv.hp.com>
437 **********************************************************/
438
439 static int copy_reg(const char *source, const char *dest)
440 {
441         SMB_STRUCT_STAT source_stats;
442         int saved_errno;
443         int ifd = -1;
444         int ofd = -1;
445
446         if (sys_lstat (source, &source_stats) == -1)
447                 return -1;
448
449         if (!S_ISREG (source_stats.st_ex_mode))
450                 return -1;
451
452         if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
453                 return -1;
454
455         if (unlink (dest) && errno != ENOENT)
456                 return -1;
457
458 #ifdef O_NOFOLLOW
459         if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
460 #else
461         if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
462 #endif
463                 goto err;
464
465         if (transfer_file(ifd, ofd, (size_t)-1) == -1)
466                 goto err;
467
468         /*
469          * Try to preserve ownership.  For non-root it might fail, but that's ok.
470          * But root probably wants to know, e.g. if NFS disallows it.
471          */
472
473 #ifdef HAVE_FCHOWN
474         if ((fchown(ofd, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
475 #else
476         if ((chown(dest, source_stats.st_ex_uid, source_stats.st_ex_gid) == -1) && (errno != EPERM))
477 #endif
478                 goto err;
479
480         /*
481          * fchown turns off set[ug]id bits for non-root,
482          * so do the chmod last.
483          */
484
485 #if defined(HAVE_FCHMOD)
486         if (fchmod (ofd, source_stats.st_ex_mode & 07777))
487 #else
488         if (chmod (dest, source_stats.st_ex_mode & 07777))
489 #endif
490                 goto err;
491
492         if (close (ifd) == -1)
493                 goto err;
494
495         if (close (ofd) == -1)
496                 return -1;
497
498         /* Try to copy the old file's modtime and access time.  */
499         {
500                 struct utimbuf tv;
501
502                 tv.actime = convert_timespec_to_time_t(source_stats.st_ex_atime);
503                 tv.modtime = convert_timespec_to_time_t(source_stats.st_ex_mtime);
504                 utime(dest, &tv);
505         }
506
507         if (unlink (source) == -1)
508                 return -1;
509
510         return 0;
511
512   err:
513
514         saved_errno = errno;
515         if (ifd != -1)
516                 close(ifd);
517         if (ofd != -1)
518                 close(ofd);
519         errno = saved_errno;
520         return -1;
521 }
522
523 static int vfswrap_rename(vfs_handle_struct *handle,  const char *oldname, const char *newname)
524 {
525         int result;
526
527         START_PROFILE(syscall_rename);
528         result = rename(oldname, newname);
529         if ((result == -1) && (errno == EXDEV)) {
530                 /* Rename across filesystems needed. */
531                 result = copy_reg(oldname, newname);
532         }
533
534         END_PROFILE(syscall_rename);
535         return result;
536 }
537
538 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
539 {
540 #ifdef HAVE_FSYNC
541         int result;
542
543         START_PROFILE(syscall_fsync);
544         result = fsync(fsp->fh->fd);
545         END_PROFILE(syscall_fsync);
546         return result;
547 #else
548         return 0;
549 #endif
550 }
551
552 static int vfswrap_stat(vfs_handle_struct *handle,
553                         struct smb_filename *smb_fname)
554 {
555         int result;
556         NTSTATUS status;
557         char *fname = NULL;
558
559         START_PROFILE(syscall_stat);
560
561         status = get_full_smb_filename(talloc_tos(), smb_fname,
562                                        &fname);
563         if (!NT_STATUS_IS_OK(status)) {
564                 errno = map_errno_from_nt_status(status);
565                 return -1;
566         }
567
568         result = sys_stat(fname, &smb_fname->st);
569
570         TALLOC_FREE(fname);
571
572         END_PROFILE(syscall_stat);
573         return result;
574 }
575
576 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
577 {
578         int result;
579
580         START_PROFILE(syscall_fstat);
581         result = sys_fstat(fsp->fh->fd, sbuf);
582         END_PROFILE(syscall_fstat);
583         return result;
584 }
585
586 static int vfswrap_lstat(vfs_handle_struct *handle,
587                          struct smb_filename *smb_fname)
588 {
589         int result;
590         NTSTATUS status;
591         char *fname = NULL;
592
593         START_PROFILE(syscall_lstat);
594
595         status = get_full_smb_filename(talloc_tos(), smb_fname,
596                                        &fname);
597         if (!NT_STATUS_IS_OK(status)) {
598                 errno = map_errno_from_nt_status(status);
599                 return -1;
600         }
601
602         result = sys_lstat(fname, &smb_fname->st);
603
604         TALLOC_FREE(fname);
605
606         END_PROFILE(syscall_lstat);
607         return result;
608 }
609
610 /********************************************************************
611  Given a stat buffer return the allocated size on disk, taking into
612  account sparse files.
613 ********************************************************************/
614 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
615                                        struct files_struct *fsp,
616                                        const SMB_STRUCT_STAT *sbuf)
617 {
618         uint64_t result;
619
620         START_PROFILE(syscall_get_alloc_size);
621
622         if(S_ISDIR(sbuf->st_ex_mode)) {
623                 result = 0;
624                 goto out;
625         }
626
627 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
628         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
629 #else
630         result = get_file_size_stat(sbuf);
631 #endif
632
633         if (fsp && fsp->initial_allocation_size)
634                 result = MAX(result,fsp->initial_allocation_size);
635
636         result = smb_roundup(handle->conn, result);
637
638  out:
639         END_PROFILE(syscall_get_alloc_size);
640         return result;
641 }
642
643 static int vfswrap_unlink(vfs_handle_struct *handle,  const char *path)
644 {
645         int result;
646
647         START_PROFILE(syscall_unlink);
648         result = unlink(path);
649         END_PROFILE(syscall_unlink);
650         return result;
651 }
652
653 static int vfswrap_chmod(vfs_handle_struct *handle,  const char *path, mode_t mode)
654 {
655         int result;
656
657         START_PROFILE(syscall_chmod);
658
659         /*
660          * We need to do this due to the fact that the default POSIX ACL
661          * chmod modifies the ACL *mask* for the group owner, not the
662          * group owner bits directly. JRA.
663          */
664
665
666         {
667                 int saved_errno = errno; /* We might get ENOSYS */
668                 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
669                         END_PROFILE(syscall_chmod);
670                         return result;
671                 }
672                 /* Error - return the old errno. */
673                 errno = saved_errno;
674         }
675
676         result = chmod(path, mode);
677         END_PROFILE(syscall_chmod);
678         return result;
679 }
680
681 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
682 {
683         int result;
684
685         START_PROFILE(syscall_fchmod);
686
687         /*
688          * We need to do this due to the fact that the default POSIX ACL
689          * chmod modifies the ACL *mask* for the group owner, not the
690          * group owner bits directly. JRA.
691          */
692
693         {
694                 int saved_errno = errno; /* We might get ENOSYS */
695                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
696                         END_PROFILE(syscall_fchmod);
697                         return result;
698                 }
699                 /* Error - return the old errno. */
700                 errno = saved_errno;
701         }
702
703 #if defined(HAVE_FCHMOD)
704         result = fchmod(fsp->fh->fd, mode);
705 #else
706         result = -1;
707         errno = ENOSYS;
708 #endif
709
710         END_PROFILE(syscall_fchmod);
711         return result;
712 }
713
714 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
715 {
716         int result;
717
718         START_PROFILE(syscall_chown);
719         result = chown(path, uid, gid);
720         END_PROFILE(syscall_chown);
721         return result;
722 }
723
724 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
725 {
726 #ifdef HAVE_FCHOWN
727         int result;
728
729         START_PROFILE(syscall_fchown);
730         result = fchown(fsp->fh->fd, uid, gid);
731         END_PROFILE(syscall_fchown);
732         return result;
733 #else
734         errno = ENOSYS;
735         return -1;
736 #endif
737 }
738
739 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
740 {
741         int result;
742
743         START_PROFILE(syscall_lchown);
744         result = lchown(path, uid, gid);
745         END_PROFILE(syscall_lchown);
746         return result;
747 }
748
749 static int vfswrap_chdir(vfs_handle_struct *handle,  const char *path)
750 {
751         int result;
752
753         START_PROFILE(syscall_chdir);
754         result = chdir(path);
755         END_PROFILE(syscall_chdir);
756         return result;
757 }
758
759 static char *vfswrap_getwd(vfs_handle_struct *handle,  char *path)
760 {
761         char *result;
762
763         START_PROFILE(syscall_getwd);
764         result = sys_getwd(path);
765         END_PROFILE(syscall_getwd);
766         return result;
767 }
768
769 /*********************************************************************
770  nsec timestamp resolution call. Convert down to whatever the underlying
771  system will support.
772 **********************************************************************/
773
774 static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path,
775                           struct smb_file_time *ft)
776 {
777         int result;
778
779         START_PROFILE(syscall_ntimes);
780 #if defined(HAVE_UTIMES)
781         if (ft != NULL) {
782                 struct timeval tv[2];
783                 tv[0] = convert_timespec_to_timeval(ft->atime);
784                 tv[1] = convert_timespec_to_timeval(ft->mtime);
785                 result = utimes(path, tv);
786         } else {
787                 result = utimes(path, NULL);
788         }
789 #elif defined(HAVE_UTIME)
790         if (ft != NULL) {
791                 struct utimbuf times;
792                 times.actime = convert_timespec_to_time_t(ft->atime);
793                 times.modtime = convert_timespec_to_time_t(ft->mtime);
794                 result = utime(path, &times);
795         } else {
796                 result = utime(path, NULL);
797         }
798 #else
799         errno = ENOSYS;
800         result = -1;
801 #endif
802         END_PROFILE(syscall_ntimes);
803         return result;
804 }
805
806 /*********************************************************************
807  A version of ftruncate that will write the space on disk if strict
808  allocate is set.
809 **********************************************************************/
810
811 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
812 {
813         SMB_STRUCT_STAT st;
814         SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
815         unsigned char zero_space[4096];
816         SMB_OFF_T space_to_write;
817
818         if (currpos == -1)
819                 return -1;
820
821         if (SMB_VFS_FSTAT(fsp, &st) == -1)
822                 return -1;
823
824         space_to_write = len - st.st_ex_size;
825
826 #ifdef S_ISFIFO
827         if (S_ISFIFO(st.st_ex_mode))
828                 return 0;
829 #endif
830
831         if (st.st_ex_size == len)
832                 return 0;
833
834         /* Shrink - just ftruncate. */
835         if (st.st_ex_size > len)
836                 return sys_ftruncate(fsp->fh->fd, len);
837
838         /* available disk space is enough or not? */
839         if (lp_strict_allocate(SNUM(fsp->conn))){
840                 uint64_t space_avail;
841                 uint64_t bsize,dfree,dsize;
842
843                 space_avail = get_dfree_info(fsp->conn,fsp->fsp_name,false,&bsize,&dfree,&dsize);
844                 /* space_avail is 1k blocks */
845                 if (space_avail == (uint64_t)-1 ||
846                                 ((uint64_t)space_to_write/1024 > space_avail) ) {
847                         errno = ENOSPC;
848                         return -1;
849                 }
850         }
851
852         /* Write out the real space on disk. */
853         if (SMB_VFS_LSEEK(fsp, st.st_ex_size, SEEK_SET) != st.st_ex_size)
854                 return -1;
855
856         space_to_write = len - st.st_ex_size;
857
858         memset(zero_space, '\0', sizeof(zero_space));
859         while ( space_to_write > 0) {
860                 SMB_OFF_T retlen;
861                 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
862
863                 retlen = SMB_VFS_WRITE(fsp,(char *)zero_space,current_len_to_write);
864                 if (retlen <= 0)
865                         return -1;
866
867                 space_to_write -= retlen;
868         }
869
870         /* Seek to where we were */
871         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
872                 return -1;
873
874         return 0;
875 }
876
877 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
878 {
879         int result = -1;
880         SMB_STRUCT_STAT st;
881         char c = 0;
882         SMB_OFF_T currpos;
883
884         START_PROFILE(syscall_ftruncate);
885
886         if (lp_strict_allocate(SNUM(fsp->conn))) {
887                 result = strict_allocate_ftruncate(handle, fsp, len);
888                 END_PROFILE(syscall_ftruncate);
889                 return result;
890         }
891
892         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
893            sys_ftruncate if the system supports it. Then I discovered that
894            you can have some filesystems that support ftruncate
895            expansion and some that don't! On Linux fat can't do
896            ftruncate extend but ext2 can. */
897
898         result = sys_ftruncate(fsp->fh->fd, len);
899         if (result == 0)
900                 goto done;
901
902         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
903            extend a file with ftruncate. Provide alternate implementation
904            for this */
905         currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
906         if (currpos == -1) {
907                 goto done;
908         }
909
910         /* Do an fstat to see if the file is longer than the requested
911            size in which case the ftruncate above should have
912            succeeded or shorter, in which case seek to len - 1 and
913            write 1 byte of zero */
914         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
915                 goto done;
916         }
917
918 #ifdef S_ISFIFO
919         if (S_ISFIFO(st.st_ex_mode)) {
920                 result = 0;
921                 goto done;
922         }
923 #endif
924
925         if (st.st_ex_size == len) {
926                 result = 0;
927                 goto done;
928         }
929
930         if (st.st_ex_size > len) {
931                 /* the sys_ftruncate should have worked */
932                 goto done;
933         }
934
935         if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
936                 goto done;
937
938         if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
939                 goto done;
940
941         /* Seek to where we were */
942         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
943                 goto done;
944         result = 0;
945
946   done:
947
948         END_PROFILE(syscall_ftruncate);
949         return result;
950 }
951
952 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
953 {
954         bool result;
955
956         START_PROFILE(syscall_fcntl_lock);
957         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
958         END_PROFILE(syscall_fcntl_lock);
959         return result;
960 }
961
962 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
963                                 uint32 share_mode)
964 {
965         START_PROFILE(syscall_kernel_flock);
966         kernel_flock(fsp->fh->fd, share_mode);
967         END_PROFILE(syscall_kernel_flock);
968         return 0;
969 }
970
971 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
972 {
973         bool result;
974
975         START_PROFILE(syscall_fcntl_getlock);
976         result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
977         END_PROFILE(syscall_fcntl_getlock);
978         return result;
979 }
980
981 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
982                                 int leasetype)
983 {
984         int result = -1;
985
986         START_PROFILE(syscall_linux_setlease);
987
988 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
989         /* first set the signal handler */
990         if(linux_set_lease_sighandler(fsp->fh->fd) == -1) {
991                 return -1;
992         }
993
994         result = linux_setlease(fsp->fh->fd, leasetype);
995 #else
996         errno = ENOSYS;
997 #endif
998         END_PROFILE(syscall_linux_setlease);
999         return result;
1000 }
1001
1002 static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1003 {
1004         int result;
1005
1006         START_PROFILE(syscall_symlink);
1007         result = symlink(oldpath, newpath);
1008         END_PROFILE(syscall_symlink);
1009         return result;
1010 }
1011
1012 static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
1013 {
1014         int result;
1015
1016         START_PROFILE(syscall_readlink);
1017         result = readlink(path, buf, bufsiz);
1018         END_PROFILE(syscall_readlink);
1019         return result;
1020 }
1021
1022 static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1023 {
1024         int result;
1025
1026         START_PROFILE(syscall_link);
1027         result = link(oldpath, newpath);
1028         END_PROFILE(syscall_link);
1029         return result;
1030 }
1031
1032 static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
1033 {
1034         int result;
1035
1036         START_PROFILE(syscall_mknod);
1037         result = sys_mknod(pathname, mode, dev);
1038         END_PROFILE(syscall_mknod);
1039         return result;
1040 }
1041
1042 static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path, char *resolved_path)
1043 {
1044         char *result;
1045
1046         START_PROFILE(syscall_realpath);
1047         result = realpath(path, resolved_path);
1048         END_PROFILE(syscall_realpath);
1049         return result;
1050 }
1051
1052 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
1053                                      struct sys_notify_context *ctx,
1054                                      struct notify_entry *e,
1055                                      void (*callback)(struct sys_notify_context *ctx, 
1056                                                       void *private_data,
1057                                                       struct notify_event *ev),
1058                                      void *private_data, void *handle)
1059 {
1060         /*
1061          * So far inotify is the only supported default notify mechanism. If
1062          * another platform like the the BSD's or a proprietary Unix comes
1063          * along and wants another default, we can play the same trick we
1064          * played with Posix ACLs.
1065          *
1066          * Until that is the case, hard-code inotify here.
1067          */
1068 #ifdef HAVE_INOTIFY
1069         if (lp_kernel_change_notify(ctx->conn->params)) {
1070                 return inotify_watch(ctx, e, callback, private_data, handle);
1071         }
1072 #endif
1073         /*
1074          * Do nothing, leave everything to notify_internal.c
1075          */
1076         return NT_STATUS_OK;
1077 }
1078
1079 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flags)
1080 {
1081 #ifdef HAVE_CHFLAGS
1082         return chflags(path, flags);
1083 #else
1084         errno = ENOSYS;
1085         return -1;
1086 #endif
1087 }
1088
1089 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
1090                                              SMB_STRUCT_STAT *sbuf)
1091 {
1092         struct file_id key;
1093
1094         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
1095          * blob */
1096         ZERO_STRUCT(key);
1097
1098         key.devid = sbuf->st_ex_dev;
1099         key.inode = sbuf->st_ex_ino;
1100         /* key.extid is unused by default. */
1101
1102         return key;
1103 }
1104
1105 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
1106                                    struct files_struct *fsp,
1107                                    const char *fname,
1108                                    TALLOC_CTX *mem_ctx,
1109                                    unsigned int *pnum_streams,
1110                                    struct stream_struct **pstreams)
1111 {
1112         SMB_STRUCT_STAT sbuf;
1113         unsigned int num_streams = 0;
1114         struct stream_struct *streams = NULL;
1115         int ret;
1116
1117         if ((fsp != NULL) && (fsp->is_directory)) {
1118                 /*
1119                  * No default streams on directories
1120                  */
1121                 goto done;
1122         }
1123
1124         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
1125                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
1126         }
1127         else {
1128                 ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf);
1129         }
1130
1131         if (ret == -1) {
1132                 return map_nt_error_from_unix(errno);
1133         }
1134
1135         if (S_ISDIR(sbuf.st_ex_mode)) {
1136                 goto done;
1137         }
1138
1139         streams = talloc(mem_ctx, struct stream_struct);
1140
1141         if (streams == NULL) {
1142                 return NT_STATUS_NO_MEMORY;
1143         }
1144
1145         streams->size = sbuf.st_ex_size;
1146         streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
1147
1148         streams->name = talloc_strdup(streams, "::$DATA");
1149         if (streams->name == NULL) {
1150                 TALLOC_FREE(streams);
1151                 return NT_STATUS_NO_MEMORY;
1152         }
1153
1154         num_streams = 1;
1155  done:
1156         *pnum_streams = num_streams;
1157         *pstreams = streams;
1158         return NT_STATUS_OK;
1159 }
1160
1161 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
1162                                      const char *path,
1163                                      const char *name,
1164                                      TALLOC_CTX *mem_ctx,
1165                                      char **found_name)
1166 {
1167         /*
1168          * Don't fall back to get_real_filename so callers can differentiate
1169          * between a full directory scan and an actual case-insensitive stat.
1170          */
1171         errno = EOPNOTSUPP;
1172         return -1;
1173 }
1174
1175 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
1176                                        const char *fname)
1177 {
1178         return handle->conn->connectpath;
1179 }
1180
1181 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
1182                                          struct byte_range_lock *br_lck,
1183                                          struct lock_struct *plock,
1184                                          bool blocking_lock,
1185                                          struct blocking_lock_record *blr)
1186 {
1187         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1188
1189         /* Note: blr is not used in the default implementation. */
1190         return brl_lock_windows_default(br_lck, plock, blocking_lock);
1191 }
1192
1193 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
1194                                        struct messaging_context *msg_ctx,
1195                                        struct byte_range_lock *br_lck,
1196                                        const struct lock_struct *plock)
1197 {
1198         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1199
1200         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
1201 }
1202
1203 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
1204                                        struct byte_range_lock *br_lck,
1205                                        struct lock_struct *plock,
1206                                        struct blocking_lock_record *blr)
1207 {
1208         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1209
1210         /* Note: blr is not used in the default implementation. */
1211         return brl_lock_cancel_default(br_lck, plock);
1212 }
1213
1214 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
1215                                 files_struct *fsp,
1216                                 struct lock_struct *plock)
1217 {
1218         SMB_ASSERT(plock->lock_type == READ_LOCK ||
1219             plock->lock_type == WRITE_LOCK);
1220
1221         return strict_lock_default(fsp, plock);
1222 }
1223
1224 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
1225                                 files_struct *fsp,
1226                                 struct lock_struct *plock)
1227 {
1228         SMB_ASSERT(plock->lock_type == READ_LOCK ||
1229             plock->lock_type == WRITE_LOCK);
1230
1231         strict_unlock_default(fsp, plock);
1232 }
1233
1234 /* NT ACL operations. */
1235
1236 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
1237                                     files_struct *fsp,
1238                                     uint32 security_info, SEC_DESC **ppdesc)
1239 {
1240         NTSTATUS result;
1241
1242         START_PROFILE(fget_nt_acl);
1243         result = posix_fget_nt_acl(fsp, security_info, ppdesc);
1244         END_PROFILE(fget_nt_acl);
1245         return result;
1246 }
1247
1248 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
1249                                    const char *name,
1250                                    uint32 security_info, SEC_DESC **ppdesc)
1251 {
1252         NTSTATUS result;
1253
1254         START_PROFILE(get_nt_acl);
1255         result = posix_get_nt_acl(handle->conn, name, security_info, ppdesc);
1256         END_PROFILE(get_nt_acl);
1257         return result;
1258 }
1259
1260 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
1261 {
1262         NTSTATUS result;
1263
1264         START_PROFILE(fset_nt_acl);
1265         result = set_nt_acl(fsp, security_info_sent, psd);
1266         END_PROFILE(fset_nt_acl);
1267         return result;
1268 }
1269
1270 static int vfswrap_chmod_acl(vfs_handle_struct *handle,  const char *name, mode_t mode)
1271 {
1272 #ifdef HAVE_NO_ACL
1273         errno = ENOSYS;
1274         return -1;
1275 #else
1276         int result;
1277
1278         START_PROFILE(chmod_acl);
1279         result = chmod_acl(handle->conn, name, mode);
1280         END_PROFILE(chmod_acl);
1281         return result;
1282 #endif
1283 }
1284
1285 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1286 {
1287 #ifdef HAVE_NO_ACL
1288         errno = ENOSYS;
1289         return -1;
1290 #else
1291         int result;
1292
1293         START_PROFILE(fchmod_acl);
1294         result = fchmod_acl(fsp, mode);
1295         END_PROFILE(fchmod_acl);
1296         return result;
1297 #endif
1298 }
1299
1300 static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle,  SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1301 {
1302         return sys_acl_get_entry(theacl, entry_id, entry_p);
1303 }
1304
1305 static int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
1306 {
1307         return sys_acl_get_tag_type(entry_d, tag_type_p);
1308 }
1309
1310 static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1311 {
1312         return sys_acl_get_permset(entry_d, permset_p);
1313 }
1314
1315 static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
1316 {
1317         return sys_acl_get_qualifier(entry_d);
1318 }
1319
1320 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
1321 {
1322         return sys_acl_get_file(handle, path_p, type);
1323 }
1324
1325 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
1326 {
1327         return sys_acl_get_fd(handle, fsp);
1328 }
1329
1330 static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset)
1331 {
1332         return sys_acl_clear_perms(permset);
1333 }
1334
1335 static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1336 {
1337         return sys_acl_add_perm(permset, perm);
1338 }
1339
1340 static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle,  SMB_ACL_T theacl, ssize_t *plen)
1341 {
1342         return sys_acl_to_text(theacl, plen);
1343 }
1344
1345 static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle,  int count)
1346 {
1347         return sys_acl_init(count);
1348 }
1349
1350 static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle,  SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1351 {
1352         return sys_acl_create_entry(pacl, pentry);
1353 }
1354
1355 static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1356 {
1357         return sys_acl_set_tag_type(entry, tagtype);
1358 }
1359
1360 static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, void *qual)
1361 {
1362         return sys_acl_set_qualifier(entry, qual);
1363 }
1364
1365 static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1366 {
1367         return sys_acl_set_permset(entry, permset);
1368 }
1369
1370 static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
1371 {
1372         return sys_acl_valid(theacl );
1373 }
1374
1375 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1376 {
1377         return sys_acl_set_file(handle, name, acltype, theacl);
1378 }
1379
1380 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
1381 {
1382         return sys_acl_set_fd(handle, fsp, theacl);
1383 }
1384
1385 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const char *path)
1386 {
1387         return sys_acl_delete_def_file(handle, path);
1388 }
1389
1390 static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1391 {
1392         return sys_acl_get_perm(permset, perm);
1393 }
1394
1395 static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle,  char *text)
1396 {
1397         return sys_acl_free_text(text);
1398 }
1399
1400 static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle,  SMB_ACL_T posix_acl)
1401 {
1402         return sys_acl_free_acl(posix_acl);
1403 }
1404
1405 static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle,  void *qualifier, SMB_ACL_TAG_T tagtype)
1406 {
1407         return sys_acl_free_qualifier(qualifier, tagtype);
1408 }
1409
1410 /****************************************************************
1411  Extended attribute operations.
1412 *****************************************************************/
1413
1414 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1415 {
1416         return sys_getxattr(path, name, value, size);
1417 }
1418
1419 static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1420 {
1421         return sys_lgetxattr(path, name, value, size);
1422 }
1423
1424 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
1425 {
1426         return sys_fgetxattr(fsp->fh->fd, name, value, size);
1427 }
1428
1429 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1430 {
1431         return sys_listxattr(path, list, size);
1432 }
1433
1434 ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1435 {
1436         return sys_llistxattr(path, list, size);
1437 }
1438
1439 ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
1440 {
1441         return sys_flistxattr(fsp->fh->fd, list, size);
1442 }
1443
1444 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1445 {
1446         return sys_removexattr(path, name);
1447 }
1448
1449 static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1450 {
1451         return sys_lremovexattr(path, name);
1452 }
1453
1454 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
1455 {
1456         return sys_fremovexattr(fsp->fh->fd, name);
1457 }
1458
1459 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1460 {
1461         return sys_setxattr(path, name, value, size, flags);
1462 }
1463
1464 static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1465 {
1466         return sys_lsetxattr(path, name, value, size, flags);
1467 }
1468
1469 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
1470 {
1471         return sys_fsetxattr(fsp->fh->fd, name, value, size, flags);
1472 }
1473
1474 static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1475 {
1476         int ret;
1477         /*
1478          * aio_read must be done as root, because in the glibc aio
1479          * implementation the helper thread needs to be able to send a signal
1480          * to the main thread, even when it has done a seteuid() to a
1481          * different user.
1482          */
1483         become_root();
1484         ret = sys_aio_read(aiocb);
1485         unbecome_root();
1486         return ret;
1487 }
1488
1489 static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1490 {
1491         int ret;
1492         /*
1493          * aio_write must be done as root, because in the glibc aio
1494          * implementation the helper thread needs to be able to send a signal
1495          * to the main thread, even when it has done a seteuid() to a
1496          * different user.
1497          */
1498         become_root();
1499         ret = sys_aio_write(aiocb);
1500         unbecome_root();
1501         return ret;
1502 }
1503
1504 static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1505 {
1506         return sys_aio_return(aiocb);
1507 }
1508
1509 static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1510 {
1511         return sys_aio_cancel(fsp->fh->fd, aiocb);
1512 }
1513
1514 static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1515 {
1516         return sys_aio_error(aiocb);
1517 }
1518
1519 static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
1520 {
1521         return sys_aio_fsync(op, aiocb);
1522 }
1523
1524 static int vfswrap_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *timeout)
1525 {
1526         return sys_aio_suspend(aiocb, n, timeout);
1527 }
1528
1529 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
1530 {
1531         return false;
1532 }
1533
1534 static bool vfswrap_is_offline(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
1535 {
1536         if (ISDOT(path) || ISDOTDOT(path)) {
1537                 return false;
1538         }
1539
1540         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
1541 #if defined(ENOTSUP)
1542                 errno = ENOTSUP;
1543 #endif
1544                 return false;
1545         }
1546
1547         return (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
1548 }
1549
1550 static int vfswrap_set_offline(struct vfs_handle_struct *handle, const char *path)
1551 {
1552         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
1553 #if defined(ENOTSUP)
1554         errno = ENOTSUP;
1555 #endif
1556         return -1;
1557 }
1558
1559 static vfs_op_tuple vfs_default_ops[] = {
1560
1561         /* Disk operations */
1562
1563         {SMB_VFS_OP(vfswrap_connect),   SMB_VFS_OP_CONNECT,
1564          SMB_VFS_LAYER_OPAQUE},
1565         {SMB_VFS_OP(vfswrap_disconnect),        SMB_VFS_OP_DISCONNECT,
1566          SMB_VFS_LAYER_OPAQUE},
1567         {SMB_VFS_OP(vfswrap_disk_free), SMB_VFS_OP_DISK_FREE,
1568          SMB_VFS_LAYER_OPAQUE},
1569         {SMB_VFS_OP(vfswrap_get_quota), SMB_VFS_OP_GET_QUOTA,
1570          SMB_VFS_LAYER_OPAQUE},
1571         {SMB_VFS_OP(vfswrap_set_quota), SMB_VFS_OP_SET_QUOTA,
1572          SMB_VFS_LAYER_OPAQUE},
1573         {SMB_VFS_OP(vfswrap_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,
1574          SMB_VFS_LAYER_OPAQUE},
1575         {SMB_VFS_OP(vfswrap_statvfs),   SMB_VFS_OP_STATVFS,
1576          SMB_VFS_LAYER_OPAQUE},
1577         {SMB_VFS_OP(vfswrap_fs_capabilities), SMB_VFS_OP_FS_CAPABILITIES,
1578          SMB_VFS_LAYER_OPAQUE},
1579
1580         /* Directory operations */
1581
1582         {SMB_VFS_OP(vfswrap_opendir),   SMB_VFS_OP_OPENDIR,
1583          SMB_VFS_LAYER_OPAQUE},
1584         {SMB_VFS_OP(vfswrap_readdir),   SMB_VFS_OP_READDIR,
1585          SMB_VFS_LAYER_OPAQUE},
1586         {SMB_VFS_OP(vfswrap_seekdir),   SMB_VFS_OP_SEEKDIR,
1587          SMB_VFS_LAYER_OPAQUE},
1588         {SMB_VFS_OP(vfswrap_telldir),   SMB_VFS_OP_TELLDIR,
1589          SMB_VFS_LAYER_OPAQUE},
1590         {SMB_VFS_OP(vfswrap_rewinddir), SMB_VFS_OP_REWINDDIR,
1591          SMB_VFS_LAYER_OPAQUE},
1592         {SMB_VFS_OP(vfswrap_mkdir),     SMB_VFS_OP_MKDIR,
1593          SMB_VFS_LAYER_OPAQUE},
1594         {SMB_VFS_OP(vfswrap_rmdir),     SMB_VFS_OP_RMDIR,
1595          SMB_VFS_LAYER_OPAQUE},
1596         {SMB_VFS_OP(vfswrap_closedir),  SMB_VFS_OP_CLOSEDIR,
1597          SMB_VFS_LAYER_OPAQUE},
1598         {SMB_VFS_OP(vfswrap_init_search_op), SMB_VFS_OP_INIT_SEARCH_OP,
1599          SMB_VFS_LAYER_OPAQUE},
1600
1601         /* File operations */
1602
1603         {SMB_VFS_OP(vfswrap_open),      SMB_VFS_OP_OPEN,
1604          SMB_VFS_LAYER_OPAQUE},
1605         {SMB_VFS_OP(vfswrap_create_file),       SMB_VFS_OP_CREATE_FILE,
1606          SMB_VFS_LAYER_OPAQUE},
1607         {SMB_VFS_OP(vfswrap_close),     SMB_VFS_OP_CLOSE,
1608          SMB_VFS_LAYER_OPAQUE},
1609         {SMB_VFS_OP(vfswrap_read),      SMB_VFS_OP_READ,
1610          SMB_VFS_LAYER_OPAQUE},
1611         {SMB_VFS_OP(vfswrap_pread),     SMB_VFS_OP_PREAD,
1612          SMB_VFS_LAYER_OPAQUE},
1613         {SMB_VFS_OP(vfswrap_write),     SMB_VFS_OP_WRITE,
1614          SMB_VFS_LAYER_OPAQUE},
1615         {SMB_VFS_OP(vfswrap_pwrite),    SMB_VFS_OP_PWRITE,
1616          SMB_VFS_LAYER_OPAQUE},
1617         {SMB_VFS_OP(vfswrap_lseek),     SMB_VFS_OP_LSEEK,
1618          SMB_VFS_LAYER_OPAQUE},
1619         {SMB_VFS_OP(vfswrap_sendfile),  SMB_VFS_OP_SENDFILE,
1620          SMB_VFS_LAYER_OPAQUE},
1621         {SMB_VFS_OP(vfswrap_recvfile),  SMB_VFS_OP_RECVFILE,
1622          SMB_VFS_LAYER_OPAQUE},
1623         {SMB_VFS_OP(vfswrap_rename),    SMB_VFS_OP_RENAME,
1624          SMB_VFS_LAYER_OPAQUE},
1625         {SMB_VFS_OP(vfswrap_fsync),     SMB_VFS_OP_FSYNC,
1626          SMB_VFS_LAYER_OPAQUE},
1627         {SMB_VFS_OP(vfswrap_stat),      SMB_VFS_OP_STAT,
1628          SMB_VFS_LAYER_OPAQUE},
1629         {SMB_VFS_OP(vfswrap_fstat),     SMB_VFS_OP_FSTAT,
1630          SMB_VFS_LAYER_OPAQUE},
1631         {SMB_VFS_OP(vfswrap_lstat),     SMB_VFS_OP_LSTAT,
1632          SMB_VFS_LAYER_OPAQUE},
1633         {SMB_VFS_OP(vfswrap_get_alloc_size),    SMB_VFS_OP_GET_ALLOC_SIZE,
1634          SMB_VFS_LAYER_OPAQUE},
1635         {SMB_VFS_OP(vfswrap_unlink),    SMB_VFS_OP_UNLINK,
1636          SMB_VFS_LAYER_OPAQUE},
1637         {SMB_VFS_OP(vfswrap_chmod),     SMB_VFS_OP_CHMOD,
1638          SMB_VFS_LAYER_OPAQUE},
1639         {SMB_VFS_OP(vfswrap_fchmod),    SMB_VFS_OP_FCHMOD,
1640          SMB_VFS_LAYER_OPAQUE},
1641         {SMB_VFS_OP(vfswrap_chown),     SMB_VFS_OP_CHOWN,
1642          SMB_VFS_LAYER_OPAQUE},
1643         {SMB_VFS_OP(vfswrap_fchown),    SMB_VFS_OP_FCHOWN,
1644          SMB_VFS_LAYER_OPAQUE},
1645         {SMB_VFS_OP(vfswrap_lchown),    SMB_VFS_OP_LCHOWN,
1646          SMB_VFS_LAYER_OPAQUE},
1647         {SMB_VFS_OP(vfswrap_chdir),     SMB_VFS_OP_CHDIR,
1648          SMB_VFS_LAYER_OPAQUE},
1649         {SMB_VFS_OP(vfswrap_getwd),     SMB_VFS_OP_GETWD,
1650          SMB_VFS_LAYER_OPAQUE},
1651         {SMB_VFS_OP(vfswrap_ntimes),    SMB_VFS_OP_NTIMES,
1652          SMB_VFS_LAYER_OPAQUE},
1653         {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE,
1654          SMB_VFS_LAYER_OPAQUE},
1655         {SMB_VFS_OP(vfswrap_lock),      SMB_VFS_OP_LOCK,
1656          SMB_VFS_LAYER_OPAQUE},
1657         {SMB_VFS_OP(vfswrap_kernel_flock),      SMB_VFS_OP_KERNEL_FLOCK,
1658          SMB_VFS_LAYER_OPAQUE},
1659         {SMB_VFS_OP(vfswrap_linux_setlease),    SMB_VFS_OP_LINUX_SETLEASE,
1660          SMB_VFS_LAYER_OPAQUE},
1661         {SMB_VFS_OP(vfswrap_getlock),   SMB_VFS_OP_GETLOCK,
1662          SMB_VFS_LAYER_OPAQUE},
1663         {SMB_VFS_OP(vfswrap_symlink),   SMB_VFS_OP_SYMLINK,
1664          SMB_VFS_LAYER_OPAQUE},
1665         {SMB_VFS_OP(vfswrap_readlink),  SMB_VFS_OP_READLINK,
1666          SMB_VFS_LAYER_OPAQUE},
1667         {SMB_VFS_OP(vfswrap_link),      SMB_VFS_OP_LINK,
1668          SMB_VFS_LAYER_OPAQUE},
1669         {SMB_VFS_OP(vfswrap_mknod),     SMB_VFS_OP_MKNOD,
1670          SMB_VFS_LAYER_OPAQUE},
1671         {SMB_VFS_OP(vfswrap_realpath),  SMB_VFS_OP_REALPATH,
1672          SMB_VFS_LAYER_OPAQUE},
1673         {SMB_VFS_OP(vfswrap_notify_watch),      SMB_VFS_OP_NOTIFY_WATCH,
1674          SMB_VFS_LAYER_OPAQUE},
1675         {SMB_VFS_OP(vfswrap_chflags),   SMB_VFS_OP_CHFLAGS,
1676          SMB_VFS_LAYER_OPAQUE},
1677         {SMB_VFS_OP(vfswrap_file_id_create),    SMB_VFS_OP_FILE_ID_CREATE,
1678          SMB_VFS_LAYER_OPAQUE},
1679         {SMB_VFS_OP(vfswrap_streaminfo),        SMB_VFS_OP_STREAMINFO,
1680          SMB_VFS_LAYER_OPAQUE},
1681         {SMB_VFS_OP(vfswrap_get_real_filename), SMB_VFS_OP_GET_REAL_FILENAME,
1682          SMB_VFS_LAYER_OPAQUE},
1683         {SMB_VFS_OP(vfswrap_connectpath),       SMB_VFS_OP_CONNECTPATH,
1684          SMB_VFS_LAYER_OPAQUE},
1685         {SMB_VFS_OP(vfswrap_brl_lock_windows),  SMB_VFS_OP_BRL_LOCK_WINDOWS,
1686          SMB_VFS_LAYER_OPAQUE},
1687         {SMB_VFS_OP(vfswrap_brl_unlock_windows),SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
1688          SMB_VFS_LAYER_OPAQUE},
1689         {SMB_VFS_OP(vfswrap_brl_cancel_windows),SMB_VFS_OP_BRL_CANCEL_WINDOWS,
1690          SMB_VFS_LAYER_OPAQUE},
1691         {SMB_VFS_OP(vfswrap_strict_lock),       SMB_VFS_OP_STRICT_LOCK,
1692          SMB_VFS_LAYER_OPAQUE},
1693         {SMB_VFS_OP(vfswrap_strict_unlock),     SMB_VFS_OP_STRICT_UNLOCK,
1694          SMB_VFS_LAYER_OPAQUE},
1695
1696         /* NT ACL operations. */
1697
1698         {SMB_VFS_OP(vfswrap_fget_nt_acl),       SMB_VFS_OP_FGET_NT_ACL,
1699          SMB_VFS_LAYER_OPAQUE},
1700         {SMB_VFS_OP(vfswrap_get_nt_acl),        SMB_VFS_OP_GET_NT_ACL,
1701          SMB_VFS_LAYER_OPAQUE},
1702         {SMB_VFS_OP(vfswrap_fset_nt_acl),       SMB_VFS_OP_FSET_NT_ACL,
1703          SMB_VFS_LAYER_OPAQUE},
1704
1705         /* POSIX ACL operations. */
1706
1707         {SMB_VFS_OP(vfswrap_chmod_acl), SMB_VFS_OP_CHMOD_ACL,
1708          SMB_VFS_LAYER_OPAQUE},
1709         {SMB_VFS_OP(vfswrap_fchmod_acl),        SMB_VFS_OP_FCHMOD_ACL,
1710          SMB_VFS_LAYER_OPAQUE},
1711         {SMB_VFS_OP(vfswrap_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY,
1712          SMB_VFS_LAYER_OPAQUE},
1713         {SMB_VFS_OP(vfswrap_sys_acl_get_tag_type),      SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,
1714          SMB_VFS_LAYER_OPAQUE},
1715         {SMB_VFS_OP(vfswrap_sys_acl_get_permset),       SMB_VFS_OP_SYS_ACL_GET_PERMSET,
1716          SMB_VFS_LAYER_OPAQUE},
1717         {SMB_VFS_OP(vfswrap_sys_acl_get_qualifier),     SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,
1718          SMB_VFS_LAYER_OPAQUE},
1719         {SMB_VFS_OP(vfswrap_sys_acl_get_file),  SMB_VFS_OP_SYS_ACL_GET_FILE,
1720          SMB_VFS_LAYER_OPAQUE},
1721         {SMB_VFS_OP(vfswrap_sys_acl_get_fd),    SMB_VFS_OP_SYS_ACL_GET_FD,
1722          SMB_VFS_LAYER_OPAQUE},
1723         {SMB_VFS_OP(vfswrap_sys_acl_clear_perms),       SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,
1724          SMB_VFS_LAYER_OPAQUE},
1725         {SMB_VFS_OP(vfswrap_sys_acl_add_perm),  SMB_VFS_OP_SYS_ACL_ADD_PERM,
1726          SMB_VFS_LAYER_OPAQUE},
1727         {SMB_VFS_OP(vfswrap_sys_acl_to_text),   SMB_VFS_OP_SYS_ACL_TO_TEXT,
1728          SMB_VFS_LAYER_OPAQUE},
1729         {SMB_VFS_OP(vfswrap_sys_acl_init),      SMB_VFS_OP_SYS_ACL_INIT,
1730          SMB_VFS_LAYER_OPAQUE},
1731         {SMB_VFS_OP(vfswrap_sys_acl_create_entry),      SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,
1732          SMB_VFS_LAYER_OPAQUE},
1733         {SMB_VFS_OP(vfswrap_sys_acl_set_tag_type),      SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,
1734          SMB_VFS_LAYER_OPAQUE},
1735         {SMB_VFS_OP(vfswrap_sys_acl_set_qualifier),     SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,
1736          SMB_VFS_LAYER_OPAQUE},
1737         {SMB_VFS_OP(vfswrap_sys_acl_set_permset),       SMB_VFS_OP_SYS_ACL_SET_PERMSET,
1738          SMB_VFS_LAYER_OPAQUE},
1739         {SMB_VFS_OP(vfswrap_sys_acl_valid),     SMB_VFS_OP_SYS_ACL_VALID,
1740          SMB_VFS_LAYER_OPAQUE},
1741         {SMB_VFS_OP(vfswrap_sys_acl_set_file),  SMB_VFS_OP_SYS_ACL_SET_FILE,
1742          SMB_VFS_LAYER_OPAQUE},
1743         {SMB_VFS_OP(vfswrap_sys_acl_set_fd),    SMB_VFS_OP_SYS_ACL_SET_FD,
1744          SMB_VFS_LAYER_OPAQUE},
1745         {SMB_VFS_OP(vfswrap_sys_acl_delete_def_file),   SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
1746          SMB_VFS_LAYER_OPAQUE},
1747         {SMB_VFS_OP(vfswrap_sys_acl_get_perm),  SMB_VFS_OP_SYS_ACL_GET_PERM,
1748          SMB_VFS_LAYER_OPAQUE},
1749         {SMB_VFS_OP(vfswrap_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT,
1750          SMB_VFS_LAYER_OPAQUE},
1751         {SMB_VFS_OP(vfswrap_sys_acl_free_acl),  SMB_VFS_OP_SYS_ACL_FREE_ACL,
1752          SMB_VFS_LAYER_OPAQUE},
1753         {SMB_VFS_OP(vfswrap_sys_acl_free_qualifier),    SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,
1754          SMB_VFS_LAYER_OPAQUE},
1755
1756         /* EA operations. */
1757
1758         {SMB_VFS_OP(vfswrap_getxattr),  SMB_VFS_OP_GETXATTR,
1759          SMB_VFS_LAYER_OPAQUE},
1760         {SMB_VFS_OP(vfswrap_lgetxattr), SMB_VFS_OP_LGETXATTR,
1761          SMB_VFS_LAYER_OPAQUE},
1762         {SMB_VFS_OP(vfswrap_fgetxattr), SMB_VFS_OP_FGETXATTR,
1763          SMB_VFS_LAYER_OPAQUE},
1764         {SMB_VFS_OP(vfswrap_listxattr), SMB_VFS_OP_LISTXATTR,
1765          SMB_VFS_LAYER_OPAQUE},
1766         {SMB_VFS_OP(vfswrap_llistxattr),        SMB_VFS_OP_LLISTXATTR,
1767          SMB_VFS_LAYER_OPAQUE},
1768         {SMB_VFS_OP(vfswrap_flistxattr),        SMB_VFS_OP_FLISTXATTR,
1769          SMB_VFS_LAYER_OPAQUE},
1770         {SMB_VFS_OP(vfswrap_removexattr),       SMB_VFS_OP_REMOVEXATTR,
1771          SMB_VFS_LAYER_OPAQUE},
1772         {SMB_VFS_OP(vfswrap_lremovexattr),      SMB_VFS_OP_LREMOVEXATTR,
1773          SMB_VFS_LAYER_OPAQUE},
1774         {SMB_VFS_OP(vfswrap_fremovexattr),      SMB_VFS_OP_FREMOVEXATTR,
1775          SMB_VFS_LAYER_OPAQUE},
1776         {SMB_VFS_OP(vfswrap_setxattr),  SMB_VFS_OP_SETXATTR,
1777          SMB_VFS_LAYER_OPAQUE},
1778         {SMB_VFS_OP(vfswrap_lsetxattr), SMB_VFS_OP_LSETXATTR,
1779          SMB_VFS_LAYER_OPAQUE},
1780         {SMB_VFS_OP(vfswrap_fsetxattr), SMB_VFS_OP_FSETXATTR,
1781          SMB_VFS_LAYER_OPAQUE},
1782
1783         {SMB_VFS_OP(vfswrap_aio_read),  SMB_VFS_OP_AIO_READ,
1784          SMB_VFS_LAYER_OPAQUE},
1785         {SMB_VFS_OP(vfswrap_aio_write), SMB_VFS_OP_AIO_WRITE,
1786          SMB_VFS_LAYER_OPAQUE},
1787         {SMB_VFS_OP(vfswrap_aio_return),        SMB_VFS_OP_AIO_RETURN,
1788          SMB_VFS_LAYER_OPAQUE},
1789         {SMB_VFS_OP(vfswrap_aio_cancel), SMB_VFS_OP_AIO_CANCEL,
1790          SMB_VFS_LAYER_OPAQUE},
1791         {SMB_VFS_OP(vfswrap_aio_error), SMB_VFS_OP_AIO_ERROR,
1792          SMB_VFS_LAYER_OPAQUE},
1793         {SMB_VFS_OP(vfswrap_aio_fsync), SMB_VFS_OP_AIO_FSYNC,
1794          SMB_VFS_LAYER_OPAQUE},
1795         {SMB_VFS_OP(vfswrap_aio_suspend),SMB_VFS_OP_AIO_SUSPEND,
1796          SMB_VFS_LAYER_OPAQUE},
1797
1798         {SMB_VFS_OP(vfswrap_aio_force), SMB_VFS_OP_AIO_FORCE,
1799          SMB_VFS_LAYER_OPAQUE},
1800
1801         {SMB_VFS_OP(vfswrap_is_offline),SMB_VFS_OP_IS_OFFLINE,
1802          SMB_VFS_LAYER_OPAQUE},
1803         {SMB_VFS_OP(vfswrap_set_offline),SMB_VFS_OP_SET_OFFLINE,
1804          SMB_VFS_LAYER_OPAQUE},
1805
1806         /* Finish VFS operations definition */
1807
1808         {SMB_VFS_OP(NULL),              SMB_VFS_OP_NOOP,
1809          SMB_VFS_LAYER_NOOP}
1810 };
1811
1812 NTSTATUS vfs_default_init(void);
1813 NTSTATUS vfs_default_init(void)
1814 {
1815         unsigned int needed = SMB_VFS_OP_LAST + 1; /* convert from index to count */
1816
1817         if (ARRAY_SIZE(vfs_default_ops) != needed) {
1818                 DEBUG(0, ("%s: %u ops registered, but %u ops are required\n",
1819                         DEFAULT_VFS_MODULE_NAME, (unsigned int)ARRAY_SIZE(vfs_default_ops), needed));
1820                 smb_panic("operation(s) missing from default VFS module");
1821         }
1822
1823         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1824                                 DEFAULT_VFS_MODULE_NAME, vfs_default_ops);
1825 }