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