From 8fee4cbd63b4682e0df8cd78bae906727d044165 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Fri, 10 Apr 2020 11:16:34 -0400 Subject: Use UIDNEXT to avoid asking IMAP to do any work --- .gitignore | 1 + archive.c | 67 +++++++++++++++++++++++++++++++++++++++----------------------- bubger.1 | 4 +++- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 0af5f60..e96af27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o UID/ +UIDNEXT UIDVALIDITY bubger tags diff --git a/archive.c b/archive.c index 2e8bf31..97bb99a 100644 --- a/archive.c +++ b/archive.c @@ -29,27 +29,22 @@ #define ENV_PASSWORD "BUBGER_IMAP_PASSWORD" -static void checkValidity(uint32_t validity) { - FILE *file = fopen("UIDVALIDITY", "r"); - if (file) { - uint32_t previous; - int n = fscanf(file, "%" SCNu32, &previous); - if (n < 1) errx(EX_DATAERR, "invalid UIDVALIDITY file"); - - if (validity != previous) { - errx(EX_TEMPFAIL, "UIDVALIDITY changed; fresh export required"); - } - - } else { - FILE *file = fopen("UIDVALIDITY", "w"); - if (!file) err(EX_CANTCREAT, "UIDVALIDITY"); - - int n = fprintf(file, "%" PRIu32 "\n", validity); - if (n < 0) err(EX_IOERR, "UIDVALIDITY"); +static uint32_t uidRead(const char *path) { + FILE *file = fopen(path, "r"); + if (!file) return 0; + uint32_t uid; + int n = fscanf(file, "%" SCNu32, &uid); + if (n < 1) errx(EX_DATAERR, "%s: invalid UID", path); + return uid; +} - int error = fclose(file); - if (error) err(EX_IOERR, "UIDVALIDITY"); - } +static void uidWrite(const char *path, uint32_t uid) { + FILE *file = fopen(path, "w"); + if (!file) err(EX_CANTCREAT, "%s", path); + int n = fprintf(file, "%" PRIu32 "\n", uid); + if (n < 0) err(EX_IOERR, "%s", path); + int error = fclose(file); + if (error) err(EX_IOERR, "%s", path); } int main(int argc, char *argv[]) { @@ -129,13 +124,35 @@ int main(int argc, char *argv[]) { if ( resp.resp == AtomOk && resp.code.len > 1 && - resp.code.ptr[0].type == Atom && - resp.code.ptr[0].atom == AtomUIDValidity + resp.code.ptr[0].type == Atom ) { - if (resp.code.ptr[1].type != Number) { - errx(EX_PROTOCOL, "invalid UIDVALIDITY"); + enum Atom code = resp.code.ptr[0].atom; + if (code == AtomUIDValidity || code == AtomUIDNext) { + if (resp.code.ptr[1].type != Number) { + errx(EX_PROTOCOL, "invalid %s", Atoms[code]); + } + } + if (code == AtomUIDValidity) { + uint32_t validity = resp.code.ptr[1].number; + uint32_t previous = uidRead("UIDVALIDITY"); + if (previous && validity != previous) { + errx( + EX_TEMPFAIL, + "UIDVALIDITY changed; fresh export required" + ); + } + if (!previous) uidWrite("UIDVALIDITY", validity); + } + if (code == AtomUIDNext) { + uint32_t next = resp.code.ptr[1].number; + uint32_t prev = uidRead("UIDNEXT"); + if (next == prev) { + examine = 0; + fprintf(imap, "ayy LOGOUT\r\n"); + } else { + uidWrite("UIDNEXT", next); + } } - checkValidity(resp.code.ptr[1].number); } if (resp.tag == examine) { diff --git a/bubger.1 b/bubger.1 index 68a3adb..db93077 100644 --- a/bubger.1 +++ b/bubger.1 @@ -1,4 +1,4 @@ -.Dd April 9, 2020 +.Dd April 10, 2020 .Dt BUBGER 1 .Os . @@ -104,6 +104,8 @@ The IMAP password. .Bl -tag -width Ds .It Pa UIDVALIDITY Stores the mailbox UID validity. +.It Pa UIDNEXT +Stores the next UID of the mailbox. .It Pa UID/*.atom , Pa UID/*.html , Pa UID/*.mbox Cached Atom, HTML and mboxrd fragments for each message. .It Pa thread/*.atom , Pa thread/*.html , Pa thread/*.mbox -- cgit 1.4.1