]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dbox: Don't write save-date to metadata, use file's ctime as fallback.
authorTimo Sirainen <tss@iki.fi>
Sun, 21 Mar 2010 15:08:36 +0000 (17:08 +0200)
committerTimo Sirainen <tss@iki.fi>
Sun, 21 Mar 2010 15:08:36 +0000 (17:08 +0200)
Copying must change the save-date, so it couldn't work well in metadata.

--HG--
branch : HEAD

src/lib-storage/index/dbox-common/dbox-file.c
src/lib-storage/index/dbox-common/dbox-file.h
src/lib-storage/index/dbox-common/dbox-mail.c
src/lib-storage/index/dbox-common/dbox-save.c
src/lib-storage/index/dbox-single/sdbox-save.c

index a1845dbc1c5d9a18d3a6dcfceeb94fe0fb3269f4..05687d85a4e7298a4ad55c6922164a36d8df73d3 100644 (file)
@@ -219,6 +219,42 @@ int dbox_file_open_primary(struct dbox_file *file, bool *notfound_r)
        return dbox_file_open_full(file, FALSE, notfound_r);
 }
 
+int dbox_file_stat(struct dbox_file *file, struct stat *st_r)
+{
+       const char *path;
+       bool alt = FALSE;
+
+       if (dbox_file_is_open(file)) {
+               if (fstat(file->fd, st_r) < 0) {
+                       mail_storage_set_critical(&file->storage->storage,
+                               "fstat(%s) failed: %m", file->cur_path);
+                       return -1;
+               }
+               return 0;
+       }
+
+       /* try the primary path first */
+       path = file->primary_path;
+       while (stat(path, st_r) < 0) {
+               if (errno != ENOENT) {
+                       mail_storage_set_critical(&file->storage->storage,
+                                                 "stat(%s) failed: %m", path);
+                       return -1;
+               }
+
+               if (file->alt_path == NULL || alt) {
+                       /* not found */
+                       return -1;
+               }
+
+               /* try the alternative path */
+               path = file->alt_path;
+               alt = TRUE;
+       }
+       file->cur_path = path;
+       return 0;
+}
+
 int dbox_file_header_write(struct dbox_file *file, struct ostream *output)
 {
        string_t *hdr;
index 2607f01cd6b9be549a66e9612c5e7ca92c37b5c7..8fefa95c9561b7b5bf817f67fc9e234f6b9259a8 100644 (file)
@@ -39,8 +39,6 @@ enum dbox_metadata_key {
        DBOX_METADATA_POP3_UIDL         = 'P',
        /* Received UNIX timestamp in hex */
        DBOX_METADATA_RECEIVED_TIME     = 'R',
-       /* Saved UNIX timestamp in hex */
-       DBOX_METADATA_SAVE_TIME         = 'S',
        /* Physical message size in hex. Necessary only if it differs from
           the dbox_message_header.message_size_hex, for example because the
           message is compressed. */
@@ -59,6 +57,7 @@ enum dbox_metadata_key {
        DBOX_METADATA_OLDV1_EXPUNGED    = 'E',
        DBOX_METADATA_OLDV1_FLAGS       = 'F',
        DBOX_METADATA_OLDV1_KEYWORDS    = 'K',
+       DBOX_METADATA_OLDV1_SAVE_TIME   = 'S',
        DBOX_METADATA_OLDV1_SPACE       = ' '
 };
 
@@ -134,6 +133,10 @@ int dbox_file_open_primary(struct dbox_file *file, bool *notfound_r);
 /* Close the file handle from the file, but don't free it. */
 void dbox_file_close(struct dbox_file *file);
 
+/* fstat() or stat() the file. If file is already deleted, fails with
+   errno=ENOENT. */
+int dbox_file_stat(struct dbox_file *file, struct stat *st_r);
+
 /* Try to lock the dbox file. Returns 1 if ok, 0 if already locked by someone
    else, -1 if error. */
 int dbox_file_try_lock(struct dbox_file *file);
index 938da26e1166d9acbffa253b3b472ecd16b1248b..4f249df5352fd986fefd3faeb3eb5a4b32973512 100644 (file)
@@ -140,29 +140,17 @@ int dbox_mail_get_save_date(struct mail *_mail, time_t *date_r)
        struct index_mail_data *data = &mail->imail.data;
        struct dbox_file *file;
        struct stat st;
-       const char *value;
 
        if (index_mail_get_save_date(_mail, date_r) == 0)
                return 0;
 
-       if (dbox_mail_metadata_read(mail, &file) < 0)
+       mail->imail.mail.stats_fstat_lookup_count++;
+       if (dbox_file_stat(file, &st) < 0) {
+               if (errno == ENOENT)
+                       mail_set_expunged(_mail);
                return -1;
-
-       value = dbox_file_metadata_get(file, DBOX_METADATA_SAVE_TIME);
-       data->save_date = value == NULL ? 0 : strtoul(value, NULL, 16);
-
-       if (data->save_date == 0) {
-               /* missing / corrupted save time - use the file's ctime */
-               i_assert(dbox_file_is_open(file));
-               mail->imail.mail.stats_fstat_lookup_count++;
-               if (fstat(file->fd, &st) < 0) {
-                       mail_storage_set_critical(_mail->box->storage,
-                               "fstat(%s) failed: %m", file->cur_path);
-                       return -1;
-               }
-               data->save_date = st.st_ctime;
        }
-       *date_r = data->save_date;
+       *date_r = data->save_date = st.st_ctime;
        return 0;
 }
 
index 836c5a87f7ed291585a8889371637e0065cdab16..b210bfe87459c22b653fb06b1a1179746b483689 100644 (file)
@@ -125,8 +125,6 @@ void dbox_save_write_metadata(struct mail_save_context *ctx,
        }
        str_printfa(str, "%c%lx\n", DBOX_METADATA_RECEIVED_TIME,
                    (unsigned long)ctx->received_date);
-       str_printfa(str, "%c%lx\n", DBOX_METADATA_SAVE_TIME,
-                   (unsigned long)ioloop_time);
        if (mail_get_virtual_size(ctx->dest_mail, &vsize) < 0)
                i_unreached();
        str_printfa(str, "%c%llx\n", DBOX_METADATA_VIRTUAL_SIZE,
index 70afc590dabb8dda8c913cb36537950d9381d464..ca1d2a0bd16916c1ec5f02a45f24e11231621b33 100644 (file)
@@ -129,6 +129,14 @@ static int dbox_save_finish_write(struct mail_save_context *_ctx)
        if (ctx->ctx.dbox_output == NULL)
                return -1;
 
+       if (_ctx->save_date != (time_t)-1) {
+               /* we can't change ctime, but we can add the date to cache */
+               struct index_mail *mail = (struct index_mail *)_ctx->dest_mail;
+               uint32_t t = _ctx->save_date;
+
+               index_mail_cache_add(mail, MAIL_CACHE_SAVE_DATE, &t, sizeof(t));
+       }
+
        index_mail_cache_parse_deinit(_ctx->dest_mail,
                                      _ctx->received_date, !ctx->ctx.failed);