2.2.5pre1: rename design flaw?
jd at epcnet.de
jd at epcnet.de
Wed Jun 12 15:02:03 GMT 2002
Hi,
after looking in vfs-wrap.c i saw in function vfswrap_rename the following:
result = rename(oldname, newname);
if (errno == EXDEV) {
/* Rename across filesystems needed. */
result = copy_reg(oldname, newname);
}
There is no rename across filesystems for directorys. rename fails with EXDEV.
Is this ok? I think no and I added a function copy_dir which moves a complete dirtree
from one device to another.
I added the diff of vfs-wrap.c to this email.
Greetings
Jochen Dolze
--- vfs-wrap.c.orig Tue Jun 4 04:11:27 2002
+++ vfs-wrap.c Wed Jun 12 22:45:04 2002
@@ -1,4 +1,4 @@
-/*
+/*
Unix SMB/Netbios implementation.
Version 1.9.
Wrap disk only vfs functions to sidestep dodgy compilers.
@@ -83,7 +83,7 @@
if (result == 0 && !has_dacl) {
/*
- * We need to do this as the default behavior of POSIX ACLs
+ * We need to do this as the default behavior of POSIX ACLs
* is to set the mask to be the requested group permission
* bits, not the group permission bits to be the requested
* group permission bits. This is not what we want, as it will
@@ -195,7 +195,7 @@
}
/*********************************************************
- For rename across filesystems Patch from Warren Birnbaum
+ For rename across filesystems Patch from Warren Birnbaum
<warrenb at hpcvscdp.cv.hp.com>
**********************************************************/
@@ -264,7 +264,12 @@
if ((chown(dest, source_stats.st_uid, source_stats.st_gid) == -1) && (errno != EPERM))
return -1;
- if (chmod (dest, source_stats.st_mode & 07777))
+ /*
+ * Try to preserve access permissions. Some filesystems (fat, smbfs)
+ * cannot set all and return EPERM.
+ */
+
+ if ((chmod (dest, source_stats.st_mode & 07777) == -1) && (errno != EPERM))
return -1;
if (unlink (source) == -1)
@@ -273,6 +278,110 @@
return 0;
}
+/*********************************************************
+ For directory renames across filesystems
+**********************************************************/
+
+static int copy_dir(const char *source, const char *dest) {
+
+ DIR *dir;
+ struct dirent *dirent;
+ SMB_STRUCT_STAT source_stats, src_state;
+ char *src, *dst;
+ int slen, dlen;
+ int s_errno;
+
+ if (sys_lstat (source, &source_stats) == -1)
+ return -1;
+
+ if (S_ISREG (source_stats.st_mode))
+ return copy_reg(source, dest);
+
+ if (!S_ISDIR(source_stats.st_mode))
+ return -1;
+
+ if (mkdir(dest, source_stats.st_mode & 07777) == -1)
+ return -1;
+
+ dir = opendir(source);
+ if (!dir)
+ return -1;
+
+ while (dirent = readdir(dir)) {
+
+ if (dirent->d_name[0]=='.') continue;
+
+ slen = strlen(source)+strlen(dirent->d_name)+10;
+ src = malloc(slen);
+ if (!src) {
+ s_errno = errno;
+ closedir(dir);
+ errno = s_errno;
+ return -1;
+ }
+ dlen = strlen(dest)+strlen(dirent->d_name)+10;
+ dst = malloc(dlen);
+ if (!dst) {
+ s_errno = errno;
+ closedir(dir);
+ free(src);
+ errno = s_errno;
+ return -1;
+ }
+
+ snprintf(src,slen,"%s/%s", source, dirent->d_name);
+ snprintf(dst,dlen,"%s/%s", dest, dirent->d_name);
+
+ if (sys_lstat (src, &src_state) == -1) {
+ s_errno = errno;
+ closedir(dir);
+ free(src);
+ free(dst);
+ errno = s_errno;
+ return -1;
+ }
+
+ if (S_ISREG(src_state.st_mode)) {
+ if (copy_reg(src, dst) == -1) {
+ s_errno = errno;
+ closedir(dir);
+ free(src);
+ free(dst);
+ errno = s_errno;
+ return -1;
+ }
+ } else
+ if (S_ISDIR(src_state.st_mode)) {
+ if (copy_dir(src, dst) == -1) {
+ s_errno = errno;
+ closedir(dir);
+ free(src);
+ free(dst);
+ errno = s_errno;
+ return -1;
+ }
+ } else {
+ free(src);
+ free(dst);
+ closedir(dir);
+ errno = EXDEV;
+ return -1;
+ }
+
+ free(src);
+ free(dst);
+ }
+
+ if (closedir(dir) == -1)
+ return -1;
+
+ if (rmdir(source) == -1)
+ return -1;
+
+ return 0;
+
+}
+
int vfswrap_rename(connection_struct *conn, const char *oldname, const char *newname)
{
int result;
@@ -281,7 +390,7 @@
result = rename(oldname, newname);
if (errno == EXDEV) {
/* Rename across filesystems needed. */
- result = copy_reg(oldname, newname);
+ result = copy_dir(oldname, newname);
}
END_PROFILE(syscall_rename);
return result;
---
EPCNet GmbH
ISP & Web Design
Bleichstrasse 24
89077 Ulm
Tel. +49 731 1416 0
Fax +49 731 1416 120
More information about the samba-technical
mailing list