bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen/* How often to reopen the log file to make sure that the changes are written
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen to the latest file. The main problem here is if the value is too high the
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen changes could be written to a file that was already rotated and deleted.
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen That wouldn't happen in any real world situations though, since the file
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen rotation time is probably measured in months or years. Still, each session
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen rarely writes anything here, so the value can just as well be a pretty small
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen one without any performance problems. */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic void mailbox_log_close(struct mailbox_log *log);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstruct mailbox_log *mailbox_log_alloc(const char *path)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen log->filepath2 = i_strconcat(path, ".2", NULL);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenvoid mailbox_log_free(struct mailbox_log **_log)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic void mailbox_log_close(struct mailbox_log *log)
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek i_close_fd_path(&log->fd, log->filepath);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenvoid mailbox_log_set_permissions(struct mailbox_log *log, mode_t mode,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic int mailbox_log_open(struct mailbox_log *log)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen log->fd = open(log->filepath, O_RDWR | O_APPEND);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen /* try to create it */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen log->fd = open(log->filepath, O_RDWR | O_APPEND | O_CREAT, 0666);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("creat(%s) failed: %m", log->filepath);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("%s", eacces_error_get("creat", log->filepath));
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (fchown(log->fd, (uid_t)-1, log->gid) < 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("fchown(%s) failed: %m", log->filepath);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic int mailbox_log_rotate_if_needed(struct mailbox_log *log)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("fstat(%s) failed: %m", log->filepath);
5e9713e7b02b2b47c339476725f9fbfd9bf78cffTimo Sirainen if (rename(log->filepath, log->filepath2) < 0 && errno != ENOENT) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenvoid mailbox_log_record_set_timestamp(struct mailbox_log_record *rec,
b9e830a81455faf3c0dadfc9dbf0c7dc8aca955cJosef 'Jeff' Sipek cpu32_to_be_unaligned(stamp, rec->timestamp);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainentime_t mailbox_log_record_get_timestamp(const struct mailbox_log_record *rec)
b9e830a81455faf3c0dadfc9dbf0c7dc8aca955cJosef 'Jeff' Sipek return (time_t) be32_to_cpu_unaligned(rec->timestamp);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenint mailbox_log_append(struct mailbox_log *log,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen /* we don't have to be too strict about appending to the latest log
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen file. the records' ordering doesn't matter and iteration goes
8a68b403f982d0f1b2d628ea826ea5385771a787Timo Sirainen through both logs anyway. still, if there's a long running session
8a68b403f982d0f1b2d628ea826ea5385771a787Timo Sirainen it shouldn't keep writing to a rotated log forever. */
b3254619187a08d0ecbdfaf4d251468158287c40Timo Sirainen if (log->open_timestamp/MAILBOX_LOG_REOPEN_SECS !=
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen /* We don't bother with locking, atomic appends will protect us.
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen If they don't (NFS), the worst that can happen is that a few
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen records get overwritten (because they're all the same size).
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen This whole log isn't supposed to be super-reliable anyway. */
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("write(%s) failed: %m", log->filepath);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("write(%s) wrote %d/%u bytes", log->filepath,
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (ftruncate(log->fd, st.st_size - ret) < 0) {
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstatic bool mailbox_log_iter_open_next(struct mailbox_log_iter *iter)
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek i_close_fd_path(&iter->fd, iter->filepath);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen else if (iter->filepath == iter->log->filepath2)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen iter->fd = open(iter->filepath, O_RDONLY | O_APPEND);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("open(%s) failed: %m", iter->filepath);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenstruct mailbox_log_iter *mailbox_log_iter_init(struct mailbox_log *log)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenmailbox_log_iter_next(struct mailbox_log_iter *iter)
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen ret = pread(iter->fd, iter->buf, sizeof(iter->buf),
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen i_error("pread(%s) failed: %m", iter->filepath);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen iter->offset += iter->count * sizeof(iter->buf[0]);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen if (rec->type < MAILBOX_LOG_RECORD_DELETE_MAILBOX ||
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainen (iter->count - iter->idx) * sizeof(iter->buf[0]);
3d7590a656f4f746b2adc6e00fa607eba5d2412dTimo Sirainen i_error("Corrupted mailbox log %s at offset %"PRIuUOFF_T": "
3d7590a656f4f746b2adc6e00fa607eba5d2412dTimo Sirainen "type=%d", iter->filepath, offset, rec->type);
fb15bb48cf8be41cd94738c868b64608b4fda1adTimo Sirainenint mailbox_log_iter_deinit(struct mailbox_log_iter **_iter)