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