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