mail-index-open.c revision 21334f6ca1d3f4e7ef0c9920e81c15b4c5485c45
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int mail_index_open_init(struct mail_index *index,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (hdr->flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((hdr->flags & MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES) != 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* update \Recent message counters */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT) != 0 &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* keep last_recent_uid to next_uid-1 */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->first_recent_uid = index->header->last_nonrecent_uid+1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->header->last_nonrecent_uid = index->header->next_uid-1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->first_recent_uid = hdr->last_nonrecent_uid+1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (hdr->next_uid >= MAX_ALLOWED_UID - 1000) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* UID values are getting too high, rebuild index */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* finally reset the modify log marks, fsck or syncing might
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen have deleted some messages, and since we're only just
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen opening the index, there's no need to remember them */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!mail_modifylog_mark_synced(index->modifylog))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int index_open_and_fix(struct mail_index *index,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->header_size < sizeof(struct mail_index_header)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* upgrading from older index file. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((index->header->flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0 ||
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((index->header->flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* no inconsistency problems since we're still opening
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* custom flags file needs to be open before rebuilding index */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->header->flags & MAIL_INDEX_HDR_FLAG_FSCK) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* index needs fscking */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* sync ourself. do it before compression which may happen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen as a result of this. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* we never want to keep shared lock if syncing happens to set it.
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen either exclusive or nothing (NOTE: drop it directly, not through
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->set_lock() so mbox lock won't be affected). */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_UNLOCK))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_FAST) == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->header->flags & MAIL_INDEX_HDR_FLAG_COMPRESS) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* remove deleted blocks from index file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->header->flags & MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* remove unused space from index data file. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int mail_index_read_header(struct mail_index *index,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* missing data */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic int mail_index_init_file(struct mail_index *index,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_syscall_error(index, "write_full()");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (file_set_size(index->fd, (off_t)file_size) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_syscall_error(index, "file_set_size()");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void get_compat_data(unsigned char compat_data[4])
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid mail_index_init_header(struct mail_index_header *hdr)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(sizeof(struct mail_index_header) < 256);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr->header_size = (uint8_t)sizeof(struct mail_index_header);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* mark the index requiring rebuild - rebuild() removes this flag
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen when it succeeds */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr->used_file_size = sizeof(struct mail_index_header);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void mail_index_cleanup_temp_files(const char *dir)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unlink_lockfiles(dir, t_strconcat(".temp.", my_hostname, ".", NULL),
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenvoid mail_index_init(struct mail_index *index, const char *dir)
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen index->mail_read_mmaped = getenv("MAIL_READ_MMAPED") != NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int mail_index_create_memory(struct mail_index *index,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->header_size = sizeof(struct mail_index_header);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_full_length = INDEX_FILE_MIN_SIZE(index);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_base = mmap_anon(index->mmap_full_length);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return index_set_error(index, "mmap_anon() failed: %m");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->mmap_used_length = index->header->used_file_size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->filepath = i_strdup_printf("(in-memory index for %s)",
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int mail_index_open_index(struct mail_index *index,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* if index is being created, we'll wait here until it's finished */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!mail_index_wait_lock(index, MAIL_LOCK_TO_FLOCK(index->lock_type)))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen mprotect(index->mmap_base, index->mmap_used_length,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((ret = mail_index_read_header(index, &hdr)) < 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (ret == 0 || hdr.major_version != MAIL_INDEX_MAJOR_VERSION ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen (hdr.flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0 ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen memcmp(compat_data, hdr.compat_data, sizeof(compat_data)) != 0 ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* so, we're creating the index */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (index->lock_type != MAIL_LOCK_EXCLUSIVE) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* have to get exclusive lock first */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* we don't want to keep the shared lock while opening
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen indexes. opening should work unlocked and some
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen things want exclusive lock */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) == 0 ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen (flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* needs a rebuild */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return mail_index_create_memory(index, flags);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* open/create the file */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen path = t_strconcat(index->dir, "/", INDEX_FILE_PREFIX, NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) != 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->fd = open(path, O_RDWR | O_CREAT, 0660);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index_file_set_syscall_error(index, path, "open()");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return mail_index_create_memory(index, flags);