Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mboxlist.c: add 'R' field (rootid, a.k.a. inboxid) to mbentry_t #4838

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 54 additions & 29 deletions imap/ctl_cyrusdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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(&copy);
}

/* 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
Expand All @@ -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 inbox",
"mboxname=<%s> inboxname=<%s> inboxid=<%s>",
mbentry->name, 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(&copy);

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(&copy);

skip_uniqueid:
; /* hush "label at end of compound statement" warning */
}

return 0;
Expand All @@ -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));
Expand Down
3 changes: 3 additions & 0 deletions imap/ctl_mboxlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,9 @@ static int dump_cb(const mbentry_t *mbentry, void *rockp)
/* char *uniqueid; */
json_object_set_new(jobj, "uniqueid", json_string(mbentry->uniqueid));

/* char *inboxid; */
json_object_set_new(jobj, "inboxid", json_string(mbentry->inboxid));

/* char *legacy_specialuse; */
json_object_set_new(jobj, "legacy_specialuse",
json_string(mbentry->legacy_specialuse));
Expand Down
25 changes: 23 additions & 2 deletions imap/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,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;
Expand Down Expand Up @@ -5868,10 +5873,10 @@ EXPORTED int mailbox_create(const char *name,
mailbox = create_listitem(lockname);

/* needs to be an exclusive namelock to create a mailbox */
char *userid = mboxname_to_userid(name);
mbname_t *mbname = mbname_from_intname(name);
const char *userid = mbname_userid(mbname);
int haslock = user_isnamespacelocked(userid);
assert(haslock == LOCK_EXCLUSIVE);
free(userid);

r = mboxname_lock(mailbox->lockname, &mailbox->namelock, LOCK_EXCLUSIVE);
if (r) {
Expand All @@ -5887,6 +5892,22 @@ EXPORTED int mailbox_create(const char *name,
mailbox->mbentry->mbtype = mbtype;
mailbox->mbentry->uniqueid = xstrdup(uniqueid);

if (userid) {
// add inboxid to mbentry
if (!strarray_size(mbname_boxes(mbname)))
mailbox->mbentry->inboxid = xstrdup(uniqueid);
else {
mbentry_t *usermbentry = NULL;
mbname_set_boxes(mbname, NULL);
mboxlist_lookup(mbname_intname(mbname), &usermbentry, NULL);
if (usermbentry) {
mailbox->mbentry->inboxid = xstrdup(usermbentry->uniqueid);
mboxlist_entry_free(&usermbentry);
}
}
}
mbname_free(&mbname);

// fill out the header too
mailbox->h.name = xstrdup(name);
mailbox->h.acl = xstrdup(acl);
Expand Down
1 change: 1 addition & 0 deletions imap/mailbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ extern int mailbox_delete(struct mailbox **mailboxptr);
extern const struct mboxlist_entry *mailbox_mbentry(const struct mailbox *mailbox);
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);
Expand Down
19 changes: 18 additions & 1 deletion imap/mboxlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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, "R", mbentry->inboxid);

if (mbentry->partition)
dlist_setatom(dl, "P", mbentry->partition);

Expand Down Expand Up @@ -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, "R")) {
rock->mbentry->inboxid = xstrdupnull(d->data);
}
else if (!strcmp(key, "M")) {
rock->mbentry->mtime = atoi(d->data);
}
Expand Down Expand Up @@ -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
* R: _r_ootmailboxid (inboxid)
* M: _m_time
* N: _n_ame
* P: _p_artition
Expand Down Expand Up @@ -1899,6 +1908,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();

Expand All @@ -1908,6 +1918,8 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,

assert_namespacelocked(mboxname);

isinbox = mboxname_isusermailbox(mboxname, 1);

if ((flags & MBOXLIST_CREATE_SYNC)) {
silent = 1;
}
Expand Down Expand Up @@ -1967,9 +1979,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) */
Expand Down Expand Up @@ -2799,6 +2813,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),
Expand Down Expand Up @@ -2863,6 +2878,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;
}
Expand All @@ -2875,6 +2891,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;

Expand Down
3 changes: 2 additions & 1 deletion imap/mboxlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,15 @@ struct mboxlist_entry {
char *acl;
/* extra fields */
char *uniqueid;
char *inboxid;
/* legacy upgrade support */
char *legacy_specialuse;
/* replication support */
ptrarray_t name_history;
};

#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;

Expand Down
Loading