2 Unix SMB/Netbios implementation.
4 Wrap disk only vfs functions to sidestep dodgy compilers.
5 Copyright (C) Tim Potter 1998
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* Check for NULL pointer parameters in vfswrap_* functions */
26 #define VFS_CHECK_NULL
28 /* We don't want to have NULL function pointers lying around. Someone
29 is sure to try and execute them. These stubs are used to prevent
32 int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user)
34 return 0; /* Return >= 0 for success */
37 void vfswrap_dummy_disconnect(connection_struct *conn)
43 SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
44 SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
49 if ((path == NULL) || (bsize == NULL) || (dfree == NULL) ||
52 smb_panic("NULL pointer passed to vfswrap_disk_free() function\n");
56 result = sys_disk_free(path, small_query, bsize, dfree, dsize);
60 /* Directory operations */
62 DIR *vfswrap_opendir(connection_struct *conn, const char *fname)
66 START_PROFILE(syscall_opendir);
70 smb_panic("NULL pointer passed to vfswrap_opendir()\n");
74 result = opendir(fname);
75 END_PROFILE(syscall_opendir);
79 struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp)
81 struct dirent *result;
83 START_PROFILE(syscall_readdir);
87 smb_panic("NULL pointer passed to vfswrap_readdir()\n");
91 result = readdir(dirp);
92 END_PROFILE(syscall_readdir);
96 int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode)
100 START_PROFILE(syscall_mkdir);
102 #ifdef VFS_CHECK_NULL
104 smb_panic("NULL pointer passed to vfswrap_mkdir()\n");
108 result = mkdir(path, mode);
112 * We need to do this as the default behavior of POSIX ACLs
113 * is to set the mask to be the requested group permission
114 * bits, not the group permission bits to be the requested
115 * group permission bits. This is not what we want, as it will
116 * mess up any inherited ACL bits that were set. JRA.
118 int saved_errno = errno; /* We may get ENOSYS */
119 if (conn->vfs_ops.chmod_acl != NULL) {
120 if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS))
125 END_PROFILE(syscall_mkdir);
129 int vfswrap_rmdir(connection_struct *conn, const char *path)
133 START_PROFILE(syscall_rmdir);
135 #ifdef VFS_CHECK_NULL
137 smb_panic("NULL pointer passed to vfswrap_rmdir()\n");
141 result = rmdir(path);
142 END_PROFILE(syscall_rmdir);
146 int vfswrap_closedir(connection_struct *conn, DIR *dirp)
150 START_PROFILE(syscall_closedir);
152 #ifdef VFS_CHECK_NULL
154 smb_panic("NULL pointer passed to vfswrap_closedir()\n");
158 result = closedir(dirp);
159 END_PROFILE(syscall_closedir);
163 /* File operations */
165 int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode)
169 START_PROFILE(syscall_open);
171 #ifdef VFS_CHECK_NULL
173 smb_panic("NULL pointer passed to vfswrap_open()\n");
177 result = sys_open(fname, flags, mode);
178 END_PROFILE(syscall_open);
182 int vfswrap_close(files_struct *fsp, int fd)
186 START_PROFILE(syscall_close);
189 END_PROFILE(syscall_close);
193 ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n)
197 START_PROFILE_BYTES(syscall_read, n);
199 #ifdef VFS_CHECK_NULL
201 smb_panic("NULL pointer passed to vfswrap_read()\n");
205 result = read(fd, data, n);
206 END_PROFILE(syscall_read);
210 ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
214 START_PROFILE_BYTES(syscall_write, n);
216 #ifdef VFS_CHECK_NULL
218 smb_panic("NULL pointer passed to vfswrap_write()\n");
222 result = write(fd, data, n);
223 END_PROFILE(syscall_write);
227 SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
231 START_PROFILE(syscall_lseek);
233 result = sys_lseek(filedes, offset, whence);
234 END_PROFILE(syscall_lseek);
238 int vfswrap_rename(connection_struct *conn, const char *old, const char *new)
242 START_PROFILE(syscall_rename);
244 #ifdef VFS_CHECK_NULL
245 if ((old == NULL) || (new == NULL)) {
246 smb_panic("NULL pointer passed to vfswrap_rename()\n");
250 result = rename(old, new);
251 END_PROFILE(syscall_rename);
255 int vfswrap_fsync(files_struct *fsp, int fd)
260 START_PROFILE(syscall_fsync);
263 END_PROFILE(syscall_fsync);
270 int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
274 START_PROFILE(syscall_stat);
276 #ifdef VFS_CHECK_NULL
277 if ((fname == NULL) || (sbuf == NULL)) {
278 smb_panic("NULL pointer passed to vfswrap_stat()\n");
282 result = sys_stat(fname, sbuf);
283 END_PROFILE(syscall_stat);
287 int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
291 START_PROFILE(syscall_fstat);
293 #ifdef VFS_CHECK_NULL
295 smb_panic("NULL pointer passed to vfswrap_fstat()\n");
299 result = sys_fstat(fd, sbuf);
300 END_PROFILE(syscall_fstat);
304 int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
308 START_PROFILE(syscall_lstat);
310 #ifdef VFS_CHECK_NULL
311 if ((path == NULL) || (sbuf == NULL)) {
312 smb_panic("NULL pointer passed to vfswrap_lstat()\n");
316 result = sys_lstat(path, sbuf);
317 END_PROFILE(syscall_lstat);
321 int vfswrap_unlink(connection_struct *conn, const char *path)
325 START_PROFILE(syscall_unlink);
327 #ifdef VFS_CHECK_NULL
329 smb_panic("NULL pointer passed to vfswrap_unlink()\n");
333 result = unlink(path);
334 END_PROFILE(syscall_unlink);
338 int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode)
342 START_PROFILE(syscall_chmod);
344 #ifdef VFS_CHECK_NULL
346 smb_panic("NULL pointer passed to vfswrap_chmod()\n");
351 * We need to do this due to the fact that the default POSIX ACL
352 * chmod modifies the ACL *mask* for the group owner, not the
353 * group owner bits directly. JRA.
357 if (conn->vfs_ops.chmod_acl != NULL) {
358 int saved_errno = errno; /* We might get ENOSYS */
359 if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) {
360 END_PROFILE(syscall_chmod);
363 /* Error - return the old errno. */
367 result = chmod(path, mode);
368 END_PROFILE(syscall_chmod);
372 int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode)
375 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
377 START_PROFILE(syscall_fchmod);
380 * We need to do this due to the fact that the default POSIX ACL
381 * chmod modifies the ACL *mask* for the group owner, not the
382 * group owner bits directly. JRA.
385 if (vfs_ops->fchmod_acl != NULL) {
386 int saved_errno = errno; /* We might get ENOSYS */
387 if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) {
388 END_PROFILE(syscall_chmod);
391 /* Error - return the old errno. */
395 result = fchmod(fd, mode);
396 END_PROFILE(syscall_fchmod);
400 int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid)
404 START_PROFILE(syscall_chown);
406 #ifdef VFS_CHECK_NULL
408 smb_panic("NULL pointer passed to vfswrap_chown()\n");
412 result = sys_chown(path, uid, gid);
413 END_PROFILE(syscall_chown);
417 int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid)
421 START_PROFILE(syscall_fchown);
423 result = fchown(fd, uid, gid);
424 END_PROFILE(syscall_fchown);
428 int vfswrap_chdir(connection_struct *conn, const char *path)
432 START_PROFILE(syscall_chdir);
434 #ifdef VFS_CHECK_NULL
436 smb_panic("NULL pointer passed to vfswrap_chdir()\n");
440 result = chdir(path);
441 END_PROFILE(syscall_chdir);
445 char *vfswrap_getwd(connection_struct *conn, char *path)
449 START_PROFILE(syscall_getwd);
451 #ifdef VFS_CHECK_NULL
453 smb_panic("NULL pointer passed to vfswrap_getwd()\n");
457 result = sys_getwd(path);
458 END_PROFILE(syscall_getwd);
462 int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times)
466 START_PROFILE(syscall_utime);
468 #ifdef VFS_CHECK_NULL
469 if ((path == NULL) || (times == NULL)) {
470 smb_panic("NULL pointer passed to vfswrap_utime()\n");
474 result = utime(path, times);
475 END_PROFILE(syscall_utime);
479 /*********************************************************************
480 A version of ftruncate that will write the space on disk if strict
482 **********************************************************************/
484 static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
486 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
488 SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
489 unsigned char zero_space[4096];
490 SMB_OFF_T space_to_write = len - st.st_size;
495 if (vfs_ops->fstat(fsp, fd, &st) == -1)
499 if (S_ISFIFO(st.st_mode))
503 if (st.st_size == len)
506 /* Shrink - just ftruncate. */
507 if (st.st_size > len)
508 return sys_ftruncate(fd, len);
510 /* Write out the real space on disk. */
511 if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
514 space_to_write = len - st.st_size;
516 memset(zero_space, '\0', sizeof(zero_space));
517 while ( space_to_write > 0) {
519 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
521 retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
525 space_to_write -= retlen;
528 /* Seek to where we were */
529 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
535 int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
538 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
543 START_PROFILE(syscall_ftruncate);
545 if (lp_strict_allocate(SNUM(fsp->conn))) {
546 result = strict_allocate_ftruncate(fsp, fd, len);
547 END_PROFILE(syscall_ftruncate);
551 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
552 sys_ftruncate if the system supports it. Then I discovered that
553 you can have some filesystems that support ftruncate
554 expansion and some that don't! On Linux fat can't do
555 ftruncate extend but ext2 can. */
557 result = sys_ftruncate(fd, len);
561 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
562 extend a file with ftruncate. Provide alternate implementation
564 currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
569 /* Do an fstat to see if the file is longer than the requested
570 size in which case the ftruncate above should have
571 succeeded or shorter, in which case seek to len - 1 and
572 write 1 byte of zero */
573 if (vfs_ops->fstat(fsp, fd, &st) == -1) {
578 if (S_ISFIFO(st.st_mode)) {
584 if (st.st_size == len) {
589 if (st.st_size > len) {
590 /* the sys_ftruncate should have worked */
594 if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1)
597 if (vfs_ops->write(fsp, fd, &c, 1)!=1)
600 /* Seek to where we were */
601 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
607 END_PROFILE(syscall_ftruncate);
611 BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
615 START_PROFILE(syscall_fcntl_lock);
617 result = fcntl_lock(fd, op, offset, count,type);
618 END_PROFILE(syscall_fcntl_lock);
622 int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath)
626 START_PROFILE(syscall_symlink);
628 #ifdef VFS_CHECK_NULL
629 if ((oldpath == NULL) || (newpath == NULL))
630 smb_panic("NULL pointer passed to vfswrap_symlink()\n");
633 result = sys_symlink(oldpath, newpath);
634 END_PROFILE(syscall_symlink);
638 int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz)
642 START_PROFILE(syscall_readlink);
644 #ifdef VFS_CHECK_NULL
645 if ((path == NULL) || (buf == NULL))
646 smb_panic("NULL pointer passed to vfswrap_readlink()\n");
649 result = sys_readlink(path, buf, bufsiz);
650 END_PROFILE(syscall_readlink);
654 int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath)
658 START_PROFILE(syscall_link);
660 #ifdef VFS_CHECK_NULL
661 if ((oldpath == NULL) || (newpath == NULL))
662 smb_panic("NULL pointer passed to vfswrap_link()\n");
664 result = sys_link(oldpath, newpath);
665 END_PROFILE(syscall_link);
669 int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
673 START_PROFILE(syscall_mknod);
675 #ifdef VFS_CHECK_NULL
676 if (pathname == NULL)
677 smb_panic("NULL pointer passed to vfswrap_mknod()\n");
679 result = sys_mknod(pathname, mode, dev);
680 END_PROFILE(syscall_mknod);
684 size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc)
688 START_PROFILE(fget_nt_acl);
689 result = get_nt_acl(fsp, ppdesc);
690 END_PROFILE(fget_nt_acl);
694 size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc)
698 START_PROFILE(get_nt_acl);
699 result = get_nt_acl(fsp, ppdesc);
700 END_PROFILE(get_nt_acl);
704 BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
708 START_PROFILE(fset_nt_acl);
709 result = set_nt_acl(fsp, security_info_sent, psd);
710 END_PROFILE(fset_nt_acl);
714 BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
718 START_PROFILE(set_nt_acl);
719 result = set_nt_acl(fsp, security_info_sent, psd);
720 END_PROFILE(set_nt_acl);
724 int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode)
728 START_PROFILE(chmod_acl);
729 result = chmod_acl(name, mode);
730 END_PROFILE(chmod_acl);
734 int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode)
738 START_PROFILE(fchmod_acl);
739 result = fchmod_acl(fd, mode);
740 END_PROFILE(fchmod_acl);