return -1;
}
-static int
-maildir_rmdir_unexpected_dir(struct mail_storage *storage, const char *path)
-{
- if (rmdir(path) == 0) {
- mail_storage_set_critical(storage,
- "Maildir: rmdir()ed unwanted empty directory: %s",
- path);
- return 0;
- } else {
- mail_storage_set_critical(storage,
- "Maildir: Found unwanted directory %s, "
- "but rmdir() failed: %m", path);
- return -1;
- }
-}
-
static struct istream *
maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
bool *deleted_r)
input = i_stream_create_fd(ctx.fd, 0, TRUE);
if (input->stream_errno == EISDIR) {
- /* there's a directory in maildir. many installations seem to
- have messed up something and causing "cur", "new" and "tmp"
- directories to be created under the "cur" directory.
- if the directory is empty, just get rid of it and log an
- error */
i_stream_destroy(&input);
- if (maildir_rmdir_unexpected_dir(&mbox->storage->storage,
- ctx.path) == 0)
+ if (maildir_lose_unexpected_dir(&mbox->storage->storage,
+ ctx.path) >= 0)
*deleted_r = TRUE;
} else {
i_stream_set_name(input, ctx.path);
#include "maildir-filename.h"
#include "maildir-sync.h"
+#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
} T_END;
return ret < 0 ? FALSE : TRUE;
}
+
+int maildir_lose_unexpected_dir(struct mail_storage *storage, const char *path)
+{
+ const char *dest, *fname, *p;
+
+ /* There's a directory in maildir, get rid of it.
+
+ In some installations this was caused by a messed up configuration
+ where e.g. mails was initially delivered to new/new/ directory.
+ Also Dovecot v2.0.0 - v2.0.4 sometimes may have renamed tmp/
+ directory under new/ or cur/. */
+ if (rmdir(path) == 0) {
+ mail_storage_set_critical(storage,
+ "Maildir: rmdir()ed unwanted empty directory: %s",
+ path);
+ return 1;
+ } else if (errno == ENOENT) {
+ /* someone else rmdired or renamed it */
+ return 0;
+ } else if (errno != ENOTEMPTY) {
+ mail_storage_set_critical(storage,
+ "Maildir: Found unwanted directory %s, "
+ "but rmdir() failed: %m", path);
+ return -1;
+ }
+
+ /* It's not safe to delete this directory since it has some files in it,
+ but it's also not helpful to log this message over and over again.
+ Get rid of this error by renaming the directory elsewhere */
+ p = strrchr(path, '/');
+ i_assert(p != NULL);
+ fname = p + 1;
+ while (p != path && p[-1] != '/') p--;
+ i_assert(p != NULL);
+
+ dest = t_strconcat(t_strdup_until(path, p), "extra-", fname, NULL);
+ if (rename(path, dest) == 0) {
+ mail_storage_set_critical(storage,
+ "Maildir: renamed unwanted directory %s to %s",
+ path, dest);
+ return 1;
+ } else if (errno == ENOENT) {
+ /* someone else renamed it (could have been flag change) */
+ return 0;
+ } else {
+ mail_storage_set_critical(storage,
+ "Maildir: Found unwanted directory, "
+ "but rename(%s, %s) failed: %m", path, dest);
+ return -1;
+ }
+}