Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/lib-index/maildir/maildir-index.c @ 0:3b1985cbc908 HEAD
Initial revision
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 09 Aug 2002 12:15:38 +0300 |
parents | |
children | 1b34ec11fff8 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3b1985cbc908 |
---|---|
1 /* Copyright (C) 2002 Timo Sirainen */ | |
2 | |
3 #include "lib.h" | |
4 #include "maildir-index.h" | |
5 #include "mail-index-util.h" | |
6 | |
7 #include <stdio.h> | |
8 | |
9 static MailIndex maildir_index; | |
10 | |
11 const char *maildir_filename_set_flags(const char *fname, MailFlags flags) | |
12 { | |
13 const char *info, *oldflags; | |
14 char *flags_buf, *p; | |
15 int i, nextflag; | |
16 | |
17 /* remove the old :info from file name, and get the old flags */ | |
18 info = strrchr(fname, ':'); | |
19 if (info != NULL && strrchr(fname, '/') > info) | |
20 info = NULL; | |
21 | |
22 oldflags = ""; | |
23 if (info != NULL) { | |
24 fname = t_strndup(fname, (unsigned int) (info-fname)); | |
25 if (info[1] == '2' && info[2] == ',') | |
26 oldflags = info+3; | |
27 } | |
28 | |
29 /* insert the new flags between old flags. flags must be sorted by | |
30 their ASCII code. unknown flags are kept. */ | |
31 flags_buf = t_malloc(MAIL_FLAGS_COUNT+strlen(oldflags)+1); | |
32 p = flags_buf; | |
33 | |
34 for (;;) { | |
35 /* skip all known flags */ | |
36 while (*oldflags == 'D' || *oldflags == 'F' || | |
37 *oldflags == 'R' || *oldflags == 'S' || | |
38 *oldflags == 'T' || | |
39 (*oldflags >= 'a' && *oldflags <= 'z')) | |
40 oldflags++; | |
41 | |
42 nextflag = *oldflags == '\0' ? 256 : | |
43 (unsigned char) *oldflags; | |
44 | |
45 if ((flags & MAIL_DRAFT) && nextflag > 'D') { | |
46 *p++ = 'D'; | |
47 flags &= ~MAIL_DRAFT; | |
48 } | |
49 if ((flags & MAIL_FLAGGED) && nextflag > 'F') { | |
50 *p++ = 'F'; | |
51 flags &= ~MAIL_FLAGGED; | |
52 } | |
53 if ((flags & MAIL_ANSWERED) && nextflag > 'R') { | |
54 *p++ = 'R'; | |
55 flags &= ~MAIL_ANSWERED; | |
56 } | |
57 if ((flags & MAIL_SEEN) && nextflag > 'S') { | |
58 *p++ = 'S'; | |
59 flags &= ~MAIL_SEEN; | |
60 } | |
61 if ((flags & MAIL_DELETED) && nextflag > 'T') { | |
62 *p++ = 'T'; | |
63 flags &= ~MAIL_DELETED; | |
64 } | |
65 | |
66 if ((flags & MAIL_CUSTOM_FLAGS_MASK) && nextflag > 'a') { | |
67 for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) { | |
68 if (flags & (1 << (i + MAIL_CUSTOM_FLAG_1_BIT))) | |
69 *p++ = 'a' + i; | |
70 } | |
71 flags &= ~MAIL_CUSTOM_FLAGS_MASK; | |
72 } | |
73 | |
74 if (*oldflags == '\0') | |
75 break; | |
76 | |
77 *p++ = *oldflags++; | |
78 } | |
79 | |
80 *p = '\0'; | |
81 | |
82 return t_strconcat(fname, ":2,", flags_buf, NULL); | |
83 } | |
84 | |
85 MailIndex *maildir_index_alloc(const char *dir) | |
86 { | |
87 MailIndex *index; | |
88 int len; | |
89 | |
90 i_assert(dir != NULL); | |
91 | |
92 index = i_new(MailIndex, 1); | |
93 memcpy(index, &maildir_index, sizeof(MailIndex)); | |
94 | |
95 index->fd = -1; | |
96 index->dir = i_strdup(dir); | |
97 | |
98 len = strlen(index->dir); | |
99 if (index->dir[len-1] == '/') | |
100 index->dir[len-1] = '\0'; | |
101 | |
102 return (MailIndex *) index; | |
103 } | |
104 | |
105 static void maildir_index_free(MailIndex *index) | |
106 { | |
107 mail_index_close(index); | |
108 i_free(index->dir); | |
109 i_free(index); | |
110 } | |
111 | |
112 static int maildir_index_update_flags(MailIndex *index, MailIndexRecord *rec, | |
113 unsigned int seq, MailFlags flags, | |
114 int external_change) | |
115 { | |
116 MailIndexUpdate *update; | |
117 const char *old_fname, *new_fname; | |
118 const char *old_path, *new_path; | |
119 | |
120 if (!mail_index_update_flags(index, rec, seq, flags, external_change)) | |
121 return FALSE; | |
122 | |
123 /* we need to update the flags in the file name */ | |
124 old_fname = index->lookup_field(index, rec, FIELD_TYPE_LOCATION); | |
125 if (old_fname == NULL) { | |
126 INDEX_MARK_CORRUPTED(index); | |
127 index_set_error(index, "Corrupted index file %s: " | |
128 "Missing location field for record %u", | |
129 index->filepath, rec->uid); | |
130 return FALSE; | |
131 } | |
132 | |
133 new_fname = maildir_filename_set_flags(old_fname, flags); | |
134 | |
135 if (strcmp(old_fname, new_fname) != 0) { | |
136 old_path = t_strconcat(index->dir, "/cur/", old_fname, NULL); | |
137 new_path = t_strconcat(index->dir, "/cur/", new_fname, NULL); | |
138 | |
139 /* minor problem: new_path is overwritten if it exists.. */ | |
140 if (rename(old_path, new_path) == -1) { | |
141 index_set_error(index, "maildir flags update: " | |
142 "rename(%s, %s) failed: %m", | |
143 old_path, new_path); | |
144 return FALSE; | |
145 } | |
146 | |
147 /* update the filename in index */ | |
148 update = index->update_begin(index, rec); | |
149 index->update_field(update, FIELD_TYPE_LOCATION, new_fname, 0); | |
150 | |
151 if (!index->update_end(update)) | |
152 return FALSE; | |
153 } | |
154 | |
155 return TRUE; | |
156 } | |
157 | |
158 static MailIndex maildir_index = { | |
159 mail_index_open, | |
160 mail_index_open_or_create, | |
161 maildir_index_free, | |
162 mail_index_set_lock, | |
163 mail_index_try_lock, | |
164 maildir_index_rebuild, | |
165 mail_index_fsck, | |
166 maildir_index_sync, | |
167 mail_index_get_header, | |
168 mail_index_lookup, | |
169 mail_index_next, | |
170 mail_index_lookup_uid_range, | |
171 mail_index_lookup_field, | |
172 mail_index_get_sequence, | |
173 maildir_open_mail, | |
174 mail_index_expunge, | |
175 maildir_index_update_flags, | |
176 mail_index_append, | |
177 mail_index_update_begin, | |
178 mail_index_update_end, | |
179 mail_index_update_field, | |
180 mail_index_get_last_error, | |
181 mail_index_is_inconsistency_error | |
182 }; |