Package: fdm Version: 1.5-3 Severity: important Tags: patch Dear maintainer,
link() fails with EXDEV when you try to link files accross file systems. On the AFS file system, this also occurs between directories : http://docs.openafs.org/AdminGuide/ch02.html#HDRWQ32 This special case breaks fdm when using maildirs on OpenAFS. I suggest a patch which workaround EXDEV by using stat() and rename(). I haven't run fdm's regressions tests on it. I have just checked it on AFS and ext3. A similar issue has been fixed in openssh (see #352589). The same bug certainly exists in other parts of fdm. Here is the code : --- fdm-1.5.orig/deliver-maildir.c 2008-03-06 10:25:32.000000000 +0100 +++ fdm-1.5-3.debian.louis/deliver-maildir.c 2009-07-23 21:28:34.418851829 +0200 @@ -146,6 +146,7 @@ char src[MAXPATHLEN], dst[MAXPATHLEN]; int fd; ssize_t n; + struct stat sb; name = NULL; fd = -1; @@ -195,28 +196,52 @@ fd = -1; /* - * Create the new path and attempt to link it. A failed link jumps - * back to find another name in the tmp directory. + * Create the new path and attempt to link it. A failed link on EEXIST + * jumps back to find another name in the tmp directory. */ if (ppath(dst, sizeof dst, "%s/new/%s", path, name) != 0) goto error_unlink; log_debug2( "%s: linking .../tmp/%s to .../new/%s", a->name, name, name); if (link(src, dst) != 0) { - if (errno == EEXIST) { - log_debug2("%s: %s: link failed", a->name, src); + log_debug2("%s: %s: link failed", a->name, src); + /* + * EXDEV must also be handled, especially for the AFS filesystem + * where hardlinks can't traverse directories : + * http://docs.openafs.org/AdminGuide/ch02.html#HDRWQ32 + */ + if (errno == EXDEV) { + log_debug2("%s: renaming .../tmp/%s to .../new/%s", + a->name, name, name); + /* + * But stat + rename can be racy. + */ + if (stat(dst, &sb) == -1) { + if (errno != ENOENT || rename(src, dst) != 0) { + log_debug2("%s: %s: rename failed", + a->name, src); + goto error_cleanup; + } + } else { /* EEXIST */ + if (unlink(src) != 0) + fatal("unlink failed"); + cleanup_deregister(src); + goto restart; + } + } else if (errno == EEXIST) { if (unlink(src) != 0) fatal("unlink failed"); cleanup_deregister(src); goto restart; - } - goto error_unlink; + } else /* Dot it only if we are not on EXDEV */ + goto error_unlink; + } else { + /* Unlink the original tmp file. */ + log_debug2("%s: unlinking .../tmp/%s", a->name, name); + if (unlink(src) != 0) + goto error_unlink; } - /* Unlink the original tmp file. */ - log_debug2("%s: unlinking .../tmp/%s", a->name, name); - if (unlink(src) != 0) - goto error_unlink; cleanup_deregister(src); /* Save the mail file as a tag. */ @@ -229,6 +254,7 @@ error_unlink: if (unlink(src) != 0) fatal("unlink failed"); +error_cleanup: cleanup_deregister(src); error_log: Please, tell me any suggestion. Best regards, Louis Opter. -- System Information: Debian Release: 5.0.2 APT prefers stable APT policy: (500, 'stable') Architecture: amd64 (x86_64) Kernel: Linux 2.6.26-2-amd64 (SMP w/2 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages fdm depends on: ii adduser 3.110 add and remove users and groups ii libc6 2.7-18 GNU C Library: Shared libraries ii libpcre3 7.6-2.1 Perl 5 Compatible Regular Expressi ii libssl0.9.8 0.9.8g-15+lenny1 SSL shared libraries ii libtdb1 1.1.2~git20080615-1 Trivial Database - shared library ii zlib1g 1:1.2.3.3.dfsg-12 compression library - runtime fdm recommends no packages. fdm suggests no packages. -- no debconf information -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org