static int mailbox_open_advanced(const char *name,
                                 int locktype,
                                 int index_locktype,
                                 const mbentry_t *mbe,
                                 struct mailbox **mailboxptr)
{
    mbentry_t *mbentry = NULL;
    struct mailboxlist *listitem;
    struct mailbox *mailbox = NULL;
    int r = 0;

    assert(*mailboxptr == NULL);

    listitem = find_listitem(name);

    /* already open?  just use this one */
    if (listitem) {
        /* can't reuse an exclusive locked mailbox */
        if (listitem->l->locktype == LOCK_EXCLUSIVE)
            return IMAP_MAILBOX_LOCKED;
        if (locktype == LOCK_EXCLUSIVE)
            return IMAP_MAILBOX_LOCKED;
        /* can't reuse an already locked index */
        if (listitem->m.index_locktype)
            return IMAP_MAILBOX_LOCKED;

        listitem->nopen++;
        mailbox = &listitem->m;

        goto lockindex;
    }

    listitem = create_listitem(name);
    mailbox = &listitem->m;

    // lock the user namespace FIRST before the mailbox namespace
    char *userid = mboxname_to_userid(name);
    if (userid) {
        int haslock = user_isnamespacelocked(userid);
        if (haslock) {
            if (index_locktype != LOCK_SHARED) assert(haslock != LOCK_SHARED);
        }
        else {
            int locktype = index_locktype;
            mailbox->local_namespacelock = user_namespacelock_full(userid, locktype);
        }
        free(userid);
    }

    if (mbe) mbentry = mboxlist_entry_copy(mbe);
    else r = mboxlist_lookup_allow_all(name, &mbentry, NULL);

    if (!r && mbentry->mbtype & MBTYPE_DELETED)
        r = IMAP_MAILBOX_NONEXISTENT;

    if (r) {
        if (mailbox->local_namespacelock)
            mboxname_release(&mailbox->local_namespacelock);
        mboxlist_entry_free(&mbentry);
        remove_listitem(listitem);
        return r;
    }

    /* XXX can we even get here for remote mbentries? */
    if (!mbentry->uniqueid && mbentry_is_local_mailbox(mbentry)) {
        /* Theoretically it shouldn't be possible for an mbentry to not
         * have a uniqueid... so if it happens, complain loudly.
         */
        xsyslog(LOG_ERR, "mbentry has no uniqueid, needs reconstruct",
                         "mboxname=<%s>", name);
    }

    uint32_t legacy_dirs = (mbentry->mbtype & MBTYPE_LEGACY_DIRS);
    r = mboxname_lock(legacy_dirs ? name : mbentry->uniqueid, &listitem->l, locktype);
    if (r) {
        /* locked is not an error - just means we asked for NONBLOCKING */
        if (r != IMAP_MAILBOX_LOCKED)
            xsyslog(LOG_ERR, "IOERROR: lock failed",
                             "mailbox=<%s> error=<%s>",
                             name, error_message(r));
        if (mailbox->local_namespacelock)
            mboxname_release(&mailbox->local_namespacelock);
        mboxlist_entry_free(&mbentry);
        remove_listitem(listitem);
        return r;
    }

    if (!mbentry->name) mbentry->name = xstrdup(name);
    mailbox->mbentry = mbentry;

    if (mbentry->mbtype & MBTYPE_MOVING) {
        r = IMAP_MAILBOX_MOVED;
        goto done;
    }

    if (mbentry->mbtype & MBTYPE_INTERMEDIATE) {
        r = IMAP_MAILBOX_NONEXISTENT;
        goto done;
    }

    if (!mbentry->partition) {
        r = IMAP_MAILBOX_NONEXISTENT;
        goto done;
    }

    if (index_locktype == LOCK_SHARED)
        mailbox->is_readonly = 1;

    r = mailbox_open_index(mailbox);
    if (r) {
        xsyslog(LOG_ERR, "IOERROR: opening index failed",
                         "mailbox=<%s> error=<%s>",
                         mailbox_name(mailbox), error_message(r));
        goto done;
    }

lockindex:
    r = mailbox_lock_index(mailbox, index_locktype);

    /* we always nuke expunged if the version is less than 12 */
    if (mailbox->i.minor_version < 12)
        cleanup_stale_expunged(mailbox);

done:
    if (r) mailbox_close(&mailbox);
    else *mailboxptr = mailbox;

    return r;
}
static int mailbox_open_advanced(const char *name,
                                 int locktype,
                                 int index_locktype,
                                 const mbentry_t *mbe,
                                 struct mailbox **mailboxptr)
{
    mbentry_t *mbentry = NULL;
    struct mailboxlist *listitem;
    struct mailbox *mailbox = NULL;
    int r = 0;

    assert(*mailboxptr == NULL);

    listitem = find_listitem(name);

     
    if (listitem) {
         
        if (listitem->l->locktype == LOCK_EXCLUSIVE)
            return IMAP_MAILBOX_LOCKED;
        if (locktype == LOCK_EXCLUSIVE)
            return IMAP_MAILBOX_LOCKED;
         
        if (listitem->m.index_locktype)
            return IMAP_MAILBOX_LOCKED;

        listitem->nopen++;
        mailbox = &listitem->m;

        goto lockindex;
    }

    listitem = create_listitem(name);
    mailbox = &listitem->m;

     
    char *userid = mboxname_to_userid(name);
    if (userid) {
        int haslock = user_isnamespacelocked(userid);
        if (haslock) {
            if (index_locktype != LOCK_SHARED) assert(haslock != LOCK_SHARED);
        }
        else {
            int locktype = index_locktype;
            mailbox->local_namespacelock = user_namespacelock_full(userid, locktype);
        }
        free(userid);
    }

    if (mbe) mbentry = mboxlist_entry_copy(mbe);
    else r = mboxlist_lookup_allow_all(name, &mbentry, NULL);

    if (!r && mbentry->mbtype & MBTYPE_DELETED)
        r = IMAP_MAILBOX_NONEXISTENT;

    if (r) {
        if (mailbox->local_namespacelock)
            mboxname_release(&mailbox->local_namespacelock);
        mboxlist_entry_free(&mbentry);
        remove_listitem(listitem);
        return r;
    }

     
    if (!mbentry->uniqueid && mbentry_is_local_mailbox(mbentry)) {
         
        xsyslog(LOG_ERR, "mbentry has no uniqueid, needs reconstruct",
                         "mboxname=<%s>", name);
    }

    uint32_t legacy_dirs = (mbentry->mbtype & MBTYPE_LEGACY_DIRS);
    r = mboxname_lock(legacy_dirs ? name : mbentry->uniqueid, &listitem->l, locktype);
    if (r) {
         
        if (r != IMAP_MAILBOX_LOCKED)
            xsyslog(LOG_ERR, "IOERROR: lock failed",
                             "mailbox=<%s> error=<%s>",
                             name, error_message(r));
        if (mailbox->local_namespacelock)
            mboxname_release(&mailbox->local_namespacelock);
        mboxlist_entry_free(&mbentry);
        remove_listitem(listitem);
        return r;
    }

    if (!mbentry->name) mbentry->name = xstrdup(name);
    mailbox->mbentry = mbentry;

    if (mbentry->mbtype & MBTYPE_MOVING) {
        r = IMAP_MAILBOX_MOVED;
        goto done;
    }

    if (mbentry->mbtype & MBTYPE_INTERMEDIATE) {
        r = IMAP_MAILBOX_NONEXISTENT;
        goto done;
    }

    if (!mbentry->partition) {
        r = IMAP_MAILBOX_NONEXISTENT;
        goto done;
    }

    if (index_locktype == LOCK_SHARED)
        mailbox->is_readonly = 1;

    r = mailbox_open_index(mailbox);
    if (r) {
        xsyslog(LOG_ERR, "IOERROR: opening index failed",
                         "mailbox=<%s> error=<%s>",
                         mailbox_name(mailbox), error_message(r));
        goto done;
    }

lockindex:
    r = mailbox_lock_index(mailbox, index_locktype);

     
    if (mailbox->i.minor_version < 12)
        cleanup_stale_expunged(mailbox);

done:
    if (r) mailbox_close(&mailbox);
    else *mailboxptr = mailbox;

    return r;
}