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