maildir-util.c revision 73a552a9ed06cd6017ad4ee4b252a8b38c8ac42d
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (C) 2004 Timo Sirainen */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstatic int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen maildir_file_do_func *callback, void *context)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen fname = maildir_uidlist_lookup(mbox->uidlist, uid, &flags);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if ((flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen /* probably in new/ dir */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen path = t_strconcat(mbox->path, "/new/", fname, NULL);
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen path = t_strconcat(mbox->path, "/cur/", fname, NULL);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid,
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen maildir_file_do_func *callback, void *context)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen /* file is either renamed or deleted. sync the maildir and
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen see which one. if file appears to be renamed constantly,
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen don't try to open it more than 10 times. */
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (i == 10) {
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen mail_storage_set_critical(STORAGE(mbox->storage),
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenconst char *maildir_generate_tmp_filename(const struct timeval *tv)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen static unsigned int create_count = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (first_stamp == 0 || first_stamp == ioloop_time) {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* it's possible that within last second another process had
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen the same PID as us. Use usecs to make sure we don't create
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen duplicate base name. */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* Don't bother with usecs. Saves a bit space :) */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenint maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen pool = pool_alloconly_create("maildir_tmp", 4096);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen tmp_fname = maildir_generate_tmp_filename(tv);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen path = p_strconcat(pool, dir, "/", tmp_fname, NULL);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* doesn't exist */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* wait and try again - very unlikely */
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen mail_storage_set_error(STORAGE(mbox->storage),
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "Not enough disk space");
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen mail_storage_set_critical(STORAGE(mbox->storage),
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainenvoid maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen unsigned int dir_len;
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
4f2fa2e5f5a27e1d59dd38fbbf38e420e006596dTimo Sirainen /* skip . and .. */
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (unlink(str_c(path)) < 0 && errno != ENOENT) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* mounted with noatime. update it ourself. */
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainenbool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*fname == ',' && fname[1] == type && fname[2] == '=') {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* a char* hash function from ASU -- from glib */
88b0427d90f1d3c2c5fb3171e53a505c46e2c39dTimo Sirainenunsigned int maildir_hash(const void *p)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen const unsigned char *s = p;
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen unsigned int g, h = 0;
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen while (*s != MAILDIR_INFO_SEP && *s != '\0') {
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen h = (h << 4) + *s;
872876c29ab50b4d3b4aeaac65546f21bfaa71f4Timo Sirainen if ((g = h & 0xf0000000UL)) {
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen h = h ^ (g >> 24);
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenint maildir_cmp(const void *p1, const void *p2)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen while (*s1 == *s2 && *s1 != MAILDIR_INFO_SEP && *s1 != '\0') {
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen if ((*s1 == '\0' || *s1 == MAILDIR_INFO_SEP) &&