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