3b000774cc
Patch by Demi <m@tfiu.de> to fix Debian bug #621690. From https://bugs.debian.org/621690: > wmbiff change path of my mailboxes next nearest. > > For example wmbiff change 'gleb' to 'glil' for second and fourth mailboxes. > However the 1st, 3rd and 5th mailboxes have correct path. Well, the indices don't really enter. I'm actually surprised this isn't more trouble. The underlying reason is that in wmbiff.c:parse_mbox_path, the program calls mboxCreate((&mbox[item]), mbox[item].path); which for maildirs calls int maildirCreate(Pop3 pc, const char *str) in maildirClient.c. str in this way is an alias for pc->path. In maildirCreate, after some char acrobatics, the program eventually does strncpy(pc->path, str + 8 + i, BUF_BIG - 1); to cut off the leading stuff from the maildir. The result of this operation is not defined, as pc->path and str point to the same memory and thus the arguments overlap, which strncpy outlaws. A simple fix is to copy manually, like this: DM(pc, DEBUG_ERROR, "maildir '%s' is too long.\n", str + 8 + i); memset(pc->path, 0, BUF_BIG); } else { + const char *sp = str + 8 + i; + char *dp = pc->path; + + while (*sp && sp-str<BUF_BIG-1) { + *dp++ = *sp++; + } + *dp = 0; - strncpy(pc->path, , BUF_BIG - 1); /* cut off ``maildir:'' */ } -- it's what I'm doing now. But I give you that's a bit pedestrian.
194 lines
4.5 KiB
C
194 lines
4.5 KiB
C
/* $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 <config.h>
|
|
#endif
|
|
|
|
#include "Client.h"
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <utime.h>
|
|
#include <unistd.h>
|
|
#ifdef USE_DMALLOC
|
|
#include <dmalloc.h>
|
|
#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 {
|
|
const char *sp = str + 8 + i;
|
|
char *dp = pc->path;
|
|
|
|
while (*sp && sp-str<BUF_BIG-1) {
|
|
*dp++ = *sp++;
|
|
}
|
|
*dp = 0;
|
|
}
|
|
|
|
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:
|
|
*/
|