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.
23 /* Check for NULL pointer parameters in vfswrap_* functions */
25 /* We don't want to have NULL function pointers lying around. Someone
26 is sure to try and execute them. These stubs are used to prevent
29 int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user)
31 return 0; /* Return >= 0 for success */
34 void vfswrap_dummy_disconnect(connection_struct *conn)
40 SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
41 SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
45 result = sys_disk_free(path, small_query, bsize, dfree, dsize);
49 /* Directory operations */
51 DIR *vfswrap_opendir(connection_struct *conn, const char *fname)
55 START_PROFILE(syscall_opendir);
56 result = opendir(fname);
57 END_PROFILE(syscall_opendir);
61 struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp)
63 struct dirent *result;
65 START_PROFILE(syscall_readdir);
66 result = readdir(dirp);
67 END_PROFILE(syscall_readdir);
71 int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode)
74 BOOL has_dacl = False;
76 START_PROFILE(syscall_mkdir);
78 if (lp_inherit_acls(SNUM(conn)) && (has_dacl = directory_has_default_acl(conn, parent_dirname(path))))
81 result = mkdir(path, mode);
83 if (result == 0 && !has_dacl) {
85 * We need to do this as the default behavior of POSIX ACLs
86 * is to set the mask to be the requested group permission
87 * bits, not the group permission bits to be the requested
88 * group permission bits. This is not what we want, as it will
89 * mess up any inherited ACL bits that were set. JRA.
91 int saved_errno = errno; /* We may get ENOSYS */
92 if (conn->vfs_ops.chmod_acl != NULL) {
93 if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS))
98 END_PROFILE(syscall_mkdir);
102 int vfswrap_rmdir(connection_struct *conn, const char *path)
106 START_PROFILE(syscall_rmdir);
107 result = rmdir(path);
108 END_PROFILE(syscall_rmdir);
112 int vfswrap_closedir(connection_struct *conn, DIR *dirp)
116 START_PROFILE(syscall_closedir);
117 result = closedir(dirp);
118 END_PROFILE(syscall_closedir);
122 /* File operations */
124 int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode)
128 START_PROFILE(syscall_open);
129 result = sys_open(fname, flags, mode);
130 END_PROFILE(syscall_open);
134 int vfswrap_close(files_struct *fsp, int fd)
138 START_PROFILE(syscall_close);
141 END_PROFILE(syscall_close);
145 ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n)
149 START_PROFILE_BYTES(syscall_read, n);
150 result = read(fd, data, n);
151 END_PROFILE(syscall_read);
155 ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
159 START_PROFILE_BYTES(syscall_write, n);
160 result = write(fd, data, n);
161 END_PROFILE(syscall_write);
165 SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
167 SMB_OFF_T result = 0;
169 START_PROFILE(syscall_lseek);
171 /* Cope with 'stat' file opens. */
173 result = sys_lseek(filedes, offset, whence);
176 * We want to maintain the fiction that we can seek
177 * on a fifo for file system purposes. This allows
178 * people to set up UNIX fifo's that feed data to Windows
182 if((result == -1) && (errno == ESPIPE)) {
187 END_PROFILE(syscall_lseek);
191 int vfswrap_rename(connection_struct *conn, const char *old, const char *new)
195 START_PROFILE(syscall_rename);
196 result = rename(old, new);
197 END_PROFILE(syscall_rename);
201 int vfswrap_fsync(files_struct *fsp, int fd)
206 START_PROFILE(syscall_fsync);
209 END_PROFILE(syscall_fsync);
216 int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
220 START_PROFILE(syscall_stat);
221 result = sys_stat(fname, sbuf);
222 END_PROFILE(syscall_stat);
226 int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
230 START_PROFILE(syscall_fstat);
231 result = sys_fstat(fd, sbuf);
232 END_PROFILE(syscall_fstat);
236 int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
240 START_PROFILE(syscall_lstat);
241 result = sys_lstat(path, sbuf);
242 END_PROFILE(syscall_lstat);
246 int vfswrap_unlink(connection_struct *conn, const char *path)
250 START_PROFILE(syscall_unlink);
251 result = unlink(path);
252 END_PROFILE(syscall_unlink);
256 int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode)
260 START_PROFILE(syscall_chmod);
263 * We need to do this due to the fact that the default POSIX ACL
264 * chmod modifies the ACL *mask* for the group owner, not the
265 * group owner bits directly. JRA.
269 if (conn->vfs_ops.chmod_acl != NULL) {
270 int saved_errno = errno; /* We might get ENOSYS */
271 if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) {
272 END_PROFILE(syscall_chmod);
275 /* Error - return the old errno. */
279 result = chmod(path, mode);
280 END_PROFILE(syscall_chmod);
284 int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode)
287 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
289 START_PROFILE(syscall_fchmod);
292 * We need to do this due to the fact that the default POSIX ACL
293 * chmod modifies the ACL *mask* for the group owner, not the
294 * group owner bits directly. JRA.
297 if (vfs_ops->fchmod_acl != NULL) {
298 int saved_errno = errno; /* We might get ENOSYS */
299 if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) {
300 END_PROFILE(syscall_chmod);
303 /* Error - return the old errno. */
307 result = fchmod(fd, mode);
308 END_PROFILE(syscall_fchmod);
312 int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid)
316 START_PROFILE(syscall_chown);
317 result = sys_chown(path, uid, gid);
318 END_PROFILE(syscall_chown);
322 int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid)
326 START_PROFILE(syscall_fchown);
328 result = fchown(fd, uid, gid);
329 END_PROFILE(syscall_fchown);
333 int vfswrap_chdir(connection_struct *conn, const char *path)
337 START_PROFILE(syscall_chdir);
338 result = chdir(path);
339 END_PROFILE(syscall_chdir);
343 char *vfswrap_getwd(connection_struct *conn, char *path)
347 START_PROFILE(syscall_getwd);
348 result = sys_getwd(path);
349 END_PROFILE(syscall_getwd);
353 int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times)
357 START_PROFILE(syscall_utime);
358 result = utime(path, times);
359 END_PROFILE(syscall_utime);
363 /*********************************************************************
364 A version of ftruncate that will write the space on disk if strict
366 **********************************************************************/
368 static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
370 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
372 SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
373 unsigned char zero_space[4096];
374 SMB_OFF_T space_to_write;
379 if (vfs_ops->fstat(fsp, fd, &st) == -1)
382 space_to_write = len - st.st_size;
385 if (S_ISFIFO(st.st_mode))
389 if (st.st_size == len)
392 /* Shrink - just ftruncate. */
393 if (st.st_size > len)
394 return sys_ftruncate(fd, len);
396 /* Write out the real space on disk. */
397 if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
400 space_to_write = len - st.st_size;
402 memset(zero_space, '\0', sizeof(zero_space));
403 while ( space_to_write > 0) {
405 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
407 retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
411 space_to_write -= retlen;
414 /* Seek to where we were */
415 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
421 int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
424 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
429 START_PROFILE(syscall_ftruncate);
431 if (lp_strict_allocate(SNUM(fsp->conn))) {
432 result = strict_allocate_ftruncate(fsp, fd, len);
433 END_PROFILE(syscall_ftruncate);
437 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
438 sys_ftruncate if the system supports it. Then I discovered that
439 you can have some filesystems that support ftruncate
440 expansion and some that don't! On Linux fat can't do
441 ftruncate extend but ext2 can. */
443 result = sys_ftruncate(fd, len);
447 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
448 extend a file with ftruncate. Provide alternate implementation
450 currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
455 /* Do an fstat to see if the file is longer than the requested
456 size in which case the ftruncate above should have
457 succeeded or shorter, in which case seek to len - 1 and
458 write 1 byte of zero */
459 if (vfs_ops->fstat(fsp, fd, &st) == -1) {
464 if (S_ISFIFO(st.st_mode)) {
470 if (st.st_size == len) {
475 if (st.st_size > len) {
476 /* the sys_ftruncate should have worked */
480 if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1)
483 if (vfs_ops->write(fsp, fd, &c, 1)!=1)
486 /* Seek to where we were */
487 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
493 END_PROFILE(syscall_ftruncate);
497 BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
501 START_PROFILE(syscall_fcntl_lock);
503 result = fcntl_lock(fd, op, offset, count,type);
504 END_PROFILE(syscall_fcntl_lock);
508 int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath)
512 START_PROFILE(syscall_symlink);
513 result = sys_symlink(oldpath, newpath);
514 END_PROFILE(syscall_symlink);
518 int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz)
522 START_PROFILE(syscall_readlink);
523 result = sys_readlink(path, buf, bufsiz);
524 END_PROFILE(syscall_readlink);
528 int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath)
532 START_PROFILE(syscall_link);
533 result = sys_link(oldpath, newpath);
534 END_PROFILE(syscall_link);
538 int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
542 START_PROFILE(syscall_mknod);
543 result = sys_mknod(pathname, mode, dev);
544 END_PROFILE(syscall_mknod);
548 char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved_path)
552 START_PROFILE(syscall_realpath);
553 result = sys_realpath(path, resolved_path);
554 END_PROFILE(syscall_realpath);
558 size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc)
562 START_PROFILE(fget_nt_acl);
563 result = get_nt_acl(fsp, ppdesc);
564 END_PROFILE(fget_nt_acl);
568 size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc)
572 START_PROFILE(get_nt_acl);
573 result = get_nt_acl(fsp, ppdesc);
574 END_PROFILE(get_nt_acl);
578 BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
582 START_PROFILE(fset_nt_acl);
583 result = set_nt_acl(fsp, security_info_sent, psd);
584 END_PROFILE(fset_nt_acl);
588 BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
592 START_PROFILE(set_nt_acl);
593 result = set_nt_acl(fsp, security_info_sent, psd);
594 END_PROFILE(set_nt_acl);
598 int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode)
602 START_PROFILE(chmod_acl);
603 result = chmod_acl(conn, name, mode);
604 END_PROFILE(chmod_acl);
608 int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode)
612 START_PROFILE(fchmod_acl);
613 result = fchmod_acl(fsp, fd, mode);
614 END_PROFILE(fchmod_acl);
618 int vfswrap_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
620 return sys_acl_get_entry(theacl, entry_id, entry_p);
623 int vfswrap_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
625 return sys_acl_get_tag_type(entry_d, tag_type_p);
628 int vfswrap_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
630 return sys_acl_get_permset(entry_d, permset_p);
633 void * vfswrap_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d)
635 return sys_acl_get_qualifier(entry_d);
638 SMB_ACL_T vfswrap_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type)
640 return sys_acl_get_file(path_p, type);
643 SMB_ACL_T vfswrap_sys_acl_get_fd(struct files_struct *fsp, int fd)
645 return sys_acl_get_fd(fd);
648 int vfswrap_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset)
650 return sys_acl_clear_perms(permset);
653 int vfswrap_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
655 return sys_acl_add_perm(permset, perm);
658 char * vfswrap_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen)
660 return sys_acl_to_text(theacl, plen);
663 SMB_ACL_T vfswrap_sys_acl_init(struct connection_struct *conn, int count)
665 return sys_acl_init(count);
668 int vfswrap_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
670 return sys_acl_create_entry(pacl, pentry);
673 int vfswrap_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
675 return sys_acl_set_tag_type(entry, tagtype);
678 int vfswrap_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual)
680 return sys_acl_set_qualifier(entry, qual);
683 int vfswrap_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
685 return sys_acl_set_permset(entry, permset);
688 int vfswrap_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl )
690 return sys_acl_valid(theacl );
693 int vfswrap_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
695 return sys_acl_set_file(name, acltype, theacl);
698 int vfswrap_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl)
700 return sys_acl_set_fd(fd, theacl);
703 int vfswrap_sys_acl_delete_def_file(struct connection_struct *conn, const char *path)
705 return sys_acl_delete_def_file(path);
708 int vfswrap_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
710 return sys_acl_get_perm(permset, perm);
713 int vfswrap_sys_acl_free_text(struct connection_struct *conn, char *text)
715 return sys_acl_free_text(text);
718 int vfswrap_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl)
720 return sys_acl_free_acl(posix_acl);
723 int vfswrap_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype)
725 return sys_acl_free_qualifier(qualifier, tagtype);