maildir-util.c revision 8a6fc472a12c5ec09e2bd19f1b3acd553d75ff91
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen maildir_file_do_func *callback, void *context)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen fname = maildir_uidlist_lookup(mbox->uidlist, uid, &flags);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* probably in new/ dir */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen path = t_strconcat(mbox->path, "/new/", fname, NULL);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen path = t_strconcat(mbox->path, "/cur/", fname, NULL);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid,
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen maildir_file_do_func *callback, void *context)
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* file is either renamed or deleted. sync the maildir and
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen see which one. if file appears to be renamed constantly,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen don't try to open it more than 10 times. */
00efa7d99981e18e286c02b18c1163dde18ee521Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
039e42997fe5e0d1c5ad9306dc0ae69bf0e1ca10Timo Sirainen if (i == 10) {
8153fdec343e40e2a78f5c12353e89b994b28f74Timo Sirainen mail_storage_set_critical(STORAGE(mbox->storage),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *maildir_generate_tmp_filename(const struct timeval *tv)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen static unsigned int create_count = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (first_stamp == 0 || first_stamp == ioloop_time) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* it's possible that within last second another process had
4c176a543191e4572910401c218a63306ed68784Timo Sirainen the same PID as us. Use usecs to make sure we don't create
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen duplicate base name. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* Don't bother with usecs. Saves a bit space :) */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenint maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool = pool_alloconly_create("maildir_tmp", 4096);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tmp_fname = maildir_generate_tmp_filename(tv);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen path = p_strconcat(pool, dir, "/", tmp_fname, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* doesn't exist */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* wait and try again - very unlikely */
8153fdec343e40e2a78f5c12353e89b994b28f74Timo Sirainen mail_storage_set_error(STORAGE(mbox->storage),
102c6b4e47a0d17699004e48740f651153fb8b76Timo Sirainen "Not enough disk space");
8153fdec343e40e2a78f5c12353e89b994b28f74Timo Sirainen mail_storage_set_critical(STORAGE(mbox->storage),
8a6fc472a12c5ec09e2bd19f1b3acd553d75ff91Timo Sirainen } else if (st.st_gid != mbox->mail_create_gid &&
8a6fc472a12c5ec09e2bd19f1b3acd553d75ff91Timo Sirainen if (fchown(fd, (uid_t)-1, mbox->mail_create_gid) < 0) {
8a6fc472a12c5ec09e2bd19f1b3acd553d75ff91Timo Sirainen mail_storage_set_critical(STORAGE(mbox->storage),
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainenvoid maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen unsigned int dir_len;
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen /* skip . and .. */
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen if (unlink(str_c(path)) < 0 && errno != ENOENT) {
73a552a9ed06cd6017ad4ee4b252a8b38c8ac42dTimo Sirainen /* mounted with noatime. update it ourself. */
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainenbool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
677e22747b82bf15b339e31d1d0106d62bf806daTimo Sirainen if (*fname == ',' && fname[1] == type && fname[2] == '=') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* a char* hash function from ASU -- from glib */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenunsigned int maildir_hash(const void *p)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const unsigned char *s = p;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int g, h = 0;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen while (*s != MAILDIR_INFO_SEP && *s != '\0') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen h = (h << 4) + *s;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((g = h & 0xf0000000UL)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen h = h ^ (g >> 24);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint maildir_cmp(const void *p1, const void *p2)
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen while (*s1 == *s2 && *s1 != MAILDIR_INFO_SEP && *s1 != '\0') {
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen if ((*s1 == '\0' || *s1 == MAILDIR_INFO_SEP) &&