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