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 };