/* $Id: maildirClient.c,v 1.15 2004/03/28 00:28:58 bluehal Exp $ */ /* Author : Yong-iL Joh ( tolkien@mizi.com ) Modified : Jorge García ( Jorge.Garcia@uv.es ) Modified : Dwayne C. Litzenberger ( dlitz@dlitz.net ) * * Maildir checker. * * Last Updated : $Date: 2004/03/28 00:28:58 $ * */ #ifdef HAVE_CONFIG_H #include #endif #include "Client.h" #include #include #include #include #include #include #ifdef USE_DMALLOC #include #endif #define PCM (pc->u).maildir static int count_msgs(char *path) { DIR *D; struct dirent *de; int count = 0; D = opendir(path); if (D == NULL) { DMA(DEBUG_ERROR, "Error opening directory '%s': %s\n", path, strerror(errno)); return -1; } while ((de = readdir(D)) != NULL) { if ((strcmp(de->d_name, ".") & strcmp(de->d_name, "..")) != 0) { count++; } } closedir(D); return count; } int maildirCheckHistory(Pop3 pc) { struct stat st_new; struct stat st_cur; struct utimbuf ut; char path_new[BUF_BIG * 2], path_cur[BUF_BIG * 2]; int count_new = 0, count_cur = 0; DM(pc, DEBUG_INFO, ">Maildir: '%s'\n", pc->path); strcpy(path_new, pc->path); strcat(path_new, "/new/"); strcpy(path_cur, pc->path); strcat(path_cur, "/cur/"); if (pc->u.maildir.dircache_flush) { /* hack to clear directory cache for network-mounted maildirs */ int fd; char path_newtmp[BUF_BIG * 2 + 32]; strcpy(path_newtmp, path_new); strcat(path_newtmp, ".wmbiff.dircache_flush.XXXXXX"); if ((fd = mkstemp(path_newtmp)) >= 0) { close(fd); unlink(path_newtmp); } else { DM(pc, DEBUG_ERROR, "Can't create dircache flush file '%s': %s\n", path_newtmp, strerror(errno)); } } /* maildir */ if (stat(path_new, &st_new)) { DM(pc, DEBUG_ERROR, "Can't stat mailbox '%s': %s\n", path_new, strerror(errno)); return -1; /* Error stating mailbox */ } if (stat(path_cur, &st_cur)) { DM(pc, DEBUG_ERROR, "Can't stat mailbox '%s': %s\n", path_cur, strerror(errno)); return -1; /* Error stating mailbox */ } /* file was changed OR initially read */ if (st_new.st_mtime != PCM.mtime_new || st_new.st_size != PCM.size_new || st_cur.st_mtime != PCM.mtime_cur || st_cur.st_size != PCM.size_cur || pc->OldMsgs < 0) { DM(pc, DEBUG_INFO, " was changed,\n" " TIME(new): old %lu, new %lu" " SIZE(new): old %lu, new %lu\n" " TIME(cur): old %lu, new %lu" " SIZE(cur): old %lu, new %lu\n", PCM.mtime_new, (unsigned long) st_new.st_mtime, (unsigned long) PCM.size_new, (unsigned long) st_new.st_size, PCM.mtime_cur, (unsigned long) st_cur.st_mtime, (unsigned long) PCM.size_cur, (unsigned long) st_cur.st_size); count_new = count_msgs(path_new); count_cur = count_msgs(path_cur); if ((count_new | count_cur) == -1) { /* errors occurred */ return -1; } pc->TotalMsgs = count_cur + count_new; pc->UnreadMsgs = count_new; /* Reset atime for MUTT and something others work correctly */ ut.actime = st_new.st_atime; ut.modtime = st_new.st_mtime; utime(path_new, &ut); ut.actime = st_cur.st_atime; ut.modtime = st_cur.st_mtime; utime(path_cur, &ut); /* Store new values */ PCM.mtime_new = st_new.st_mtime; /* Store new mtime_new */ PCM.size_new = st_new.st_size; /* Store new size_new */ PCM.mtime_cur = st_cur.st_mtime; /* Store new mtime_cur */ PCM.size_cur = st_cur.st_size; /* Store new size_cur */ } return 0; } int maildirCreate(Pop3 pc, const char *str) { int i; char c; /* Maildir format: maildir:fullpathname */ pc->TotalMsgs = 0; pc->UnreadMsgs = 0; pc->OldMsgs = -1; pc->OldUnreadMsgs = -1; pc->checkMail = maildirCheckHistory; pc->u.maildir.dircache_flush = 0; /* special flags */ if (*(str + 8) == ':') { /* path is of the format maildir::flags:path */ c = ' '; for (i = 1; c != ':' && c != '\0'; i++) { c = *(str + 8 + i); switch (c) { case 'F': pc->u.maildir.dircache_flush = 1; DM(pc, DEBUG_INFO, "maildir: dircache_flush enabled\n"); } } } else { i = 0; } if (strlen(str + 8 + i) + 1 > BUF_BIG) { DM(pc, DEBUG_ERROR, "maildir '%s' is too long.\n", str + 8 + i); memset(pc->path, 0, BUF_BIG); } else { strncpy(pc->path, str + 8 + i, BUF_BIG - 1); /* cut off ``maildir:'' */ } DM(pc, DEBUG_INFO, "maildir: str = '%s'\n", str); DM(pc, DEBUG_INFO, "maildir: path= '%s'\n", pc->path); return 0; } /* vim:set ts=4: */ /* * Local Variables: * tab-width: 4 * c-indent-level: 4 * c-basic-offset: 4 * End: */