mailbox-uidvalidity.c revision 0e881a691e6d2d2836d923ef3e92b14aeda60f0d
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainenstatic uint32_t mailbox_uidvalidity_next_fallback(void)
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* we failed to use the uidvalidity file. don't fail the mailbox
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen creation because of it though, most of the time it's safe enough
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen to use the current time as the uidvalidity value. */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainenstatic void mailbox_uidvalidity_write(const char *path, uint32_t uid_validity)
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen i_snprintf(buf, sizeof(buf), "%08x", uid_validity);
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainenstatic int mailbox_uidvalidity_rename(const char *path, uint32_t *uid_validity)
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen unsigned int i, prefix_len;
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen for (i = 0; i < RETRY_COUNT; i++) {
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen if ((ret = rename(str_c(src), str_c(dest))) == 0 ||
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* possibly a race condition. try the next value. */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen i_error("rename(%s, %s) failed: %m", str_c(src), str_c(dest));
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainenstatic uint32_t mailbox_uidvalidity_next_rescan(const char *path)
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen unsigned int i, prefix_len;
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* just in case there happens to be multiple matching uidvalidity
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen files, track the min/max values. use the max value and delete the
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen min value file. */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen if (strncmp(dp->d_name, prefix, prefix_len) == 0) {
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen cur_value = strtoul(dp->d_name + prefix_len, &endp, 16);
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* no uidvalidity files. create one. */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen for (i = 0; i < RETRY_COUNT; i++) {
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen cur_value = mailbox_uidvalidity_next_fallback();
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen tmp = t_strdup_printf("%s.%08x", path, cur_value);
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen fd = open(tmp, O_RDWR | O_CREAT | O_EXCL, 0666);
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* already exists. although it's quite unlikely we'll
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen hit this race condition. more likely we'll create
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen a duplicate file.. */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* duplicate uidvalidity files, delete the oldest */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen tmp = t_strdup_printf("%s.%08x", path, min_value);
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen if (mailbox_uidvalidity_rename(path, &cur_value) < 0)
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainenuint32_t mailbox_uidvalidity_next(const char *path)
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* broken value */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* we now have the current uidvalidity value that's hopefully correct */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen if (mailbox_uidvalidity_rename(path, &cur_value) < 0)
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen /* fast path succeeded. write the current value to the main
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen uidvalidity file. */
300baf826ba39003b861e7716c35bae372e6f23eTimo Sirainen i_snprintf(buf, sizeof(buf), "%08x", cur_value);