maildir-util.c revision 73a552a9ed06cd6017ad4ee4b252a8b38c8ac42d
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (C) 2004 Timo Sirainen */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "lib.h"
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "hostpid.h"
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen#include "ioloop.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "str.h"
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen#include "maildir-storage.h"
57f5683fd9dc9bc79816c418bb30fdbc33b68a8cTimo Sirainen#include "maildir-uidlist.h"
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen#include "maildir-keywords.h"
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#include "maildir-sync.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <unistd.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <dirent.h>
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen#include <fcntl.h>
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen#include <utime.h>
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen#include <sys/stat.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstatic int maildir_file_do_try(struct maildir_mailbox *mbox, uint32_t uid,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen maildir_file_do_func *callback, void *context)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen const char *fname, *path;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen enum maildir_uidlist_rec_flag flags;
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen int ret;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen fname = maildir_uidlist_lookup(mbox->uidlist, uid, &flags);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (fname == NULL)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return -2; /* expunged */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen t_push();
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);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ret = callback(mbox, path, context);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ret != 0) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen t_pop();
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return ret;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen path = t_strconcat(mbox->path, "/cur/", fname, NULL);
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen ret = callback(mbox, path, context);
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen t_pop();
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen return ret;
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen#undef maildir_file_do
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid,
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen maildir_file_do_func *callback, void *context)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen{
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen int i, ret;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen for (i = 0; i < 10 && ret == 0; i++) {
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. */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (maildir_storage_sync_force(mbox) < 0)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen return -1;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen ret = maildir_file_do_try(mbox, uid, callback, context);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (i == 10) {
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen ret = -1;
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen mail_storage_set_critical(STORAGE(mbox->storage),
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen "maildir_file_do(%s) racing", mbox->path);
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen }
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen return ret == -2 ? 0 : ret;
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen}
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenconst char *maildir_generate_tmp_filename(const struct timeval *tv)
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen{
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen static unsigned int create_count = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen static time_t first_stamp = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
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 first_stamp = ioloop_time;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return t_strdup_printf("%s.P%sQ%uM%s.%s",
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dec2str(tv->tv_sec), my_pid,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen create_count++,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dec2str(tv->tv_usec), my_hostname);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen } else {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* Don't bother with usecs. Saves a bit space :) */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return t_strdup_printf("%s.P%sQ%u.%s",
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dec2str(tv->tv_sec), my_pid,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen create_count++, my_hostname);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenint maildir_create_tmp(struct maildir_mailbox *mbox, const char *dir,
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen mode_t mode, const char **fname_r)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen const char *path, *tmp_fname;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct stat st;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen struct timeval *tv, tv_now;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen pool_t pool;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen int fd;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen tv = &ioloop_timeval;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen pool = pool_alloconly_create("maildir_tmp", 4096);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen for (;;) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen p_clear(pool);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen tmp_fname = maildir_generate_tmp_filename(tv);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen path = p_strconcat(pool, dir, "/", tmp_fname, NULL);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (stat(path, &st) < 0 && errno == ENOENT) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* doesn't exist */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mode_t old_mask = umask(0);
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen umask(old_mask);
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen if (fd != -1 || errno != EEXIST)
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen break;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen }
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* wait and try again - very unlikely */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen sleep(2);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tv = &tv_now;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (gettimeofday(&tv_now, NULL) < 0)
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen i_fatal("gettimeofday(): %m");
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen }
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen *fname_r = t_strdup(path);
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen if (fd == -1) {
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen if (ENOSPACE(errno)) {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen mail_storage_set_error(STORAGE(mbox->storage),
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "Not enough disk space");
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen } else {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen mail_storage_set_critical(STORAGE(mbox->storage),
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen "open(%s) failed: %m", path);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen }
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen pool_unref(pool);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen return fd;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen}
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainenvoid maildir_tmp_cleanup(struct mail_storage *storage, const char *dir)
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen{
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen DIR *dirp;
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen struct dirent *d;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct stat st;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen string_t *path;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen unsigned int dir_len;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen dirp = opendir(dir);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (dirp == NULL) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (errno != ENOENT) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen mail_storage_set_critical(storage,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen "opendir(%s) failed: %m", dir);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen }
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen t_push();
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen path = t_str_new(256);
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen str_printfa(path, "%s/", dir);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen dir_len = str_len(path);
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen while ((d = readdir(dirp)) != NULL) {
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen if (d->d_name[0] == '.' &&
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen (d->d_name[1] == '\0' ||
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
4f2fa2e5f5a27e1d59dd38fbbf38e420e006596dTimo Sirainen /* skip . and .. */
4f2fa2e5f5a27e1d59dd38fbbf38e420e006596dTimo Sirainen continue;
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen }
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen str_truncate(path, dir_len);
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen str_append(path, d->d_name);
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen if (stat(str_c(path), &st) < 0) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (errno != ENOENT) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen mail_storage_set_critical(storage,
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen "stat(%s) failed: %m", str_c(path));
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen }
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen } else if (st.st_ctime <=
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen ioloop_time - MAILDIR_TMP_DELETE_SECS) {
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (unlink(str_c(path)) < 0 && errno != ENOENT) {
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen mail_storage_set_critical(storage,
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen "unlink(%s) failed: %m", str_c(path));
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen }
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen }
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen }
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen t_pop();
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen#ifdef HAVE_DIRFD
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (fstat(dirfd(dirp), &st) < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_storage_set_critical(storage,
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen "fstat(%s) failed: %m", dir);
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#else
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (stat(dir, &st) < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_storage_set_critical(storage,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "stat(%s) failed: %m", dir);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen#endif
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (st.st_atime < ioloop_time) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* mounted with noatime. update it ourself. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct utimbuf ut;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ut.actime = ioloop_time;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ut.modtime = st.st_mtime;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (utime(dir, &ut) < 0 && errno != ENOENT) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_storage_set_critical(storage,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "utime(%s) failed: %m", dir);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (closedir(dirp) < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_storage_set_critical(storage,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "closedir(%s) failed: %m", dir);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a2150da2dc906c26a26219cbefbe28a119aafee2Timo Sirainen
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainenbool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen{
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen uoff_t size = 0;
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (; *fname != '\0'; fname++) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(*fname != '/');
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*fname == ',' && fname[1] == type && fname[2] == '=') {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen fname += 3;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen }
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen if (*fname == '\0')
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen while (*fname >= '0' && *fname <= '9') {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen size = size * 10 + (*fname - '0');
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen fname++;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*fname != MAILDIR_INFO_SEP &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *fname != MAILDIR_EXTRA_SEP &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *fname != '\0')
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *size_r = size;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* a char* hash function from ASU -- from glib */
88b0427d90f1d3c2c5fb3171e53a505c46e2c39dTimo Sirainenunsigned int maildir_hash(const void *p)
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen{
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen const unsigned char *s = p;
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen unsigned int g, h = 0;
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen while (*s != MAILDIR_INFO_SEP && *s != '\0') {
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen i_assert(*s != '/');
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen h = (h << 4) + *s;
872876c29ab50b4d3b4aeaac65546f21bfaa71f4Timo Sirainen if ((g = h & 0xf0000000UL)) {
f182955da33263be83a8d45af4aab0253f8f274fTimo Sirainen h = h ^ (g >> 24);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen h = h ^ g;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen s++;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen return h;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen}
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenint maildir_cmp(const void *p1, const void *p2)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen{
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen const char *s1 = p1, *s2 = p2;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen while (*s1 == *s2 && *s1 != MAILDIR_INFO_SEP && *s1 != '\0') {
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen i_assert(*s1 != '/');
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen s1++; s2++;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen }
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen if ((*s1 == '\0' || *s1 == MAILDIR_INFO_SEP) &&
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen (*s2 == '\0' || *s2 == MAILDIR_INFO_SEP))
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen return 0;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen return *s1 - *s2;
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen}
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen