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