2 Unix SMB/CIFS implementation.
3 Wrap disk only vfs functions to sidestep dodgy compilers.
4 Copyright (C) Tim Potter 1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define DBGC_CLASS DBGC_VFS
27 /* Check for NULL pointer parameters in vfswrap_* functions */
29 /* We don't want to have NULL function pointers lying around. Someone
30 is sure to try and execute them. These stubs are used to prevent
33 int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user)
35 return 0; /* Return >= 0 for success */
38 void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn)
44 SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
45 SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
49 result = sys_disk_free(path, small_query, bsize, dfree, dsize);
53 /* Directory operations */
55 DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname)
59 START_PROFILE(syscall_opendir);
60 result = opendir(fname);
61 END_PROFILE(syscall_opendir);
65 struct dirent *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
67 struct dirent *result;
69 START_PROFILE(syscall_readdir);
70 result = readdir(dirp);
71 END_PROFILE(syscall_readdir);
75 int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
78 BOOL has_dacl = False;
80 START_PROFILE(syscall_mkdir);
82 if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
85 result = mkdir(path, mode);
87 if (result == 0 && !has_dacl) {
89 * We need to do this as the default behavior of POSIX ACLs
90 * is to set the mask to be the requested group permission
91 * bits, not the group permission bits to be the requested
92 * group permission bits. This is not what we want, as it will
93 * mess up any inherited ACL bits that were set. JRA.
95 int saved_errno = errno; /* We may get ENOSYS */
96 if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS))
100 END_PROFILE(syscall_mkdir);
104 int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
108 START_PROFILE(syscall_rmdir);
109 result = rmdir(path);
110 END_PROFILE(syscall_rmdir);
114 int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp)
118 START_PROFILE(syscall_closedir);
119 result = closedir(dirp);
120 END_PROFILE(syscall_closedir);
124 /* File operations */
126 int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode)
130 START_PROFILE(syscall_open);
131 result = sys_open(fname, flags, mode);
132 END_PROFILE(syscall_open);
136 int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd)
140 START_PROFILE(syscall_close);
143 END_PROFILE(syscall_close);
147 ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n)
151 START_PROFILE_BYTES(syscall_read, n);
152 result = sys_read(fd, data, n);
153 END_PROFILE(syscall_read);
157 ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n)
161 START_PROFILE_BYTES(syscall_write, n);
162 result = sys_write(fd, data, n);
163 END_PROFILE(syscall_write);
167 SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
169 SMB_OFF_T result = 0;
171 START_PROFILE(syscall_lseek);
173 /* Cope with 'stat' file opens. */
175 result = sys_lseek(filedes, offset, whence);
178 * We want to maintain the fiction that we can seek
179 * on a fifo for file system purposes. This allows
180 * people to set up UNIX fifo's that feed data to Windows
184 if((result == -1) && (errno == ESPIPE)) {
189 END_PROFILE(syscall_lseek);
193 ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
194 SMB_OFF_T offset, size_t n)
198 START_PROFILE_BYTES(syscall_sendfile, n);
199 result = sys_sendfile(tofd, fromfd, hdr, offset, n);
200 END_PROFILE(syscall_sendfile);
204 int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new)
208 START_PROFILE(syscall_rename);
209 result = rename(old, new);
210 END_PROFILE(syscall_rename);
214 int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd)
219 START_PROFILE(syscall_fsync);
222 END_PROFILE(syscall_fsync);
229 int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
233 START_PROFILE(syscall_stat);
234 result = sys_stat(fname, sbuf);
235 END_PROFILE(syscall_stat);
239 int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
243 START_PROFILE(syscall_fstat);
244 result = sys_fstat(fd, sbuf);
245 END_PROFILE(syscall_fstat);
249 int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
253 START_PROFILE(syscall_lstat);
254 result = sys_lstat(path, sbuf);
255 END_PROFILE(syscall_lstat);
259 int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path)
263 START_PROFILE(syscall_unlink);
264 result = unlink(path);
265 END_PROFILE(syscall_unlink);
269 int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode)
273 START_PROFILE(syscall_chmod);
276 * We need to do this due to the fact that the default POSIX ACL
277 * chmod modifies the ACL *mask* for the group owner, not the
278 * group owner bits directly. JRA.
283 int saved_errno = errno; /* We might get ENOSYS */
284 if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) {
285 END_PROFILE(syscall_chmod);
288 /* Error - return the old errno. */
292 result = chmod(path, mode);
293 END_PROFILE(syscall_chmod);
297 int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
301 START_PROFILE(syscall_fchmod);
304 * We need to do this due to the fact that the default POSIX ACL
305 * chmod modifies the ACL *mask* for the group owner, not the
306 * group owner bits directly. JRA.
310 int saved_errno = errno; /* We might get ENOSYS */
311 if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) {
312 END_PROFILE(syscall_chmod);
315 /* Error - return the old errno. */
319 #if defined(HAVE_FCHMOD)
320 result = fchmod(fd, mode);
326 END_PROFILE(syscall_fchmod);
330 int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid)
334 START_PROFILE(syscall_chown);
335 result = sys_chown(path, uid, gid);
336 END_PROFILE(syscall_chown);
340 int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid)
345 START_PROFILE(syscall_fchown);
347 result = fchown(fd, uid, gid);
348 END_PROFILE(syscall_fchown);
356 int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path)
360 START_PROFILE(syscall_chdir);
361 result = chdir(path);
362 END_PROFILE(syscall_chdir);
366 char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path)
370 START_PROFILE(syscall_getwd);
371 result = sys_getwd(path);
372 END_PROFILE(syscall_getwd);
376 int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times)
380 START_PROFILE(syscall_utime);
381 result = utime(path, times);
382 END_PROFILE(syscall_utime);
386 /*********************************************************************
387 A version of ftruncate that will write the space on disk if strict
389 **********************************************************************/
391 static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
394 SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
395 unsigned char zero_space[4096];
396 SMB_OFF_T space_to_write;
401 if (SMB_VFS_FSTAT(fsp, fd, &st) == -1)
404 space_to_write = len - st.st_size;
407 if (S_ISFIFO(st.st_mode))
411 if (st.st_size == len)
414 /* Shrink - just ftruncate. */
415 if (st.st_size > len)
416 return sys_ftruncate(fd, len);
418 /* Write out the real space on disk. */
419 if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
422 space_to_write = len - st.st_size;
424 memset(zero_space, '\0', sizeof(zero_space));
425 while ( space_to_write > 0) {
427 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
429 retlen = SMB_VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
433 space_to_write -= retlen;
436 /* Seek to where we were */
437 if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
443 int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len)
450 START_PROFILE(syscall_ftruncate);
452 if (lp_strict_allocate(SNUM(fsp->conn))) {
453 result = strict_allocate_ftruncate(handle, fsp, fd, len);
454 END_PROFILE(syscall_ftruncate);
458 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
459 sys_ftruncate if the system supports it. Then I discovered that
460 you can have some filesystems that support ftruncate
461 expansion and some that don't! On Linux fat can't do
462 ftruncate extend but ext2 can. */
464 result = sys_ftruncate(fd, len);
468 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
469 extend a file with ftruncate. Provide alternate implementation
471 currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR);
476 /* Do an fstat to see if the file is longer than the requested
477 size in which case the ftruncate above should have
478 succeeded or shorter, in which case seek to len - 1 and
479 write 1 byte of zero */
480 if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) {
485 if (S_ISFIFO(st.st_mode)) {
491 if (st.st_size == len) {
496 if (st.st_size > len) {
497 /* the sys_ftruncate should have worked */
501 if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1)
504 if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1)
507 /* Seek to where we were */
508 if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos)
514 END_PROFILE(syscall_ftruncate);
518 BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
522 START_PROFILE(syscall_fcntl_lock);
524 result = fcntl_lock(fd, op, offset, count,type);
525 END_PROFILE(syscall_fcntl_lock);
529 int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
533 START_PROFILE(syscall_symlink);
534 result = sys_symlink(oldpath, newpath);
535 END_PROFILE(syscall_symlink);
539 int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz)
543 START_PROFILE(syscall_readlink);
544 result = sys_readlink(path, buf, bufsiz);
545 END_PROFILE(syscall_readlink);
549 int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath)
553 START_PROFILE(syscall_link);
554 result = sys_link(oldpath, newpath);
555 END_PROFILE(syscall_link);
559 int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
563 START_PROFILE(syscall_mknod);
564 result = sys_mknod(pathname, mode, dev);
565 END_PROFILE(syscall_mknod);
569 char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path)
573 START_PROFILE(syscall_realpath);
574 result = sys_realpath(path, resolved_path);
575 END_PROFILE(syscall_realpath);
579 size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
583 START_PROFILE(fget_nt_acl);
584 result = get_nt_acl(fsp, security_info, ppdesc);
585 END_PROFILE(fget_nt_acl);
589 size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc)
593 START_PROFILE(get_nt_acl);
594 result = get_nt_acl(fsp, security_info, ppdesc);
595 END_PROFILE(get_nt_acl);
599 BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
603 START_PROFILE(fset_nt_acl);
604 result = set_nt_acl(fsp, security_info_sent, psd);
605 END_PROFILE(fset_nt_acl);
609 BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
613 START_PROFILE(set_nt_acl);
614 result = set_nt_acl(fsp, security_info_sent, psd);
615 END_PROFILE(set_nt_acl);
619 int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode)
627 START_PROFILE(chmod_acl);
628 result = chmod_acl(conn, name, mode);
629 END_PROFILE(chmod_acl);
634 int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode)
642 START_PROFILE(fchmod_acl);
643 result = fchmod_acl(fsp, fd, mode);
644 END_PROFILE(fchmod_acl);
649 int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
651 return sys_acl_get_entry(theacl, entry_id, entry_p);
654 int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
656 return sys_acl_get_tag_type(entry_d, tag_type_p);
659 int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
661 return sys_acl_get_permset(entry_d, permset_p);
664 void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
666 return sys_acl_get_qualifier(entry_d);
669 SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
671 return sys_acl_get_file(path_p, type);
674 SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd)
676 return sys_acl_get_fd(fd);
679 int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset)
681 return sys_acl_clear_perms(permset);
684 int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
686 return sys_acl_add_perm(permset, perm);
689 char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
691 return sys_acl_to_text(theacl, plen);
694 SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count)
696 return sys_acl_init(count);
699 int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
701 return sys_acl_create_entry(pacl, pentry);
704 int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
706 return sys_acl_set_tag_type(entry, tagtype);
709 int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
711 return sys_acl_set_qualifier(entry, qual);
714 int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
716 return sys_acl_set_permset(entry, permset);
719 int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl )
721 return sys_acl_valid(theacl );
724 int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
726 return sys_acl_set_file(name, acltype, theacl);
729 int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl)
731 return sys_acl_set_fd(fd, theacl);
734 int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path)
736 return sys_acl_delete_def_file(path);
739 int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
741 return sys_acl_get_perm(permset, perm);
744 int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text)
746 return sys_acl_free_text(text);
749 int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl)
751 return sys_acl_free_acl(posix_acl);
754 int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
756 return sys_acl_free_qualifier(qualifier, tagtype);
759 int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
761 #ifdef HAVE_SYS_QUOTAS
764 START_PROFILE(syscall_get_quota);
765 result = sys_get_quota(conn->connectpath, qtype, id, qt);
766 END_PROFILE(syscall_get_quota);
774 int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt)
776 #ifdef HAVE_SYS_QUOTAS
779 START_PROFILE(syscall_set_quota);
780 result = sys_set_quota(conn->connectpath, qtype, id, qt);
781 END_PROFILE(syscall_set_quota);
789 /****************************************************************
790 Extended attribute operations.
791 *****************************************************************/
793 ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
795 return sys_getxattr(path, name, value, size);
798 ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size)
800 return sys_lgetxattr(path, name, value, size);
803 ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size)
805 return sys_fgetxattr(fd, name, value, size);
808 ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
810 return sys_listxattr(path, list, size);
813 ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size)
815 return sys_llistxattr(path, list, size);
818 ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size)
820 return sys_flistxattr(fd, list, size);
823 int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
825 return sys_removexattr(path, name);
828 int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name)
830 return sys_lremovexattr(path, name);
833 int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name)
835 return sys_fremovexattr(fd, name);
838 int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
840 return sys_setxattr(path, name, value, size, flags);
843 int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags)
845 return sys_lsetxattr(path, name, value, size, flags);
848 int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags)
850 return sys_fsetxattr(fd, name, value, size, flags);