maildir-filename.c revision eac60b7aef3924a611656b184412be1e80b2ed5b
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2002-2007 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "array.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hostpid.h"
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen#include "maildir-storage.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "maildir-keywords.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "maildir-filename.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainenconst char *maildir_filename_generate(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen static struct timeval last_tv = { 0, 0 };
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct timeval tv;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen /* use secs + usecs to guarantee uniqueness within this process. */
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (ioloop_timeval.tv_sec > last_tv.tv_sec ||
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen (ioloop_timeval.tv_sec == last_tv.tv_sec &&
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen ioloop_timeval.tv_usec > last_tv.tv_usec))
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen tv = ioloop_timeval;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tv = last_tv;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (++tv.tv_usec == 1000000) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tv.tv_sec++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tv.tv_usec = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen last_tv = tv;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen return t_strdup_printf("%s.M%sP%s.%s",
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen dec2str(tv.tv_sec), dec2str(tv.tv_usec),
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen my_pid, my_hostname);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen}
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenvoid maildir_filename_get_flags(struct maildir_keywords_sync_ctx *ctx,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const char *fname, enum mail_flags *flags_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ARRAY_TYPE(keyword_indexes) *keywords_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *info;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen array_clear(keywords_r);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen *flags_r = 0;
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen info = strchr(fname, MAILDIR_INFO_SEP);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (info == NULL || info[1] != '2' || info[2] != MAILDIR_FLAGS_SEP)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (info += 3; *info != '\0' && *info != MAILDIR_FLAGS_SEP; info++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen switch (*info) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case 'R': /* replied */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *flags_r |= MAIL_ANSWERED;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen case 'S': /* seen */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *flags_r |= MAIL_SEEN;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen break;
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen case 'T': /* trashed */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *flags_r |= MAIL_DELETED;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen break;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen case 'D': /* draft */
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen *flags_r |= MAIL_DRAFT;
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen break;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen case 'F': /* flagged */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *flags_r |= MAIL_FLAGGED;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*info >= MAILDIR_KEYWORD_FIRST &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *info <= MAILDIR_KEYWORD_LAST) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int idx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idx = maildir_keywords_char_idx(ctx, *info);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (idx < 0) {
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen /* unknown keyword. */
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen break;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen }
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen array_append(keywords_r,
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen (unsigned int *)&idx, 1);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* unknown flag - ignore */
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen break;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenstatic int char_cmp(const void *p1, const void *p2)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const unsigned char *c1 = p1, *c2 = p2;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return *c1 - *c2;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen}
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainenstatic void
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainenmaildir_filename_append_keywords(struct maildir_keywords_sync_ctx *ctx,
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen ARRAY_TYPE(keyword_indexes) *keywords,
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen string_t *fname)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen const unsigned int *indexes;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen unsigned int i, count, start = str_len(fname);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen char chr;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen indexes = array_get(keywords, &count);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen for (i = 0; i < count; i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen chr = maildir_keywords_idx_char(ctx, indexes[i]);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (chr != '\0')
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen str_append_c(fname, chr);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen qsort(str_c_modifiable(fname) + start, str_len(fname) - start, 1,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen char_cmp);
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen}
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenconst char *maildir_filename_set_flags(struct maildir_keywords_sync_ctx *ctx,
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen const char *fname, enum mail_flags flags,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ARRAY_TYPE(keyword_indexes) *keywords)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen string_t *flags_str;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen enum mail_flags flags_left;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *info, *oldflags;
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen int nextflag;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen /* remove the old :info from file name, and get the old flags */
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen info = strrchr(fname, MAILDIR_INFO_SEP);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (info != NULL && strrchr(fname, '/') > info)
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen info = NULL;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen oldflags = "";
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (info != NULL) {
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen fname = t_strdup_until(fname, info);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (info[1] == '2' && info[2] == MAILDIR_FLAGS_SEP)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen oldflags = info+3;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen /* insert the new flags between old flags. flags must be sorted by
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen their ASCII code. unknown flags are kept. */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen flags_str = t_str_new(256);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append(flags_str, fname);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen str_append(flags_str, MAILDIR_FLAGS_FULL_SEP);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen flags_left = flags;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen for (;;) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* skip all known flags */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen while (*oldflags == 'D' || *oldflags == 'F' ||
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *oldflags == 'R' || *oldflags == 'S' ||
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen *oldflags == 'T' ||
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (*oldflags >= MAILDIR_KEYWORD_FIRST &&
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen *oldflags <= MAILDIR_KEYWORD_LAST))
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen oldflags++;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen nextflag = *oldflags == '\0' || *oldflags == MAILDIR_FLAGS_SEP ?
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen 256 : (unsigned char) *oldflags;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if ((flags_left & MAIL_DRAFT) && nextflag > 'D') {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen str_append_c(flags_str, 'D');
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen flags_left &= ~MAIL_DRAFT;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if ((flags_left & MAIL_FLAGGED) && nextflag > 'F') {
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen str_append_c(flags_str, 'F');
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen flags_left &= ~MAIL_FLAGGED;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if ((flags_left & MAIL_ANSWERED) && nextflag > 'R') {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen str_append_c(flags_str, 'R');
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen flags_left &= ~MAIL_ANSWERED;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if ((flags_left & MAIL_SEEN) && nextflag > 'S') {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen str_append_c(flags_str, 'S');
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen flags_left &= ~MAIL_SEEN;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if ((flags_left & MAIL_DELETED) && nextflag > 'T') {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen str_append_c(flags_str, 'T');
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen flags_left &= ~MAIL_DELETED;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (keywords != NULL && array_is_created(keywords) &&
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen nextflag > MAILDIR_KEYWORD_FIRST) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen maildir_filename_append_keywords(ctx, keywords,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen flags_str);
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen keywords = NULL;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (*oldflags == '\0' || *oldflags == MAILDIR_FLAGS_SEP)
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen break;
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen str_append_c(flags_str, *oldflags);
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen oldflags++;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (*oldflags == MAILDIR_FLAGS_SEP) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen /* another flagset, we don't know about these, just keep them */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen while (*oldflags != '\0')
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen str_append_c(flags_str, *oldflags++);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return str_c(flags_str);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenbool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uoff_t size = 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for (; *fname != '\0'; fname++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen i_assert(*fname != '/');
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (*fname == ',' && fname[1] == type && fname[2] == '=') {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen fname += 3;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen break;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (*fname == '\0')
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen while (*fname >= '0' && *fname <= '9') {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen size = size * 10 + (*fname - '0');
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen fname++;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (*fname != MAILDIR_INFO_SEP &&
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *fname != MAILDIR_EXTRA_SEP &&
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *fname != '\0')
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen *size_r = size;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return TRUE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen/* a char* hash function from ASU -- from glib */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenunsigned int maildir_filename_base_hash(const void *p)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const unsigned char *s = p;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen unsigned int g, h = 0;
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen while (*s != MAILDIR_INFO_SEP && *s != '\0') {
053843989f13d9013b265fb401a4bde7e0e6568eTimo Sirainen i_assert(*s != '/');
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen h = (h << 4) + *s;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if ((g = h & 0xf0000000UL)) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen h = h ^ (g >> 24);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen h = h ^ g;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen s++;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return h;
ab286a8b58306eb8d22fc18342b6c199fd428e1eTimo Sirainen}
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenint maildir_filename_base_cmp(const void *p1, const void *p2)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const char *fname1 = p1, *fname2 = p2;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen while (*fname1 == *fname2 && *fname1 != MAILDIR_INFO_SEP &&
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen *fname1 != '\0') {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen i_assert(*fname1 != '/');
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen fname1++; fname2++;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((*fname1 == '\0' || *fname1 == MAILDIR_INFO_SEP) &&
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen (*fname2 == '\0' || *fname2 == MAILDIR_INFO_SEP))
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return *fname1 - *fname2;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic bool maildir_fname_get_usecs(const char *fname, int *usecs_r)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int usecs = 0;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* Assume we already read the timestamp. Next up is
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen ".<uniqueness>.<host>". Find usecs inside the uniqueness. */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (*fname != '.')
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return FALSE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen fname++;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen while (*fname != '\0' && *fname != '.' && *fname != MAILDIR_INFO_SEP) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (*fname++ == 'M') {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen while (*fname >= '0' && *fname <= '9') {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen usecs = usecs * 10 + (*fname - '0');
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen fname++;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen *usecs_r = usecs;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return TRUE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenint maildir_filename_sort_cmp(const char *fname1, const char *fname2)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char *s1, *s2;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen time_t secs1 = 0, secs2 = 0;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen int ret, usecs1, usecs2;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* sort primarily by the timestamp in file name */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen for (s1 = fname1; *s1 >= '0' && *s1 <= '9'; s1++)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen secs1 = secs1 * 10 + (*s1 - '0');
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen for (s2 = fname2; *s2 >= '0' && *s2 <= '9'; s2++)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen secs2 = secs2 * 10 + (*s2 - '0');
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen ret = (int)((long)secs1 - (long)secs2);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if (ret == 0) {
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen /* sort secondarily by microseconds, if they exist */
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if (maildir_fname_get_usecs(s1, &usecs1) &&
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen maildir_fname_get_usecs(s2, &usecs2))
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ret = usecs1 - usecs2;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (ret == 0) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen /* fallback to comparing the base file name */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ret = maildir_filename_base_cmp(s1, s2);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return ret;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen