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