diff options
Diffstat (limited to 'source/smbd/vfs-wrap.c')
-rw-r--r-- | source/smbd/vfs-wrap.c | 147 |
1 files changed, 111 insertions, 36 deletions
diff --git a/source/smbd/vfs-wrap.c b/source/smbd/vfs-wrap.c index bae304096ce..2d7cf05bf9b 100644 --- a/source/smbd/vfs-wrap.c +++ b/source/smbd/vfs-wrap.c @@ -1,5 +1,6 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/Netbios implementation. + Version 1.9. Wrap disk only vfs functions to sidestep dodgy compilers. Copyright (C) Tim Potter 1998 @@ -20,12 +21,6 @@ #include "includes.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_VFS - - -/* Check for NULL pointer parameters in vfswrap_* functions */ - /* We don't want to have NULL function pointers lying around. Someone is sure to try and execute them. These stubs are used to prevent this possibility. */ @@ -57,6 +52,7 @@ DIR *vfswrap_opendir(connection_struct *conn, const char *fname) DIR *result; START_PROFILE(syscall_opendir); + result = opendir(fname); END_PROFILE(syscall_opendir); return result; @@ -67,6 +63,7 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) struct dirent *result; START_PROFILE(syscall_readdir); + result = readdir(dirp); END_PROFILE(syscall_readdir); return result; @@ -99,8 +96,8 @@ int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) } } - END_PROFILE(syscall_mkdir); - return result; + END_PROFILE(syscall_mkdir); + return result; } int vfswrap_rmdir(connection_struct *conn, const char *path) @@ -108,6 +105,7 @@ int vfswrap_rmdir(connection_struct *conn, const char *path) int result; START_PROFILE(syscall_rmdir); + result = rmdir(path); END_PROFILE(syscall_rmdir); return result; @@ -118,6 +116,7 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) int result; START_PROFILE(syscall_closedir); + result = closedir(dirp); END_PROFILE(syscall_closedir); return result; @@ -127,12 +126,13 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode) { - int result; + int result; - START_PROFILE(syscall_open); - result = sys_open(fname, flags, mode); - END_PROFILE(syscall_open); - return result; + START_PROFILE(syscall_open); + + result = sys_open(fname, flags, mode); + END_PROFILE(syscall_open); + return result; } int vfswrap_close(files_struct *fsp, int fd) @@ -151,6 +151,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) ssize_t result; START_PROFILE_BYTES(syscall_read, n); + result = sys_read(fd, data, n); END_PROFILE(syscall_read); return result; @@ -161,6 +162,7 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) ssize_t result; START_PROFILE_BYTES(syscall_write, n); + result = sys_write(fd, data, n); END_PROFILE(syscall_write); return result; @@ -192,25 +194,97 @@ SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int wh return result; } -ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const DATA_BLOB *hdr, - SMB_OFF_T offset, size_t n) +/********************************************************* + For rename across filesystems Patch from Warren Birnbaum + <warrenb@hpcvscdp.cv.hp.com> +**********************************************************/ + +static int copy_reg(const char *source, const char *dest) { - ssize_t result; + SMB_STRUCT_STAT source_stats; + int ifd; + int ofd; - START_PROFILE_BYTES(syscall_sendfile, n); - result = sys_sendfile(tofd, fromfd, hdr, offset, n); - END_PROFILE(syscall_sendfile); - return result; + if (sys_lstat (source, &source_stats) == -1) + return -1; + + if (!S_ISREG (source_stats.st_mode)) + return -1; + + if (unlink (dest) && errno != ENOENT) + return -1; + + if((ifd = sys_open (source, O_RDONLY, 0)) < 0) + return -1; + + if((ofd = sys_open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 ) { + int saved_errno = errno; + close (ifd); + errno = saved_errno; + return -1; + } + + if (transfer_file(ifd, ofd, (size_t)-1) == -1) { + int saved_errno = errno; + close (ifd); + close (ofd); + unlink (dest); + errno = saved_errno; + return -1; + } + + if (close (ifd) == -1) { + int saved_errno = errno; + close (ofd); + errno = saved_errno; + return -1; + } + if (close (ofd) == -1) + return -1; + + /* + * chown turns off set[ug]id bits for non-root, + * so do the chmod last. + */ + + /* Try to copy the old file's modtime and access time. */ + { + struct utimbuf tv; + + tv.actime = source_stats.st_atime; + tv.modtime = source_stats.st_mtime; + utime (dest, &tv); + } + + /* + * Try to preserve ownership. For non-root it might fail, but that's ok. + * But root probably wants to know, e.g. if NFS disallows it. + */ + + if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM)) + return -1; + + if (chmod (dest, source_stats.st_mode & 07777)) + return -1; + + if (unlink (source) == -1) + return -1; + + return 0; } -int vfswrap_rename(connection_struct *conn, const char *old, const char *new) +int vfswrap_rename(connection_struct *conn, const char *oldname, const char *newname) { - int result; + int result; - START_PROFILE(syscall_rename); - result = rename(old, new); - END_PROFILE(syscall_rename); - return result; + START_PROFILE(syscall_rename); + result = rename(oldname, newname); + if (errno == EXDEV) { + /* Rename across filesystems needed. */ + result = copy_reg(oldname, newname); + } + END_PROFILE(syscall_rename); + return result; } int vfswrap_fsync(files_struct *fsp, int fd) @@ -219,7 +293,6 @@ int vfswrap_fsync(files_struct *fsp, int fd) int result; START_PROFILE(syscall_fsync); - result = fsync(fd); END_PROFILE(syscall_fsync); return result; @@ -298,10 +371,10 @@ int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) { - int result; + int result; struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; - START_PROFILE(syscall_fchmod); + START_PROFILE(syscall_fchmod); /* * We need to do this due to the fact that the default POSIX ACL @@ -319,9 +392,9 @@ int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) errno = saved_errno; } - result = fchmod(fd, mode); - END_PROFILE(syscall_fchmod); - return result; + result = fchmod(fd, mode); + END_PROFILE(syscall_fchmod); + return result; } int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid) @@ -336,6 +409,7 @@ int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gi int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) { +#ifdef HAVE_FCHOWN int result; START_PROFILE(syscall_fchown); @@ -343,6 +417,10 @@ int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) result = fchown(fd, uid, gid); END_PROFILE(syscall_fchown); return result; +#else + errno = ENOSYS; + return -1; +#endif } int vfswrap_chdir(connection_struct *conn, const char *path) @@ -394,8 +472,6 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) if (vfs_ops->fstat(fsp, fd, &st) == -1) return -1; - space_to_write = len - st.st_size; - #ifdef S_ISFIFO if (S_ISFIFO(st.st_mode)) return 0; @@ -514,7 +590,6 @@ BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T BOOL result; START_PROFILE(syscall_fcntl_lock); - result = fcntl_lock(fd, op, offset, count,type); END_PROFILE(syscall_fcntl_lock); return result; |