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 #define VFS_CHECK_NULL
27 /* We don't want to have NULL function pointers lying around. Someone
28 is sure to try and execute them. These stubs are used to prevent
31 int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user)
33 return 0; /* Return >= 0 for success */
36 void vfswrap_dummy_disconnect(connection_struct *conn)
42 SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize,
43 SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
48 if ((path == NULL) || (bsize == NULL) || (dfree == NULL) ||
51 smb_panic("NULL pointer passed to vfswrap_disk_free() function\n");
55 result = sys_disk_free(path, small_query, bsize, dfree, dsize);
59 /* Directory operations */
61 DIR *vfswrap_opendir(connection_struct *conn, const char *fname)
65 START_PROFILE(syscall_opendir);
69 smb_panic("NULL pointer passed to vfswrap_opendir()\n");
73 result = opendir(fname);
74 END_PROFILE(syscall_opendir);
78 struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp)
80 struct dirent *result;
82 START_PROFILE(syscall_readdir);
86 smb_panic("NULL pointer passed to vfswrap_readdir()\n");
90 result = readdir(dirp);
91 END_PROFILE(syscall_readdir);
95 int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode)
99 START_PROFILE(syscall_mkdir);
101 #ifdef VFS_CHECK_NULL
103 smb_panic("NULL pointer passed to vfswrap_mkdir()\n");
107 result = mkdir(path, mode);
111 * We need to do this as the default behavior of POSIX ACLs
112 * is to set the mask to be the requested group permission
113 * bits, not the group permission bits to be the requested
114 * group permission bits. This is not what we want, as it will
115 * mess up any inherited ACL bits that were set. JRA.
117 int saved_errno = errno; /* We may get ENOSYS */
118 if (conn->vfs_ops.chmod_acl != NULL) {
119 if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS))
124 END_PROFILE(syscall_mkdir);
128 int vfswrap_rmdir(connection_struct *conn, const char *path)
132 START_PROFILE(syscall_rmdir);
134 #ifdef VFS_CHECK_NULL
136 smb_panic("NULL pointer passed to vfswrap_rmdir()\n");
140 result = rmdir(path);
141 END_PROFILE(syscall_rmdir);
145 int vfswrap_closedir(connection_struct *conn, DIR *dirp)
149 START_PROFILE(syscall_closedir);
151 #ifdef VFS_CHECK_NULL
153 smb_panic("NULL pointer passed to vfswrap_closedir()\n");
157 result = closedir(dirp);
158 END_PROFILE(syscall_closedir);
162 /* File operations */
164 int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode)
168 START_PROFILE(syscall_open);
170 #ifdef VFS_CHECK_NULL
172 smb_panic("NULL pointer passed to vfswrap_open()\n");
176 result = sys_open(fname, flags, mode);
177 END_PROFILE(syscall_open);
181 int vfswrap_close(files_struct *fsp, int fd)
185 START_PROFILE(syscall_close);
188 END_PROFILE(syscall_close);
192 ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n)
196 START_PROFILE_BYTES(syscall_read, n);
198 #ifdef VFS_CHECK_NULL
200 smb_panic("NULL pointer passed to vfswrap_read()\n");
204 result = read(fd, data, n);
205 END_PROFILE(syscall_read);
209 ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n)
213 START_PROFILE_BYTES(syscall_write, n);
215 #ifdef VFS_CHECK_NULL
217 smb_panic("NULL pointer passed to vfswrap_write()\n");
221 result = write(fd, data, n);
222 END_PROFILE(syscall_write);
226 SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence)
230 START_PROFILE(syscall_lseek);
232 result = sys_lseek(filedes, offset, whence);
233 END_PROFILE(syscall_lseek);
237 int vfswrap_rename(connection_struct *conn, const char *old, const char *new)
241 START_PROFILE(syscall_rename);
243 #ifdef VFS_CHECK_NULL
244 if ((old == NULL) || (new == NULL)) {
245 smb_panic("NULL pointer passed to vfswrap_rename()\n");
249 result = rename(old, new);
250 END_PROFILE(syscall_rename);
254 int vfswrap_fsync(files_struct *fsp, int fd)
259 START_PROFILE(syscall_fsync);
262 END_PROFILE(syscall_fsync);
269 int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf)
273 START_PROFILE(syscall_stat);
275 #ifdef VFS_CHECK_NULL
276 if ((fname == NULL) || (sbuf == NULL)) {
277 smb_panic("NULL pointer passed to vfswrap_stat()\n");
281 result = sys_stat(fname, sbuf);
282 END_PROFILE(syscall_stat);
286 int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf)
290 START_PROFILE(syscall_fstat);
292 #ifdef VFS_CHECK_NULL
294 smb_panic("NULL pointer passed to vfswrap_fstat()\n");
298 result = sys_fstat(fd, sbuf);
299 END_PROFILE(syscall_fstat);
303 int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
307 START_PROFILE(syscall_lstat);
309 #ifdef VFS_CHECK_NULL
310 if ((path == NULL) || (sbuf == NULL)) {
311 smb_panic("NULL pointer passed to vfswrap_lstat()\n");
315 result = sys_lstat(path, sbuf);
316 END_PROFILE(syscall_lstat);
320 int vfswrap_unlink(connection_struct *conn, const char *path)
324 START_PROFILE(syscall_unlink);
326 #ifdef VFS_CHECK_NULL
328 smb_panic("NULL pointer passed to vfswrap_unlink()\n");
332 result = unlink(path);
333 END_PROFILE(syscall_unlink);
337 int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode)
341 START_PROFILE(syscall_chmod);
343 #ifdef VFS_CHECK_NULL
345 smb_panic("NULL pointer passed to vfswrap_chmod()\n");
350 * We need to do this due to the fact that the default POSIX ACL
351 * chmod modifies the ACL *mask* for the group owner, not the
352 * group owner bits directly. JRA.
356 if (conn->vfs_ops.chmod_acl != NULL) {
357 int saved_errno = errno; /* We might get ENOSYS */
358 if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) {
359 END_PROFILE(syscall_chmod);
362 /* Error - return the old errno. */
366 result = chmod(path, mode);
367 END_PROFILE(syscall_chmod);
371 int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode)
374 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
376 START_PROFILE(syscall_fchmod);
379 * We need to do this due to the fact that the default POSIX ACL
380 * chmod modifies the ACL *mask* for the group owner, not the
381 * group owner bits directly. JRA.
384 if (vfs_ops->fchmod_acl != NULL) {
385 int saved_errno = errno; /* We might get ENOSYS */
386 if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) {
387 END_PROFILE(syscall_chmod);
390 /* Error - return the old errno. */
394 result = fchmod(fd, mode);
395 END_PROFILE(syscall_fchmod);
399 int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid)
403 START_PROFILE(syscall_chown);
405 #ifdef VFS_CHECK_NULL
407 smb_panic("NULL pointer passed to vfswrap_chown()\n");
411 result = sys_chown(path, uid, gid);
412 END_PROFILE(syscall_chown);
416 int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid)
420 START_PROFILE(syscall_fchown);
422 result = fchown(fd, uid, gid);
423 END_PROFILE(syscall_fchown);
427 int vfswrap_chdir(connection_struct *conn, const char *path)
431 START_PROFILE(syscall_chdir);
433 #ifdef VFS_CHECK_NULL
435 smb_panic("NULL pointer passed to vfswrap_chdir()\n");
439 result = chdir(path);
440 END_PROFILE(syscall_chdir);
444 char *vfswrap_getwd(connection_struct *conn, char *path)
448 START_PROFILE(syscall_getwd);
450 #ifdef VFS_CHECK_NULL
452 smb_panic("NULL pointer passed to vfswrap_getwd()\n");
456 result = sys_getwd(path);
457 END_PROFILE(syscall_getwd);
461 int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times)
465 START_PROFILE(syscall_utime);
467 #ifdef VFS_CHECK_NULL
468 if ((path == NULL) || (times == NULL)) {
469 smb_panic("NULL pointer passed to vfswrap_utime()\n");
473 result = utime(path, times);
474 END_PROFILE(syscall_utime);
478 /*********************************************************************
479 A version of ftruncate that will write the space on disk if strict
481 **********************************************************************/
483 static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
485 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
487 SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
488 unsigned char zero_space[4096];
489 SMB_OFF_T space_to_write;
494 if (vfs_ops->fstat(fsp, fd, &st) == -1)
497 space_to_write = len - st.st_size;
500 if (S_ISFIFO(st.st_mode))
504 if (st.st_size == len)
507 /* Shrink - just ftruncate. */
508 if (st.st_size > len)
509 return sys_ftruncate(fd, len);
511 /* Write out the real space on disk. */
512 if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size)
515 space_to_write = len - st.st_size;
517 memset(zero_space, '\0', sizeof(zero_space));
518 while ( space_to_write > 0) {
520 SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write);
522 retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write);
526 space_to_write -= retlen;
529 /* Seek to where we were */
530 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
536 int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
539 struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
544 START_PROFILE(syscall_ftruncate);
546 if (lp_strict_allocate(SNUM(fsp->conn))) {
547 result = strict_allocate_ftruncate(fsp, fd, len);
548 END_PROFILE(syscall_ftruncate);
552 /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
553 sys_ftruncate if the system supports it. Then I discovered that
554 you can have some filesystems that support ftruncate
555 expansion and some that don't! On Linux fat can't do
556 ftruncate extend but ext2 can. */
558 result = sys_ftruncate(fd, len);
562 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
563 extend a file with ftruncate. Provide alternate implementation
565 currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
570 /* Do an fstat to see if the file is longer than the requested
571 size in which case the ftruncate above should have
572 succeeded or shorter, in which case seek to len - 1 and
573 write 1 byte of zero */
574 if (vfs_ops->fstat(fsp, fd, &st) == -1) {
579 if (S_ISFIFO(st.st_mode)) {
585 if (st.st_size == len) {
590 if (st.st_size > len) {
591 /* the sys_ftruncate should have worked */
595 if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1)
598 if (vfs_ops->write(fsp, fd, &c, 1)!=1)
601 /* Seek to where we were */
602 if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos)
608 END_PROFILE(syscall_ftruncate);
612 BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
616 START_PROFILE(syscall_fcntl_lock);
618 result = fcntl_lock(fd, op, offset, count,type);
619 END_PROFILE(syscall_fcntl_lock);
623 int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath)
627 START_PROFILE(syscall_symlink);
629 #ifdef VFS_CHECK_NULL
630 if ((oldpath == NULL) || (newpath == NULL))
631 smb_panic("NULL pointer passed to vfswrap_symlink()\n");
634 result = sys_symlink(oldpath, newpath);
635 END_PROFILE(syscall_symlink);
639 int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz)
643 START_PROFILE(syscall_readlink);
645 #ifdef VFS_CHECK_NULL
646 if ((path == NULL) || (buf == NULL))
647 smb_panic("NULL pointer passed to vfswrap_readlink()\n");
650 result = sys_readlink(path, buf, bufsiz);
651 END_PROFILE(syscall_readlink);
655 int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath)
659 START_PROFILE(syscall_link);
661 #ifdef VFS_CHECK_NULL
662 if ((oldpath == NULL) || (newpath == NULL))
663 smb_panic("NULL pointer passed to vfswrap_link()\n");
665 result = sys_link(oldpath, newpath);
666 END_PROFILE(syscall_link);
670 int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev)
674 START_PROFILE(syscall_mknod);
676 #ifdef VFS_CHECK_NULL
677 if (pathname == NULL)
678 smb_panic("NULL pointer passed to vfswrap_mknod()\n");
680 result = sys_mknod(pathname, mode, dev);
681 END_PROFILE(syscall_mknod);
685 size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc)
689 START_PROFILE(fget_nt_acl);
690 result = get_nt_acl(fsp, ppdesc);
691 END_PROFILE(fget_nt_acl);
695 size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc)
699 START_PROFILE(get_nt_acl);
700 result = get_nt_acl(fsp, ppdesc);
701 END_PROFILE(get_nt_acl);
705 BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
709 START_PROFILE(fset_nt_acl);
710 result = set_nt_acl(fsp, security_info_sent, psd);
711 END_PROFILE(fset_nt_acl);
715 BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
719 START_PROFILE(set_nt_acl);
720 result = set_nt_acl(fsp, security_info_sent, psd);
721 END_PROFILE(set_nt_acl);
725 int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode)
729 START_PROFILE(chmod_acl);
730 result = chmod_acl(name, mode);
731 END_PROFILE(chmod_acl);
735 int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode)
739 START_PROFILE(fchmod_acl);
740 result = fchmod_acl(fd, mode);
741 END_PROFILE(fchmod_acl);