mailbox-log.c revision 5e9713e7b02b2b47c339476725f9fbfd9bf78cff
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "lib.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "eacces-error.h"
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi#include "mailbox-log.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen#include <stdio.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <unistd.h>
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen#include <fcntl.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <sys/stat.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#define MAILBOX_LOG_ROTATE_SIZE (1024*4)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainenstruct mailbox_log {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen char *filepath, *filepath2;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen int fd;
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen mode_t mode;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen gid_t gid;
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen char *gid_origin;
46ec5983bf4519ea42dbfcae3d7c62be0d8ef95fTimo Sirainen};
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen
6523f54d1521edf894880f2d45e75cef5dd31c3dTimo Sirainenstruct mailbox_log_iter {
72f5f2c5c6905b5d3f389b424313e2c450dfad96Timo Sirainen struct mailbox_log *log;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen int fd;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen const char *filepath;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct mailbox_log_record buf[128];
373492be949e159fda651807b3acda2c5c077027Timo Sirainen unsigned int idx, count;
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen uoff_t offset;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch bool failed;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch};
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic void mailbox_log_close(struct mailbox_log *log);
da7f1a07f583df8905684a7b78469960afd7c78dPhil Carmody
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstruct mailbox_log *mailbox_log_alloc(const char *path)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen{
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct mailbox_log *log;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen log = i_new(struct mailbox_log, 1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen log->filepath = i_strdup(path);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen log->filepath2 = i_strconcat(path, ".2", NULL);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen log->mode = 0644;
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen log->gid = (gid_t)-1;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen log->fd = -1;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return log;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenvoid mailbox_log_free(struct mailbox_log **_log)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct mailbox_log *log = *_log;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen *_log = NULL;
51fb710488efa419a2964335c30451c62b9633b1Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mailbox_log_close(log);
93a7d1ee4b518b5c85f9721dc6539e4dab6aae00Timo Sirainen i_free(log->gid_origin);
f7f25f9e1a38678d0e97d2e609beac16285fac6bTimo Sirainen i_free(log->filepath);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_free(log->filepath2);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_free(log);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainenstatic void mailbox_log_close(struct mailbox_log *log)
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen{
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen if (log->fd != -1) {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen if (close(log->fd) < 0)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen i_error("close(%s) failed: %m", log->filepath);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen }
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen}
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenvoid mailbox_log_set_permissions(struct mailbox_log *log, mode_t mode,
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen gid_t gid, const char *gid_origin)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen{
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen log->mode = mode;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen log->gid = gid;
da7f1a07f583df8905684a7b78469960afd7c78dPhil Carmody i_free(log->gid_origin);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen log->gid_origin = i_strdup(gid_origin);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen}
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic int mailbox_log_open(struct mailbox_log *log)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mode_t old_mode;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen log->fd = open(log->filepath, O_RDWR | O_APPEND);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (log->fd != -1)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return 0;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* try to create it */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen old_mode = umask(0666 ^ log->mode);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen log->fd = open(log->filepath, O_RDWR | O_APPEND | O_CREAT, 0666);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen umask(old_mode);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (log->fd == -1) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (errno != EACCES)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_error("creat(%s) failed: %m", log->filepath);
ba8498efbf886ca8b69fdb20c0ba2f5dba9416e3Timo Sirainen else
93a7d1ee4b518b5c85f9721dc6539e4dab6aae00Timo Sirainen i_error("%s", eacces_error_get("creat", log->filepath));
f7f25f9e1a38678d0e97d2e609beac16285fac6bTimo Sirainen return -1;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (fchown(log->fd, (uid_t)-1, log->gid) < 0) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (errno != EPERM)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_error("fchown(%s) failed: %m", log->filepath);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen else {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen i_error("%s", eperm_error_get_chgrp("fchown",
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen log->filepath, log->gid,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen log->gid_origin));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return 0;
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen}
544a727de8ab0e6c55cab18a7ee475fffdf5eff3Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic int mailbox_log_rotate_if_needed(struct mailbox_log *log)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen struct stat st;
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (fstat(log->fd, &st) < 0) {
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen i_error("fstat(%s) failed: %m", log->filepath);
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen return -1;
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen }
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (st.st_size < MAILBOX_LOG_ROTATE_SIZE)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return 0;
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen if (rename(log->filepath, log->filepath2) < 0 && errno != ENOENT) {
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen i_error("rename(%s, %s) failed: %m",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen log->filepath, log->filepath2);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return 0;
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen}
544a727de8ab0e6c55cab18a7ee475fffdf5eff3Timo Sirainen
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainenvoid mailbox_log_record_set_timestamp(struct mailbox_log_record *rec,
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen time_t stamp)
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen{
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen rec->timestamp[0] = (stamp & 0xff000000) >> 24;
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen rec->timestamp[1] = (stamp & 0x00ff0000) >> 16;
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen rec->timestamp[2] = (stamp & 0x0000ff00) >> 8;
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen rec->timestamp[3] = (stamp & 0x000000ff);
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen}
559f278a4c54d9fa7e0f2e96ebceda30562f9009Timo Sirainen
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainentime_t mailbox_log_record_get_timestamp(const struct mailbox_log_record *rec)
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen{
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen return ((time_t)rec->timestamp[0] << 24) |
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen ((time_t)rec->timestamp[1] << 16) |
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen ((time_t)rec->timestamp[2] << 8) |
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen (time_t)rec->timestamp[3];
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen}
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenint mailbox_log_append(struct mailbox_log *log,
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen const struct mailbox_log_record *rec)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
544a727de8ab0e6c55cab18a7ee475fffdf5eff3Timo Sirainen struct stat st;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen ssize_t ret;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* we don't have to be too strict about appending to the latest log
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen file. the records' ordering doesn't matter and iteration goes
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen through both logs anyway. */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (log->fd == -1) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mailbox_log_open(log) < 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* We don't bother with locking, atomic appends will protect us.
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen If they don't (NFS), the worst that can happen is that a few
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen records get overwritten (because they're all the same size).
544a727de8ab0e6c55cab18a7ee475fffdf5eff3Timo Sirainen This whole log isn't supposed to be super-reliable anyway. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = write(log->fd, rec, sizeof(*rec));
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ret < 0) {
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen i_error("write(%s) failed: %m", log->filepath);
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else if (ret != sizeof(*rec)) {
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen i_error("write(%s) wrote %d/%u bytes", log->filepath,
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen (int)ret, (unsigned int)sizeof(*rec));
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (fstat(log->fd, &st) == 0) {
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (ftruncate(log->fd, st.st_size - ret) < 0) {
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen i_error("ftruncate(%s) failed: %m",
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen log->filepath);
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen
74fb6b5a156c5a61bb6ec827089bb142a10547ddTimo Sirainen (void)mailbox_log_rotate_if_needed(log);
544a727de8ab0e6c55cab18a7ee475fffdf5eff3Timo Sirainen return 0;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen}
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainenstatic bool mailbox_log_iter_open_next(struct mailbox_log_iter *iter)
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen{
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (iter->fd != -1) {
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen if (close(iter->fd) < 0)
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen i_error("close(%s) failed: %m", iter->filepath);
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen iter->fd = -1;
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen }
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen if (iter->filepath == NULL)
b484ab4b55b0d5341f2f4dd98a655a75f0bf1275Timo Sirainen iter->filepath = iter->log->filepath2;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen else if (iter->filepath == iter->log->filepath2)
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen iter->filepath = iter->log->filepath;
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen else
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return FALSE;
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen iter->fd = open(iter->filepath, O_RDONLY | O_APPEND);
544a727de8ab0e6c55cab18a7ee475fffdf5eff3Timo Sirainen if (iter->fd != -1)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (errno == ENOENT) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (iter->filepath == iter->log->filepath2)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen return mailbox_log_iter_open_next(iter);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen } else {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen i_error("open(%s) failed: %m", iter->filepath);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen iter->failed = TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainen return FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstruct mailbox_log_iter *mailbox_log_iter_init(struct mailbox_log *log)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainen struct mailbox_log_iter *iter;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen iter = i_new(struct mailbox_log_iter, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen iter->log = log;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen iter->fd = -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen (void)mailbox_log_iter_open_next(iter);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen return iter;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenconst struct mailbox_log_record *
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainenmailbox_log_iter_next(struct mailbox_log_iter *iter)
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen{
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen const struct mailbox_log_record *rec;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uoff_t offset;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ssize_t ret;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (iter->idx == iter->count) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (iter->fd == -1)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return NULL;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = pread(iter->fd, iter->buf, sizeof(iter->buf),
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen iter->offset);
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen if (ret < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_error("pread(%s) failed: %m", iter->filepath);
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi iter->failed = TRUE;
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi return NULL;
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi }
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi if (ret == 0) {
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi if (!mailbox_log_iter_open_next(iter))
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi return NULL;
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi iter->idx = iter->count = 0;
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi return mailbox_log_iter_next(iter);
203bb272804e4394ae07103cdc8ce67041ba21a1Aki Tuomi }
44cf91b7a701a9b4d9f59a990552eab4f7f64fbcTimo Sirainen iter->count = ret / sizeof(iter->buf[0]);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen iter->offset += iter->count * sizeof(iter->buf[0]);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen rec = &iter->buf[iter->idx++];
4addfd26372c6ae32ec93252696d86fd32081327Timo Sirainen if (rec->type < MAILBOX_LOG_RECORD_DELETE_MAILBOX ||
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen rec->type > MAILBOX_LOG_RECORD_UNSUBSCRIBE) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen offset = iter->offset -
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen (iter->count - iter->idx) * sizeof(iter->buf[0]);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_error("Corrupted mailbox log at offset %"PRIuUOFF_T": %s",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen offset, iter->filepath);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (unlink(iter->filepath) < 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_error("unlink(%s) failed: %m", iter->filepath);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return NULL;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
1da01eaa962be13cee75771064e2256b1a82d90aTimo Sirainen return rec;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen}
f01eb1f51d618633c0189be9ab60a774f47fb7dfTimo Sirainen
f01eb1f51d618633c0189be9ab60a774f47fb7dfTimo Sirainenint mailbox_log_iter_deinit(struct mailbox_log_iter **_iter)
ca5b3ec5331545b46ec1f1c4ecfa1302ddb10653Timo Sirainen{
ca5b3ec5331545b46ec1f1c4ecfa1302ddb10653Timo Sirainen struct mailbox_log_iter *iter = *_iter;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen int ret = iter->failed ? -1 : 0;
317689976ad393ab9eb78e7d9399fe3d899912adAki Tuomi
317689976ad393ab9eb78e7d9399fe3d899912adAki Tuomi *_iter = NULL;
317689976ad393ab9eb78e7d9399fe3d899912adAki Tuomi
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (iter->fd != -1) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (close(iter->fd) < 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_error("close(%s) failed: %m", iter->filepath);
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_free(iter);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return ret;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen