3e78c69a5e6412ce3bf75372e5e4c134aba2f10e
[tprouty/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 SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle,  const char *path, bool small_query, SMB_BIG_UINT *bsize,
44                                SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
45 {
46         SMB_BIG_UINT 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 /* Directory operations */
94
95 static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
96 {
97         SMB_STRUCT_DIR *result;
98
99         START_PROFILE(syscall_opendir);
100         result = sys_opendir(fname);
101         END_PROFILE(syscall_opendir);
102         return result;
103 }
104
105 static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
106 {
107         SMB_STRUCT_DIRENT *result;
108
109         START_PROFILE(syscall_readdir);
110         result = sys_readdir(dirp);
111         END_PROFILE(syscall_readdir);
112         return result;
113 }
114
115 static void vfswrap_seekdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp, long offset)
116 {
117         START_PROFILE(syscall_seekdir);
118         sys_seekdir(dirp, offset);
119         END_PROFILE(syscall_seekdir);
120 }
121
122 static long vfswrap_telldir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
123 {
124         long result;
125         START_PROFILE(syscall_telldir);
126         result = sys_telldir(dirp);
127         END_PROFILE(syscall_telldir);
128         return result;
129 }
130
131 static void vfswrap_rewinddir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
132 {
133         START_PROFILE(syscall_rewinddir);
134         sys_rewinddir(dirp);
135         END_PROFILE(syscall_rewinddir);
136 }
137
138 static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mode)
139 {
140         int result;
141         bool has_dacl = False;
142
143         START_PROFILE(syscall_mkdir);
144
145         if (lp_inherit_acls(SNUM(handle->conn)) && (has_dacl = directory_has_default_acl(handle->conn, parent_dirname(path))))
146                 mode = 0777;
147
148         result = mkdir(path, mode);
149
150         if (result == 0 && !has_dacl) {
151                 /*
152                  * We need to do this as the default behavior of POSIX ACLs
153                  * is to set the mask to be the requested group permission
154                  * bits, not the group permission bits to be the requested
155                  * group permission bits. This is not what we want, as it will
156                  * mess up any inherited ACL bits that were set. JRA.
157                  */
158                 int saved_errno = errno; /* We may get ENOSYS */
159                 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
160                         errno = saved_errno;
161         }
162
163         END_PROFILE(syscall_mkdir);
164         return result;
165 }
166
167 static int vfswrap_rmdir(vfs_handle_struct *handle,  const char *path)
168 {
169         int result;
170
171         START_PROFILE(syscall_rmdir);
172         result = rmdir(path);
173         END_PROFILE(syscall_rmdir);
174         return result;
175 }
176
177 static int vfswrap_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
178 {
179         int result;
180
181         START_PROFILE(syscall_closedir);
182         result = sys_closedir(dirp);
183         END_PROFILE(syscall_closedir);
184         return result;
185 }
186
187 /* File operations */
188
189 static int vfswrap_open(vfs_handle_struct *handle,  const char *fname,
190         files_struct *fsp, int flags, mode_t mode)
191 {
192         int result;
193
194         START_PROFILE(syscall_open);
195         result = sys_open(fname, flags, mode);
196         END_PROFILE(syscall_open);
197         return result;
198 }
199
200 static int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
201 {
202         int result;
203
204         START_PROFILE(syscall_close);
205
206         result = close(fd);
207         END_PROFILE(syscall_close);
208         return result;
209 }
210
211 static ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, void *data, size_t n)
212 {
213         ssize_t result;
214
215         START_PROFILE_BYTES(syscall_read, n);
216         result = sys_read(fsp->fh->fd, data, n);
217         END_PROFILE(syscall_read);
218         return result;
219 }
220
221 static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void *data,
222                         size_t n, SMB_OFF_T offset)
223 {
224         ssize_t result;
225
226 #if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
227         START_PROFILE_BYTES(syscall_pread, n);
228         result = sys_pread(fsp->fh->fd, data, n, offset);
229         END_PROFILE(syscall_pread);
230
231         if (result == -1 && errno == ESPIPE) {
232                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
233                 result = SMB_VFS_READ(fsp, data, n);
234                 fsp->fh->pos = 0;
235         }
236
237 #else /* HAVE_PREAD */
238         SMB_OFF_T   curr;
239         int lerrno;
240
241         curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
242         if (curr == -1 && errno == ESPIPE) {
243                 /* Maintain the fiction that pipes can be seeked (sought?) on. */
244                 result = SMB_VFS_READ(fsp, data, n);
245                 fsp->fh->pos = 0;
246                 return result;
247         }
248
249         if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
250                 return -1;
251         }
252
253         errno = 0;
254         result = SMB_VFS_READ(fsp, data, n);
255         lerrno = errno;
256
257         SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
258         errno = lerrno;
259
260 #endif /* HAVE_PREAD */
261
262         return result;
263 }
264
265 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
266 {
267         ssize_t result;
268
269         START_PROFILE_BYTES(syscall_write, n);
270         result = sys_write(fsp->fh->fd, data, n);
271         END_PROFILE(syscall_write);
272         return result;
273 }
274
275 static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data,
276                         size_t n, SMB_OFF_T offset)
277 {
278         ssize_t result;
279
280 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
281         START_PROFILE_BYTES(syscall_pwrite, n);
282         result = sys_pwrite(fsp->fh->fd, data, n, offset);
283         END_PROFILE(syscall_pwrite);
284
285         if (result == -1 && errno == ESPIPE) {
286                 /* Maintain the fiction that pipes can be sought on. */
287                 result = SMB_VFS_WRITE(fsp, data, n);
288         }
289
290 #else /* HAVE_PWRITE */
291         SMB_OFF_T   curr;
292         int         lerrno;
293
294         curr = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
295         if (curr == -1) {
296                 return -1;
297         }
298
299         if (SMB_VFS_LSEEK(fsp, offset, SEEK_SET) == -1) {
300                 return -1;
301         }
302
303         result = SMB_VFS_WRITE(fsp, data, n);
304         lerrno = errno;
305
306         SMB_VFS_LSEEK(fsp, curr, SEEK_SET);
307         errno = lerrno;
308
309 #endif /* HAVE_PWRITE */
310
311         return result;
312 }
313
314 static SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T offset, int whence)
315 {
316         SMB_OFF_T result = 0;
317
318         START_PROFILE(syscall_lseek);
319
320         /* Cope with 'stat' file opens. */
321         if (fsp->fh->fd != -1)
322                 result = sys_lseek(fsp->fh->fd, offset, whence);
323
324         /*
325          * We want to maintain the fiction that we can seek
326          * on a fifo for file system purposes. This allows
327          * people to set up UNIX fifo's that feed data to Windows
328          * applications. JRA.
329          */
330
331         if((result == -1) && (errno == ESPIPE)) {
332                 result = 0;
333                 errno = 0;
334         }
335
336         END_PROFILE(syscall_lseek);
337         return result;
338 }
339
340 static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *hdr,
341                         SMB_OFF_T offset, size_t n)
342 {
343         ssize_t result;
344
345         START_PROFILE_BYTES(syscall_sendfile, n);
346         result = sys_sendfile(tofd, fromfsp->fh->fd, hdr, offset, n);
347         END_PROFILE(syscall_sendfile);
348         return result;
349 }
350
351 static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
352                         int fromfd,
353                         files_struct *tofsp,
354                         SMB_OFF_T offset,
355                         size_t n)
356 {
357         ssize_t result;
358
359         START_PROFILE_BYTES(syscall_recvfile, n);
360         result = sys_recvfile(fromfd, tofsp->fh->fd, offset, n);
361         END_PROFILE(syscall_recvfile);
362         return result;
363 }
364
365 /*********************************************************
366  For rename across filesystems Patch from Warren Birnbaum
367  <warrenb@hpcvscdp.cv.hp.com>
368 **********************************************************/
369
370 static int copy_reg(const char *source, const char *dest)
371 {
372         SMB_STRUCT_STAT source_stats;
373         int saved_errno;
374         int ifd = -1;
375         int ofd = -1;
376
377         if (sys_lstat (source, &source_stats) == -1)
378                 return -1;
379
380         if (!S_ISREG (source_stats.st_mode))
381                 return -1;
382
383         if((ifd = sys_open (source, O_RDONLY, 0)) < 0)
384                 return -1;
385
386         if (unlink (dest) && errno != ENOENT)
387                 return -1;
388
389 #ifdef O_NOFOLLOW
390         if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600)) < 0 )
391 #else
392         if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC , 0600)) < 0 )
393 #endif
394                 goto err;
395
396         if (transfer_file(ifd, ofd, (size_t)-1) == -1)
397                 goto err;
398
399         /*
400          * Try to preserve ownership.  For non-root it might fail, but that's ok.
401          * But root probably wants to know, e.g. if NFS disallows it.
402          */
403
404 #ifdef HAVE_FCHOWN
405         if ((fchown(ofd, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
406 #else
407         if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
408 #endif
409                 goto err;
410
411         /*
412          * fchown turns off set[ug]id bits for non-root,
413          * so do the chmod last.
414          */
415
416 #if defined(HAVE_FCHMOD)
417         if (fchmod (ofd, source_stats.st_mode & 07777))
418 #else
419         if (chmod (dest, source_stats.st_mode & 07777))
420 #endif
421                 goto err;
422
423         if (close (ifd) == -1)
424                 goto err;
425
426         if (close (ofd) == -1)
427                 return -1;
428
429         /* Try to copy the old file's modtime and access time.  */
430         {
431                 struct utimbuf tv;
432
433                 tv.actime = source_stats.st_atime;
434                 tv.modtime = source_stats.st_mtime;
435                 utime(dest, &tv);
436         }
437
438         if (unlink (source) == -1)
439                 return -1;
440
441         return 0;
442
443   err:
444
445         saved_errno = errno;
446         if (ifd != -1)
447                 close(ifd);
448         if (ofd != -1)
449                 close(ofd);
450         errno = saved_errno;
451         return -1;
452 }
453
454 static int vfswrap_rename(vfs_handle_struct *handle,  const char *oldname, const char *newname)
455 {
456         int result;
457
458         START_PROFILE(syscall_rename);
459         result = rename(oldname, newname);
460         if (errno == EXDEV) {
461                 /* Rename across filesystems needed. */
462                 result = copy_reg(oldname, newname);
463         }
464
465         END_PROFILE(syscall_rename);
466         return result;
467 }
468
469 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
470 {
471 #ifdef HAVE_FSYNC
472         int result;
473
474         START_PROFILE(syscall_fsync);
475         result = fsync(fsp->fh->fd);
476         END_PROFILE(syscall_fsync);
477         return result;
478 #else
479         return 0;
480 #endif
481 }
482
483 static int vfswrap_stat(vfs_handle_struct *handle,  const char *fname, SMB_STRUCT_STAT *sbuf)
484 {
485         int result;
486
487         START_PROFILE(syscall_stat);
488         result = sys_stat(fname, sbuf);
489         END_PROFILE(syscall_stat);
490         return result;
491 }
492
493 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
494 {
495         int result;
496
497         START_PROFILE(syscall_fstat);
498         result = sys_fstat(fsp->fh->fd, sbuf);
499         END_PROFILE(syscall_fstat);
500         return result;
501 }
502
503 int vfswrap_lstat(vfs_handle_struct *handle,  const char *path, SMB_STRUCT_STAT *sbuf)
504 {
505         int result;
506
507         START_PROFILE(syscall_lstat);
508         result = sys_lstat(path, sbuf);
509         END_PROFILE(syscall_lstat);
510         return result;
511 }
512
513 static int vfswrap_unlink(vfs_handle_struct *handle,  const char *path)
514 {
515         int result;
516
517         START_PROFILE(syscall_unlink);
518         result = unlink(path);
519         END_PROFILE(syscall_unlink);
520         return result;
521 }
522
523 static int vfswrap_chmod(vfs_handle_struct *handle,  const char *path, mode_t mode)
524 {
525         int result;
526
527         START_PROFILE(syscall_chmod);
528
529         /*
530          * We need to do this due to the fact that the default POSIX ACL
531          * chmod modifies the ACL *mask* for the group owner, not the
532          * group owner bits directly. JRA.
533          */
534
535
536         {
537                 int saved_errno = errno; /* We might get ENOSYS */
538                 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
539                         END_PROFILE(syscall_chmod);
540                         return result;
541                 }
542                 /* Error - return the old errno. */
543                 errno = saved_errno;
544         }
545
546         result = chmod(path, mode);
547         END_PROFILE(syscall_chmod);
548         return result;
549 }
550
551 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
552 {
553         int result;
554
555         START_PROFILE(syscall_fchmod);
556
557         /*
558          * We need to do this due to the fact that the default POSIX ACL
559          * chmod modifies the ACL *mask* for the group owner, not the
560          * group owner bits directly. JRA.
561          */
562
563         {
564                 int saved_errno = errno; /* We might get ENOSYS */
565                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
566                         END_PROFILE(syscall_fchmod);
567                         return result;
568                 }
569                 /* Error - return the old errno. */
570                 errno = saved_errno;
571         }
572
573 #if defined(HAVE_FCHMOD)
574         result = fchmod(fsp->fh->fd, mode);
575 #else
576         result = -1;
577         errno = ENOSYS;
578 #endif
579
580         END_PROFILE(syscall_fchmod);
581         return result;
582 }
583
584 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
585 {
586         int result;
587
588         START_PROFILE(syscall_chown);
589         result = sys_chown(path, uid, gid);
590         END_PROFILE(syscall_chown);
591         return result;
592 }
593
594 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
595 {
596 #ifdef HAVE_FCHOWN
597         int result;
598
599         START_PROFILE(syscall_fchown);
600         result = fchown(fsp->fh->fd, uid, gid);
601         END_PROFILE(syscall_fchown);
602         return result;
603 #else
604         errno = ENOSYS;
605         return -1;
606 #endif
607 }
608
609 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
610 {
611         int result;
612
613         START_PROFILE(syscall_lchown);
614         result = sys_lchown(path, uid, gid);
615         END_PROFILE(syscall_lchown);
616         return result;
617 }
618
619 static int vfswrap_chdir(vfs_handle_struct *handle,  const char *path)
620 {
621         int result;
622
623         START_PROFILE(syscall_chdir);
624         result = chdir(path);
625         END_PROFILE(syscall_chdir);
626         return result;
627 }
628
629 static char *vfswrap_getwd(vfs_handle_struct *handle,  char *path)
630 {
631         char *result;
632
633         START_PROFILE(syscall_getwd);
634         result = sys_getwd(path);
635         END_PROFILE(syscall_getwd);
636         return result;
637 }
638
639 /*********************************************************************
640  nsec timestamp resolution call. Convert down to whatever the underlying
641  system will support.
642 **********************************************************************/
643
644 static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2])
645 {
646         int result;
647
648         START_PROFILE(syscall_ntimes);
649 #if defined(HAVE_UTIMES)
650         {
651                 struct timeval tv[2];
652                 tv[0] = convert_timespec_to_timeval(ts[0]);
653                 tv[1] = convert_timespec_to_timeval(ts[1]);
654                 result = utimes(path, tv);
655         }
656 #elif defined(HAVE_UTIME)
657         {
658                 struct utimbuf times;
659                 times.actime = convert_timespec_to_time_t(ts[0]);
660                 times.modtime = convert_timespec_to_time_t(ts[1]);
661                 result = utime(path, times);
662         }
663 #else
664         errno = ENOSYS;
665         result = -1;
666 #endif
667         END_PROFILE(syscall_ntimes);
668         return result;
669 }
670
671 /*********************************************************************
672  A version of ftruncate that will write the space on disk if strict
673  allocate is set.
674 **********************************************************************/
675
676 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
677 {
678         SMB_STRUCT_STAT st;
679         SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
680         unsigned char zero_space[4096];
681         SMB_OFF_T space_to_write;
682
683         if (currpos == -1)
684                 return -1;
685
686         if (SMB_VFS_FSTAT(fsp, &st) == -1)
687                 return -1;
688
689         space_to_write = len - st.st_size;
690
691 #ifdef S_ISFIFO
692         if (S_ISFIFO(st.st_mode))
693                 return 0;
694 #endif
695
696         if (st.st_size == len)
697                 return 0;
698
699         /* Shrink - just ftruncate. */
700         if (st.st_size > len)
701                 return sys_ftruncate(fsp->fh->fd, len);
702
703         /* Write out the real space on disk. */
704         if (SMB_VFS_LSEEK(fsp, st.st_size, SEEK_SET) != st.st_size)
705                 return -1;
706
707         space_to_write = len - st.st_size;
708
709         memset(zero_space, '\0', sizeof(zero_space));
710         while ( space_to_write > 0) {
711                 SMB_OFF_T retlen;
712                 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
713
714                 retlen = SMB_VFS_WRITE(fsp,(char *)zero_space,current_len_to_write);
715                 if (retlen <= 0)
716                         return -1;
717
718                 space_to_write -= retlen;
719         }
720
721         /* Seek to where we were */
722         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
723                 return -1;
724
725         return 0;
726 }
727
728 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
729 {
730         int result = -1;
731         SMB_STRUCT_STAT st;
732         char c = 0;
733         SMB_OFF_T currpos;
734
735         START_PROFILE(syscall_ftruncate);
736
737         if (lp_strict_allocate(SNUM(fsp->conn))) {
738                 result = strict_allocate_ftruncate(handle, fsp, len);
739                 END_PROFILE(syscall_ftruncate);
740                 return result;
741         }
742
743         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
744            sys_ftruncate if the system supports it. Then I discovered that
745            you can have some filesystems that support ftruncate
746            expansion and some that don't! On Linux fat can't do
747            ftruncate extend but ext2 can. */
748
749         result = sys_ftruncate(fsp->fh->fd, len);
750         if (result == 0)
751                 goto done;
752
753         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
754            extend a file with ftruncate. Provide alternate implementation
755            for this */
756         currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
757         if (currpos == -1) {
758                 goto done;
759         }
760
761         /* Do an fstat to see if the file is longer than the requested
762            size in which case the ftruncate above should have
763            succeeded or shorter, in which case seek to len - 1 and
764            write 1 byte of zero */
765         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
766                 goto done;
767         }
768
769 #ifdef S_ISFIFO
770         if (S_ISFIFO(st.st_mode)) {
771                 result = 0;
772                 goto done;
773         }
774 #endif
775
776         if (st.st_size == len) {
777                 result = 0;
778                 goto done;
779         }
780
781         if (st.st_size > len) {
782                 /* the sys_ftruncate should have worked */
783                 goto done;
784         }
785
786         if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
787                 goto done;
788
789         if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
790                 goto done;
791
792         /* Seek to where we were */
793         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
794                 goto done;
795         result = 0;
796
797   done:
798
799         END_PROFILE(syscall_ftruncate);
800         return result;
801 }
802
803 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
804 {
805         bool result;
806
807         START_PROFILE(syscall_fcntl_lock);
808         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
809         END_PROFILE(syscall_fcntl_lock);
810         return result;
811 }
812
813 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
814                                 uint32 share_mode)
815 {
816         START_PROFILE(syscall_kernel_flock);
817         kernel_flock(fsp->fh->fd, share_mode);
818         END_PROFILE(syscall_kernel_flock);
819         return 0;
820 }
821
822 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
823 {
824         bool result;
825
826         START_PROFILE(syscall_fcntl_getlock);
827         result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
828         END_PROFILE(syscall_fcntl_getlock);
829         return result;
830 }
831
832 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
833                                 int leasetype)
834 {
835         int result = -1;
836
837         START_PROFILE(syscall_linux_setlease);
838
839 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
840         /* first set the signal handler */
841         if(linux_set_lease_sighandler(fsp->fh->fd) == -1) {
842                 return -1;
843         }
844
845         result = linux_setlease(fsp->fh->fd, leasetype);
846 #else
847         errno = ENOSYS;
848 #endif
849         END_PROFILE(syscall_linux_setlease);
850         return result;
851 }
852
853 static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
854 {
855         int result;
856
857         START_PROFILE(syscall_symlink);
858         result = sys_symlink(oldpath, newpath);
859         END_PROFILE(syscall_symlink);
860         return result;
861 }
862
863 static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
864 {
865         int result;
866
867         START_PROFILE(syscall_readlink);
868         result = sys_readlink(path, buf, bufsiz);
869         END_PROFILE(syscall_readlink);
870         return result;
871 }
872
873 static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
874 {
875         int result;
876
877         START_PROFILE(syscall_link);
878         result = sys_link(oldpath, newpath);
879         END_PROFILE(syscall_link);
880         return result;
881 }
882
883 static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
884 {
885         int result;
886
887         START_PROFILE(syscall_mknod);
888         result = sys_mknod(pathname, mode, dev);
889         END_PROFILE(syscall_mknod);
890         return result;
891 }
892
893 static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path, char *resolved_path)
894 {
895         char *result;
896
897         START_PROFILE(syscall_realpath);
898         result = sys_realpath(path, resolved_path);
899         END_PROFILE(syscall_realpath);
900         return result;
901 }
902
903 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
904                                      struct sys_notify_context *ctx,
905                                      struct notify_entry *e,
906                                      void (*callback)(struct sys_notify_context *ctx, 
907                                                       void *private_data,
908                                                       struct notify_event *ev),
909                                      void *private_data, void *handle)
910 {
911         /*
912          * So far inotify is the only supported default notify mechanism. If
913          * another platform like the the BSD's or a proprietary Unix comes
914          * along and wants another default, we can play the same trick we
915          * played with Posix ACLs.
916          *
917          * Until that is the case, hard-code inotify here.
918          */
919 #ifdef HAVE_INOTIFY
920         if (lp_kernel_change_notify(ctx->conn->params)) {
921                 return inotify_watch(ctx, e, callback, private_data, handle);
922         }
923 #endif
924         /*
925          * Do nothing, leave everything to notify_internal.c
926          */
927         return NT_STATUS_OK;
928 }
929
930 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flags)
931 {
932 #ifdef HAVE_CHFLAGS
933         return chflags(path, flags);
934 #else
935         errno = ENOSYS;
936         return -1;
937 #endif
938 }
939
940 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle, SMB_DEV_T dev, SMB_INO_T inode)
941 {
942         return file_id_create_dev(dev, inode);
943 }
944
945 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
946                                     files_struct *fsp,
947                                     uint32 security_info, SEC_DESC **ppdesc)
948 {
949         NTSTATUS result;
950
951         START_PROFILE(fget_nt_acl);
952         result = posix_fget_nt_acl(fsp, security_info, ppdesc);
953         END_PROFILE(fget_nt_acl);
954         return result;
955 }
956
957 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
958                                    const char *name,
959                                    uint32 security_info, SEC_DESC **ppdesc)
960 {
961         NTSTATUS result;
962
963         START_PROFILE(get_nt_acl);
964         result = posix_get_nt_acl(handle->conn, name, security_info, ppdesc);
965         END_PROFILE(get_nt_acl);
966         return result;
967 }
968
969 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
970 {
971         NTSTATUS result;
972
973         START_PROFILE(fset_nt_acl);
974         result = set_nt_acl(fsp, security_info_sent, psd);
975         END_PROFILE(fset_nt_acl);
976         return result;
977 }
978
979 static NTSTATUS vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
980 {
981         NTSTATUS result;
982
983         START_PROFILE(set_nt_acl);
984         result = set_nt_acl(fsp, security_info_sent, psd);
985         END_PROFILE(set_nt_acl);
986         return result;
987 }
988
989 static int vfswrap_chmod_acl(vfs_handle_struct *handle,  const char *name, mode_t mode)
990 {
991 #ifdef HAVE_NO_ACL
992         errno = ENOSYS;
993         return -1;
994 #else
995         int result;
996
997         START_PROFILE(chmod_acl);
998         result = chmod_acl(handle->conn, name, mode);
999         END_PROFILE(chmod_acl);
1000         return result;
1001 #endif
1002 }
1003
1004 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1005 {
1006 #ifdef HAVE_NO_ACL
1007         errno = ENOSYS;
1008         return -1;
1009 #else
1010         int result;
1011
1012         START_PROFILE(fchmod_acl);
1013         result = fchmod_acl(fsp, mode);
1014         END_PROFILE(fchmod_acl);
1015         return result;
1016 #endif
1017 }
1018
1019 static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle,  SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1020 {
1021         return sys_acl_get_entry(theacl, entry_id, entry_p);
1022 }
1023
1024 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)
1025 {
1026         return sys_acl_get_tag_type(entry_d, tag_type_p);
1027 }
1028
1029 static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1030 {
1031         return sys_acl_get_permset(entry_d, permset_p);
1032 }
1033
1034 static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
1035 {
1036         return sys_acl_get_qualifier(entry_d);
1037 }
1038
1039 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
1040 {
1041         return sys_acl_get_file(handle, path_p, type);
1042 }
1043
1044 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
1045 {
1046         return sys_acl_get_fd(handle, fsp);
1047 }
1048
1049 static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset)
1050 {
1051         return sys_acl_clear_perms(permset);
1052 }
1053
1054 static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1055 {
1056         return sys_acl_add_perm(permset, perm);
1057 }
1058
1059 static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle,  SMB_ACL_T theacl, ssize_t *plen)
1060 {
1061         return sys_acl_to_text(theacl, plen);
1062 }
1063
1064 static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle,  int count)
1065 {
1066         return sys_acl_init(count);
1067 }
1068
1069 static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle,  SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1070 {
1071         return sys_acl_create_entry(pacl, pentry);
1072 }
1073
1074 static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1075 {
1076         return sys_acl_set_tag_type(entry, tagtype);
1077 }
1078
1079 static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, void *qual)
1080 {
1081         return sys_acl_set_qualifier(entry, qual);
1082 }
1083
1084 static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1085 {
1086         return sys_acl_set_permset(entry, permset);
1087 }
1088
1089 static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
1090 {
1091         return sys_acl_valid(theacl );
1092 }
1093
1094 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1095 {
1096         return sys_acl_set_file(handle, name, acltype, theacl);
1097 }
1098
1099 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
1100 {
1101         return sys_acl_set_fd(handle, fsp, theacl);
1102 }
1103
1104 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const char *path)
1105 {
1106         return sys_acl_delete_def_file(handle, path);
1107 }
1108
1109 static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1110 {
1111         return sys_acl_get_perm(permset, perm);
1112 }
1113
1114 static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle,  char *text)
1115 {
1116         return sys_acl_free_text(text);
1117 }
1118
1119 static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle,  SMB_ACL_T posix_acl)
1120 {
1121         return sys_acl_free_acl(posix_acl);
1122 }
1123
1124 static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle,  void *qualifier, SMB_ACL_TAG_T tagtype)
1125 {
1126         return sys_acl_free_qualifier(qualifier, tagtype);
1127 }
1128
1129 /****************************************************************
1130  Extended attribute operations.
1131 *****************************************************************/
1132
1133 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1134 {
1135         return sys_getxattr(path, name, value, size);
1136 }
1137
1138 static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1139 {
1140         return sys_lgetxattr(path, name, value, size);
1141 }
1142
1143 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
1144 {
1145         return sys_fgetxattr(fsp->fh->fd, name, value, size);
1146 }
1147
1148 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1149 {
1150         return sys_listxattr(path, list, size);
1151 }
1152
1153 ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1154 {
1155         return sys_llistxattr(path, list, size);
1156 }
1157
1158 ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
1159 {
1160         return sys_flistxattr(fsp->fh->fd, list, size);
1161 }
1162
1163 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1164 {
1165         return sys_removexattr(path, name);
1166 }
1167
1168 static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1169 {
1170         return sys_lremovexattr(path, name);
1171 }
1172
1173 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
1174 {
1175         return sys_fremovexattr(fsp->fh->fd, name);
1176 }
1177
1178 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1179 {
1180         return sys_setxattr(path, name, value, size, flags);
1181 }
1182
1183 static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1184 {
1185         return sys_lsetxattr(path, name, value, size, flags);
1186 }
1187
1188 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
1189 {
1190         return sys_fsetxattr(fsp->fh->fd, name, value, size, flags);
1191 }
1192
1193 static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1194 {
1195         return sys_aio_read(aiocb);
1196 }
1197
1198 static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1199 {
1200         return sys_aio_write(aiocb);
1201 }
1202
1203 static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1204 {
1205         return sys_aio_return(aiocb);
1206 }
1207
1208 static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1209 {
1210         return sys_aio_cancel(fsp->fh->fd, aiocb);
1211 }
1212
1213 static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1214 {
1215         return sys_aio_error(aiocb);
1216 }
1217
1218 static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
1219 {
1220         return sys_aio_fsync(op, aiocb);
1221 }
1222
1223 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)
1224 {
1225         return sys_aio_suspend(aiocb, n, timeout);
1226 }
1227
1228 static int vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
1229 {
1230         return False;
1231 }
1232
1233 static int vfswrap_is_offline(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, bool *offline)
1234 {
1235         if (ISDOT(path) || ISDOTDOT(path)) {
1236                 return 1;
1237         }
1238         
1239         if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
1240                 return -1;
1241         }
1242         
1243         *offline = (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
1244         return 0;
1245 }
1246
1247 static int vfswrap_set_offline(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
1248 {
1249         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
1250         return -1;
1251 }
1252
1253 static bool vfswrap_is_remotestorage(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path)
1254 {
1255         /* We don't know how to detect that volume is remote storage. VFS modules should redefine it. */
1256         return False;
1257 }
1258
1259
1260 static vfs_op_tuple vfs_default_ops[] = {
1261
1262         /* Disk operations */
1263
1264         {SMB_VFS_OP(vfswrap_connect),   SMB_VFS_OP_CONNECT,
1265          SMB_VFS_LAYER_OPAQUE},
1266         {SMB_VFS_OP(vfswrap_disconnect),        SMB_VFS_OP_DISCONNECT,
1267          SMB_VFS_LAYER_OPAQUE},
1268         {SMB_VFS_OP(vfswrap_disk_free), SMB_VFS_OP_DISK_FREE,
1269          SMB_VFS_LAYER_OPAQUE},
1270         {SMB_VFS_OP(vfswrap_get_quota), SMB_VFS_OP_GET_QUOTA,
1271          SMB_VFS_LAYER_OPAQUE},
1272         {SMB_VFS_OP(vfswrap_set_quota), SMB_VFS_OP_SET_QUOTA,
1273          SMB_VFS_LAYER_OPAQUE},
1274         {SMB_VFS_OP(vfswrap_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,
1275          SMB_VFS_LAYER_OPAQUE},
1276         {SMB_VFS_OP(vfswrap_statvfs),   SMB_VFS_OP_STATVFS,
1277          SMB_VFS_LAYER_OPAQUE},
1278
1279         /* Directory operations */
1280
1281         {SMB_VFS_OP(vfswrap_opendir),   SMB_VFS_OP_OPENDIR,
1282          SMB_VFS_LAYER_OPAQUE},
1283         {SMB_VFS_OP(vfswrap_readdir),   SMB_VFS_OP_READDIR,
1284          SMB_VFS_LAYER_OPAQUE},
1285         {SMB_VFS_OP(vfswrap_seekdir),   SMB_VFS_OP_SEEKDIR,
1286          SMB_VFS_LAYER_OPAQUE},
1287         {SMB_VFS_OP(vfswrap_telldir),   SMB_VFS_OP_TELLDIR,
1288          SMB_VFS_LAYER_OPAQUE},
1289         {SMB_VFS_OP(vfswrap_rewinddir), SMB_VFS_OP_REWINDDIR,
1290          SMB_VFS_LAYER_OPAQUE},
1291         {SMB_VFS_OP(vfswrap_mkdir),     SMB_VFS_OP_MKDIR,
1292          SMB_VFS_LAYER_OPAQUE},
1293         {SMB_VFS_OP(vfswrap_rmdir),     SMB_VFS_OP_RMDIR,
1294          SMB_VFS_LAYER_OPAQUE},
1295         {SMB_VFS_OP(vfswrap_closedir),  SMB_VFS_OP_CLOSEDIR,
1296          SMB_VFS_LAYER_OPAQUE},
1297
1298         /* File operations */
1299
1300         {SMB_VFS_OP(vfswrap_open),      SMB_VFS_OP_OPEN,
1301          SMB_VFS_LAYER_OPAQUE},
1302         {SMB_VFS_OP(vfswrap_close),     SMB_VFS_OP_CLOSE,
1303          SMB_VFS_LAYER_OPAQUE},
1304         {SMB_VFS_OP(vfswrap_read),      SMB_VFS_OP_READ,
1305          SMB_VFS_LAYER_OPAQUE},
1306         {SMB_VFS_OP(vfswrap_pread),     SMB_VFS_OP_PREAD,
1307          SMB_VFS_LAYER_OPAQUE},
1308         {SMB_VFS_OP(vfswrap_write),     SMB_VFS_OP_WRITE,
1309          SMB_VFS_LAYER_OPAQUE},
1310         {SMB_VFS_OP(vfswrap_pwrite),    SMB_VFS_OP_PWRITE,
1311          SMB_VFS_LAYER_OPAQUE},
1312         {SMB_VFS_OP(vfswrap_lseek),     SMB_VFS_OP_LSEEK,
1313          SMB_VFS_LAYER_OPAQUE},
1314         {SMB_VFS_OP(vfswrap_sendfile),  SMB_VFS_OP_SENDFILE,
1315          SMB_VFS_LAYER_OPAQUE},
1316         {SMB_VFS_OP(vfswrap_recvfile),  SMB_VFS_OP_RECVFILE,
1317          SMB_VFS_LAYER_OPAQUE},
1318         {SMB_VFS_OP(vfswrap_rename),    SMB_VFS_OP_RENAME,
1319          SMB_VFS_LAYER_OPAQUE},
1320         {SMB_VFS_OP(vfswrap_fsync),     SMB_VFS_OP_FSYNC,
1321          SMB_VFS_LAYER_OPAQUE},
1322         {SMB_VFS_OP(vfswrap_stat),      SMB_VFS_OP_STAT,
1323          SMB_VFS_LAYER_OPAQUE},
1324         {SMB_VFS_OP(vfswrap_fstat),     SMB_VFS_OP_FSTAT,
1325          SMB_VFS_LAYER_OPAQUE},
1326         {SMB_VFS_OP(vfswrap_lstat),     SMB_VFS_OP_LSTAT,
1327          SMB_VFS_LAYER_OPAQUE},
1328         {SMB_VFS_OP(vfswrap_unlink),    SMB_VFS_OP_UNLINK,
1329          SMB_VFS_LAYER_OPAQUE},
1330         {SMB_VFS_OP(vfswrap_chmod),     SMB_VFS_OP_CHMOD,
1331          SMB_VFS_LAYER_OPAQUE},
1332         {SMB_VFS_OP(vfswrap_fchmod),    SMB_VFS_OP_FCHMOD,
1333          SMB_VFS_LAYER_OPAQUE},
1334         {SMB_VFS_OP(vfswrap_chown),     SMB_VFS_OP_CHOWN,
1335          SMB_VFS_LAYER_OPAQUE},
1336         {SMB_VFS_OP(vfswrap_fchown),    SMB_VFS_OP_FCHOWN,
1337          SMB_VFS_LAYER_OPAQUE},
1338         {SMB_VFS_OP(vfswrap_lchown),    SMB_VFS_OP_LCHOWN,
1339          SMB_VFS_LAYER_OPAQUE},
1340         {SMB_VFS_OP(vfswrap_chdir),     SMB_VFS_OP_CHDIR,
1341          SMB_VFS_LAYER_OPAQUE},
1342         {SMB_VFS_OP(vfswrap_getwd),     SMB_VFS_OP_GETWD,
1343          SMB_VFS_LAYER_OPAQUE},
1344         {SMB_VFS_OP(vfswrap_ntimes),    SMB_VFS_OP_NTIMES,
1345          SMB_VFS_LAYER_OPAQUE},
1346         {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE,
1347          SMB_VFS_LAYER_OPAQUE},
1348         {SMB_VFS_OP(vfswrap_lock),      SMB_VFS_OP_LOCK,
1349          SMB_VFS_LAYER_OPAQUE},
1350         {SMB_VFS_OP(vfswrap_kernel_flock),      SMB_VFS_OP_KERNEL_FLOCK,
1351          SMB_VFS_LAYER_OPAQUE},
1352         {SMB_VFS_OP(vfswrap_linux_setlease),    SMB_VFS_OP_LINUX_SETLEASE,
1353          SMB_VFS_LAYER_OPAQUE},
1354         {SMB_VFS_OP(vfswrap_getlock),   SMB_VFS_OP_GETLOCK,
1355          SMB_VFS_LAYER_OPAQUE},
1356         {SMB_VFS_OP(vfswrap_symlink),   SMB_VFS_OP_SYMLINK,
1357          SMB_VFS_LAYER_OPAQUE},
1358         {SMB_VFS_OP(vfswrap_readlink),  SMB_VFS_OP_READLINK,
1359          SMB_VFS_LAYER_OPAQUE},
1360         {SMB_VFS_OP(vfswrap_link),      SMB_VFS_OP_LINK,
1361          SMB_VFS_LAYER_OPAQUE},
1362         {SMB_VFS_OP(vfswrap_mknod),     SMB_VFS_OP_MKNOD,
1363          SMB_VFS_LAYER_OPAQUE},
1364         {SMB_VFS_OP(vfswrap_realpath),  SMB_VFS_OP_REALPATH,
1365          SMB_VFS_LAYER_OPAQUE},
1366         {SMB_VFS_OP(vfswrap_notify_watch),      SMB_VFS_OP_NOTIFY_WATCH,
1367          SMB_VFS_LAYER_OPAQUE},
1368         {SMB_VFS_OP(vfswrap_chflags),   SMB_VFS_OP_CHFLAGS,
1369          SMB_VFS_LAYER_OPAQUE},
1370         {SMB_VFS_OP(vfswrap_file_id_create),    SMB_VFS_OP_FILE_ID_CREATE,
1371          SMB_VFS_LAYER_OPAQUE},
1372
1373         /* NT ACL operations. */
1374
1375         {SMB_VFS_OP(vfswrap_fget_nt_acl),       SMB_VFS_OP_FGET_NT_ACL,
1376          SMB_VFS_LAYER_OPAQUE},
1377         {SMB_VFS_OP(vfswrap_get_nt_acl),        SMB_VFS_OP_GET_NT_ACL,
1378          SMB_VFS_LAYER_OPAQUE},
1379         {SMB_VFS_OP(vfswrap_fset_nt_acl),       SMB_VFS_OP_FSET_NT_ACL,
1380          SMB_VFS_LAYER_OPAQUE},
1381         {SMB_VFS_OP(vfswrap_set_nt_acl),        SMB_VFS_OP_SET_NT_ACL,
1382          SMB_VFS_LAYER_OPAQUE},
1383
1384         /* POSIX ACL operations. */
1385
1386         {SMB_VFS_OP(vfswrap_chmod_acl), SMB_VFS_OP_CHMOD_ACL,
1387          SMB_VFS_LAYER_OPAQUE},
1388         {SMB_VFS_OP(vfswrap_fchmod_acl),        SMB_VFS_OP_FCHMOD_ACL,
1389          SMB_VFS_LAYER_OPAQUE},
1390         {SMB_VFS_OP(vfswrap_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY,
1391          SMB_VFS_LAYER_OPAQUE},
1392         {SMB_VFS_OP(vfswrap_sys_acl_get_tag_type),      SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,
1393          SMB_VFS_LAYER_OPAQUE},
1394         {SMB_VFS_OP(vfswrap_sys_acl_get_permset),       SMB_VFS_OP_SYS_ACL_GET_PERMSET,
1395          SMB_VFS_LAYER_OPAQUE},
1396         {SMB_VFS_OP(vfswrap_sys_acl_get_qualifier),     SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,
1397          SMB_VFS_LAYER_OPAQUE},
1398         {SMB_VFS_OP(vfswrap_sys_acl_get_file),  SMB_VFS_OP_SYS_ACL_GET_FILE,
1399          SMB_VFS_LAYER_OPAQUE},
1400         {SMB_VFS_OP(vfswrap_sys_acl_get_fd),    SMB_VFS_OP_SYS_ACL_GET_FD,
1401          SMB_VFS_LAYER_OPAQUE},
1402         {SMB_VFS_OP(vfswrap_sys_acl_clear_perms),       SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,
1403          SMB_VFS_LAYER_OPAQUE},
1404         {SMB_VFS_OP(vfswrap_sys_acl_add_perm),  SMB_VFS_OP_SYS_ACL_ADD_PERM,
1405          SMB_VFS_LAYER_OPAQUE},
1406         {SMB_VFS_OP(vfswrap_sys_acl_to_text),   SMB_VFS_OP_SYS_ACL_TO_TEXT,
1407          SMB_VFS_LAYER_OPAQUE},
1408         {SMB_VFS_OP(vfswrap_sys_acl_init),      SMB_VFS_OP_SYS_ACL_INIT,
1409          SMB_VFS_LAYER_OPAQUE},
1410         {SMB_VFS_OP(vfswrap_sys_acl_create_entry),      SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,
1411          SMB_VFS_LAYER_OPAQUE},
1412         {SMB_VFS_OP(vfswrap_sys_acl_set_tag_type),      SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,
1413          SMB_VFS_LAYER_OPAQUE},
1414         {SMB_VFS_OP(vfswrap_sys_acl_set_qualifier),     SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,
1415          SMB_VFS_LAYER_OPAQUE},
1416         {SMB_VFS_OP(vfswrap_sys_acl_set_permset),       SMB_VFS_OP_SYS_ACL_SET_PERMSET,
1417          SMB_VFS_LAYER_OPAQUE},
1418         {SMB_VFS_OP(vfswrap_sys_acl_valid),     SMB_VFS_OP_SYS_ACL_VALID,
1419          SMB_VFS_LAYER_OPAQUE},
1420         {SMB_VFS_OP(vfswrap_sys_acl_set_file),  SMB_VFS_OP_SYS_ACL_SET_FILE,
1421          SMB_VFS_LAYER_OPAQUE},
1422         {SMB_VFS_OP(vfswrap_sys_acl_set_fd),    SMB_VFS_OP_SYS_ACL_SET_FD,
1423          SMB_VFS_LAYER_OPAQUE},
1424         {SMB_VFS_OP(vfswrap_sys_acl_delete_def_file),   SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
1425          SMB_VFS_LAYER_OPAQUE},
1426         {SMB_VFS_OP(vfswrap_sys_acl_get_perm),  SMB_VFS_OP_SYS_ACL_GET_PERM,
1427          SMB_VFS_LAYER_OPAQUE},
1428         {SMB_VFS_OP(vfswrap_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT,
1429          SMB_VFS_LAYER_OPAQUE},
1430         {SMB_VFS_OP(vfswrap_sys_acl_free_acl),  SMB_VFS_OP_SYS_ACL_FREE_ACL,
1431          SMB_VFS_LAYER_OPAQUE},
1432         {SMB_VFS_OP(vfswrap_sys_acl_free_qualifier),    SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,
1433          SMB_VFS_LAYER_OPAQUE},
1434
1435         /* EA operations. */
1436
1437         {SMB_VFS_OP(vfswrap_getxattr),  SMB_VFS_OP_GETXATTR,
1438          SMB_VFS_LAYER_OPAQUE},
1439         {SMB_VFS_OP(vfswrap_lgetxattr), SMB_VFS_OP_LGETXATTR,
1440          SMB_VFS_LAYER_OPAQUE},
1441         {SMB_VFS_OP(vfswrap_fgetxattr), SMB_VFS_OP_FGETXATTR,
1442          SMB_VFS_LAYER_OPAQUE},
1443         {SMB_VFS_OP(vfswrap_listxattr), SMB_VFS_OP_LISTXATTR,
1444          SMB_VFS_LAYER_OPAQUE},
1445         {SMB_VFS_OP(vfswrap_llistxattr),        SMB_VFS_OP_LLISTXATTR,
1446          SMB_VFS_LAYER_OPAQUE},
1447         {SMB_VFS_OP(vfswrap_flistxattr),        SMB_VFS_OP_FLISTXATTR,
1448          SMB_VFS_LAYER_OPAQUE},
1449         {SMB_VFS_OP(vfswrap_removexattr),       SMB_VFS_OP_REMOVEXATTR,
1450          SMB_VFS_LAYER_OPAQUE},
1451         {SMB_VFS_OP(vfswrap_lremovexattr),      SMB_VFS_OP_LREMOVEXATTR,
1452          SMB_VFS_LAYER_OPAQUE},
1453         {SMB_VFS_OP(vfswrap_fremovexattr),      SMB_VFS_OP_FREMOVEXATTR,
1454          SMB_VFS_LAYER_OPAQUE},
1455         {SMB_VFS_OP(vfswrap_setxattr),  SMB_VFS_OP_SETXATTR,
1456          SMB_VFS_LAYER_OPAQUE},
1457         {SMB_VFS_OP(vfswrap_lsetxattr), SMB_VFS_OP_LSETXATTR,
1458          SMB_VFS_LAYER_OPAQUE},
1459         {SMB_VFS_OP(vfswrap_fsetxattr), SMB_VFS_OP_FSETXATTR,
1460          SMB_VFS_LAYER_OPAQUE},
1461
1462         {SMB_VFS_OP(vfswrap_aio_read),  SMB_VFS_OP_AIO_READ,
1463          SMB_VFS_LAYER_OPAQUE},
1464         {SMB_VFS_OP(vfswrap_aio_write), SMB_VFS_OP_AIO_WRITE,
1465          SMB_VFS_LAYER_OPAQUE},
1466         {SMB_VFS_OP(vfswrap_aio_return),        SMB_VFS_OP_AIO_RETURN,
1467          SMB_VFS_LAYER_OPAQUE},
1468         {SMB_VFS_OP(vfswrap_aio_cancel), SMB_VFS_OP_AIO_CANCEL,
1469          SMB_VFS_LAYER_OPAQUE},
1470         {SMB_VFS_OP(vfswrap_aio_error), SMB_VFS_OP_AIO_ERROR,
1471          SMB_VFS_LAYER_OPAQUE},
1472         {SMB_VFS_OP(vfswrap_aio_fsync), SMB_VFS_OP_AIO_FSYNC,
1473          SMB_VFS_LAYER_OPAQUE},
1474         {SMB_VFS_OP(vfswrap_aio_suspend),SMB_VFS_OP_AIO_SUSPEND,
1475          SMB_VFS_LAYER_OPAQUE},
1476
1477         {SMB_VFS_OP(vfswrap_aio_force), SMB_VFS_OP_AIO_FORCE,
1478          SMB_VFS_LAYER_OPAQUE},
1479         
1480         {SMB_VFS_OP(vfswrap_is_offline),SMB_VFS_OP_IS_OFFLINE,
1481          SMB_VFS_LAYER_OPAQUE},
1482         {SMB_VFS_OP(vfswrap_set_offline),SMB_VFS_OP_SET_OFFLINE,
1483          SMB_VFS_LAYER_OPAQUE},
1484         {SMB_VFS_OP(vfswrap_is_remotestorage),SMB_VFS_OP_IS_REMOTESTORAGE,
1485          SMB_VFS_LAYER_OPAQUE},
1486         
1487         /* Finish VFS operations definition */
1488
1489         {SMB_VFS_OP(NULL),              SMB_VFS_OP_NOOP,
1490          SMB_VFS_LAYER_NOOP}
1491 };
1492
1493 NTSTATUS vfs_default_init(void);
1494 NTSTATUS vfs_default_init(void)
1495 {
1496         unsigned int needed = SMB_VFS_OP_LAST + 1; /* convert from index to count */
1497
1498         if (ARRAY_SIZE(vfs_default_ops) != needed) {
1499                 DEBUG(0, ("%s: %u ops registered, but %u ops are required\n",
1500                         DEFAULT_VFS_MODULE_NAME, (unsigned int)ARRAY_SIZE(vfs_default_ops), needed));
1501                 smb_panic("operation(s) missing from default VFS module");
1502         }
1503
1504         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1505                                 DEFAULT_VFS_MODULE_NAME, vfs_default_ops);
1506 }