Hello, I've been porting rsync-3.0.7 to run on UWIN, an AT&T Labs open source project, supporting a Unix environment on Windows. The code configured easily and compiled without any modifications or ifdef's added to the code. The backup test was failing because it didn't create a subdirectory. In tracing the code I realized the problem was in robust_move() in backup.c. UWIN returns ENOTDIR, when the rename(2) is called when a directory component is not in the new pathname. According to the Open Group website this is a valid errno value. The code in robust_move() only checked for ENOENT. When I added checking for ENOTDIR, the backup test passes. I suggest changing lines 192 and 264 of backup.c from if (errno == ENOENT && make_bak_dir(dst) == 0) { to if ((errno == ENOENT || errno == ENOTDIR) && make_bak_dir(dst) == 0) { to conform to the POSIX specification of rename(2) error returns. Thank you Jeff Fellin AT&T Labs 180 Park Ave Florham Park, NJ
On Thu, 2010-09-23 at 09:20 -0400, Jeff Fellin wrote:> I've been porting rsync-3.0.7 to run on UWIN, an AT&T Labs open source > project, supporting a Unix environment on Windows. The code configured > easily and compiled without any modifications or ifdef's added to the > code. > > The backup test was failing because it didn't create a subdirectory. > In tracing the code I realized the problem was in robust_move() in > backup.c. UWIN returns ENOTDIR, when the rename(2) is called when a > directory component is not in the new pathname. According to the Open > Group website this is a valid errno value.Ugh. The standard says: [ENOTDIR] A component of either path prefix is not a directory; ... http://www.opengroup.org/onlinepubs/9699919799/functions/rename.html I always interpreted this to mean, "is a file that is not a directory", and assumed that a nonexistent component would be reported as ENOENT. This behavior better separates the meanings of the error codes and corresponds to the most natural way to implement walking of a non-final path component in the OS: first call a generic function that looks up the dentry and returns ENOENT if it isn't there, and then check whether the inode is a directory and return ENOTDIR if it isn't. Linux does this, and rsync assumes it in many more places than the two you cited. It might be worth seeking official clarification. If your interpretation is correct, it becomes Wayne's decision whether working on all POSIX-compliant systems is important enough to merit adding extra code throughout rsync. -- Matt
On Thu, Sep 23, 2010 at 6:20 AM, Jeff Fellin <jkf at research.att.com> wrote:> The backup test was failing because it didn't create a subdirectory. In > tracing the code I realized the problem was in robust_move() in backup.c. > UWIN returns ENOTDIR, when the rename(2) is called when a directory > component is not in the new pathname.I believe that ENOTDIR should only be returned if some component in the path exists but is not a directory. If the path is not fully there, it should instead return ENOENT. For 3.0.x, I don't want to treat ENOTDIR as a valid return because it is indicating a path failure that the 3.0.x code cannot handle (since it doesn't try to fix conflicting backup paths). The 3.1.0 code (in git) validates the backup paths to ensure that any conflicting bits turn into dirs (e.g. it will avoid an accidental use of a symlink as a dir in the path), and I'd imagine that this code should work fine in your environment. ..wayne.. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.samba.org/pipermail/rsync/attachments/20100925/15ebca04/attachment.html>