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,