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(connection_struct
*conn
, const char *service
, const char *user
)
35 return 0; /* Return >= 0 for success */
38 void vfswrap_dummy_disconnect(connection_struct
*conn
)
44 SMB_BIG_UINT
vfswrap_disk_free(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(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(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(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 (conn
->vfs_ops
.chmod_acl
!= NULL
) {
97 if ((conn
->vfs_ops
.chmod_acl(conn
, path
, mode
) == -1) && (errno
== ENOSYS
))
102 END_PROFILE(syscall_mkdir
);
106 int vfswrap_rmdir(connection_struct
*conn
, const char *path
)
110 START_PROFILE(syscall_rmdir
);
111 result
= rmdir(path
);
112 END_PROFILE(syscall_rmdir
);
116 int vfswrap_closedir(connection_struct
*conn
, DIR *dirp
)
120 START_PROFILE(syscall_closedir
);
121 result
= closedir(dirp
);
122 END_PROFILE(syscall_closedir
);
126 /* File operations */
128 int vfswrap_open(connection_struct
*conn
, const char *fname
, int flags
, mode_t mode
)
132 START_PROFILE(syscall_open
);
133 result
= sys_open(fname
, flags
, mode
);
134 END_PROFILE(syscall_open
);
138 int vfswrap_close(files_struct
*fsp
, int fd
)
142 START_PROFILE(syscall_close
);
145 END_PROFILE(syscall_close
);
149 ssize_t
vfswrap_read(files_struct
*fsp
, int fd
, void *data
, size_t n
)
153 START_PROFILE_BYTES(syscall_read
, n
);
154 result
= sys_read(fd
, data
, n
);
155 END_PROFILE(syscall_read
);
159 ssize_t
vfswrap_write(files_struct
*fsp
, int fd
, const void *data
, size_t n
)
163 START_PROFILE_BYTES(syscall_write
, n
);
164 result
= sys_write(fd
, data
, n
);
165 END_PROFILE(syscall_write
);
169 SMB_OFF_T
vfswrap_lseek(files_struct
*fsp
, int filedes
, SMB_OFF_T offset
, int whence
)
171 SMB_OFF_T result
= 0;
173 START_PROFILE(syscall_lseek
);
175 /* Cope with 'stat' file opens. */
177 result
= sys_lseek(filedes
, offset
, whence
);
180 * We want to maintain the fiction that we can seek
181 * on a fifo for file system purposes. This allows
182 * people to set up UNIX fifo's that feed data to Windows
186 if((result
== -1) && (errno
== ESPIPE
)) {
191 END_PROFILE(syscall_lseek
);
195 ssize_t
vfswrap_sendfile(int tofd
, struct files_struct
*fsp
, int fromfd
, const DATA_BLOB
*hdr
,
196 SMB_OFF_T offset
, size_t n
)
200 START_PROFILE_BYTES(syscall_sendfile
, n
);
201 result
= sys_sendfile(tofd
, fromfd
, hdr
, offset
, n
);
202 END_PROFILE(syscall_sendfile
);
206 int vfswrap_rename(connection_struct
*conn
, const char *old
, const char *new)
210 START_PROFILE(syscall_rename
);
211 result
= rename(old
, new);
212 END_PROFILE(syscall_rename
);
216 int vfswrap_fsync(files_struct
*fsp
, int fd
)
221 START_PROFILE(syscall_fsync
);
224 END_PROFILE(syscall_fsync
);
231 int vfswrap_stat(connection_struct
*conn
, const char *fname
, SMB_STRUCT_STAT
*sbuf
)
235 START_PROFILE(syscall_stat
);
236 result
= sys_stat(fname
, sbuf
);
237 END_PROFILE(syscall_stat
);
241 int vfswrap_fstat(files_struct
*fsp
, int fd
, SMB_STRUCT_STAT
*sbuf
)
245 START_PROFILE(syscall_fstat
);
246 result
= sys_fstat(fd
, sbuf
);
247 END_PROFILE(syscall_fstat
);
251 int vfswrap_lstat(connection_struct
*conn
, const char *path
, SMB_STRUCT_STAT
*sbuf
)
255 START_PROFILE(syscall_lstat
);
256 result
= sys_lstat(path
, sbuf
);
257 END_PROFILE(syscall_lstat
);
261 int vfswrap_unlink(connection_struct
*conn
, const char *path
)
265 START_PROFILE(syscall_unlink
);
266 result
= unlink(path
);
267 END_PROFILE(syscall_unlink
);
271 int vfswrap_chmod(connection_struct
*conn
, const char *path
, mode_t mode
)
275 START_PROFILE(syscall_chmod
);
278 * We need to do this due to the fact that the default POSIX ACL
279 * chmod modifies the ACL *mask* for the group owner, not the
280 * group owner bits directly. JRA.
284 if (conn
->vfs_ops
.chmod_acl
!= NULL
) {
285 int saved_errno
= errno
; /* We might get ENOSYS */
286 if ((result
= conn
->vfs_ops
.chmod_acl(conn
, path
, mode
)) == 0) {
287 END_PROFILE(syscall_chmod
);
290 /* Error - return the old errno. */
294 result
= chmod(path
, mode
);
295 END_PROFILE(syscall_chmod
);
299 int vfswrap_fchmod(files_struct
*fsp
, int fd
, mode_t mode
)
302 struct vfs_ops
*vfs_ops
= &fsp
->conn
->vfs_ops
;
304 START_PROFILE(syscall_fchmod
);
307 * We need to do this due to the fact that the default POSIX ACL
308 * chmod modifies the ACL *mask* for the group owner, not the
309 * group owner bits directly. JRA.
312 if (vfs_ops
->fchmod_acl
!= NULL
) {
313 int saved_errno
= errno
; /* We might get ENOSYS */
314 if ((result
= vfs_ops
->fchmod_acl(fsp
, fd
, mode
)) == 0) {
315 END_PROFILE(syscall_chmod
);
318 /* Error - return the old errno. */
322 result
= fchmod(fd
, mode
);
323 END_PROFILE(syscall_fchmod
);
327 int vfswrap_chown(connection_struct
*conn
, const char *path
, uid_t uid
, gid_t gid
)
331 START_PROFILE(syscall_chown
);
332 result
= sys_chown(path
, uid
, gid
);
333 END_PROFILE(syscall_chown
);
337 int vfswrap_fchown(files_struct
*fsp
, int fd
, uid_t uid
, gid_t gid
)
341 START_PROFILE(syscall_fchown
);
343 result
= fchown(fd
, uid
, gid
);
344 END_PROFILE(syscall_fchown
);
348 int vfswrap_chdir(connection_struct
*conn
, const char *path
)
352 START_PROFILE(syscall_chdir
);
353 result
= chdir(path
);
354 END_PROFILE(syscall_chdir
);
358 char *vfswrap_getwd(connection_struct
*conn
, char *path
)
362 START_PROFILE(syscall_getwd
);
363 result
= sys_getwd(path
);
364 END_PROFILE(syscall_getwd
);
368 int vfswrap_utime(connection_struct
*conn
, const char *path
, struct utimbuf
*times
)
372 START_PROFILE(syscall_utime
);
373 result
= utime(path
, times
);
374 END_PROFILE(syscall_utime
);
378 /*********************************************************************
379 A version of ftruncate that will write the space on disk if strict
381 **********************************************************************/
383 static int strict_allocate_ftruncate(files_struct
*fsp
, int fd
, SMB_OFF_T len
)
385 struct vfs_ops
*vfs_ops
= &fsp
->conn
->vfs_ops
;
387 SMB_OFF_T currpos
= vfs_ops
->lseek(fsp
, fd
, 0, SEEK_CUR
);
388 unsigned char zero_space
[4096];
389 SMB_OFF_T space_to_write
;
394 if (vfs_ops
->fstat(fsp
, fd
, &st
) == -1)
397 space_to_write
= len
- st
.st_size
;
400 if (S_ISFIFO(st
.st_mode
))
404 if (st
.st_size
== len
)
407 /* Shrink - just ftruncate. */
408 if (st
.st_size
> len
)
409 return sys_ftruncate(fd
, len
);
411 /* Write out the real space on disk. */
412 if (vfs_ops
->lseek(fsp
, fd
, st
.st_size
, SEEK_SET
) != st
.st_size
)
415 space_to_write
= len
- st
.st_size
;
417 memset(zero_space
, '\0', sizeof(zero_space
));
418 while ( space_to_write
> 0) {
420 SMB_OFF_T current_len_to_write
= MIN(sizeof(zero_space
),space_to_write
);
422 retlen
= vfs_ops
->write(fsp
,fsp
->fd
,(char *)zero_space
,current_len_to_write
);
426 space_to_write
-= retlen
;
429 /* Seek to where we were */
430 if (vfs_ops
->lseek(fsp
, fd
, currpos
, SEEK_SET
) != currpos
)
436 int vfswrap_ftruncate(files_struct
*fsp
, int fd
, SMB_OFF_T len
)
439 struct vfs_ops
*vfs_ops
= &fsp
->conn
->vfs_ops
;
444 START_PROFILE(syscall_ftruncate
);
446 if (lp_strict_allocate(SNUM(fsp
->conn
))) {
447 result
= strict_allocate_ftruncate(fsp
, fd
, len
);
448 END_PROFILE(syscall_ftruncate
);
452 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
453 sys_ftruncate if the system supports it. Then I discovered that
454 you can have some filesystems that support ftruncate
455 expansion and some that don't! On Linux fat can't do
456 ftruncate extend but ext2 can. */
458 result
= sys_ftruncate(fd
, len
);
462 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
463 extend a file with ftruncate. Provide alternate implementation
465 currpos
= vfs_ops
->lseek(fsp
, fd
, 0, SEEK_CUR
);
470 /* Do an fstat to see if the file is longer than the requested
471 size in which case the ftruncate above should have
472 succeeded or shorter, in which case seek to len - 1 and
473 write 1 byte of zero */
474 if (vfs_ops
->fstat(fsp
, fd
, &st
) == -1) {
479 if (S_ISFIFO(st
.st_mode
)) {
485 if (st
.st_size
== len
) {
490 if (st
.st_size
> len
) {
491 /* the sys_ftruncate should have worked */
495 if (vfs_ops
->lseek(fsp
, fd
, len
-1, SEEK_SET
) != len
-1)
498 if (vfs_ops
->write(fsp
, fd
, &c
, 1)!=1)
501 /* Seek to where we were */
502 if (vfs_ops
->lseek(fsp
, fd
, currpos
, SEEK_SET
) != currpos
)
508 END_PROFILE(syscall_ftruncate
);
512 BOOL
vfswrap_lock(files_struct
*fsp
, int fd
, int op
, SMB_OFF_T offset
, SMB_OFF_T count
, int type
)
516 START_PROFILE(syscall_fcntl_lock
);
518 result
= fcntl_lock(fd
, op
, offset
, count
,type
);
519 END_PROFILE(syscall_fcntl_lock
);
523 int vfswrap_symlink(connection_struct
*conn
, const char *oldpath
, const char *newpath
)
527 START_PROFILE(syscall_symlink
);
528 result
= sys_symlink(oldpath
, newpath
);
529 END_PROFILE(syscall_symlink
);
533 int vfswrap_readlink(connection_struct
*conn
, const char *path
, char *buf
, size_t bufsiz
)
537 START_PROFILE(syscall_readlink
);
538 result
= sys_readlink(path
, buf
, bufsiz
);
539 END_PROFILE(syscall_readlink
);
543 int vfswrap_link(connection_struct
*conn
, const char *oldpath
, const char *newpath
)
547 START_PROFILE(syscall_link
);
548 result
= sys_link(oldpath
, newpath
);
549 END_PROFILE(syscall_link
);
553 int vfswrap_mknod(connection_struct
*conn
, const char *pathname
, mode_t mode
, SMB_DEV_T dev
)
557 START_PROFILE(syscall_mknod
);
558 result
= sys_mknod(pathname
, mode
, dev
);
559 END_PROFILE(syscall_mknod
);
563 char *vfswrap_realpath(connection_struct
*conn
, const char *path
, char *resolved_path
)
567 START_PROFILE(syscall_realpath
);
568 result
= sys_realpath(path
, resolved_path
);
569 END_PROFILE(syscall_realpath
);
573 size_t vfswrap_fget_nt_acl(files_struct
*fsp
, int fd
, SEC_DESC
**ppdesc
)
577 START_PROFILE(fget_nt_acl
);
578 result
= get_nt_acl(fsp
, ppdesc
);
579 END_PROFILE(fget_nt_acl
);
583 size_t vfswrap_get_nt_acl(files_struct
*fsp
, const char *name
, SEC_DESC
**ppdesc
)
587 START_PROFILE(get_nt_acl
);
588 result
= get_nt_acl(fsp
, ppdesc
);
589 END_PROFILE(get_nt_acl
);
593 BOOL
vfswrap_fset_nt_acl(files_struct
*fsp
, int fd
, uint32 security_info_sent
, SEC_DESC
*psd
)
597 START_PROFILE(fset_nt_acl
);
598 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
599 END_PROFILE(fset_nt_acl
);
603 BOOL
vfswrap_set_nt_acl(files_struct
*fsp
, const char *name
, uint32 security_info_sent
, SEC_DESC
*psd
)
607 START_PROFILE(set_nt_acl
);
608 result
= set_nt_acl(fsp
, security_info_sent
, psd
);
609 END_PROFILE(set_nt_acl
);
613 int vfswrap_chmod_acl(connection_struct
*conn
, const char *name
, mode_t mode
)
617 START_PROFILE(chmod_acl
);
618 result
= chmod_acl(conn
, name
, mode
);
619 END_PROFILE(chmod_acl
);
623 int vfswrap_fchmod_acl(files_struct
*fsp
, int fd
, mode_t mode
)
627 START_PROFILE(fchmod_acl
);
628 result
= fchmod_acl(fsp
, fd
, mode
);
629 END_PROFILE(fchmod_acl
);
633 int vfswrap_sys_acl_get_entry(struct connection_struct
*conn
, SMB_ACL_T theacl
, int entry_id
, SMB_ACL_ENTRY_T
*entry_p
)
635 return sys_acl_get_entry(theacl
, entry_id
, entry_p
);
638 int vfswrap_sys_acl_get_tag_type(struct connection_struct
*conn
, SMB_ACL_ENTRY_T entry_d
, SMB_ACL_TAG_T
*tag_type_p
)
640 return sys_acl_get_tag_type(entry_d
, tag_type_p
);
643 int vfswrap_sys_acl_get_permset(struct connection_struct
*conn
, SMB_ACL_ENTRY_T entry_d
, SMB_ACL_PERMSET_T
*permset_p
)
645 return sys_acl_get_permset(entry_d
, permset_p
);
648 void * vfswrap_sys_acl_get_qualifier(struct connection_struct
*conn
, SMB_ACL_ENTRY_T entry_d
)
650 return sys_acl_get_qualifier(entry_d
);
653 SMB_ACL_T
vfswrap_sys_acl_get_file(struct connection_struct
*conn
, const char *path_p
, SMB_ACL_TYPE_T type
)
655 return sys_acl_get_file(path_p
, type
);
658 SMB_ACL_T
vfswrap_sys_acl_get_fd(struct files_struct
*fsp
, int fd
)
660 return sys_acl_get_fd(fd
);
663 int vfswrap_sys_acl_clear_perms(struct connection_struct
*conn
, SMB_ACL_PERMSET_T permset
)
665 return sys_acl_clear_perms(permset
);
668 int vfswrap_sys_acl_add_perm(struct connection_struct
*conn
, SMB_ACL_PERMSET_T permset
, SMB_ACL_PERM_T perm
)
670 return sys_acl_add_perm(permset
, perm
);
673 char * vfswrap_sys_acl_to_text(struct connection_struct
*conn
, SMB_ACL_T theacl
, ssize_t
*plen
)
675 return sys_acl_to_text(theacl
, plen
);
678 SMB_ACL_T
vfswrap_sys_acl_init(struct connection_struct
*conn
, int count
)
680 return sys_acl_init(count
);
683 int vfswrap_sys_acl_create_entry(struct connection_struct
*conn
, SMB_ACL_T
*pacl
, SMB_ACL_ENTRY_T
*pentry
)
685 return sys_acl_create_entry(pacl
, pentry
);
688 int vfswrap_sys_acl_set_tag_type(struct connection_struct
*conn
, SMB_ACL_ENTRY_T entry
, SMB_ACL_TAG_T tagtype
)
690 return sys_acl_set_tag_type(entry
, tagtype
);
693 int vfswrap_sys_acl_set_qualifier(struct connection_struct
*conn
, SMB_ACL_ENTRY_T entry
, void *qual
)
695 return sys_acl_set_qualifier(entry
, qual
);
698 int vfswrap_sys_acl_set_permset(struct connection_struct
*conn
, SMB_ACL_ENTRY_T entry
, SMB_ACL_PERMSET_T permset
)
700 return sys_acl_set_permset(entry
, permset
);
703 int vfswrap_sys_acl_valid(struct connection_struct
*conn
, SMB_ACL_T theacl
)
705 return sys_acl_valid(theacl
);
708 int vfswrap_sys_acl_set_file(struct connection_struct
*conn
, const char *name
, SMB_ACL_TYPE_T acltype
, SMB_ACL_T theacl
)
710 return sys_acl_set_file(name
, acltype
, theacl
);
713 int vfswrap_sys_acl_set_fd(struct files_struct
*fsp
, int fd
, SMB_ACL_T theacl
)
715 return sys_acl_set_fd(fd
, theacl
);
718 int vfswrap_sys_acl_delete_def_file(struct connection_struct
*conn
, const char *path
)
720 return sys_acl_delete_def_file(path
);
723 int vfswrap_sys_acl_get_perm(struct connection_struct
*conn
, SMB_ACL_PERMSET_T permset
, SMB_ACL_PERM_T perm
)
725 return sys_acl_get_perm(permset
, perm
);
728 int vfswrap_sys_acl_free_text(struct connection_struct
*conn
, char *text
)
730 return sys_acl_free_text(text
);
733 int vfswrap_sys_acl_free_acl(struct connection_struct
*conn
, SMB_ACL_T posix_acl
)
735 return sys_acl_free_acl(posix_acl
);
738 int vfswrap_sys_acl_free_qualifier(struct connection_struct
*conn
, void *qualifier
, SMB_ACL_TAG_T tagtype
)
740 return sys_acl_free_qualifier(qualifier
, tagtype
);