Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/lib-storage/index/maildir/maildir-mail.c @ 6280:eb7c9d8ece54 HEAD
mail_*() APIs changed to return int and return the actual data as pointer.
Changed some code to do error handling a bit better.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 12 Aug 2007 19:40:54 +0300 |
parents | 63b744cb99a4 |
children | 4a57baddc8b8 |
comparison
equal
deleted
inserted
replaced
6279:f52e7d1402b5 | 6280:eb7c9d8ece54 |
---|---|
72 const char *path; | 72 const char *path; |
73 int fd, ret; | 73 int fd, ret; |
74 | 74 |
75 if (data->access_part != 0 && data->stream == NULL) { | 75 if (data->access_part != 0 && data->stream == NULL) { |
76 /* we're going to open the mail anyway */ | 76 /* we're going to open the mail anyway */ |
77 (void)mail_get_stream(mail, NULL, NULL); | 77 struct istream *input; |
78 | |
79 (void)mail_get_stream(mail, NULL, NULL, &input); | |
78 } | 80 } |
79 | 81 |
80 if (data->stream != NULL) { | 82 if (data->stream != NULL) { |
81 fd = i_stream_get_fd(data->stream); | 83 fd = i_stream_get_fd(data->stream); |
82 i_assert(fd != -1); | 84 i_assert(fd != -1); |
93 mail_set_expunged(mail); | 95 mail_set_expunged(mail); |
94 return -1; | 96 return -1; |
95 } | 97 } |
96 } else { | 98 } else { |
97 path = maildir_save_file_get_path(mail->transaction, mail->seq); | 99 path = maildir_save_file_get_path(mail->transaction, mail->seq); |
98 if (do_stat(mbox, path, st) <= 0) | 100 if (stat(path, st) < 0) { |
99 return -1; | 101 mail_storage_set_critical(mail->box->storage, |
102 "stat(%s) failed: %m", path); | |
103 return -1; | |
104 } | |
100 } | 105 } |
101 return 0; | 106 return 0; |
102 } | 107 } |
103 | 108 |
104 static time_t maildir_mail_get_received_date(struct mail *_mail) | 109 static int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r) |
105 { | 110 { |
106 struct index_mail *mail = (struct index_mail *)_mail; | 111 struct index_mail *mail = (struct index_mail *)_mail; |
107 struct index_mail_data *data = &mail->data; | 112 struct index_mail_data *data = &mail->data; |
108 struct stat st; | 113 struct stat st; |
109 uint32_t t; | 114 uint32_t t; |
110 | 115 |
111 (void)index_mail_get_received_date(_mail); | 116 (void)index_mail_get_received_date(_mail, date_r); |
112 if (data->received_date != (time_t)-1) | 117 if (*date_r != (time_t)-1) |
113 return data->received_date; | 118 return 0; |
114 | 119 |
115 if (maildir_mail_stat(_mail, &st) < 0) | 120 if (maildir_mail_stat(_mail, &st) < 0) |
116 return (time_t)-1; | 121 return -1; |
117 | 122 |
118 data->received_date = t = st.st_mtime; | 123 *date_r = data->received_date = t = st.st_mtime; |
119 index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t)); | 124 index_mail_cache_add(mail, MAIL_CACHE_RECEIVED_DATE, &t, sizeof(t)); |
120 return data->received_date; | 125 return 0; |
121 } | 126 } |
122 | 127 |
123 static time_t maildir_mail_get_save_date(struct mail *_mail) | 128 static int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r) |
124 { | 129 { |
125 struct index_mail *mail = (struct index_mail *)_mail; | 130 struct index_mail *mail = (struct index_mail *)_mail; |
126 struct index_mail_data *data = &mail->data; | 131 struct index_mail_data *data = &mail->data; |
127 struct stat st; | 132 struct stat st; |
128 uint32_t t; | 133 uint32_t t; |
129 | 134 |
130 (void)index_mail_get_save_date(_mail); | 135 (void)index_mail_get_save_date(_mail, date_r); |
131 if (data->save_date != (time_t)-1) | 136 if (*date_r != (time_t)-1) |
132 return data->save_date; | 137 return 0; |
133 | 138 |
134 if (maildir_mail_stat(_mail, &st) < 0) | 139 if (maildir_mail_stat(_mail, &st) < 0) |
135 return (time_t)-1; | 140 return -1; |
136 | 141 |
137 data->save_date = t = st.st_ctime; | 142 *date_r = data->save_date = t = st.st_ctime; |
138 index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t)); | 143 index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t)); |
139 return data->save_date; | 144 return data->save_date; |
140 } | 145 } |
141 | 146 |
142 static bool | 147 static bool |
208 } | 213 } |
209 mail->pop3_state_set = TRUE; | 214 mail->pop3_state_set = TRUE; |
210 return mail->pop3_state; | 215 return mail->pop3_state; |
211 } | 216 } |
212 | 217 |
213 static uoff_t maildir_mail_get_virtual_size(struct mail *_mail) | 218 static int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r) |
214 { | 219 { |
215 struct index_mail *mail = (struct index_mail *)_mail; | 220 struct index_mail *mail = (struct index_mail *)_mail; |
216 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; | 221 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; |
217 struct index_mail_data *data = &mail->data; | 222 struct index_mail_data *data = &mail->data; |
218 struct message_size hdr_size, body_size; | 223 struct message_size hdr_size, body_size; |
224 struct istream *input; | |
219 const char *path, *fname, *value; | 225 const char *path, *fname, *value; |
220 uoff_t old_offset; | 226 uoff_t old_offset, size; |
221 int pop3_state; | 227 int pop3_state; |
222 | 228 |
223 if (index_mail_get_cached_virtual_size(mail) != (uoff_t)-1) | 229 if (index_mail_get_cached_virtual_size(mail, size_r)) |
224 return data->virtual_size; | 230 return 0; |
225 | 231 |
226 if (_mail->uid != 0) { | 232 if (_mail->uid != 0) { |
227 if (!maildir_mail_get_fname(mbox, _mail, &fname)) | 233 if (!maildir_mail_get_fname(mbox, _mail, &fname)) |
228 return (uoff_t)-1; | 234 return -1; |
229 } else { | 235 } else { |
230 path = maildir_save_file_get_path(_mail->transaction, | 236 path = maildir_save_file_get_path(_mail->transaction, |
231 _mail->seq); | 237 _mail->seq); |
232 fname = strrchr(path, '/'); | 238 fname = strrchr(path, '/'); |
233 fname = fname != NULL ? fname + 1 : path; | 239 fname = fname != NULL ? fname + 1 : path; |
234 } | 240 } |
235 | 241 |
236 /* size can be included in filename */ | 242 /* size can be included in filename */ |
237 if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE, | 243 if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE, |
238 &data->virtual_size)) | 244 &data->virtual_size)) { |
239 return data->virtual_size; | 245 *size_r = data->virtual_size; |
246 return 0; | |
247 } | |
240 | 248 |
241 /* size can be included in uidlist entry */ | 249 /* size can be included in uidlist entry */ |
242 if (_mail->uid != 0) { | 250 if (_mail->uid != 0) { |
243 value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, | 251 value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid, |
244 MAILDIR_UIDLIST_REC_EXT_VSIZE); | 252 MAILDIR_UIDLIST_REC_EXT_VSIZE); |
245 if (value != NULL) { | 253 if (value != NULL) { |
246 char *p; | 254 char *p; |
247 | 255 |
248 data->virtual_size = strtoull(value, &p, 10); | 256 size = strtoull(value, &p, 10); |
249 if (*p == '\0') | 257 if (*p == '\0') { |
250 return data->virtual_size; | 258 data->virtual_size = *size_r = size; |
259 return 0; | |
260 } | |
251 } | 261 } |
252 } | 262 } |
253 | 263 |
254 /* fallback to reading the file */ | 264 /* fallback to reading the file */ |
255 old_offset = data->stream == NULL ? 0 : data->stream->v_offset; | 265 old_offset = data->stream == NULL ? 0 : data->stream->v_offset; |
256 if (mail_get_stream(_mail, &hdr_size, &body_size) == NULL) | 266 if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0) |
257 return (uoff_t)-1; | 267 return -1; |
258 i_stream_seek(data->stream, old_offset); | 268 i_stream_seek(data->stream, old_offset); |
259 i_assert(data->virtual_size != (uoff_t)-1); | 269 i_assert(data->virtual_size != (uoff_t)-1); |
260 | 270 |
261 /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */ | 271 /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */ |
262 pop3_state = maildir_get_pop3_state(mail); | 272 pop3_state = maildir_get_pop3_state(mail); |
270 so that in case cache file gets lost we can get it quickly */ | 280 so that in case cache file gets lost we can get it quickly */ |
271 maildir_uidlist_set_ext(mbox->uidlist, _mail->uid, | 281 maildir_uidlist_set_ext(mbox->uidlist, _mail->uid, |
272 MAILDIR_UIDLIST_REC_EXT_VSIZE, | 282 MAILDIR_UIDLIST_REC_EXT_VSIZE, |
273 dec2str(data->virtual_size)); | 283 dec2str(data->virtual_size)); |
274 } | 284 } |
275 return data->virtual_size; | 285 *size_r = data->virtual_size; |
276 } | 286 return 0; |
277 | 287 } |
278 static const char * | 288 |
279 maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field) | 289 static int |
290 maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field, | |
291 const char **value_r) | |
280 { | 292 { |
281 struct index_mail *mail = (struct index_mail *)_mail; | 293 struct index_mail *mail = (struct index_mail *)_mail; |
282 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; | 294 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; |
283 const char *path, *fname, *end; | 295 const char *path, *fname, *end; |
284 | 296 |
285 if (field == MAIL_FETCH_UIDL_FILE_NAME) { | 297 if (field == MAIL_FETCH_UIDL_FILE_NAME) { |
286 if (_mail->uid != 0) { | 298 if (_mail->uid != 0) { |
287 if (!maildir_mail_get_fname(mbox, _mail, &fname)) | 299 if (!maildir_mail_get_fname(mbox, _mail, &fname)) |
288 return NULL; | 300 return -1; |
289 } else { | 301 } else { |
290 path = maildir_save_file_get_path(_mail->transaction, | 302 path = maildir_save_file_get_path(_mail->transaction, |
291 _mail->seq); | 303 _mail->seq); |
292 fname = strrchr(path, '/'); | 304 fname = strrchr(path, '/'); |
293 fname = fname != NULL ? fname + 1 : path; | 305 fname = fname != NULL ? fname + 1 : path; |
294 } | 306 } |
295 end = strchr(fname, MAILDIR_INFO_SEP); | 307 end = strchr(fname, MAILDIR_INFO_SEP); |
296 return end == NULL ? fname : t_strdup_until(fname, end); | 308 *value_r = end == NULL ? fname : t_strdup_until(fname, end); |
297 } | 309 return 0; |
298 | 310 } |
299 return index_mail_get_special(_mail, field); | 311 |
312 return index_mail_get_special(_mail, field, value_r); | |
300 } | 313 } |
301 | 314 |
302 static uoff_t maildir_mail_get_physical_size(struct mail *_mail) | 315 static int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r) |
303 { | 316 { |
304 struct index_mail *mail = (struct index_mail *)_mail; | 317 struct index_mail *mail = (struct index_mail *)_mail; |
305 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; | 318 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; |
306 struct index_mail_data *data = &mail->data; | 319 struct index_mail_data *data = &mail->data; |
307 struct stat st; | 320 struct stat st; |
308 const char *path, *fname; | 321 const char *path, *fname; |
309 uoff_t size; | 322 uoff_t size; |
310 int ret; | 323 int ret; |
311 | 324 |
312 size = index_mail_get_physical_size(_mail); | 325 (void)index_mail_get_physical_size(_mail, size_r); |
313 if (size != (uoff_t)-1) | 326 if (*size_r != (uoff_t)-1) |
314 return size; | 327 return 0; |
315 | 328 |
316 if (_mail->uid != 0) { | 329 if (_mail->uid != 0) { |
317 if (!maildir_mail_get_fname(mbox, _mail, &fname)) | 330 if (!maildir_mail_get_fname(mbox, _mail, &fname)) |
318 return (uoff_t)-1; | 331 return -1; |
319 path = NULL; | 332 path = NULL; |
320 } else { | 333 } else { |
321 path = maildir_save_file_get_path(_mail->transaction, | 334 path = maildir_save_file_get_path(_mail->transaction, |
322 _mail->seq); | 335 _mail->seq); |
323 fname = strrchr(path, '/'); | 336 fname = strrchr(path, '/'); |
329 if (_mail->uid != 0) { | 342 if (_mail->uid != 0) { |
330 ret = maildir_file_do(mbox, _mail->uid, do_stat, &st); | 343 ret = maildir_file_do(mbox, _mail->uid, do_stat, &st); |
331 if (ret <= 0) { | 344 if (ret <= 0) { |
332 if (ret == 0) | 345 if (ret == 0) |
333 mail_set_expunged(_mail); | 346 mail_set_expunged(_mail); |
334 return (uoff_t)-1; | 347 return -1; |
335 } | 348 } |
336 } else { | 349 } else { |
337 /* saved mail which hasn't been committed yet */ | 350 /* saved mail which hasn't been committed yet */ |
338 if (do_stat(mbox, path, &st) <= 0) | 351 if (stat(path, &st) < 0) { |
339 return (uoff_t)-1; | 352 mail_storage_set_critical(_mail->box->storage, |
353 "stat(%s) failed: %m", path); | |
354 return -1; | |
355 } | |
340 } | 356 } |
341 size = st.st_size; | 357 size = st.st_size; |
342 } | 358 } |
343 | 359 |
344 index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE, | 360 index_mail_cache_add(mail, MAIL_CACHE_PHYSICAL_FULL_SIZE, |
345 &size, sizeof(size)); | 361 &size, sizeof(size)); |
346 data->physical_size = size; | 362 data->physical_size = size; |
347 return size; | 363 *size_r = size; |
348 } | 364 return 0; |
349 | 365 } |
350 static struct istream *maildir_mail_get_stream(struct mail *_mail, | 366 |
351 struct message_size *hdr_size, | 367 static int maildir_mail_get_stream(struct mail *_mail, |
352 struct message_size *body_size) | 368 struct message_size *hdr_size, |
369 struct message_size *body_size, | |
370 struct istream **stream_r) | |
353 { | 371 { |
354 struct index_mail *mail = (struct index_mail *)_mail; | 372 struct index_mail *mail = (struct index_mail *)_mail; |
355 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; | 373 struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox; |
356 struct index_mail_data *data = &mail->data; | 374 struct index_mail_data *data = &mail->data; |
357 bool deleted; | 375 bool deleted; |
359 if (data->stream == NULL) { | 377 if (data->stream == NULL) { |
360 data->stream = maildir_open_mail(mbox, _mail, &deleted); | 378 data->stream = maildir_open_mail(mbox, _mail, &deleted); |
361 if (data->stream == NULL) { | 379 if (data->stream == NULL) { |
362 if (deleted) | 380 if (deleted) |
363 mail_set_expunged(_mail); | 381 mail_set_expunged(_mail); |
364 return NULL; | 382 return -1; |
365 } | 383 } |
366 } | 384 } |
367 | 385 |
368 return index_mail_init_stream(mail, hdr_size, body_size); | 386 return index_mail_init_stream(mail, hdr_size, body_size, stream_r); |
369 } | 387 } |
370 | 388 |
371 struct mail_vfuncs maildir_mail_vfuncs = { | 389 struct mail_vfuncs maildir_mail_vfuncs = { |
372 index_mail_free, | 390 index_mail_free, |
373 index_mail_set_seq, | 391 index_mail_set_seq, |