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