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