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