s3: Plumb smb_filename through SMB_VFS_RENAME
[metze/samba/wip.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_VFS
25
26 /* Check for NULL pointer parameters in vfswrap_* functions */
27
28 /* We don't want to have NULL function pointers lying around.  Someone
29    is sure to try and execute them.  These stubs are used to prevent
30    this possibility. */
31
32 static int vfswrap_connect(vfs_handle_struct *handle,  const char *service, const char *user)
33 {
34     return 0;    /* Return >= 0 for success */
35 }
36
37 static void vfswrap_disconnect(vfs_handle_struct *handle)
38 {
39 }
40
41 /* Disk operations */
42
43 static 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,
524                           const struct smb_filename *smb_fname_src,
525                           const struct smb_filename *smb_fname_dst)
526 {
527         int result;
528
529         START_PROFILE(syscall_rename);
530
531         if (smb_fname_src->stream_name || smb_fname_dst->stream_name) {
532                 errno = ENOENT;
533                 result = -1;
534                 goto out;
535         }
536
537         result = rename(smb_fname_src->base_name, smb_fname_dst->base_name);
538         if ((result == -1) && (errno == EXDEV)) {
539                 /* Rename across filesystems needed. */
540                 result = copy_reg(smb_fname_src->base_name,
541                                   smb_fname_dst->base_name);
542         }
543
544  out:
545         END_PROFILE(syscall_rename);
546         return result;
547 }
548
549 static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp)
550 {
551 #ifdef HAVE_FSYNC
552         int result;
553
554         START_PROFILE(syscall_fsync);
555         result = fsync(fsp->fh->fd);
556         END_PROFILE(syscall_fsync);
557         return result;
558 #else
559         return 0;
560 #endif
561 }
562
563 static int vfswrap_stat(vfs_handle_struct *handle,
564                         struct smb_filename *smb_fname)
565 {
566         int result;
567         NTSTATUS status;
568         char *fname = NULL;
569
570         START_PROFILE(syscall_stat);
571
572         status = get_full_smb_filename(talloc_tos(), smb_fname,
573                                        &fname);
574         if (!NT_STATUS_IS_OK(status)) {
575                 errno = map_errno_from_nt_status(status);
576                 return -1;
577         }
578
579         result = sys_stat(fname, &smb_fname->st);
580
581         TALLOC_FREE(fname);
582
583         END_PROFILE(syscall_stat);
584         return result;
585 }
586
587 static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
588 {
589         int result;
590
591         START_PROFILE(syscall_fstat);
592         result = sys_fstat(fsp->fh->fd, sbuf);
593         END_PROFILE(syscall_fstat);
594         return result;
595 }
596
597 static int vfswrap_lstat(vfs_handle_struct *handle,
598                          struct smb_filename *smb_fname)
599 {
600         int result;
601         NTSTATUS status;
602         char *fname = NULL;
603
604         START_PROFILE(syscall_lstat);
605
606         status = get_full_smb_filename(talloc_tos(), smb_fname,
607                                        &fname);
608         if (!NT_STATUS_IS_OK(status)) {
609                 errno = map_errno_from_nt_status(status);
610                 return -1;
611         }
612
613         result = sys_lstat(fname, &smb_fname->st);
614
615         TALLOC_FREE(fname);
616
617         END_PROFILE(syscall_lstat);
618         return result;
619 }
620
621 /********************************************************************
622  Given a stat buffer return the allocated size on disk, taking into
623  account sparse files.
624 ********************************************************************/
625 static uint64_t vfswrap_get_alloc_size(vfs_handle_struct *handle,
626                                        struct files_struct *fsp,
627                                        const SMB_STRUCT_STAT *sbuf)
628 {
629         uint64_t result;
630
631         START_PROFILE(syscall_get_alloc_size);
632
633         if(S_ISDIR(sbuf->st_ex_mode)) {
634                 result = 0;
635                 goto out;
636         }
637
638 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
639         result = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_ex_blocks;
640 #else
641         result = get_file_size_stat(sbuf);
642 #endif
643
644         if (fsp && fsp->initial_allocation_size)
645                 result = MAX(result,fsp->initial_allocation_size);
646
647         result = smb_roundup(handle->conn, result);
648
649  out:
650         END_PROFILE(syscall_get_alloc_size);
651         return result;
652 }
653
654 static int vfswrap_unlink(vfs_handle_struct *handle,  const char *path)
655 {
656         int result;
657
658         START_PROFILE(syscall_unlink);
659         result = unlink(path);
660         END_PROFILE(syscall_unlink);
661         return result;
662 }
663
664 static int vfswrap_chmod(vfs_handle_struct *handle,  const char *path, mode_t mode)
665 {
666         int result;
667
668         START_PROFILE(syscall_chmod);
669
670         /*
671          * We need to do this due to the fact that the default POSIX ACL
672          * chmod modifies the ACL *mask* for the group owner, not the
673          * group owner bits directly. JRA.
674          */
675
676
677         {
678                 int saved_errno = errno; /* We might get ENOSYS */
679                 if ((result = SMB_VFS_CHMOD_ACL(handle->conn, path, mode)) == 0) {
680                         END_PROFILE(syscall_chmod);
681                         return result;
682                 }
683                 /* Error - return the old errno. */
684                 errno = saved_errno;
685         }
686
687         result = chmod(path, mode);
688         END_PROFILE(syscall_chmod);
689         return result;
690 }
691
692 static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
693 {
694         int result;
695
696         START_PROFILE(syscall_fchmod);
697
698         /*
699          * We need to do this due to the fact that the default POSIX ACL
700          * chmod modifies the ACL *mask* for the group owner, not the
701          * group owner bits directly. JRA.
702          */
703
704         {
705                 int saved_errno = errno; /* We might get ENOSYS */
706                 if ((result = SMB_VFS_FCHMOD_ACL(fsp, mode)) == 0) {
707                         END_PROFILE(syscall_fchmod);
708                         return result;
709                 }
710                 /* Error - return the old errno. */
711                 errno = saved_errno;
712         }
713
714 #if defined(HAVE_FCHMOD)
715         result = fchmod(fsp->fh->fd, mode);
716 #else
717         result = -1;
718         errno = ENOSYS;
719 #endif
720
721         END_PROFILE(syscall_fchmod);
722         return result;
723 }
724
725 static int vfswrap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
726 {
727         int result;
728
729         START_PROFILE(syscall_chown);
730         result = chown(path, uid, gid);
731         END_PROFILE(syscall_chown);
732         return result;
733 }
734
735 static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid)
736 {
737 #ifdef HAVE_FCHOWN
738         int result;
739
740         START_PROFILE(syscall_fchown);
741         result = fchown(fsp->fh->fd, uid, gid);
742         END_PROFILE(syscall_fchown);
743         return result;
744 #else
745         errno = ENOSYS;
746         return -1;
747 #endif
748 }
749
750 static int vfswrap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
751 {
752         int result;
753
754         START_PROFILE(syscall_lchown);
755         result = lchown(path, uid, gid);
756         END_PROFILE(syscall_lchown);
757         return result;
758 }
759
760 static int vfswrap_chdir(vfs_handle_struct *handle,  const char *path)
761 {
762         int result;
763
764         START_PROFILE(syscall_chdir);
765         result = chdir(path);
766         END_PROFILE(syscall_chdir);
767         return result;
768 }
769
770 static char *vfswrap_getwd(vfs_handle_struct *handle,  char *path)
771 {
772         char *result;
773
774         START_PROFILE(syscall_getwd);
775         result = sys_getwd(path);
776         END_PROFILE(syscall_getwd);
777         return result;
778 }
779
780 /*********************************************************************
781  nsec timestamp resolution call. Convert down to whatever the underlying
782  system will support.
783 **********************************************************************/
784
785 static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path,
786                           struct smb_file_time *ft)
787 {
788         int result;
789
790         START_PROFILE(syscall_ntimes);
791 #if defined(HAVE_UTIMES)
792         if (ft != NULL) {
793                 struct timeval tv[2];
794                 tv[0] = convert_timespec_to_timeval(ft->atime);
795                 tv[1] = convert_timespec_to_timeval(ft->mtime);
796                 result = utimes(path, tv);
797         } else {
798                 result = utimes(path, NULL);
799         }
800 #elif defined(HAVE_UTIME)
801         if (ft != NULL) {
802                 struct utimbuf times;
803                 times.actime = convert_timespec_to_time_t(ft->atime);
804                 times.modtime = convert_timespec_to_time_t(ft->mtime);
805                 result = utime(path, &times);
806         } else {
807                 result = utime(path, NULL);
808         }
809 #else
810         errno = ENOSYS;
811         result = -1;
812 #endif
813         END_PROFILE(syscall_ntimes);
814         return result;
815 }
816
817 /*********************************************************************
818  A version of ftruncate that will write the space on disk if strict
819  allocate is set.
820 **********************************************************************/
821
822 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
823 {
824         SMB_STRUCT_STAT st;
825         SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
826         unsigned char zero_space[4096];
827         SMB_OFF_T space_to_write;
828
829         if (currpos == -1)
830                 return -1;
831
832         if (SMB_VFS_FSTAT(fsp, &st) == -1)
833                 return -1;
834
835         space_to_write = len - st.st_ex_size;
836
837 #ifdef S_ISFIFO
838         if (S_ISFIFO(st.st_ex_mode))
839                 return 0;
840 #endif
841
842         if (st.st_ex_size == len)
843                 return 0;
844
845         /* Shrink - just ftruncate. */
846         if (st.st_ex_size > len)
847                 return sys_ftruncate(fsp->fh->fd, len);
848
849         /* available disk space is enough or not? */
850         if (lp_strict_allocate(SNUM(fsp->conn))){
851                 uint64_t space_avail;
852                 uint64_t bsize,dfree,dsize;
853
854                 space_avail = get_dfree_info(fsp->conn,fsp->fsp_name,false,&bsize,&dfree,&dsize);
855                 /* space_avail is 1k blocks */
856                 if (space_avail == (uint64_t)-1 ||
857                                 ((uint64_t)space_to_write/1024 > space_avail) ) {
858                         errno = ENOSPC;
859                         return -1;
860                 }
861         }
862
863         /* Write out the real space on disk. */
864         if (SMB_VFS_LSEEK(fsp, st.st_ex_size, SEEK_SET) != st.st_ex_size)
865                 return -1;
866
867         space_to_write = len - st.st_ex_size;
868
869         memset(zero_space, '\0', sizeof(zero_space));
870         while ( space_to_write > 0) {
871                 SMB_OFF_T retlen;
872                 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
873
874                 retlen = SMB_VFS_WRITE(fsp,(char *)zero_space,current_len_to_write);
875                 if (retlen <= 0)
876                         return -1;
877
878                 space_to_write -= retlen;
879         }
880
881         /* Seek to where we were */
882         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
883                 return -1;
884
885         return 0;
886 }
887
888 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
889 {
890         int result = -1;
891         SMB_STRUCT_STAT st;
892         char c = 0;
893         SMB_OFF_T currpos;
894
895         START_PROFILE(syscall_ftruncate);
896
897         if (lp_strict_allocate(SNUM(fsp->conn))) {
898                 result = strict_allocate_ftruncate(handle, fsp, len);
899                 END_PROFILE(syscall_ftruncate);
900                 return result;
901         }
902
903         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
904            sys_ftruncate if the system supports it. Then I discovered that
905            you can have some filesystems that support ftruncate
906            expansion and some that don't! On Linux fat can't do
907            ftruncate extend but ext2 can. */
908
909         result = sys_ftruncate(fsp->fh->fd, len);
910         if (result == 0)
911                 goto done;
912
913         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
914            extend a file with ftruncate. Provide alternate implementation
915            for this */
916         currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
917         if (currpos == -1) {
918                 goto done;
919         }
920
921         /* Do an fstat to see if the file is longer than the requested
922            size in which case the ftruncate above should have
923            succeeded or shorter, in which case seek to len - 1 and
924            write 1 byte of zero */
925         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
926                 goto done;
927         }
928
929 #ifdef S_ISFIFO
930         if (S_ISFIFO(st.st_ex_mode)) {
931                 result = 0;
932                 goto done;
933         }
934 #endif
935
936         if (st.st_ex_size == len) {
937                 result = 0;
938                 goto done;
939         }
940
941         if (st.st_ex_size > len) {
942                 /* the sys_ftruncate should have worked */
943                 goto done;
944         }
945
946         if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
947                 goto done;
948
949         if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
950                 goto done;
951
952         /* Seek to where we were */
953         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
954                 goto done;
955         result = 0;
956
957   done:
958
959         END_PROFILE(syscall_ftruncate);
960         return result;
961 }
962
963 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
964 {
965         bool result;
966
967         START_PROFILE(syscall_fcntl_lock);
968         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
969         END_PROFILE(syscall_fcntl_lock);
970         return result;
971 }
972
973 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
974                                 uint32 share_mode)
975 {
976         START_PROFILE(syscall_kernel_flock);
977         kernel_flock(fsp->fh->fd, share_mode);
978         END_PROFILE(syscall_kernel_flock);
979         return 0;
980 }
981
982 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
983 {
984         bool result;
985
986         START_PROFILE(syscall_fcntl_getlock);
987         result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
988         END_PROFILE(syscall_fcntl_getlock);
989         return result;
990 }
991
992 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
993                                 int leasetype)
994 {
995         int result = -1;
996
997         START_PROFILE(syscall_linux_setlease);
998
999 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1000         /* first set the signal handler */
1001         if(linux_set_lease_sighandler(fsp->fh->fd) == -1) {
1002                 return -1;
1003         }
1004
1005         result = linux_setlease(fsp->fh->fd, leasetype);
1006 #else
1007         errno = ENOSYS;
1008 #endif
1009         END_PROFILE(syscall_linux_setlease);
1010         return result;
1011 }
1012
1013 static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1014 {
1015         int result;
1016
1017         START_PROFILE(syscall_symlink);
1018         result = symlink(oldpath, newpath);
1019         END_PROFILE(syscall_symlink);
1020         return result;
1021 }
1022
1023 static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
1024 {
1025         int result;
1026
1027         START_PROFILE(syscall_readlink);
1028         result = readlink(path, buf, bufsiz);
1029         END_PROFILE(syscall_readlink);
1030         return result;
1031 }
1032
1033 static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1034 {
1035         int result;
1036
1037         START_PROFILE(syscall_link);
1038         result = link(oldpath, newpath);
1039         END_PROFILE(syscall_link);
1040         return result;
1041 }
1042
1043 static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
1044 {
1045         int result;
1046
1047         START_PROFILE(syscall_mknod);
1048         result = sys_mknod(pathname, mode, dev);
1049         END_PROFILE(syscall_mknod);
1050         return result;
1051 }
1052
1053 static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path, char *resolved_path)
1054 {
1055         char *result;
1056
1057         START_PROFILE(syscall_realpath);
1058         result = realpath(path, resolved_path);
1059         END_PROFILE(syscall_realpath);
1060         return result;
1061 }
1062
1063 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
1064                                      struct sys_notify_context *ctx,
1065                                      struct notify_entry *e,
1066                                      void (*callback)(struct sys_notify_context *ctx, 
1067                                                       void *private_data,
1068                                                       struct notify_event *ev),
1069                                      void *private_data, void *handle)
1070 {
1071         /*
1072          * So far inotify is the only supported default notify mechanism. If
1073          * another platform like the the BSD's or a proprietary Unix comes
1074          * along and wants another default, we can play the same trick we
1075          * played with Posix ACLs.
1076          *
1077          * Until that is the case, hard-code inotify here.
1078          */
1079 #ifdef HAVE_INOTIFY
1080         if (lp_kernel_change_notify(ctx->conn->params)) {
1081                 return inotify_watch(ctx, e, callback, private_data, handle);
1082         }
1083 #endif
1084         /*
1085          * Do nothing, leave everything to notify_internal.c
1086          */
1087         return NT_STATUS_OK;
1088 }
1089
1090 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flags)
1091 {
1092 #ifdef HAVE_CHFLAGS
1093         return chflags(path, flags);
1094 #else
1095         errno = ENOSYS;
1096         return -1;
1097 #endif
1098 }
1099
1100 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
1101                                              SMB_STRUCT_STAT *sbuf)
1102 {
1103         struct file_id key;
1104
1105         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
1106          * blob */
1107         ZERO_STRUCT(key);
1108
1109         key.devid = sbuf->st_ex_dev;
1110         key.inode = sbuf->st_ex_ino;
1111         /* key.extid is unused by default. */
1112
1113         return key;
1114 }
1115
1116 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
1117                                    struct files_struct *fsp,
1118                                    const char *fname,
1119                                    TALLOC_CTX *mem_ctx,
1120                                    unsigned int *pnum_streams,
1121                                    struct stream_struct **pstreams)
1122 {
1123         SMB_STRUCT_STAT sbuf;
1124         unsigned int num_streams = 0;
1125         struct stream_struct *streams = NULL;
1126         int ret;
1127
1128         if ((fsp != NULL) && (fsp->is_directory)) {
1129                 /*
1130                  * No default streams on directories
1131                  */
1132                 goto done;
1133         }
1134
1135         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
1136                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
1137         }
1138         else {
1139                 ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf);
1140         }
1141
1142         if (ret == -1) {
1143                 return map_nt_error_from_unix(errno);
1144         }
1145
1146         if (S_ISDIR(sbuf.st_ex_mode)) {
1147                 goto done;
1148         }
1149
1150         streams = talloc(mem_ctx, struct stream_struct);
1151
1152         if (streams == NULL) {
1153                 return NT_STATUS_NO_MEMORY;
1154         }
1155
1156         streams->size = sbuf.st_ex_size;
1157         streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
1158
1159         streams->name = talloc_strdup(streams, "::$DATA");
1160         if (streams->name == NULL) {
1161                 TALLOC_FREE(streams);
1162                 return NT_STATUS_NO_MEMORY;
1163         }
1164
1165         num_streams = 1;
1166  done:
1167         *pnum_streams = num_streams;
1168         *pstreams = streams;
1169         return NT_STATUS_OK;
1170 }
1171
1172 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
1173                                      const char *path,
1174                                      const char *name,
1175                                      TALLOC_CTX *mem_ctx,
1176                                      char **found_name)
1177 {
1178         /*
1179          * Don't fall back to get_real_filename so callers can differentiate
1180          * between a full directory scan and an actual case-insensitive stat.
1181          */
1182         errno = EOPNOTSUPP;
1183         return -1;
1184 }
1185
1186 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
1187                                        const char *fname)
1188 {
1189         return handle->conn->connectpath;
1190 }
1191
1192 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
1193                                          struct byte_range_lock *br_lck,
1194                                          struct lock_struct *plock,
1195                                          bool blocking_lock,
1196                                          struct blocking_lock_record *blr)
1197 {
1198         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1199
1200         /* Note: blr is not used in the default implementation. */
1201         return brl_lock_windows_default(br_lck, plock, blocking_lock);
1202 }
1203
1204 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
1205                                        struct messaging_context *msg_ctx,
1206                                        struct byte_range_lock *br_lck,
1207                                        const struct lock_struct *plock)
1208 {
1209         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1210
1211         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
1212 }
1213
1214 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
1215                                        struct byte_range_lock *br_lck,
1216                                        struct lock_struct *plock,
1217                                        struct blocking_lock_record *blr)
1218 {
1219         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1220
1221         /* Note: blr is not used in the default implementation. */
1222         return brl_lock_cancel_default(br_lck, plock);
1223 }
1224
1225 static bool vfswrap_strict_lock(struct vfs_handle_struct *handle,
1226                                 files_struct *fsp,
1227                                 struct lock_struct *plock)
1228 {
1229         SMB_ASSERT(plock->lock_type == READ_LOCK ||
1230             plock->lock_type == WRITE_LOCK);
1231
1232         return strict_lock_default(fsp, plock);
1233 }
1234
1235 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
1236                                 files_struct *fsp,
1237                                 struct lock_struct *plock)
1238 {
1239         SMB_ASSERT(plock->lock_type == READ_LOCK ||
1240             plock->lock_type == WRITE_LOCK);
1241
1242         strict_unlock_default(fsp, plock);
1243 }
1244
1245 /* NT ACL operations. */
1246
1247 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
1248                                     files_struct *fsp,
1249                                     uint32 security_info, SEC_DESC **ppdesc)
1250 {
1251         NTSTATUS result;
1252
1253         START_PROFILE(fget_nt_acl);
1254         result = posix_fget_nt_acl(fsp, security_info, ppdesc);
1255         END_PROFILE(fget_nt_acl);
1256         return result;
1257 }
1258
1259 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
1260                                    const char *name,
1261                                    uint32 security_info, SEC_DESC **ppdesc)
1262 {
1263         NTSTATUS result;
1264
1265         START_PROFILE(get_nt_acl);
1266         result = posix_get_nt_acl(handle->conn, name, security_info, ppdesc);
1267         END_PROFILE(get_nt_acl);
1268         return result;
1269 }
1270
1271 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
1272 {
1273         NTSTATUS result;
1274
1275         START_PROFILE(fset_nt_acl);
1276         result = set_nt_acl(fsp, security_info_sent, psd);
1277         END_PROFILE(fset_nt_acl);
1278         return result;
1279 }
1280
1281 static int vfswrap_chmod_acl(vfs_handle_struct *handle,  const char *name, mode_t mode)
1282 {
1283 #ifdef HAVE_NO_ACL
1284         errno = ENOSYS;
1285         return -1;
1286 #else
1287         int result;
1288
1289         START_PROFILE(chmod_acl);
1290         result = chmod_acl(handle->conn, name, mode);
1291         END_PROFILE(chmod_acl);
1292         return result;
1293 #endif
1294 }
1295
1296 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1297 {
1298 #ifdef HAVE_NO_ACL
1299         errno = ENOSYS;
1300         return -1;
1301 #else
1302         int result;
1303
1304         START_PROFILE(fchmod_acl);
1305         result = fchmod_acl(fsp, mode);
1306         END_PROFILE(fchmod_acl);
1307         return result;
1308 #endif
1309 }
1310
1311 static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle,  SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1312 {
1313         return sys_acl_get_entry(theacl, entry_id, entry_p);
1314 }
1315
1316 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)
1317 {
1318         return sys_acl_get_tag_type(entry_d, tag_type_p);
1319 }
1320
1321 static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1322 {
1323         return sys_acl_get_permset(entry_d, permset_p);
1324 }
1325
1326 static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
1327 {
1328         return sys_acl_get_qualifier(entry_d);
1329 }
1330
1331 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
1332 {
1333         return sys_acl_get_file(handle, path_p, type);
1334 }
1335
1336 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
1337 {
1338         return sys_acl_get_fd(handle, fsp);
1339 }
1340
1341 static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset)
1342 {
1343         return sys_acl_clear_perms(permset);
1344 }
1345
1346 static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1347 {
1348         return sys_acl_add_perm(permset, perm);
1349 }
1350
1351 static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle,  SMB_ACL_T theacl, ssize_t *plen)
1352 {
1353         return sys_acl_to_text(theacl, plen);
1354 }
1355
1356 static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle,  int count)
1357 {
1358         return sys_acl_init(count);
1359 }
1360
1361 static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle,  SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1362 {
1363         return sys_acl_create_entry(pacl, pentry);
1364 }
1365
1366 static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1367 {
1368         return sys_acl_set_tag_type(entry, tagtype);
1369 }
1370
1371 static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, void *qual)
1372 {
1373         return sys_acl_set_qualifier(entry, qual);
1374 }
1375
1376 static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1377 {
1378         return sys_acl_set_permset(entry, permset);
1379 }
1380
1381 static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
1382 {
1383         return sys_acl_valid(theacl );
1384 }
1385
1386 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1387 {
1388         return sys_acl_set_file(handle, name, acltype, theacl);
1389 }
1390
1391 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
1392 {
1393         return sys_acl_set_fd(handle, fsp, theacl);
1394 }
1395
1396 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const char *path)
1397 {
1398         return sys_acl_delete_def_file(handle, path);
1399 }
1400
1401 static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1402 {
1403         return sys_acl_get_perm(permset, perm);
1404 }
1405
1406 static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle,  char *text)
1407 {
1408         return sys_acl_free_text(text);
1409 }
1410
1411 static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle,  SMB_ACL_T posix_acl)
1412 {
1413         return sys_acl_free_acl(posix_acl);
1414 }
1415
1416 static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle,  void *qualifier, SMB_ACL_TAG_T tagtype)
1417 {
1418         return sys_acl_free_qualifier(qualifier, tagtype);
1419 }
1420
1421 /****************************************************************
1422  Extended attribute operations.
1423 *****************************************************************/
1424
1425 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1426 {
1427         return sys_getxattr(path, name, value, size);
1428 }
1429
1430 static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1431 {
1432         return sys_lgetxattr(path, name, value, size);
1433 }
1434
1435 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
1436 {
1437         return sys_fgetxattr(fsp->fh->fd, name, value, size);
1438 }
1439
1440 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1441 {
1442         return sys_listxattr(path, list, size);
1443 }
1444
1445 ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1446 {
1447         return sys_llistxattr(path, list, size);
1448 }
1449
1450 ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
1451 {
1452         return sys_flistxattr(fsp->fh->fd, list, size);
1453 }
1454
1455 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1456 {
1457         return sys_removexattr(path, name);
1458 }
1459
1460 static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1461 {
1462         return sys_lremovexattr(path, name);
1463 }
1464
1465 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
1466 {
1467         return sys_fremovexattr(fsp->fh->fd, name);
1468 }
1469
1470 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1471 {
1472         return sys_setxattr(path, name, value, size, flags);
1473 }
1474
1475 static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1476 {
1477         return sys_lsetxattr(path, name, value, size, flags);
1478 }
1479
1480 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
1481 {
1482         return sys_fsetxattr(fsp->fh->fd, name, value, size, flags);
1483 }
1484
1485 static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1486 {
1487         int ret;
1488         /*
1489          * aio_read must be done as root, because in the glibc aio
1490          * implementation the helper thread needs to be able to send a signal
1491          * to the main thread, even when it has done a seteuid() to a
1492          * different user.
1493          */
1494         become_root();
1495         ret = sys_aio_read(aiocb);
1496         unbecome_root();
1497         return ret;
1498 }
1499
1500 static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1501 {
1502         int ret;
1503         /*
1504          * aio_write must be done as root, because in the glibc aio
1505          * implementation the helper thread needs to be able to send a signal
1506          * to the main thread, even when it has done a seteuid() to a
1507          * different user.
1508          */
1509         become_root();
1510         ret = sys_aio_write(aiocb);
1511         unbecome_root();
1512         return ret;
1513 }
1514
1515 static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1516 {
1517         return sys_aio_return(aiocb);
1518 }
1519
1520 static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1521 {
1522         return sys_aio_cancel(fsp->fh->fd, aiocb);
1523 }
1524
1525 static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1526 {
1527         return sys_aio_error(aiocb);
1528 }
1529
1530 static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
1531 {
1532         return sys_aio_fsync(op, aiocb);
1533 }
1534
1535 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)
1536 {
1537         return sys_aio_suspend(aiocb, n, timeout);
1538 }
1539
1540 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
1541 {
1542         return false;
1543 }
1544
1545 static bool vfswrap_is_offline(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
1546 {
1547         if (ISDOT(path) || ISDOTDOT(path)) {
1548                 return false;
1549         }
1550
1551         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
1552 #if defined(ENOTSUP)
1553                 errno = ENOTSUP;
1554 #endif
1555                 return false;
1556         }
1557
1558         return (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
1559 }
1560
1561 static int vfswrap_set_offline(struct vfs_handle_struct *handle, const char *path)
1562 {
1563         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
1564 #if defined(ENOTSUP)
1565         errno = ENOTSUP;
1566 #endif
1567         return -1;
1568 }
1569
1570 static vfs_op_tuple vfs_default_ops[] = {
1571
1572         /* Disk operations */
1573
1574         {SMB_VFS_OP(vfswrap_connect),   SMB_VFS_OP_CONNECT,
1575          SMB_VFS_LAYER_OPAQUE},
1576         {SMB_VFS_OP(vfswrap_disconnect),        SMB_VFS_OP_DISCONNECT,
1577          SMB_VFS_LAYER_OPAQUE},
1578         {SMB_VFS_OP(vfswrap_disk_free), SMB_VFS_OP_DISK_FREE,
1579          SMB_VFS_LAYER_OPAQUE},
1580         {SMB_VFS_OP(vfswrap_get_quota), SMB_VFS_OP_GET_QUOTA,
1581          SMB_VFS_LAYER_OPAQUE},
1582         {SMB_VFS_OP(vfswrap_set_quota), SMB_VFS_OP_SET_QUOTA,
1583          SMB_VFS_LAYER_OPAQUE},
1584         {SMB_VFS_OP(vfswrap_get_shadow_copy_data), SMB_VFS_OP_GET_SHADOW_COPY_DATA,
1585          SMB_VFS_LAYER_OPAQUE},
1586         {SMB_VFS_OP(vfswrap_statvfs),   SMB_VFS_OP_STATVFS,
1587          SMB_VFS_LAYER_OPAQUE},
1588         {SMB_VFS_OP(vfswrap_fs_capabilities), SMB_VFS_OP_FS_CAPABILITIES,
1589          SMB_VFS_LAYER_OPAQUE},
1590
1591         /* Directory operations */
1592
1593         {SMB_VFS_OP(vfswrap_opendir),   SMB_VFS_OP_OPENDIR,
1594          SMB_VFS_LAYER_OPAQUE},
1595         {SMB_VFS_OP(vfswrap_readdir),   SMB_VFS_OP_READDIR,
1596          SMB_VFS_LAYER_OPAQUE},
1597         {SMB_VFS_OP(vfswrap_seekdir),   SMB_VFS_OP_SEEKDIR,
1598          SMB_VFS_LAYER_OPAQUE},
1599         {SMB_VFS_OP(vfswrap_telldir),   SMB_VFS_OP_TELLDIR,
1600          SMB_VFS_LAYER_OPAQUE},
1601         {SMB_VFS_OP(vfswrap_rewinddir), SMB_VFS_OP_REWINDDIR,
1602          SMB_VFS_LAYER_OPAQUE},
1603         {SMB_VFS_OP(vfswrap_mkdir),     SMB_VFS_OP_MKDIR,
1604          SMB_VFS_LAYER_OPAQUE},
1605         {SMB_VFS_OP(vfswrap_rmdir),     SMB_VFS_OP_RMDIR,
1606          SMB_VFS_LAYER_OPAQUE},
1607         {SMB_VFS_OP(vfswrap_closedir),  SMB_VFS_OP_CLOSEDIR,
1608          SMB_VFS_LAYER_OPAQUE},
1609         {SMB_VFS_OP(vfswrap_init_search_op), SMB_VFS_OP_INIT_SEARCH_OP,
1610          SMB_VFS_LAYER_OPAQUE},
1611
1612         /* File operations */
1613
1614         {SMB_VFS_OP(vfswrap_open),      SMB_VFS_OP_OPEN,
1615          SMB_VFS_LAYER_OPAQUE},
1616         {SMB_VFS_OP(vfswrap_create_file),       SMB_VFS_OP_CREATE_FILE,
1617          SMB_VFS_LAYER_OPAQUE},
1618         {SMB_VFS_OP(vfswrap_close),     SMB_VFS_OP_CLOSE,
1619          SMB_VFS_LAYER_OPAQUE},
1620         {SMB_VFS_OP(vfswrap_read),      SMB_VFS_OP_READ,
1621          SMB_VFS_LAYER_OPAQUE},
1622         {SMB_VFS_OP(vfswrap_pread),     SMB_VFS_OP_PREAD,
1623          SMB_VFS_LAYER_OPAQUE},
1624         {SMB_VFS_OP(vfswrap_write),     SMB_VFS_OP_WRITE,
1625          SMB_VFS_LAYER_OPAQUE},
1626         {SMB_VFS_OP(vfswrap_pwrite),    SMB_VFS_OP_PWRITE,
1627          SMB_VFS_LAYER_OPAQUE},
1628         {SMB_VFS_OP(vfswrap_lseek),     SMB_VFS_OP_LSEEK,
1629          SMB_VFS_LAYER_OPAQUE},
1630         {SMB_VFS_OP(vfswrap_sendfile),  SMB_VFS_OP_SENDFILE,
1631          SMB_VFS_LAYER_OPAQUE},
1632         {SMB_VFS_OP(vfswrap_recvfile),  SMB_VFS_OP_RECVFILE,
1633          SMB_VFS_LAYER_OPAQUE},
1634         {SMB_VFS_OP(vfswrap_rename),    SMB_VFS_OP_RENAME,
1635          SMB_VFS_LAYER_OPAQUE},
1636         {SMB_VFS_OP(vfswrap_fsync),     SMB_VFS_OP_FSYNC,
1637          SMB_VFS_LAYER_OPAQUE},
1638         {SMB_VFS_OP(vfswrap_stat),      SMB_VFS_OP_STAT,
1639          SMB_VFS_LAYER_OPAQUE},
1640         {SMB_VFS_OP(vfswrap_fstat),     SMB_VFS_OP_FSTAT,
1641          SMB_VFS_LAYER_OPAQUE},
1642         {SMB_VFS_OP(vfswrap_lstat),     SMB_VFS_OP_LSTAT,
1643          SMB_VFS_LAYER_OPAQUE},
1644         {SMB_VFS_OP(vfswrap_get_alloc_size),    SMB_VFS_OP_GET_ALLOC_SIZE,
1645          SMB_VFS_LAYER_OPAQUE},
1646         {SMB_VFS_OP(vfswrap_unlink),    SMB_VFS_OP_UNLINK,
1647          SMB_VFS_LAYER_OPAQUE},
1648         {SMB_VFS_OP(vfswrap_chmod),     SMB_VFS_OP_CHMOD,
1649          SMB_VFS_LAYER_OPAQUE},
1650         {SMB_VFS_OP(vfswrap_fchmod),    SMB_VFS_OP_FCHMOD,
1651          SMB_VFS_LAYER_OPAQUE},
1652         {SMB_VFS_OP(vfswrap_chown),     SMB_VFS_OP_CHOWN,
1653          SMB_VFS_LAYER_OPAQUE},
1654         {SMB_VFS_OP(vfswrap_fchown),    SMB_VFS_OP_FCHOWN,
1655          SMB_VFS_LAYER_OPAQUE},
1656         {SMB_VFS_OP(vfswrap_lchown),    SMB_VFS_OP_LCHOWN,
1657          SMB_VFS_LAYER_OPAQUE},
1658         {SMB_VFS_OP(vfswrap_chdir),     SMB_VFS_OP_CHDIR,
1659          SMB_VFS_LAYER_OPAQUE},
1660         {SMB_VFS_OP(vfswrap_getwd),     SMB_VFS_OP_GETWD,
1661          SMB_VFS_LAYER_OPAQUE},
1662         {SMB_VFS_OP(vfswrap_ntimes),    SMB_VFS_OP_NTIMES,
1663          SMB_VFS_LAYER_OPAQUE},
1664         {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE,
1665          SMB_VFS_LAYER_OPAQUE},
1666         {SMB_VFS_OP(vfswrap_lock),      SMB_VFS_OP_LOCK,
1667          SMB_VFS_LAYER_OPAQUE},
1668         {SMB_VFS_OP(vfswrap_kernel_flock),      SMB_VFS_OP_KERNEL_FLOCK,
1669          SMB_VFS_LAYER_OPAQUE},
1670         {SMB_VFS_OP(vfswrap_linux_setlease),    SMB_VFS_OP_LINUX_SETLEASE,
1671          SMB_VFS_LAYER_OPAQUE},
1672         {SMB_VFS_OP(vfswrap_getlock),   SMB_VFS_OP_GETLOCK,
1673          SMB_VFS_LAYER_OPAQUE},
1674         {SMB_VFS_OP(vfswrap_symlink),   SMB_VFS_OP_SYMLINK,
1675          SMB_VFS_LAYER_OPAQUE},
1676         {SMB_VFS_OP(vfswrap_readlink),  SMB_VFS_OP_READLINK,
1677          SMB_VFS_LAYER_OPAQUE},
1678         {SMB_VFS_OP(vfswrap_link),      SMB_VFS_OP_LINK,
1679          SMB_VFS_LAYER_OPAQUE},
1680         {SMB_VFS_OP(vfswrap_mknod),     SMB_VFS_OP_MKNOD,
1681          SMB_VFS_LAYER_OPAQUE},
1682         {SMB_VFS_OP(vfswrap_realpath),  SMB_VFS_OP_REALPATH,
1683          SMB_VFS_LAYER_OPAQUE},
1684         {SMB_VFS_OP(vfswrap_notify_watch),      SMB_VFS_OP_NOTIFY_WATCH,
1685          SMB_VFS_LAYER_OPAQUE},
1686         {SMB_VFS_OP(vfswrap_chflags),   SMB_VFS_OP_CHFLAGS,
1687          SMB_VFS_LAYER_OPAQUE},
1688         {SMB_VFS_OP(vfswrap_file_id_create),    SMB_VFS_OP_FILE_ID_CREATE,
1689          SMB_VFS_LAYER_OPAQUE},
1690         {SMB_VFS_OP(vfswrap_streaminfo),        SMB_VFS_OP_STREAMINFO,
1691          SMB_VFS_LAYER_OPAQUE},
1692         {SMB_VFS_OP(vfswrap_get_real_filename), SMB_VFS_OP_GET_REAL_FILENAME,
1693          SMB_VFS_LAYER_OPAQUE},
1694         {SMB_VFS_OP(vfswrap_connectpath),       SMB_VFS_OP_CONNECTPATH,
1695          SMB_VFS_LAYER_OPAQUE},
1696         {SMB_VFS_OP(vfswrap_brl_lock_windows),  SMB_VFS_OP_BRL_LOCK_WINDOWS,
1697          SMB_VFS_LAYER_OPAQUE},
1698         {SMB_VFS_OP(vfswrap_brl_unlock_windows),SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
1699          SMB_VFS_LAYER_OPAQUE},
1700         {SMB_VFS_OP(vfswrap_brl_cancel_windows),SMB_VFS_OP_BRL_CANCEL_WINDOWS,
1701          SMB_VFS_LAYER_OPAQUE},
1702         {SMB_VFS_OP(vfswrap_strict_lock),       SMB_VFS_OP_STRICT_LOCK,
1703          SMB_VFS_LAYER_OPAQUE},
1704         {SMB_VFS_OP(vfswrap_strict_unlock),     SMB_VFS_OP_STRICT_UNLOCK,
1705          SMB_VFS_LAYER_OPAQUE},
1706
1707         /* NT ACL operations. */
1708
1709         {SMB_VFS_OP(vfswrap_fget_nt_acl),       SMB_VFS_OP_FGET_NT_ACL,
1710          SMB_VFS_LAYER_OPAQUE},
1711         {SMB_VFS_OP(vfswrap_get_nt_acl),        SMB_VFS_OP_GET_NT_ACL,
1712          SMB_VFS_LAYER_OPAQUE},
1713         {SMB_VFS_OP(vfswrap_fset_nt_acl),       SMB_VFS_OP_FSET_NT_ACL,
1714          SMB_VFS_LAYER_OPAQUE},
1715
1716         /* POSIX ACL operations. */
1717
1718         {SMB_VFS_OP(vfswrap_chmod_acl), SMB_VFS_OP_CHMOD_ACL,
1719          SMB_VFS_LAYER_OPAQUE},
1720         {SMB_VFS_OP(vfswrap_fchmod_acl),        SMB_VFS_OP_FCHMOD_ACL,
1721          SMB_VFS_LAYER_OPAQUE},
1722         {SMB_VFS_OP(vfswrap_sys_acl_get_entry), SMB_VFS_OP_SYS_ACL_GET_ENTRY,
1723          SMB_VFS_LAYER_OPAQUE},
1724         {SMB_VFS_OP(vfswrap_sys_acl_get_tag_type),      SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,
1725          SMB_VFS_LAYER_OPAQUE},
1726         {SMB_VFS_OP(vfswrap_sys_acl_get_permset),       SMB_VFS_OP_SYS_ACL_GET_PERMSET,
1727          SMB_VFS_LAYER_OPAQUE},
1728         {SMB_VFS_OP(vfswrap_sys_acl_get_qualifier),     SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,
1729          SMB_VFS_LAYER_OPAQUE},
1730         {SMB_VFS_OP(vfswrap_sys_acl_get_file),  SMB_VFS_OP_SYS_ACL_GET_FILE,
1731          SMB_VFS_LAYER_OPAQUE},
1732         {SMB_VFS_OP(vfswrap_sys_acl_get_fd),    SMB_VFS_OP_SYS_ACL_GET_FD,
1733          SMB_VFS_LAYER_OPAQUE},
1734         {SMB_VFS_OP(vfswrap_sys_acl_clear_perms),       SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,
1735          SMB_VFS_LAYER_OPAQUE},
1736         {SMB_VFS_OP(vfswrap_sys_acl_add_perm),  SMB_VFS_OP_SYS_ACL_ADD_PERM,
1737          SMB_VFS_LAYER_OPAQUE},
1738         {SMB_VFS_OP(vfswrap_sys_acl_to_text),   SMB_VFS_OP_SYS_ACL_TO_TEXT,
1739          SMB_VFS_LAYER_OPAQUE},
1740         {SMB_VFS_OP(vfswrap_sys_acl_init),      SMB_VFS_OP_SYS_ACL_INIT,
1741          SMB_VFS_LAYER_OPAQUE},
1742         {SMB_VFS_OP(vfswrap_sys_acl_create_entry),      SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,
1743          SMB_VFS_LAYER_OPAQUE},
1744         {SMB_VFS_OP(vfswrap_sys_acl_set_tag_type),      SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,
1745          SMB_VFS_LAYER_OPAQUE},
1746         {SMB_VFS_OP(vfswrap_sys_acl_set_qualifier),     SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,
1747          SMB_VFS_LAYER_OPAQUE},
1748         {SMB_VFS_OP(vfswrap_sys_acl_set_permset),       SMB_VFS_OP_SYS_ACL_SET_PERMSET,
1749          SMB_VFS_LAYER_OPAQUE},
1750         {SMB_VFS_OP(vfswrap_sys_acl_valid),     SMB_VFS_OP_SYS_ACL_VALID,
1751          SMB_VFS_LAYER_OPAQUE},
1752         {SMB_VFS_OP(vfswrap_sys_acl_set_file),  SMB_VFS_OP_SYS_ACL_SET_FILE,
1753          SMB_VFS_LAYER_OPAQUE},
1754         {SMB_VFS_OP(vfswrap_sys_acl_set_fd),    SMB_VFS_OP_SYS_ACL_SET_FD,
1755          SMB_VFS_LAYER_OPAQUE},
1756         {SMB_VFS_OP(vfswrap_sys_acl_delete_def_file),   SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
1757          SMB_VFS_LAYER_OPAQUE},
1758         {SMB_VFS_OP(vfswrap_sys_acl_get_perm),  SMB_VFS_OP_SYS_ACL_GET_PERM,
1759          SMB_VFS_LAYER_OPAQUE},
1760         {SMB_VFS_OP(vfswrap_sys_acl_free_text), SMB_VFS_OP_SYS_ACL_FREE_TEXT,
1761          SMB_VFS_LAYER_OPAQUE},
1762         {SMB_VFS_OP(vfswrap_sys_acl_free_acl),  SMB_VFS_OP_SYS_ACL_FREE_ACL,
1763          SMB_VFS_LAYER_OPAQUE},
1764         {SMB_VFS_OP(vfswrap_sys_acl_free_qualifier),    SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,
1765          SMB_VFS_LAYER_OPAQUE},
1766
1767         /* EA operations. */
1768
1769         {SMB_VFS_OP(vfswrap_getxattr),  SMB_VFS_OP_GETXATTR,
1770          SMB_VFS_LAYER_OPAQUE},
1771         {SMB_VFS_OP(vfswrap_lgetxattr), SMB_VFS_OP_LGETXATTR,
1772          SMB_VFS_LAYER_OPAQUE},
1773         {SMB_VFS_OP(vfswrap_fgetxattr), SMB_VFS_OP_FGETXATTR,
1774          SMB_VFS_LAYER_OPAQUE},
1775         {SMB_VFS_OP(vfswrap_listxattr), SMB_VFS_OP_LISTXATTR,
1776          SMB_VFS_LAYER_OPAQUE},
1777         {SMB_VFS_OP(vfswrap_llistxattr),        SMB_VFS_OP_LLISTXATTR,
1778          SMB_VFS_LAYER_OPAQUE},
1779         {SMB_VFS_OP(vfswrap_flistxattr),        SMB_VFS_OP_FLISTXATTR,
1780          SMB_VFS_LAYER_OPAQUE},
1781         {SMB_VFS_OP(vfswrap_removexattr),       SMB_VFS_OP_REMOVEXATTR,
1782          SMB_VFS_LAYER_OPAQUE},
1783         {SMB_VFS_OP(vfswrap_lremovexattr),      SMB_VFS_OP_LREMOVEXATTR,
1784          SMB_VFS_LAYER_OPAQUE},
1785         {SMB_VFS_OP(vfswrap_fremovexattr),      SMB_VFS_OP_FREMOVEXATTR,
1786          SMB_VFS_LAYER_OPAQUE},
1787         {SMB_VFS_OP(vfswrap_setxattr),  SMB_VFS_OP_SETXATTR,
1788          SMB_VFS_LAYER_OPAQUE},
1789         {SMB_VFS_OP(vfswrap_lsetxattr), SMB_VFS_OP_LSETXATTR,
1790          SMB_VFS_LAYER_OPAQUE},
1791         {SMB_VFS_OP(vfswrap_fsetxattr), SMB_VFS_OP_FSETXATTR,
1792          SMB_VFS_LAYER_OPAQUE},
1793
1794         {SMB_VFS_OP(vfswrap_aio_read),  SMB_VFS_OP_AIO_READ,
1795          SMB_VFS_LAYER_OPAQUE},
1796         {SMB_VFS_OP(vfswrap_aio_write), SMB_VFS_OP_AIO_WRITE,
1797          SMB_VFS_LAYER_OPAQUE},
1798         {SMB_VFS_OP(vfswrap_aio_return),        SMB_VFS_OP_AIO_RETURN,
1799          SMB_VFS_LAYER_OPAQUE},
1800         {SMB_VFS_OP(vfswrap_aio_cancel), SMB_VFS_OP_AIO_CANCEL,
1801          SMB_VFS_LAYER_OPAQUE},
1802         {SMB_VFS_OP(vfswrap_aio_error), SMB_VFS_OP_AIO_ERROR,
1803          SMB_VFS_LAYER_OPAQUE},
1804         {SMB_VFS_OP(vfswrap_aio_fsync), SMB_VFS_OP_AIO_FSYNC,
1805          SMB_VFS_LAYER_OPAQUE},
1806         {SMB_VFS_OP(vfswrap_aio_suspend),SMB_VFS_OP_AIO_SUSPEND,
1807          SMB_VFS_LAYER_OPAQUE},
1808
1809         {SMB_VFS_OP(vfswrap_aio_force), SMB_VFS_OP_AIO_FORCE,
1810          SMB_VFS_LAYER_OPAQUE},
1811
1812         {SMB_VFS_OP(vfswrap_is_offline),SMB_VFS_OP_IS_OFFLINE,
1813          SMB_VFS_LAYER_OPAQUE},
1814         {SMB_VFS_OP(vfswrap_set_offline),SMB_VFS_OP_SET_OFFLINE,
1815          SMB_VFS_LAYER_OPAQUE},
1816
1817         /* Finish VFS operations definition */
1818
1819         {SMB_VFS_OP(NULL),              SMB_VFS_OP_NOOP,
1820          SMB_VFS_LAYER_NOOP}
1821 };
1822
1823 NTSTATUS vfs_default_init(void);
1824 NTSTATUS vfs_default_init(void)
1825 {
1826         unsigned int needed = SMB_VFS_OP_LAST + 1; /* convert from index to count */
1827
1828         if (ARRAY_SIZE(vfs_default_ops) != needed) {
1829                 DEBUG(0, ("%s: %u ops registered, but %u ops are required\n",
1830                         DEFAULT_VFS_MODULE_NAME, (unsigned int)ARRAY_SIZE(vfs_default_ops), needed));
1831                 smb_panic("operation(s) missing from default VFS module");
1832         }
1833
1834         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1835                                 DEFAULT_VFS_MODULE_NAME, vfs_default_ops);
1836 }