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