From 7ccf3c9341de9dc5319e7269793c4fcc7ece4eab Mon Sep 17 00:00:00 2001 From: Sam Varshavchik Date: Thu, 3 Feb 2022 23:38:02 -0500 Subject: Add additional tests. Test keyword handling. Fix memory corruption in the maildirkw utilty. --- maildir/.gitignore | 1 + maildir/Makefile.am | 8 +- maildir/maildirkeywords2.c | 14 +- maildir/maildirkw.C | 375 +++++++++++++++++++++++++++++++++++++++++++++ maildir/maildirkw.c | 361 ------------------------------------------- maildir/maildirkwtest2.c | 25 +++ maildir/testsuite | 30 +++- maildir/testsuite.txt | 28 ++++ 8 files changed, 476 insertions(+), 366 deletions(-) create mode 100644 maildir/maildirkw.C delete mode 100644 maildir/maildirkw.c create mode 100644 maildir/maildirkwtest2.c diff --git a/maildir/.gitignore b/maildir/.gitignore index 8b7d08e..0d863fa 100644 --- a/maildir/.gitignore +++ b/maildir/.gitignore @@ -21,6 +21,7 @@ /maildirkw.1 /maildirkw.html /maildirkwtest +/maildirkwtest2 /maildirmake /maildirmake.1 /maildirmake.1.in diff --git a/maildir/Makefile.am b/maildir/Makefile.am index bd4dadc..bcac417 100644 --- a/maildir/Makefile.am +++ b/maildir/Makefile.am @@ -53,6 +53,7 @@ libmaildir_la_SOURCES=autoresponse.c autoresponse.h \ maildirwatch.c maildirwatch.h loginexec.c loginexec.h noinst_PROGRAMS=deliverquota maildirmake testmaildirfilter maildirkwtest \ + maildirkwtest2 \ maildirkw maildiracl maildiraclttest testmaildirsearch maildirwatch deliverquota_SOURCES=deliverquota.c @@ -80,12 +81,17 @@ maildirkwtest_LDADD=libmaildir.la maildirkwtest_DEPENDENCIES=libmaildir.la maildirkwtest_LDFLAGS=-static -maildirkw_SOURCES=maildirkw.c +maildirkw_SOURCES=maildirkw.C maildirkw_LDADD=libmaildir.la ../liblock/liblock.la ../numlib/libnumlib.la maildirkw_DEPENDENCIES=libmaildir.la ../liblock/liblock.la \ ../numlib/libnumlib.la maildirkw_LDFLAGS=-static +maildirkwtest2_SOURCES=maildirkw.C maildirkwtest2.c +maildirkwtest2_LDADD=$(maildirkw_LDADD) +maildirkwtest2_DEPENDENCIES=$(maildirkw_DEPENDENCIES) +maildirkwtest2_LDFLAGS=-static + maildirwatch_SOURCES=maildirwatchprog.c maildirwatch_LDADD=libmaildir.la ../liblock/liblock.la ../numlib/libnumlib.la maildirwatch_DEPENDENCIES=libmaildir.la ../liblock/liblock.la \ diff --git a/maildir/maildirkeywords2.c b/maildir/maildirkeywords2.c index 6923a7a..4bcbcff 100644 --- a/maildir/maildirkeywords2.c +++ b/maildir/maildirkeywords2.c @@ -148,7 +148,12 @@ static void doReadKeywords2(const char *maildir, const char *dir, struct keywordUpdateInfo *updateInfo; time_t t=time(NULL); - time_t tn=t/300; + time_t tn; +#ifdef MAILDIRKW_MOCKTIME + MAILDIRKW_MOCKTIME(); +#endif + + tn=t/300; rki->updateNeeded=0; rki->tryagain=0; @@ -307,6 +312,9 @@ int maildir_kwImport(FILE *fp, struct maildir_kwReadInfo *rki) *q++=0; +#ifdef MAILDIRKW_MOCKTIME2 + MAILDIRKW_MOCKTIME2() +#endif i= (*rki->findMessageByFilename)(p, 0, &n, rki->voidarg); @@ -458,7 +466,7 @@ static void scan_updates(const char *dir, if (in >= n) { /* libmail_kwgReadMaildir autocrerate */ - + struct keywordUpdateInfo *u= realloc(*updateInfo, sizeof(**updateInfo) * (in+1)); @@ -919,7 +927,7 @@ static int maildir_kwSaveCommon(const char *maildir, if (p) *p=0; - + maildir_tmpcreate_init(&createInfo); createInfo.maildir=maildir; diff --git a/maildir/maildirkw.C b/maildir/maildirkw.C new file mode 100644 index 0000000..1c17959 --- /dev/null +++ b/maildir/maildirkw.C @@ -0,0 +1,375 @@ +/* +** Copyright 2003-2022 Double Precision, Inc. +** See COPYING for distribution information. +*/ + + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include + +#if HAVE_UNISTD_H +#include +#endif +#include +#include "maildirkeywords.h" +#include "maildirwatch.h" + +#include +#include + +static void usage() +{ + printf("Usage: maildirkw [ options ] maildir [+/-]flag [+/-]flag...\n"); + exit(1); +} + +static int doit_locked(const char *maildir, + const char *filename, + int lockflag, int plusminus, + char **argv, + int optind, int argc) +{ + char *tmpname, *newname; + + if (!plusminus) + { + struct libmail_kwHashtable kwh; + struct libmail_kwMessage *kwm; + + struct libmail_kwGeneric g; + int rc; + + libmail_kwgInit(&g); + + /* Make sure courierimapkeywords directory exists */ + + libmail_kwEnabled=0; + rc=libmail_kwgReadMaildir(&g, maildir); + libmail_kwEnabled=1; + libmail_kwgDestroy(&g); + + if (rc) + return -1; + + + libmail_kwhInit(&kwh); + + if (!(kwm=libmail_kwmCreate())) + { + perror("libmail_kwmCreate"); + return -1; + } + + while (optind < argc) + if (libmail_kwmSetName(&kwh, kwm, + argv[optind++]) < 0) + { + libmail_kwmDestroy(kwm); + perror("libmail_kwmSetName"); + return -1; + } + + if (maildir_kwSave(maildir, filename, kwm, + &tmpname, &newname, 0) < 0) + { + perror(maildir); + libmail_kwmDestroy(kwm); + return -1; + } + libmail_kwmDestroy(kwm); + + if (rename(tmpname, newname) < 0) + { + perror(newname); + free(tmpname); + free(newname); + return -1; + } + free(tmpname); + free(newname); + return 0; + } + else + { + struct libmail_kwGeneric g; + int rc; + struct libmail_kwGenericEntry *e; + struct libmail_kwMessage *kwm, *kwm_alloced; + + libmail_kwgInit(&g); + + rc=libmail_kwgReadMaildir(&g, maildir); + + if (rc != 0) + return rc; + + e=libmail_kwgFindByName(&g, filename); + + kwm_alloced=NULL; + + if (e && e->keywords) + kwm=e->keywords; + else + { + if ((kwm=kwm_alloced=libmail_kwmCreate()) == NULL) + { + perror("libmail_kwmCreate"); + libmail_kwgDestroy(&g); + return -1; + } + } + + while (optind < argc) + { + const char *f=argv[optind++]; + + if ( plusminus == '+') + { + if (libmail_kwmSetName(&g.kwHashTable, + kwm, f) < 0) + { + perror("libmail_kwmSetName"); + if (kwm_alloced) + libmail_kwmDestroy(kwm_alloced + ); + libmail_kwgDestroy(&g); + return -1; + } + } else + { + struct libmail_keywordEntry *kwe= + libmail_kweFind(&g.kwHashTable, + f, 0); + + if (kwe) + libmail_kwmClear(kwm, kwe); + } + } + + rc=maildir_kwSave(maildir, filename, kwm, + &tmpname, &newname, 1); + + if (rc == 0) + { + if (link(tmpname, newname) == 0) + { + struct stat stat_buf; + + if (stat(tmpname, &stat_buf) == 0 && + stat_buf.st_nlink == 2) + unlink(tmpname); + else + rc=1; /* What's up? */ + } + else + { + if (errno == EEXIST) + rc=1; + else + rc= -1; + unlink(tmpname); + } + free(tmpname); + free(newname); + } + + if (kwm_alloced) + libmail_kwmDestroy(kwm_alloced); + libmail_kwgDestroy(&g); + + return rc; + } +} + +static int list_locked(const char *maildir) +{ + struct libmail_kwGeneric g; + int rc; + size_t n; + + libmail_kwgInit(&g); + + rc=libmail_kwgReadMaildir(&g, maildir); + + if (rc) + return rc; + + std::map messages; + + for (n=0; nfilename]=n; + } + + for (auto b=messages.begin(), ee=messages.end(); b != ee; ++b) + { + struct libmail_kwGenericEntry *e= + libmail_kwgFindByIndex(&g, b->second); + struct libmail_kwMessageEntry *k; + + if (!e) + continue; + + printf("%s", e->filename); + + for (k=e->keywords ? e->keywords->firstEntry:NULL; k; + k=k->next) + printf(" %s", keywordName(k->libmail_keywordEntryPtr)); + printf("\n"); + } + libmail_kwgDestroy(&g); + return 0; +} + +static int doit(const char *maildir, const char *filename, int lockflag, + int plusminus, + char **argv, int optind, int argc) +{ + if (lockflag) + { + struct maildirwatch *w=maildirwatch_alloc(maildir); + int tryAnyway; + char *lockname; + int rc; + + if (!w) + { + perror(maildir); + return -1; + } + + lockname=maildir_lock(maildir, w, &tryAnyway); + + if (!lockname) + { + perror(maildir); + if (!tryAnyway) + { + maildirwatch_free(w); + maildirwatch_cleanup(); + return -1; + } + } + + rc=doit_locked(maildir, filename, 1, plusminus, + argv, optind, argc); + if (lockname) + { + unlink(lockname); + free(lockname); + } + maildirwatch_free(w); + maildirwatch_cleanup(); + return rc; + } + + return doit_locked(maildir, filename, 0, plusminus, + argv, optind, argc); +} + +static int dolist(const char *maildir, int lockflag) +{ + if (lockflag) + { + struct maildirwatch *w=maildirwatch_alloc(maildir); + int tryAnyway; + char *lockname; + int rc; + + if (!w) + { + perror(maildir); + return -1; + } + + lockname=maildir_lock(maildir, w, &tryAnyway); + + if (!lockname) + { + perror(maildir); + if (!tryAnyway) + { + maildirwatch_free(w); + maildirwatch_cleanup(); + return -1; + } + } + + rc=list_locked(maildir); + if (lockname) + { + unlink(lockname); + free(lockname); + } + maildirwatch_free(w); + maildirwatch_cleanup(); + return rc; + } + + return list_locked(maildir); +} + +int main(int argc, char *argv[]) +{ + int lockflag=0; + int optc; + const char *maildir; + const char *filename; + int list=0; + int plusminus=0; + int n; + + libmail_kwCaseSensitive=0; + + while ((optc=getopt(argc, argv, "arLlhc")) != -1) + switch (optc) { + case 'c': + libmail_kwCaseSensitive=1; + break; + case 'l': + lockflag=1; + break; + case 'L': + list=1; + break; + case 'a': + plusminus='+'; + break; + case 'r': + plusminus='-'; + break; + default: + usage(); + } + + if (optind >= argc) + usage(); + + maildir=argv[optind++]; + + if (list) + { + exit (dolist(maildir, lockflag)); + } + + if (optind >= argc) + usage(); + + filename=argv[optind++]; + + while ((n=doit(maildir, filename, lockflag, plusminus, + argv, optind, argc)) > 0) + ; + + exit(-n); + return (0); +} diff --git a/maildir/maildirkw.c b/maildir/maildirkw.c deleted file mode 100644 index a0df76c..0000000 --- a/maildir/maildirkw.c +++ /dev/null @@ -1,361 +0,0 @@ -/* -** Copyright 2003-2004 Double Precision, Inc. -** See COPYING for distribution information. -*/ - - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include - -#if HAVE_UNISTD_H -#include -#endif -#include -#include "maildirkeywords.h" -#include "maildirwatch.h" - -static void usage() -{ - printf("Usage: maildirkw [ options ] maildir [+/-]flag [+/-]flag...\n"); - exit(1); -} - -static int doit_locked(const char *maildir, - const char *filename, - int lockflag, int plusminus, - char **argv, - int optind, int argc) -{ - char *tmpname, *newname; - - if (!plusminus) - { - struct libmail_kwHashtable kwh; - struct libmail_kwMessage *kwm; - - struct libmail_kwGeneric g; - int rc; - - libmail_kwgInit(&g); - - /* Make sure courierimapkeywords directory exists */ - - libmail_kwEnabled=0; - rc=libmail_kwgReadMaildir(&g, maildir); - libmail_kwEnabled=1; - libmail_kwgDestroy(&g); - - if (rc) - return -1; - - - libmail_kwhInit(&kwh); - - if (!(kwm=libmail_kwmCreate())) - { - perror("libmail_kwmCreate"); - return -1; - } - - while (optind < argc) - if (libmail_kwmSetName(&kwh, kwm, - argv[optind++]) < 0) - { - libmail_kwmDestroy(kwm); - perror("libmail_kwmSetName"); - return -1; - } - - if (maildir_kwSave(maildir, filename, kwm, - &tmpname, &newname, 0) < 0) - { - perror(maildir); - libmail_kwmDestroy(kwm); - return -1; - } - libmail_kwmDestroy(kwm); - - if (rename(tmpname, newname) < 0) - { - perror(newname); - free(tmpname); - free(newname); - return -1; - } - free(tmpname); - free(newname); - return 0; - } - else - { - struct libmail_kwGeneric g; - int rc; - struct libmail_kwGenericEntry *e; - struct libmail_kwMessage *kwm, *kwm_alloced; - - libmail_kwgInit(&g); - - rc=libmail_kwgReadMaildir(&g, maildir); - - if (rc != 0) - return rc; - - e=libmail_kwgFindByName(&g, filename); - - kwm_alloced=NULL; - - if (e && e->keywords) - kwm=e->keywords; - else - { - if ((kwm=kwm_alloced=libmail_kwmCreate()) == NULL) - { - perror("libmail_kwmCreate"); - libmail_kwgDestroy(&g); - return -1; - } - } - - while (optind < argc) - { - const char *f=argv[optind++]; - - if ( plusminus == '+') - { - if (libmail_kwmSetName(&g.kwHashTable, - kwm, f) < 0) - { - perror("libmail_kwmSetName"); - if (kwm_alloced) - libmail_kwmDestroy(kwm_alloced - ); - libmail_kwgDestroy(&g); - return -1; - } - } else - { - struct libmail_keywordEntry *kwe= - libmail_kweFind(&g.kwHashTable, - f, 0); - - if (kwe) - libmail_kwmClear(kwm, kwe); - } - } - - rc=maildir_kwSave(maildir, filename, kwm, - &tmpname, &newname, 1); - - if (rc == 0) - { - if (link(tmpname, newname) == 0) - { - struct stat stat_buf; - - if (stat(tmpname, &stat_buf) == 0 && - stat_buf.st_nlink == 2) - unlink(tmpname); - else - rc=1; /* What's up? */ - } - else - { - if (errno == EEXIST) - rc=1; - else - rc= -1; - unlink(tmpname); - } - } - - free(tmpname); - free(newname); - if (kwm_alloced) - libmail_kwmDestroy(kwm_alloced); - libmail_kwgDestroy(&g); - - return rc; - } -} - -static int list_locked(const char *maildir) -{ - struct libmail_kwGeneric g; - int rc; - size_t n; - - libmail_kwgInit(&g); - - rc=libmail_kwgReadMaildir(&g, maildir); - - if (rc) - return rc; - - for (n=0; nfilename); - - for (k=e->keywords ? e->keywords->firstEntry:NULL; k; - k=k->next) - printf(" %s", keywordName(k->libmail_keywordEntryPtr)); - printf("\n"); - } - libmail_kwgDestroy(&g); - return 0; -} - -static int doit(const char *maildir, const char *filename, int lockflag, - int plusminus, - char **argv, int optind, int argc) -{ - if (lockflag) - { - struct maildirwatch *w=maildirwatch_alloc(maildir); - int tryAnyway; - char *lockname; - int rc; - - if (!w) - { - perror(maildir); - return -1; - } - - lockname=maildir_lock(maildir, w, &tryAnyway); - - if (!lockname) - { - perror(maildir); - if (!tryAnyway) - { - maildirwatch_free(w); - maildirwatch_cleanup(); - return -1; - } - } - - rc=doit_locked(maildir, filename, 1, plusminus, - argv, optind, argc); - if (lockname) - { - unlink(lockname); - free(lockname); - } - maildirwatch_free(w); - maildirwatch_cleanup(); - return rc; - } - - return doit_locked(maildir, filename, 0, plusminus, - argv, optind, argc); -} - -static int dolist(const char *maildir, int lockflag) -{ - if (lockflag) - { - struct maildirwatch *w=maildirwatch_alloc(maildir); - int tryAnyway; - char *lockname; - int rc; - - if (!w) - { - perror(maildir); - return -1; - } - - lockname=maildir_lock(maildir, w, &tryAnyway); - - if (!lockname) - { - perror(maildir); - if (!tryAnyway) - { - maildirwatch_free(w); - maildirwatch_cleanup(); - return -1; - } - } - - rc=list_locked(maildir); - if (lockname) - { - unlink(lockname); - free(lockname); - } - maildirwatch_free(w); - maildirwatch_cleanup(); - return rc; - } - - return list_locked(maildir); -} - -int main(int argc, char *argv[]) -{ - int lockflag=0; - int optc; - const char *maildir; - const char *filename; - int list=0; - int plusminus=0; - int n; - - libmail_kwCaseSensitive=0; - - while ((optc=getopt(argc, argv, "arLlhc")) != -1) - switch (optc) { - case 'c': - libmail_kwCaseSensitive=1; - break; - case 'l': - lockflag=1; - break; - case 'L': - list=1; - break; - case 'a': - plusminus='+'; - break; - case 'r': - plusminus='-'; - break; - default: - usage(); - } - - if (optind >= argc) - usage(); - - maildir=argv[optind++]; - - if (list) - { - exit (dolist(maildir, lockflag)); - } - - if (optind >= argc) - usage(); - - filename=argv[optind++]; - - while ((n=doit(maildir, filename, lockflag, plusminus, - argv, optind, argc)) > 0) - ; - - exit(-n); - return (0); -} diff --git a/maildir/maildirkwtest2.c b/maildir/maildirkwtest2.c new file mode 100644 index 0000000..9a1dd7d --- /dev/null +++ b/maildir/maildirkwtest2.c @@ -0,0 +1,25 @@ +#define MAILDIRKW_MOCKTIME() \ + do { \ + const char *p=getenv("MOCKTIME"); \ + if (p) \ + t=atoi(p); \ + } while (0) + +#define MAILDIRKW_MOCKTIME2() \ + do { \ + const char *eee=getenv("MOCKTIME"); \ + \ + if (eee && strcmp(eee, "1000") == 0 && \ + strcmp(p, "004") == 0) \ + { \ + printf("Faked stale filename\n"); \ + fflush(stdout); \ + p=NULL; \ + \ + } \ + } while(0); \ + \ + i=NULL; \ + if (p) + +#include "maildirkeywords2.c" diff --git a/maildir/testsuite b/maildir/testsuite index 71b9fe2..7245f9c 100644 --- a/maildir/testsuite +++ b/maildir/testsuite @@ -40,7 +40,7 @@ echo "" $VALGRIND ./maildirkw -L md | sort rm -rf md testmd -maildirmake ./testmd +./maildirmake ./testmd $VALGRIND ./maildiracl -set testmd INBOX.Folder user1 rw $VALGRIND ./maildiracl -list testmd INBOX.Folder | sort @@ -49,3 +49,31 @@ $VALGRIND ./maildirmake -f Folder testmd $VALGRIND ./maildiracl -list testmd INBOX.Folder | sort ls testmd/courierimaphieracl rm -rf testmd + +./maildirmake ./testmd +echo "Subject: message 1" >testmd/cur/001:2,S +echo "Subject: message 2" >testmd/cur/002:2,S +echo "Subject: message 3" >testmd/cur/003:2,S +$VALGRIND ./maildirkw testmd 003 gamma alpha beta +$VALGRIND ./maildirkw testmd 002 alpha gamma +$VALGRIND ./maildirkw testmd 001 beta gamma +$VALGRIND ./maildirkw testmd 004 000 +MOCKTIME=1000 $VALGRIND ./maildirkwtest2 -L testmd +echo "===" +MOCKTIME=1000 $VALGRIND ./maildirkwtest2 -L testmd +MOCKTIME=2000 $VALGRIND ./maildirkwtest2 -L testmd +MOCKTIME=1000 $VALGRIND ./maildirkwtest2 -L testmd +>testmd/courierimapkeywords/.tmp.4.foo +>testmd/courierimapkeywords/.tmp.1000.baz +MOCKTIME=1000 $VALGRIND ./maildirkwtest2 -L testmd +ls testmd/courierimapkeywords/.tmp.* 2>&1 +rm -f testmd/courierimapkeywords/:list +echo "epsilon" >testmd/courierimapkeywords/.1.002 +echo "zeta" >testmd/courierimapkeywords/.2.002 +MOCKTIME=1000 $VALGRIND ./maildirkwtest2 -L testmd +ls testmd/courierimapkeywords/.*002 +$VALGRIND ./maildirkw -a testmd 001 alpha beta +$VALGRIND ./maildirkw -L testmd +$VALGRIND ./maildirkw -r testmd 001 beta +$VALGRIND ./maildirkw -L testmd +rm -rf testmd diff --git a/maildir/testsuite.txt b/maildir/testsuite.txt index ed34d92..cc5eb74 100644 --- a/maildir/testsuite.txt +++ b/maildir/testsuite.txt @@ -38,3 +38,31 @@ administrators aceilrstwx owner aceilrstwx user1 rw Folder.Subfolder +001 beta gamma +002 alpha gamma +003 alpha beta gamma +004 000 +=== +Faked stale filename +001 beta gamma +002 alpha gamma +003 alpha beta gamma +004 000 +001 beta gamma +002 alpha gamma +003 alpha beta gamma +004 000 +Faked stale filename +001 beta gamma +002 alpha gamma +003 alpha beta gamma +001 beta gamma +002 alpha gamma +003 alpha beta gamma +testmd/courierimapkeywords/.tmp.1000.baz +002 zeta +testmd/courierimapkeywords/.2.002 +001 alpha beta +002 zeta +001 alpha +002 zeta -- cgit v1.2.3