From a02794d62dab3ffcc14bafe0ff358bc62905d6ac Mon Sep 17 00:00:00 2001 From: Ken Murchison Date: Tue, 12 Mar 2024 01:55:51 -0400 Subject: [PATCH] mboxlist.c: add 'U' field (user inboxid) to mbentry_t --- imap/ctl_cyrusdb.c | 83 ++++++++++++++++++++++++++++++---------------- imap/mailbox.c | 5 +++ imap/mailbox.h | 1 + imap/mboxlist.c | 19 ++++++++++- imap/mboxlist.h | 3 +- 5 files changed, 80 insertions(+), 31 deletions(-) diff --git a/imap/ctl_cyrusdb.c b/imap/ctl_cyrusdb.c index 0b1ae081614..9a0b9439609 100644 --- a/imap/ctl_cyrusdb.c +++ b/imap/ctl_cyrusdb.c @@ -127,10 +127,17 @@ static void usage(void) exit(-1); } +struct fix_rock { + char *inboxname; + char *inboxid; +}; + /* Callback for use by process_mboxlist */ -static int fixmbox(const mbentry_t *mbentry, - void *rock __attribute__((unused))) +static int fixmbox(const mbentry_t *mbentry, void *rock) { + struct fix_rock *frock = (struct fix_rock *) rock; + struct mailbox *mailbox = NULL; + mbentry_t *copy = NULL; int r, r2; /* if MBTYPE_RESERVED, unset it & call mboxlist_delete */ @@ -160,17 +167,12 @@ static int fixmbox(const mbentry_t *mbentry, buf_free(&buf); free(userid); } - mbentry_t *copy = mboxlist_entry_copy(mbentry); + mbentry = copy = mboxlist_entry_copy(mbentry); xzfree(copy->legacy_specialuse); - mboxlist_updatelock(copy, /*localonly*/1); - mboxlist_entry_free(©); } /* make sure every local mbentry has a uniqueid! */ if (!mbentry->uniqueid && mbentry_is_local_mailbox(mbentry)) { - struct mailbox *mailbox = NULL; - mbentry_t *copy = NULL; - r = mailbox_open_from_mbe(mbentry, &mailbox); if (r) { /* XXX what does it mean if there's an mbentry, but the mailbox @@ -189,35 +191,55 @@ static int fixmbox(const mbentry_t *mbentry, mbentry->name, mailbox->h.uniqueid); } - copy = mboxlist_entry_copy(mbentry); + if (!copy) mbentry = copy = mboxlist_entry_copy(mbentry); copy->uniqueid = xstrdup(mailbox->h.uniqueid); xsyslog(LOG_INFO, "mbentry had no uniqueid, setting from header", "mboxname=<%s> newuniqueid=<%s>", copy->name, copy->uniqueid); +skip_uniqueid: + ; /* hush "label at end of compound statement" warning */ + } + + if (mboxname_isusermailbox(mbentry->name, 1)) { + free(frock->inboxname); + free(frock->inboxid); + frock->inboxname = xstrdup(mbentry->name); + frock->inboxid = xstrdup(mbentry->uniqueid); + } + if (!mbentry->inboxid && frock->inboxname && + mboxname_is_prefix(mbentry->name, frock->inboxname)) { + xsyslog(LOG_INFO, "mbentry had no inboxid, setting from", + "inboxname=<%s> inboxid=<%s>", + frock->inboxname, frock->inboxid); + if (!copy) mbentry = copy = mboxlist_entry_copy(mbentry); + copy->inboxid = xstrdup(frock->inboxid); + } + + if (copy) { r = mboxlist_updatelock(copy, /*localonly*/1); - if (r) { - xsyslog(LOG_ERR, "failed to update mboxlist", - "mboxname=<%s> error=<%s>", - mbentry->name, error_message(r)); - r2 = mailbox_abort(mailbox); - if (r2) { - xsyslog(LOG_ERR, "DBERROR: error aborting transaction", - "error=<%s>", cyrusdb_strerror(r2)); + mboxlist_entry_free(©); + + if (mailbox) { + if (r) { + xsyslog(LOG_ERR, "failed to update mboxlist", + "mboxname=<%s> error=<%s>", + mbentry->name, error_message(r)); + r2 = mailbox_abort(mailbox); + if (r2) { + xsyslog(LOG_ERR, "DBERROR: error aborting transaction", + "error=<%s>", cyrusdb_strerror(r2)); + } } - } - else { - r2 = mailbox_commit(mailbox); - if (r2) { - xsyslog(LOG_ERR, "DBERROR: error committing transaction", - "error=<%s>", cyrusdb_strerror(r2)); + else { + r2 = mailbox_commit(mailbox); + if (r2) { + xsyslog(LOG_ERR, "DBERROR: error committing transaction", + "error=<%s>", cyrusdb_strerror(r2)); + } } + mailbox_close(&mailbox); } - mailbox_close(&mailbox); - mboxlist_entry_free(©); - -skip_uniqueid: - ; /* hush "label at end of compound statement" warning */ } return 0; @@ -229,7 +251,10 @@ static void process_mboxlist(int *upgraded) mboxlist_upgrade(upgraded); /* run fixmbox across all mboxlist entries */ - mboxlist_allmbox(NULL, fixmbox, NULL, MBOXTREE_INTERMEDIATES); + struct fix_rock frock = { 0 }; + mboxlist_allmbox(NULL, fixmbox, &frock, MBOXTREE_INTERMEDIATES); + free(frock.inboxname); + free(frock.inboxid); /* enable or disable RACLs per config */ mboxlist_set_racls(config_getswitch(IMAPOPT_REVERSEACLS)); diff --git a/imap/mailbox.c b/imap/mailbox.c index a61968ee597..83cc0fab877 100644 --- a/imap/mailbox.c +++ b/imap/mailbox.c @@ -1133,6 +1133,11 @@ EXPORTED const char *mailbox_uniqueid(const struct mailbox *mailbox) return mbentry->uniqueid ? mbentry->uniqueid : mailbox->h.uniqueid; } +EXPORTED const char *mailbox_inboxid(const struct mailbox *mailbox) +{ + return mailbox->mbentry->inboxid; +} + EXPORTED const char *mailbox_partition(const struct mailbox *mailbox) { return mailbox->mbentry->partition; diff --git a/imap/mailbox.h b/imap/mailbox.h index 471987efd6c..e8c64ba295b 100644 --- a/imap/mailbox.h +++ b/imap/mailbox.h @@ -590,6 +590,7 @@ extern int mailbox_delete(struct mailbox **mailboxptr); /* reading details */ extern const char *mailbox_name(const struct mailbox *mailbox); extern const char *mailbox_uniqueid(const struct mailbox *mailbox); +extern const char *mailbox_inboxid(const struct mailbox *mailbox); extern const char *mailbox_partition(const struct mailbox *mailbox); extern const char *mailbox_acl(const struct mailbox *mailbox); extern const char *mailbox_quotaroot(const struct mailbox *mailbox); diff --git a/imap/mboxlist.c b/imap/mboxlist.c index fb567578441..04c814f9935 100644 --- a/imap/mboxlist.c +++ b/imap/mboxlist.c @@ -148,6 +148,7 @@ EXPORTED mbentry_t *mboxlist_entry_copy(const mbentry_t *src) copy->server = xstrdupnull(src->server); copy->acl = xstrdupnull(src->acl); copy->uniqueid = xstrdupnull(src->uniqueid); + copy->inboxid = xstrdupnull(src->inboxid); copy->legacy_specialuse = xstrdupnull(src->legacy_specialuse); @@ -187,6 +188,7 @@ EXPORTED void mboxlist_entry_free(mbentry_t **mbentryptr) free(mbentry->server); free(mbentry->acl); free(mbentry->uniqueid); + free(mbentry->inboxid); free(mbentry->legacy_specialuse); @@ -273,6 +275,9 @@ static struct dlist *mboxlist_entry_dlist(const char *dbname, else if (mbentry->uniqueid) dlist_setatom(dl, "I", mbentry->uniqueid); + if (mbentry->inboxid) + dlist_setatom(dl, "U", mbentry->inboxid); + if (mbentry->partition) dlist_setatom(dl, "P", mbentry->partition); @@ -618,6 +623,9 @@ static int parseentry_cb(int type, struct dlistsax_data *d) else if (!strcmp(key, "I")) { rock->mbentry->uniqueid = xstrdupnull(d->data); } + else if (!strcmp(key, "U")) { + rock->mbentry->inboxid = xstrdupnull(d->data); + } else if (!strcmp(key, "M")) { rock->mbentry->mtime = atoi(d->data); } @@ -652,6 +660,7 @@ static int parseentry_cb(int type, struct dlistsax_data *d) * F: _f_oldermodseq * H: name_h_istory * I: unique_i_d + * U: _u_serinboxid * M: _m_time * N: _n_ame * P: _p_artition @@ -1865,6 +1874,7 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry, int isremote = mbtype & MBTYPE_REMOTE; mbentry_t *usermbentry = NULL, *newmbentry = NULL; int silent = 0; + int isinbox; init_internal(); @@ -1874,6 +1884,8 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry, assert_namespacelocked(mboxname); + isinbox = mboxname_isusermailbox(mboxname, 1); + if ((flags & MBOXLIST_CREATE_SYNC)) { silent = 1; } @@ -1933,9 +1945,11 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry, newmbentry->mbtype = mbtype; newmbentry->partition = xstrdupnull(newpartition); newmbentry->uniqueid = xstrdup(uniqueid ? uniqueid : makeuuid()); + if (isinbox) newmbentry->inboxid = xstrdup(newmbentry->uniqueid); + else if (usermbentry) newmbentry->inboxid = xstrdup(usermbentry->uniqueid); if (!(flags & MBOXLIST_CREATE_DBONLY) && !isremote) { - if (mboxname_isusermailbox(mboxname, 1)) { + if (isinbox) { /* Create initial mbentry for new users -- the uniqueid in the record is required to open user metadata files (conversations, counters) */ @@ -2766,6 +2780,7 @@ EXPORTED int mboxlist_renamemailbox(const mbentry_t *mbentry, newmbentry->acl = xstrdupnull(mailbox_acl(oldmailbox)); newmbentry->uidvalidity = oldmailbox->i.uidvalidity; newmbentry->uniqueid = xstrdupnull(mailbox_uniqueid(oldmailbox)); + newmbentry->inboxid = xstrdupnull(mailbox_inboxid(oldmailbox)); newmbentry->createdmodseq = oldmailbox->i.createdmodseq; newmbentry->foldermodseq = silent ? mailbox_foldermodseq(oldmailbox) : mboxname_nextmodseq(newname, mailbox_foldermodseq(oldmailbox), @@ -2830,6 +2845,7 @@ EXPORTED int mboxlist_renamemailbox(const mbentry_t *mbentry, newmbentry->acl = xstrdupnull(mailbox_acl(newmailbox)); newmbentry->uidvalidity = newmailbox->i.uidvalidity; newmbentry->uniqueid = xstrdupnull(mailbox_uniqueid(newmailbox)); + newmbentry->inboxid = xstrdupnull(mailbox_inboxid(newmailbox)); newmbentry->createdmodseq = newmailbox->i.createdmodseq; newmbentry->foldermodseq = newmailbox->i.highestmodseq; } @@ -2842,6 +2858,7 @@ EXPORTED int mboxlist_renamemailbox(const mbentry_t *mbentry, newmbentry->acl = xstrdupnull(mailbox_acl(oldmailbox)); newmbentry->uidvalidity = oldmailbox->i.uidvalidity; newmbentry->uniqueid = xstrdupnull(mailbox_uniqueid(oldmailbox)); + newmbentry->inboxid = xstrdupnull(mailbox_inboxid(oldmailbox)); newmbentry->createdmodseq = oldmailbox->i.createdmodseq; newmbentry->foldermodseq = oldmailbox->i.highestmodseq; diff --git a/imap/mboxlist.h b/imap/mboxlist.h index f73952be6fd..26584cbc9da 100644 --- a/imap/mboxlist.h +++ b/imap/mboxlist.h @@ -120,6 +120,7 @@ struct mboxlist_entry { char *acl; /* extra fields */ char *uniqueid; + char *inboxid; /* legacy upgrade support */ char *legacy_specialuse; /* replication support */ @@ -127,7 +128,7 @@ struct mboxlist_entry { }; #define MBENTRY_INITIALIZER { NULL, NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, \ - NULL, NULL, PTRARRAY_INITIALIZER } + NULL, NULL, NULL, PTRARRAY_INITIALIZER } typedef struct mboxlist_entry mbentry_t;