s3: Fix bug 7940 -- fall back for utimes calls
[samba.git] / source3 / modules / vfs_default.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap disk only vfs functions to sidestep dodgy compilers.
4    Copyright (C) Tim Potter 1998
5    Copyright (C) Jeremy Allison 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22
23 #undef DBGC_CLASS
24 #define DBGC_CLASS DBGC_VFS
25
26 /* Check for NULL pointer parameters in vfswrap_* functions */
27
28 /* We don't want to have NULL function pointers lying around.  Someone
29    is sure to try and execute them.  These stubs are used to prevent
30    this possibility. */
31
32 static int vfswrap_connect(vfs_handle_struct *handle,  const char *service, const char *user)
33 {
34     return 0;    /* Return >= 0 for success */
35 }
36
37 static void vfswrap_disconnect(vfs_handle_struct *handle)
38 {
39 }
40
41 /* Disk operations */
42
43 static uint64_t vfswrap_disk_free(vfs_handle_struct *handle,  const char *path, bool small_query, uint64_t *bsize,
44                                uint64_t *dfree, uint64_t *dsize)
45 {
46         uint64_t result;
47
48         result = sys_disk_free(handle->conn, path, small_query, bsize, dfree, dsize);
49         return result;
50 }
51
52 static int vfswrap_get_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
53 {
54 #ifdef HAVE_SYS_QUOTAS
55         int result;
56
57         START_PROFILE(syscall_get_quota);
58         result = sys_get_quota(handle->conn->connectpath, qtype, id, qt);
59         END_PROFILE(syscall_get_quota);
60         return result;
61 #else
62         errno = ENOSYS;
63         return -1;
64 #endif
65 }
66
67 static int vfswrap_set_quota(struct vfs_handle_struct *handle,  enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
68 {
69 #ifdef HAVE_SYS_QUOTAS
70         int result;
71
72         START_PROFILE(syscall_set_quota);
73         result = sys_set_quota(handle->conn->connectpath, qtype, id, qt);
74         END_PROFILE(syscall_set_quota);
75         return result;
76 #else
77         errno = ENOSYS;
78         return -1;
79 #endif
80 }
81
82 static int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, bool labels)
83 {
84         errno = ENOSYS;
85         return -1;  /* Not implemented. */
86 }
87
88 static int vfswrap_statvfs(struct vfs_handle_struct *handle,  const char *path, vfs_statvfs_struct *statbuf)
89 {
90         return sys_statvfs(path, statbuf);
91 }
92
93 static uint32_t vfswrap_fs_capabilities(struct vfs_handle_struct *handle,
94                 enum timestamp_set_resolution *p_ts_res)
95 {
96         connection_struct *conn = handle->conn;
97         uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES;
98         struct smb_filename *smb_fname_cpath = NULL;
99         NTSTATUS status;
100         int ret = -1;
101
102 #if defined(DARWINOS)
103         struct vfs_statvfs_struct statbuf;
104         ZERO_STRUCT(statbuf);
105         sys_statvfs(conn->connectpath, &statbuf);
106         caps = statbuf.FsCapabilities;
107 #endif
108
109         *p_ts_res = TIMESTAMP_SET_SECONDS;
110
111         /* Work out what timestamp resolution we can
112          * use when setting a timestamp. */
113
114         status = create_synthetic_smb_fname(talloc_tos(),
115                                 conn->connectpath,
116                                 NULL,
117                                 NULL,
118                                 &smb_fname_cpath);
119         if (!NT_STATUS_IS_OK(status)) {
120                 return caps;
121         }
122
123         ret = SMB_VFS_STAT(conn, smb_fname_cpath);
124         if (ret == -1) {
125                 TALLOC_FREE(smb_fname_cpath);
126                 return caps;
127         }
128
129         if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
130                         smb_fname_cpath->st.st_ex_atime.tv_nsec ||
131                         smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
132                 /* If any of the normal UNIX directory timestamps
133                  * have a non-zero tv_nsec component assume
134                  * we might be able to set sub-second timestamps.
135                  * See what filetime set primitives we have.
136                  */
137 #if defined(HAVE_UTIMENSAT)
138                 *p_ts_res = TIMESTAMP_SET_NT_OR_BETTER;
139 #elif defined(HAVE_UTIMES)
140                 /* utimes allows msec timestamps to be set. */
141                 *p_ts_res = TIMESTAMP_SET_MSEC;
142 #elif defined(HAVE_UTIME)
143                 /* utime only allows sec timestamps to be set. */
144                 *p_ts_res = TIMESTAMP_SET_SECONDS;
145 #endif
146
147                 DEBUG(10,("vfswrap_fs_capabilities: timestamp "
148                         "resolution of %s "
149                         "available on share %s, directory %s\n",
150                         *p_ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
151                         lp_servicename(conn->params->service),
152                         conn->connectpath ));
153         }
154         TALLOC_FREE(smb_fname_cpath);
155         return caps;
156 }
157
158 /* Directory operations */
159
160 static SMB_STRUCT_DIR *vfswrap_opendir(vfs_handle_struct *handle,  const char *fname, const char *mask, uint32 attr)
161 {
162         SMB_STRUCT_DIR *result;
163
164         START_PROFILE(syscall_opendir);
165         result = sys_opendir(fname);
166         END_PROFILE(syscall_opendir);
167         return result;
168 }
169
170 static SMB_STRUCT_DIRENT *vfswrap_readdir(vfs_handle_struct *handle,
171                                           SMB_STRUCT_DIR *dirp,
172                                           SMB_STRUCT_STAT *sbuf)
173 {
174         SMB_STRUCT_DIRENT *result;
175
176         START_PROFILE(syscall_readdir);
177         result = sys_readdir(dirp);
178         /* Default Posix readdir() does not give us stat info.
179          * Set to invalid to indicate we didn't return this info. */
180         if (sbuf)
181                 SET_STAT_INVALID(*sbuf);
182         END_PROFILE(syscall_readdir);
183         return result;
184 }
185
186 static void vfswrap_seekdir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp, long offset)
187 {
188         START_PROFILE(syscall_seekdir);
189         sys_seekdir(dirp, offset);
190         END_PROFILE(syscall_seekdir);
191 }
192
193 static long vfswrap_telldir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
194 {
195         long result;
196         START_PROFILE(syscall_telldir);
197         result = sys_telldir(dirp);
198         END_PROFILE(syscall_telldir);
199         return result;
200 }
201
202 static void vfswrap_rewinddir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
203 {
204         START_PROFILE(syscall_rewinddir);
205         sys_rewinddir(dirp);
206         END_PROFILE(syscall_rewinddir);
207 }
208
209 static int vfswrap_mkdir(vfs_handle_struct *handle,  const char *path, mode_t mode)
210 {
211         int result;
212         bool has_dacl = False;
213         char *parent = NULL;
214
215         START_PROFILE(syscall_mkdir);
216
217         if (lp_inherit_acls(SNUM(handle->conn))
218             && parent_dirname(talloc_tos(), path, &parent, NULL)
219             && (has_dacl = directory_has_default_acl(handle->conn, parent)))
220                 mode = (0777 & lp_dir_mask(SNUM(handle->conn)));
221
222         TALLOC_FREE(parent);
223
224         result = mkdir(path, mode);
225
226         if (result == 0 && !has_dacl) {
227                 /*
228                  * We need to do this as the default behavior of POSIX ACLs
229                  * is to set the mask to be the requested group permission
230                  * bits, not the group permission bits to be the requested
231                  * group permission bits. This is not what we want, as it will
232                  * mess up any inherited ACL bits that were set. JRA.
233                  */
234                 int saved_errno = errno; /* We may get ENOSYS */
235                 if ((SMB_VFS_CHMOD_ACL(handle->conn, path, mode) == -1) && (errno == ENOSYS))
236                         errno = saved_errno;
237         }
238
239         END_PROFILE(syscall_mkdir);
240         return result;
241 }
242
243 static int vfswrap_rmdir(vfs_handle_struct *handle,  const char *path)
244 {
245         int result;
246
247         START_PROFILE(syscall_rmdir);
248         result = rmdir(path);
249         END_PROFILE(syscall_rmdir);
250         return result;
251 }
252
253 static int vfswrap_closedir(vfs_handle_struct *handle,  SMB_STRUCT_DIR *dirp)
254 {
255         int result;
256
257         START_PROFILE(syscall_closedir);
258         result = sys_closedir(dirp);
259         END_PROFILE(syscall_closedir);
260         return result;
261 }
262
263 static void vfswrap_init_search_op(vfs_handle_struct *handle,
264                                    SMB_STRUCT_DIR *dirp)
265 {
266         /* Default behavior is a NOOP */
267 }
268
269 /* File operations */
270
271 static int vfswrap_open(vfs_handle_struct *handle,
272                         struct smb_filename *smb_fname,
273                         files_struct *fsp, int flags, mode_t mode)
274 {
275         int result = -1;
276
277         START_PROFILE(syscall_open);
278
279         if (smb_fname->stream_name) {
280                 errno = ENOENT;
281                 goto out;
282         }
283
284         result = sys_open(smb_fname->base_name, flags, mode);
285  out:
286         END_PROFILE(syscall_open);
287         return result;
288 }
289
290 static NTSTATUS vfswrap_create_file(vfs_handle_struct *handle,
291                                     struct smb_request *req,
292                                     uint16_t root_dir_fid,
293                                     struct smb_filename *smb_fname,
294                                     uint32_t access_mask,
295                                     uint32_t share_access,
296                                     uint32_t create_disposition,
297                                     uint32_t create_options,
298                                     uint32_t file_attributes,
299                                     uint32_t oplock_request,
300                                     uint64_t allocation_size,
301                                     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         if (!((result == -1) && (errno == ENOSYS))) {
902                 goto out;
903         }
904 #endif
905 #if defined(HAVE_UTIMES)
906         if (ft != NULL) {
907                 struct timeval tv[2];
908                 tv[0] = convert_timespec_to_timeval(ft->atime);
909                 tv[1] = convert_timespec_to_timeval(ft->mtime);
910                 result = utimes(smb_fname->base_name, tv);
911         } else {
912                 result = utimes(smb_fname->base_name, NULL);
913         }
914         if (!((result == -1) && (errno == ENOSYS))) {
915                 goto out;
916         }
917 #endif
918 #if defined(HAVE_UTIME)
919         if (ft != NULL) {
920                 struct utimbuf times;
921                 times.actime = convert_timespec_to_time_t(ft->atime);
922                 times.modtime = convert_timespec_to_time_t(ft->mtime);
923                 result = utime(smb_fname->base_name, &times);
924         } else {
925                 result = utime(smb_fname->base_name, NULL);
926         }
927         if (!((result == -1) && (errno == ENOSYS))) {
928                 goto out;
929         }
930 #endif
931         errno = ENOSYS;
932         result = -1;
933
934  out:
935         END_PROFILE(syscall_ntimes);
936         return result;
937 }
938
939 /*********************************************************************
940  A version of ftruncate that will write the space on disk if strict
941  allocate is set.
942 **********************************************************************/
943
944 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
945 {
946         SMB_STRUCT_STAT st;
947         SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
948         unsigned char zero_space[4096];
949         SMB_OFF_T space_to_write;
950         uint64_t space_avail;
951         uint64_t bsize,dfree,dsize;
952         int ret;
953
954         if (currpos == -1)
955                 return -1;
956
957         if (SMB_VFS_FSTAT(fsp, &st) == -1)
958                 return -1;
959
960 #ifdef S_ISFIFO
961         if (S_ISFIFO(st.st_ex_mode))
962                 return 0;
963 #endif
964
965         if (st.st_ex_size == len)
966                 return 0;
967
968         /* Shrink - just ftruncate. */
969         if (st.st_ex_size > len)
970                 return sys_ftruncate(fsp->fh->fd, len);
971
972         space_to_write = len - st.st_ex_size;
973
974         /* for allocation try posix_fallocate first. This can fail on some
975            platforms e.g. when the filesystem doesn't support it and no
976            emulation is being done by the libc (like on AIX with JFS1). In that
977            case we do our own emulation. posix_fallocate implementations can
978            return ENOTSUP or EINVAL in cases like that. */
979         ret = sys_posix_fallocate(fsp->fh->fd, st.st_ex_size, space_to_write);
980         if (ret == ENOSPC) {
981                 errno = ENOSPC;
982                 return -1;
983         }
984         if (ret == 0) {
985                 return 0;
986         }
987         DEBUG(10,("strict_allocate_ftruncate: sys_posix_fallocate failed with "
988                 "error %d. Falling back to slow manual allocation\n", ret));
989
990         /* available disk space is enough or not? */
991         space_avail = get_dfree_info(fsp->conn,
992                                      fsp->fsp_name->base_name, false,
993                                      &bsize,&dfree,&dsize);
994         /* space_avail is 1k blocks */
995         if (space_avail == (uint64_t)-1 ||
996                         ((uint64_t)space_to_write/1024 > space_avail) ) {
997                 errno = ENOSPC;
998                 return -1;
999         }
1000
1001         /* Write out the real space on disk. */
1002         if (SMB_VFS_LSEEK(fsp, st.st_ex_size, SEEK_SET) != st.st_ex_size)
1003                 return -1;
1004
1005         memset(zero_space, '\0', sizeof(zero_space));
1006         while ( space_to_write > 0) {
1007                 SMB_OFF_T retlen;
1008                 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
1009
1010                 retlen = SMB_VFS_WRITE(fsp,(char *)zero_space,current_len_to_write);
1011                 if (retlen <= 0)
1012                         return -1;
1013
1014                 space_to_write -= retlen;
1015         }
1016
1017         /* Seek to where we were */
1018         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
1019                 return -1;
1020
1021         return 0;
1022 }
1023
1024 static int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T len)
1025 {
1026         int result = -1;
1027         SMB_STRUCT_STAT st;
1028         char c = 0;
1029         SMB_OFF_T currpos;
1030
1031         START_PROFILE(syscall_ftruncate);
1032
1033         if (lp_strict_allocate(SNUM(fsp->conn))) {
1034                 result = strict_allocate_ftruncate(handle, fsp, len);
1035                 END_PROFILE(syscall_ftruncate);
1036                 return result;
1037         }
1038
1039         /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
1040            sys_ftruncate if the system supports it. Then I discovered that
1041            you can have some filesystems that support ftruncate
1042            expansion and some that don't! On Linux fat can't do
1043            ftruncate extend but ext2 can. */
1044
1045         result = sys_ftruncate(fsp->fh->fd, len);
1046         if (result == 0)
1047                 goto done;
1048
1049         /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1050            extend a file with ftruncate. Provide alternate implementation
1051            for this */
1052         currpos = SMB_VFS_LSEEK(fsp, 0, SEEK_CUR);
1053         if (currpos == -1) {
1054                 goto done;
1055         }
1056
1057         /* Do an fstat to see if the file is longer than the requested
1058            size in which case the ftruncate above should have
1059            succeeded or shorter, in which case seek to len - 1 and
1060            write 1 byte of zero */
1061         if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1062                 goto done;
1063         }
1064
1065 #ifdef S_ISFIFO
1066         if (S_ISFIFO(st.st_ex_mode)) {
1067                 result = 0;
1068                 goto done;
1069         }
1070 #endif
1071
1072         if (st.st_ex_size == len) {
1073                 result = 0;
1074                 goto done;
1075         }
1076
1077         if (st.st_ex_size > len) {
1078                 /* the sys_ftruncate should have worked */
1079                 goto done;
1080         }
1081
1082         if (SMB_VFS_LSEEK(fsp, len-1, SEEK_SET) != len -1)
1083                 goto done;
1084
1085         if (SMB_VFS_WRITE(fsp, &c, 1)!=1)
1086                 goto done;
1087
1088         /* Seek to where we were */
1089         if (SMB_VFS_LSEEK(fsp, currpos, SEEK_SET) != currpos)
1090                 goto done;
1091         result = 0;
1092
1093   done:
1094
1095         END_PROFILE(syscall_ftruncate);
1096         return result;
1097 }
1098
1099 static bool vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
1100 {
1101         bool result;
1102
1103         START_PROFILE(syscall_fcntl_lock);
1104         result =  fcntl_lock(fsp->fh->fd, op, offset, count, type);
1105         END_PROFILE(syscall_fcntl_lock);
1106         return result;
1107 }
1108
1109 static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
1110                                 uint32 share_mode, uint32 access_mask)
1111 {
1112         START_PROFILE(syscall_kernel_flock);
1113         kernel_flock(fsp->fh->fd, share_mode, access_mask);
1114         END_PROFILE(syscall_kernel_flock);
1115         return 0;
1116 }
1117
1118 static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
1119 {
1120         bool result;
1121
1122         START_PROFILE(syscall_fcntl_getlock);
1123         result =  fcntl_getlock(fsp->fh->fd, poffset, pcount, ptype, ppid);
1124         END_PROFILE(syscall_fcntl_getlock);
1125         return result;
1126 }
1127
1128 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
1129                                 int leasetype)
1130 {
1131         int result = -1;
1132
1133         START_PROFILE(syscall_linux_setlease);
1134
1135 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1136         /* first set the signal handler */
1137         if(linux_set_lease_sighandler(fsp->fh->fd) == -1) {
1138                 return -1;
1139         }
1140
1141         result = linux_setlease(fsp->fh->fd, leasetype);
1142 #else
1143         errno = ENOSYS;
1144 #endif
1145         END_PROFILE(syscall_linux_setlease);
1146         return result;
1147 }
1148
1149 static int vfswrap_symlink(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1150 {
1151         int result;
1152
1153         START_PROFILE(syscall_symlink);
1154         result = symlink(oldpath, newpath);
1155         END_PROFILE(syscall_symlink);
1156         return result;
1157 }
1158
1159 static int vfswrap_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
1160 {
1161         int result;
1162
1163         START_PROFILE(syscall_readlink);
1164         result = readlink(path, buf, bufsiz);
1165         END_PROFILE(syscall_readlink);
1166         return result;
1167 }
1168
1169 static int vfswrap_link(vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
1170 {
1171         int result;
1172
1173         START_PROFILE(syscall_link);
1174         result = link(oldpath, newpath);
1175         END_PROFILE(syscall_link);
1176         return result;
1177 }
1178
1179 static int vfswrap_mknod(vfs_handle_struct *handle,  const char *pathname, mode_t mode, SMB_DEV_T dev)
1180 {
1181         int result;
1182
1183         START_PROFILE(syscall_mknod);
1184         result = sys_mknod(pathname, mode, dev);
1185         END_PROFILE(syscall_mknod);
1186         return result;
1187 }
1188
1189 static char *vfswrap_realpath(vfs_handle_struct *handle,  const char *path, char *resolved_path)
1190 {
1191         char *result;
1192
1193         START_PROFILE(syscall_realpath);
1194         result = realpath(path, resolved_path);
1195         END_PROFILE(syscall_realpath);
1196         return result;
1197 }
1198
1199 static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
1200                                      struct sys_notify_context *ctx,
1201                                      struct notify_entry *e,
1202                                      void (*callback)(struct sys_notify_context *ctx, 
1203                                                       void *private_data,
1204                                                       struct notify_event *ev),
1205                                      void *private_data, void *handle)
1206 {
1207         /*
1208          * So far inotify is the only supported default notify mechanism. If
1209          * another platform like the the BSD's or a proprietary Unix comes
1210          * along and wants another default, we can play the same trick we
1211          * played with Posix ACLs.
1212          *
1213          * Until that is the case, hard-code inotify here.
1214          */
1215 #ifdef HAVE_INOTIFY
1216         if (lp_kernel_change_notify(ctx->conn->params)) {
1217                 return inotify_watch(ctx, e, callback, private_data, handle);
1218         }
1219 #endif
1220         /*
1221          * Do nothing, leave everything to notify_internal.c
1222          */
1223         return NT_STATUS_OK;
1224 }
1225
1226 static int vfswrap_chflags(vfs_handle_struct *handle, const char *path,
1227                            unsigned int flags)
1228 {
1229 #ifdef HAVE_CHFLAGS
1230         return chflags(path, flags);
1231 #else
1232         errno = ENOSYS;
1233         return -1;
1234 #endif
1235 }
1236
1237 static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle,
1238                                              const SMB_STRUCT_STAT *sbuf)
1239 {
1240         struct file_id key;
1241
1242         /* the ZERO_STRUCT ensures padding doesn't break using the key as a
1243          * blob */
1244         ZERO_STRUCT(key);
1245
1246         key.devid = sbuf->st_ex_dev;
1247         key.inode = sbuf->st_ex_ino;
1248         /* key.extid is unused by default. */
1249
1250         return key;
1251 }
1252
1253 static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle,
1254                                    struct files_struct *fsp,
1255                                    const char *fname,
1256                                    TALLOC_CTX *mem_ctx,
1257                                    unsigned int *pnum_streams,
1258                                    struct stream_struct **pstreams)
1259 {
1260         SMB_STRUCT_STAT sbuf;
1261         unsigned int num_streams = 0;
1262         struct stream_struct *streams = NULL;
1263         int ret;
1264
1265         if ((fsp != NULL) && (fsp->is_directory)) {
1266                 /*
1267                  * No default streams on directories
1268                  */
1269                 goto done;
1270         }
1271
1272         if ((fsp != NULL) && (fsp->fh->fd != -1)) {
1273                 ret = SMB_VFS_FSTAT(fsp, &sbuf);
1274         }
1275         else {
1276                 struct smb_filename smb_fname;
1277
1278                 ZERO_STRUCT(smb_fname);
1279                 smb_fname.base_name = discard_const_p(char, fname);
1280
1281                 if (lp_posix_pathnames()) {
1282                         ret = SMB_VFS_LSTAT(handle->conn, &smb_fname);
1283                 } else {
1284                         ret = SMB_VFS_STAT(handle->conn, &smb_fname);
1285                 }
1286                 sbuf = smb_fname.st;
1287         }
1288
1289         if (ret == -1) {
1290                 return map_nt_error_from_unix(errno);
1291         }
1292
1293         if (S_ISDIR(sbuf.st_ex_mode)) {
1294                 goto done;
1295         }
1296
1297         streams = talloc(mem_ctx, struct stream_struct);
1298
1299         if (streams == NULL) {
1300                 return NT_STATUS_NO_MEMORY;
1301         }
1302
1303         streams->size = sbuf.st_ex_size;
1304         streams->alloc_size = SMB_VFS_GET_ALLOC_SIZE(handle->conn, fsp, &sbuf);
1305
1306         streams->name = talloc_strdup(streams, "::$DATA");
1307         if (streams->name == NULL) {
1308                 TALLOC_FREE(streams);
1309                 return NT_STATUS_NO_MEMORY;
1310         }
1311
1312         num_streams = 1;
1313  done:
1314         *pnum_streams = num_streams;
1315         *pstreams = streams;
1316         return NT_STATUS_OK;
1317 }
1318
1319 static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
1320                                      const char *path,
1321                                      const char *name,
1322                                      TALLOC_CTX *mem_ctx,
1323                                      char **found_name)
1324 {
1325         /*
1326          * Don't fall back to get_real_filename so callers can differentiate
1327          * between a full directory scan and an actual case-insensitive stat.
1328          */
1329         errno = EOPNOTSUPP;
1330         return -1;
1331 }
1332
1333 static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
1334                                        const char *fname)
1335 {
1336         return handle->conn->connectpath;
1337 }
1338
1339 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
1340                                          struct byte_range_lock *br_lck,
1341                                          struct lock_struct *plock,
1342                                          bool blocking_lock,
1343                                          struct blocking_lock_record *blr)
1344 {
1345         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1346
1347         /* Note: blr is not used in the default implementation. */
1348         return brl_lock_windows_default(br_lck, plock, blocking_lock);
1349 }
1350
1351 static bool vfswrap_brl_unlock_windows(struct vfs_handle_struct *handle,
1352                                        struct messaging_context *msg_ctx,
1353                                        struct byte_range_lock *br_lck,
1354                                        const struct lock_struct *plock)
1355 {
1356         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1357
1358         return brl_unlock_windows_default(msg_ctx, br_lck, plock);
1359 }
1360
1361 static bool vfswrap_brl_cancel_windows(struct vfs_handle_struct *handle,
1362                                        struct byte_range_lock *br_lck,
1363                                        struct lock_struct *plock,
1364                                        struct blocking_lock_record *blr)
1365 {
1366         SMB_ASSERT(plock->lock_flav == WINDOWS_LOCK);
1367
1368         /* Note: blr is not used in the default implementation. */
1369         return brl_lock_cancel_default(br_lck, plock);
1370 }
1371
1372 static bool vfswrap_strict_lock(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         return strict_lock_default(fsp, plock);
1380 }
1381
1382 static void vfswrap_strict_unlock(struct vfs_handle_struct *handle,
1383                                 files_struct *fsp,
1384                                 struct lock_struct *plock)
1385 {
1386         SMB_ASSERT(plock->lock_type == READ_LOCK ||
1387             plock->lock_type == WRITE_LOCK);
1388
1389         strict_unlock_default(fsp, plock);
1390 }
1391
1392 /* NT ACL operations. */
1393
1394 static NTSTATUS vfswrap_fget_nt_acl(vfs_handle_struct *handle,
1395                                     files_struct *fsp,
1396                                     uint32 security_info, SEC_DESC **ppdesc)
1397 {
1398         NTSTATUS result;
1399
1400         START_PROFILE(fget_nt_acl);
1401         result = posix_fget_nt_acl(fsp, security_info, ppdesc);
1402         END_PROFILE(fget_nt_acl);
1403         return result;
1404 }
1405
1406 static NTSTATUS vfswrap_get_nt_acl(vfs_handle_struct *handle,
1407                                    const char *name,
1408                                    uint32 security_info, SEC_DESC **ppdesc)
1409 {
1410         NTSTATUS result;
1411
1412         START_PROFILE(get_nt_acl);
1413         result = posix_get_nt_acl(handle->conn, name, security_info, ppdesc);
1414         END_PROFILE(get_nt_acl);
1415         return result;
1416 }
1417
1418 static NTSTATUS vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
1419 {
1420         NTSTATUS result;
1421
1422         START_PROFILE(fset_nt_acl);
1423         result = set_nt_acl(fsp, security_info_sent, psd);
1424         END_PROFILE(fset_nt_acl);
1425         return result;
1426 }
1427
1428 static int vfswrap_chmod_acl(vfs_handle_struct *handle,  const char *name, mode_t mode)
1429 {
1430 #ifdef HAVE_NO_ACL
1431         errno = ENOSYS;
1432         return -1;
1433 #else
1434         int result;
1435
1436         START_PROFILE(chmod_acl);
1437         result = chmod_acl(handle->conn, name, mode);
1438         END_PROFILE(chmod_acl);
1439         return result;
1440 #endif
1441 }
1442
1443 static int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1444 {
1445 #ifdef HAVE_NO_ACL
1446         errno = ENOSYS;
1447         return -1;
1448 #else
1449         int result;
1450
1451         START_PROFILE(fchmod_acl);
1452         result = fchmod_acl(fsp, mode);
1453         END_PROFILE(fchmod_acl);
1454         return result;
1455 #endif
1456 }
1457
1458 static int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle,  SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
1459 {
1460         return sys_acl_get_entry(theacl, entry_id, entry_p);
1461 }
1462
1463 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)
1464 {
1465         return sys_acl_get_tag_type(entry_d, tag_type_p);
1466 }
1467
1468 static int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
1469 {
1470         return sys_acl_get_permset(entry_d, permset_p);
1471 }
1472
1473 static void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry_d)
1474 {
1475         return sys_acl_get_qualifier(entry_d);
1476 }
1477
1478 static SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle,  const char *path_p, SMB_ACL_TYPE_T type)
1479 {
1480         return sys_acl_get_file(handle, path_p, type);
1481 }
1482
1483 static SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp)
1484 {
1485         return sys_acl_get_fd(handle, fsp);
1486 }
1487
1488 static int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset)
1489 {
1490         return sys_acl_clear_perms(permset);
1491 }
1492
1493 static int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1494 {
1495         return sys_acl_add_perm(permset, perm);
1496 }
1497
1498 static char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle,  SMB_ACL_T theacl, ssize_t *plen)
1499 {
1500         return sys_acl_to_text(theacl, plen);
1501 }
1502
1503 static SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle,  int count)
1504 {
1505         return sys_acl_init(count);
1506 }
1507
1508 static int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle,  SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
1509 {
1510         return sys_acl_create_entry(pacl, pentry);
1511 }
1512
1513 static int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
1514 {
1515         return sys_acl_set_tag_type(entry, tagtype);
1516 }
1517
1518 static int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, void *qual)
1519 {
1520         return sys_acl_set_qualifier(entry, qual);
1521 }
1522
1523 static int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle,  SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
1524 {
1525         return sys_acl_set_permset(entry, permset);
1526 }
1527
1528 static int vfswrap_sys_acl_valid(vfs_handle_struct *handle,  SMB_ACL_T theacl )
1529 {
1530         return sys_acl_valid(theacl );
1531 }
1532
1533 static int vfswrap_sys_acl_set_file(vfs_handle_struct *handle,  const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
1534 {
1535         return sys_acl_set_file(handle, name, acltype, theacl);
1536 }
1537
1538 static int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl)
1539 {
1540         return sys_acl_set_fd(handle, fsp, theacl);
1541 }
1542
1543 static int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle,  const char *path)
1544 {
1545         return sys_acl_delete_def_file(handle, path);
1546 }
1547
1548 static int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle,  SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
1549 {
1550         return sys_acl_get_perm(permset, perm);
1551 }
1552
1553 static int vfswrap_sys_acl_free_text(vfs_handle_struct *handle,  char *text)
1554 {
1555         return sys_acl_free_text(text);
1556 }
1557
1558 static int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle,  SMB_ACL_T posix_acl)
1559 {
1560         return sys_acl_free_acl(posix_acl);
1561 }
1562
1563 static int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle,  void *qualifier, SMB_ACL_TAG_T tagtype)
1564 {
1565         return sys_acl_free_qualifier(qualifier, tagtype);
1566 }
1567
1568 /****************************************************************
1569  Extended attribute operations.
1570 *****************************************************************/
1571
1572 static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1573 {
1574         return sys_getxattr(path, name, value, size);
1575 }
1576
1577 static ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,const char *path, const char *name, void *value, size_t size)
1578 {
1579         return sys_lgetxattr(path, name, value, size);
1580 }
1581
1582 static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, void *value, size_t size)
1583 {
1584         return sys_fgetxattr(fsp->fh->fd, name, value, size);
1585 }
1586
1587 static ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1588 {
1589         return sys_listxattr(path, list, size);
1590 }
1591
1592 ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, const char *path, char *list, size_t size)
1593 {
1594         return sys_llistxattr(path, list, size);
1595 }
1596
1597 ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size)
1598 {
1599         return sys_flistxattr(fsp->fh->fd, list, size);
1600 }
1601
1602 static int vfswrap_removexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1603 {
1604         return sys_removexattr(path, name);
1605 }
1606
1607 static int vfswrap_lremovexattr(struct vfs_handle_struct *handle, const char *path, const char *name)
1608 {
1609         return sys_lremovexattr(path, name);
1610 }
1611
1612 static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name)
1613 {
1614         return sys_fremovexattr(fsp->fh->fd, name);
1615 }
1616
1617 static int vfswrap_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1618 {
1619         return sys_setxattr(path, name, value, size, flags);
1620 }
1621
1622 static int vfswrap_lsetxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
1623 {
1624         return sys_lsetxattr(path, name, value, size, flags);
1625 }
1626
1627 static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags)
1628 {
1629         return sys_fsetxattr(fsp->fh->fd, name, value, size, flags);
1630 }
1631
1632 static int vfswrap_aio_read(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1633 {
1634         int ret;
1635         /*
1636          * aio_read must be done as root, because in the glibc aio
1637          * implementation the helper thread needs to be able to send a signal
1638          * to the main thread, even when it has done a seteuid() to a
1639          * different user.
1640          */
1641         become_root();
1642         ret = sys_aio_read(aiocb);
1643         unbecome_root();
1644         return ret;
1645 }
1646
1647 static int vfswrap_aio_write(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1648 {
1649         int ret;
1650         /*
1651          * aio_write must be done as root, because in the glibc aio
1652          * implementation the helper thread needs to be able to send a signal
1653          * to the main thread, even when it has done a seteuid() to a
1654          * different user.
1655          */
1656         become_root();
1657         ret = sys_aio_write(aiocb);
1658         unbecome_root();
1659         return ret;
1660 }
1661
1662 static ssize_t vfswrap_aio_return(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1663 {
1664         return sys_aio_return(aiocb);
1665 }
1666
1667 static int vfswrap_aio_cancel(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1668 {
1669         return sys_aio_cancel(fsp->fh->fd, aiocb);
1670 }
1671
1672 static int vfswrap_aio_error(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
1673 {
1674         return sys_aio_error(aiocb);
1675 }
1676
1677 static int vfswrap_aio_fsync(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, SMB_STRUCT_AIOCB *aiocb)
1678 {
1679         return sys_aio_fsync(op, aiocb);
1680 }
1681
1682 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)
1683 {
1684         return sys_aio_suspend(aiocb, n, timeout);
1685 }
1686
1687 static bool vfswrap_aio_force(struct vfs_handle_struct *handle, struct files_struct *fsp)
1688 {
1689         return false;
1690 }
1691
1692 static bool vfswrap_is_offline(struct vfs_handle_struct *handle, const char *path, SMB_STRUCT_STAT *sbuf)
1693 {
1694         if (ISDOT(path) || ISDOTDOT(path)) {
1695                 return false;
1696         }
1697
1698         if (!lp_dmapi_support(SNUM(handle->conn)) || !dmapi_have_session()) {
1699 #if defined(ENOTSUP)
1700                 errno = ENOTSUP;
1701 #endif
1702                 return false;
1703         }
1704
1705         return (dmapi_file_flags(path) & FILE_ATTRIBUTE_OFFLINE) != 0;
1706 }
1707
1708 static int vfswrap_set_offline(struct vfs_handle_struct *handle, const char *path)
1709 {
1710         /* We don't know how to set offline bit by default, needs to be overriden in the vfs modules */
1711 #if defined(ENOTSUP)
1712         errno = ENOTSUP;
1713 #endif
1714         return -1;
1715 }
1716
1717 static struct vfs_fn_pointers vfs_default_fns = {
1718         /* Disk operations */
1719
1720         .connect_fn = vfswrap_connect,
1721         .disconnect = vfswrap_disconnect,
1722         .disk_free = vfswrap_disk_free,
1723         .get_quota = vfswrap_get_quota,
1724         .set_quota = vfswrap_set_quota,
1725         .get_shadow_copy_data = vfswrap_get_shadow_copy_data,
1726         .statvfs = vfswrap_statvfs,
1727         .fs_capabilities = vfswrap_fs_capabilities,
1728
1729         /* Directory operations */
1730
1731         .opendir = vfswrap_opendir,
1732         .readdir = vfswrap_readdir,
1733         .seekdir = vfswrap_seekdir,
1734         .telldir = vfswrap_telldir,
1735         .rewind_dir = vfswrap_rewinddir,
1736         .mkdir = vfswrap_mkdir,
1737         .rmdir = vfswrap_rmdir,
1738         .closedir = vfswrap_closedir,
1739         .init_search_op = vfswrap_init_search_op,
1740
1741         /* File operations */
1742
1743         .open = vfswrap_open,
1744         .create_file = vfswrap_create_file,
1745         .close_fn = vfswrap_close,
1746         .vfs_read = vfswrap_read,
1747         .pread = vfswrap_pread,
1748         .write = vfswrap_write,
1749         .pwrite = vfswrap_pwrite,
1750         .lseek = vfswrap_lseek,
1751         .sendfile = vfswrap_sendfile,
1752         .recvfile = vfswrap_recvfile,
1753         .rename = vfswrap_rename,
1754         .fsync = vfswrap_fsync,
1755         .stat = vfswrap_stat,
1756         .fstat = vfswrap_fstat,
1757         .lstat = vfswrap_lstat,
1758         .get_alloc_size = vfswrap_get_alloc_size,
1759         .unlink = vfswrap_unlink,
1760         .chmod = vfswrap_chmod,
1761         .fchmod = vfswrap_fchmod,
1762         .chown = vfswrap_chown,
1763         .fchown = vfswrap_fchown,
1764         .lchown = vfswrap_lchown,
1765         .chdir = vfswrap_chdir,
1766         .getwd = vfswrap_getwd,
1767         .ntimes = vfswrap_ntimes,
1768         .ftruncate = vfswrap_ftruncate,
1769         .lock = vfswrap_lock,
1770         .kernel_flock = vfswrap_kernel_flock,
1771         .linux_setlease = vfswrap_linux_setlease,
1772         .getlock = vfswrap_getlock,
1773         .symlink = vfswrap_symlink,
1774         .vfs_readlink = vfswrap_readlink,
1775         .link = vfswrap_link,
1776         .mknod = vfswrap_mknod,
1777         .realpath = vfswrap_realpath,
1778         .notify_watch = vfswrap_notify_watch,
1779         .chflags = vfswrap_chflags,
1780         .file_id_create = vfswrap_file_id_create,
1781         .streaminfo = vfswrap_streaminfo,
1782         .get_real_filename = vfswrap_get_real_filename,
1783         .connectpath = vfswrap_connectpath,
1784         .brl_lock_windows = vfswrap_brl_lock_windows,
1785         .brl_unlock_windows = vfswrap_brl_unlock_windows,
1786         .brl_cancel_windows = vfswrap_brl_cancel_windows,
1787         .strict_lock = vfswrap_strict_lock,
1788         .strict_unlock = vfswrap_strict_unlock,
1789         .translate_name = vfswrap_translate_name,
1790
1791         /* NT ACL operations. */
1792
1793         .fget_nt_acl = vfswrap_fget_nt_acl,
1794         .get_nt_acl = vfswrap_get_nt_acl,
1795         .fset_nt_acl = vfswrap_fset_nt_acl,
1796
1797         /* POSIX ACL operations. */
1798
1799         .chmod_acl = vfswrap_chmod_acl,
1800         .fchmod_acl = vfswrap_fchmod_acl,
1801
1802         .sys_acl_get_entry = vfswrap_sys_acl_get_entry,
1803         .sys_acl_get_tag_type = vfswrap_sys_acl_get_tag_type,
1804         .sys_acl_get_permset = vfswrap_sys_acl_get_permset,
1805         .sys_acl_get_qualifier = vfswrap_sys_acl_get_qualifier,
1806         .sys_acl_get_file = vfswrap_sys_acl_get_file,
1807         .sys_acl_get_fd = vfswrap_sys_acl_get_fd,
1808         .sys_acl_clear_perms = vfswrap_sys_acl_clear_perms,
1809         .sys_acl_add_perm = vfswrap_sys_acl_add_perm,
1810         .sys_acl_to_text = vfswrap_sys_acl_to_text,
1811         .sys_acl_init = vfswrap_sys_acl_init,
1812         .sys_acl_create_entry = vfswrap_sys_acl_create_entry,
1813         .sys_acl_set_tag_type = vfswrap_sys_acl_set_tag_type,
1814         .sys_acl_set_qualifier = vfswrap_sys_acl_set_qualifier,
1815         .sys_acl_set_permset = vfswrap_sys_acl_set_permset,
1816         .sys_acl_valid = vfswrap_sys_acl_valid,
1817         .sys_acl_set_file = vfswrap_sys_acl_set_file,
1818         .sys_acl_set_fd = vfswrap_sys_acl_set_fd,
1819         .sys_acl_delete_def_file = vfswrap_sys_acl_delete_def_file,
1820         .sys_acl_get_perm = vfswrap_sys_acl_get_perm,
1821         .sys_acl_free_text = vfswrap_sys_acl_free_text,
1822         .sys_acl_free_acl = vfswrap_sys_acl_free_acl,
1823         .sys_acl_free_qualifier = vfswrap_sys_acl_free_qualifier,
1824
1825         /* EA operations. */
1826         .getxattr = vfswrap_getxattr,
1827         .lgetxattr = vfswrap_lgetxattr,
1828         .fgetxattr = vfswrap_fgetxattr,
1829         .listxattr = vfswrap_listxattr,
1830         .llistxattr = vfswrap_llistxattr,
1831         .flistxattr = vfswrap_flistxattr,
1832         .removexattr = vfswrap_removexattr,
1833         .lremovexattr = vfswrap_lremovexattr,
1834         .fremovexattr = vfswrap_fremovexattr,
1835         .setxattr = vfswrap_setxattr,
1836         .lsetxattr = vfswrap_lsetxattr,
1837         .fsetxattr = vfswrap_fsetxattr,
1838
1839         /* aio operations */
1840         .aio_read = vfswrap_aio_read,
1841         .aio_write = vfswrap_aio_write,
1842         .aio_return_fn = vfswrap_aio_return,
1843         .aio_cancel = vfswrap_aio_cancel,
1844         .aio_error_fn = vfswrap_aio_error,
1845         .aio_fsync = vfswrap_aio_fsync,
1846         .aio_suspend = vfswrap_aio_suspend,
1847         .aio_force = vfswrap_aio_force,
1848
1849         /* offline operations */
1850         .is_offline = vfswrap_is_offline,
1851         .set_offline = vfswrap_set_offline
1852 };
1853
1854 NTSTATUS vfs_default_init(void);
1855 NTSTATUS vfs_default_init(void)
1856 {
1857         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
1858                                 DEFAULT_VFS_MODULE_NAME, &vfs_default_fns);
1859 }
1860
1861