Howdy,
Here is a problem with fix affecting dovecot-1.0.10 (and 1.1rc13).
On a linux system's CIFS mounted filesystem, it is not possible to
rename a file opened read-write:
$ sleep 5 >> .subscriptions.lock & mv .subscriptions.lock .subscriptions
mv: cannot move `.subscriptions.lock' to `.subscriptions': Text file busy
This causes problems in editing subscriptions, as the new subscription
list is still open for writing before it is renamed in:
lib-storage/subscription-file/subscription-file.c line 169
in dovecot version 1.0.10 (and 1.1rc13)
This is an unpatched linux 2.6.21-5, CIFS mounted filesystem from a
windows 2003 sp2 server.
The documentation for rename(2) indicates that it is allowed to return
an error when the file is already opened, so perhaps the file should be
closed before the replace. Should this be done in file_dotlock_replace
(before line 672) generally?
Here is a patch that does so:
diff -rw -U3 dovecot-1.0.10/src/lib/file-dotlock.c
dovecot-1.0.10-patch/src/lib/file-dotlock.c
--- dovecot-1.0.10/src/lib/file-dotlock.c 2007-12-11 13:52:08.000000000
-0500
+++ dovecot-1.0.10/src/lib/file-dotlock.c 2008-01-23 08:53:33.000000000
-0500
@@ -635,7 +635,7 @@
struct dotlock *dotlock;
struct stat st, st2;
const char *lock_path;
- int fd;
+ int fd, old_errno;
dotlock = *dotlock_p;
*dotlock_p = NULL;
@@ -669,6 +669,14 @@
}
}
+ if (dotlock->fd != -1) {
+ old_errno = errno;
+ if (close(dotlock->fd) < 0)
+ i_error("close(%s) failed: %m", dotlock->path);
+ dotlock->fd = -1;
+ errno = old_errno;
+ }
+
if (rename(lock_path, dotlock->path) < 0) {
i_error("rename(%s, %s) failed: %m", lock_path, dotlock->path);
file_dotlock_free(dotlock);