maildir-uidlist.c revision 0add8c99ca65e56dbf613595fc37c41aafff3f7f
/* Copyright (C) 2003 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "buffer.h"
#include "hash.h"
#include "istream.h"
#include "str.h"
#include "file-dotlock.h"
#include "write-full.h"
#include "maildir-storage.h"
#include "maildir-uidlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <utime.h>
/* how many seconds to wait before overriding uidlist.lock */
#define UIDLIST_IS_LOCKED(uidlist) \
#define MAILDIR_UIDLIST_REC_FLAG_NEW_DIR 0x01
struct maildir_uidlist_rec {
char *filename;
};
struct maildir_uidlist {
struct index_mailbox *ibox;
char *fname;
int lock_fd;
struct hash_table *files;
unsigned int version;
};
struct maildir_uidlist_sync_ctx {
struct maildir_uidlist *uidlist;
struct hash_table *files;
unsigned int new_files:1;
unsigned int synced:1;
unsigned int failed:1;
};
struct maildir_uidlist_iter_ctx {
};
{
const char *path;
int fd;
if (UIDLIST_IS_LOCKED(uidlist))
return 1;
if (fd == -1) {
return 0;
"file_dotlock_open(%s) failed: %m", path);
return -1;
}
return 1;
}
{
const char *path;
if (!UIDLIST_IS_LOCKED(uidlist))
return;
}
{
struct maildir_uidlist *uidlist;
return uidlist;
}
{
}
const char *line)
{
struct maildir_uidlist_rec *rec;
line++;
}
/* invalid file */
return 0;
}
"UIDs not ordered in file %s (%u > %u)",
return 0;
}
"UID larger than next_uid in file %s (%u >= %u)",
return 0;
}
flags = 0;
while (*line != ' ') {
switch (*line) {
case 'N':
break;
}
line++;
}
} else {
/* old version, have to assume it's in new dir since we
don't know */
}
"Duplicate file in uidlist file %s: %s",
return 0;
}
return 1;
}
{
const char *line;
if (uidlist->last_mtime != 0) {
return -1;
}
return 0;
}
/* unchanged */
return 1;
}
}
if (fd == -1) {
return -1;
}
return 0;
}
return -1;
}
else {
pool_alloconly_create("uidlist filename_pool",
}
/* get header */
/* broken file */
"Corrupted header in file %s (version = %u)",
ret = 0;
} else {
ret = 1;
ret = 0;
break;
}
}
}
if (ret != 0)
else {
uidlist->last_mtime = 0;
}
return ret;
}
{
const struct maildir_uidlist_rec *rec;
idx = 0;
left_idx = 0;
else {
}
}
return NULL;
}
const char *temp_path)
{
struct maildir_uidlist_iter_ctx *iter;
int ret = 0;
/* flush buffer */
"write_full(%s) failed: %m", temp_path);
ret = -1;
break;
}
str_truncate(str, 0);
}
"N" : "-";
}
if (ret < 0)
return -1;
"write_full(%s) failed: %m", temp_path);
return -1;
}
/* uidlist's mtime must grow every time */
"utime(%s) failed: %m", temp_path);
return -1;
}
"fsync(%s) failed: %m", temp_path);
return -1;
}
return 0;
}
{
int ret;
if (ret == 0) {
FALSE) <= 0) {
"file_dotlock_replace(%s) failed: %m", db_path);
ret = -1;
}
} else {
}
if (ret < 0)
return ret;
}
struct maildir_uidlist_sync_ctx *
{
struct maildir_uidlist_sync_ctx *ctx;
ctx->filename_pool =
if (uidlist->last_mtime == 0) {
/* uidlist not read yet, do it */
if (maildir_uidlist_update(uidlist) < 0)
}
return ctx;
}
{
struct maildir_uidlist_rec *rec;
char *fname;
int ret;
return -1;
/* possibly duplicate */
return 0;
}
} else {
/* lock and update uidlist to see if it's just
been added */
if (ret <= 0) {
if (ret == 0)
return 1; // FIXME: does it work right?
return -1;
}
return -1;
}
}
}
}
return 1;
}
{
/* we have to do numeric comparision, strcmp() will break when
there's different amount of digits (mostly the 999999999 ->
1000000000 change in Sep 9 2001) */
s1++;
}
s2++;
}
}
{
struct maildir_uidlist_rec *rec;
struct hash_iterate_context *iter;
/* update filename pointers, skip deleted messages */
dest++;
}
}
/* append new files */
sizeof(*rec));
}
}
/* sort new files and assign UIDs for them */
}
{
int ret;
ret = -1;
else {
ret = 0;
else
}
return ret;
}
struct maildir_uidlist_iter_ctx *
{
struct maildir_uidlist_iter_ctx *ctx;
return ctx;
}
const char **filename_r)
{
return 0;
return 1;
}
{
}