]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage/index/dbox-multi: mdbox-map - Treat size=0 as last message in record
authorKarl Fleischmann <karl.fleischmann@open-xchange.com>
Mon, 18 Aug 2025 21:07:55 +0000 (23:07 +0200)
committerKarl Fleischmann <karl.fleischmann@open-xchange.com>
Thu, 21 Aug 2025 11:50:11 +0000 (13:50 +0200)
src/lib-storage/index/dbox-multi/mdbox-map.c
src/lib-storage/index/dbox-multi/mdbox-map.h

index 47174601841a8e06fa33acf26ab78af6cd36c9d4..a2f3c862abc125cc62d0825630d0636e705d9d12 100644 (file)
@@ -872,7 +872,8 @@ mdbox_map_file_try_append(struct mdbox_map_append_context *ctx,
                if (errno != ENOENT)
                        e_error(event, "stat(%s) failed: %m", file->cur_path);
                /* the file was unlinked between opening and locking it. */
-       } else if (st.st_size != rec->offset + rec->size &&
+       } else if (rec->size != 0 &&
+                  st.st_size != rec->offset + rec->size &&
                   /* check if there's any garbage at the end of file.
                      note that there may be valid messages added by another
                      session before we locked it (but after we refreshed
@@ -1049,6 +1050,11 @@ mdbox_map_find_appendable_file(struct mdbox_map_append_context *ctx,
                        break;
                }
 
+               /* Don't append to the index if the record indicates this is the
+                  last mail with special size=0. */
+               if (rec->size == 0)
+                       continue;
+
                /* first lookup: this should be enough usually, but we can't
                   be sure until after locking. also if messages were recently
                   moved, this message might not be the last one in the file. */
@@ -1309,7 +1315,9 @@ int mdbox_map_append_assign_map_uids(struct mdbox_map_append_context *ctx,
 
                rec.file_id = mfile->file_id;
                rec.offset = appends[i].offset;
-               rec.size = appends[i].size;
+               /* A mail that exceeds 4GB is the final mail in the record and
+                  thusly is registered with size=0. */
+               rec.size = (appends[i].size > UINT32_MAX) ? 0 : appends[i].size;
 
                mail_index_append(ctx->trans, 0, &seq);
                mail_index_update_ext(ctx->trans, seq, ctx->map->map_ext_id,
@@ -1371,7 +1379,9 @@ int mdbox_map_append_move(struct mdbox_map_append_context *ctx,
                i_assert(j < appends_count);
                rec.file_id = mfile->file_id;
                rec.offset = appends[j].offset;
-               rec.size = appends[j].size;
+               /* A mail that exceeds 4GB is the final mail in the record and
+                  thusly is registered with size=0. */
+               rec.size = (appends[j].size > UINT32_MAX) ? 0 : appends[j].size;
                j++;
 
                if (!mail_index_lookup_seq(ctx->atomic->sync_view,
index 9571f0e9ec494b6167152e9f2eff1e8997d7f480..19e4adf5d0e622c58e381f3311f506301e4dea25 100644 (file)
@@ -20,7 +20,11 @@ struct mdbox_map_mail_index_header {
 struct mdbox_map_mail_index_record {
        uint32_t file_id;
        uint32_t offset;
-       uint32_t size; /* including pre/post metadata */
+       /* Size is used to find the next mail in the same mdbox file.
+          Special case is size=0, which indicates it's the last mail in the
+          record and can be arbitrarily sized (i.e. larger than 4GB).
+          Includes pre/post metadata. */
+       uint32_t size;
 };
 
 struct mdbox_map_file_msg {