EXPORTED void mailbox_close(struct mailbox **mailboxptr)
{
    int flag;
    struct mailbox *mailbox = *mailboxptr;
    struct mailboxlist *listitem;

    /* be safe against double-close */
    if (!mailbox) return;

    listitem = find_listitem(mailbox_name(mailbox));
    assert(listitem && &listitem->m == mailbox);

    *mailboxptr = NULL;

    /* open multiple times?  Just close this one */
    if (listitem->nopen > 1) {
        listitem->nopen--;
        mailbox_unlock_index(mailbox, NULL);
        return;
    }

    if (mailbox->index_fd != -1) {
        /* drop the index lock here because we'll lose our right to it
         * when try to upgrade the mboxlock anyway. */
        mailbox_unlock_index(mailbox, NULL);
    }

    if (mailbox->i.options & OPT_MAILBOX_DELETED) {
        int r = mailbox_mboxlock_reopen(listitem, LOCK_EXCLUSIVE, LOCK_EXCLUSIVE);
        if (!r) r = mailbox_open_index(mailbox);
        /* lock_internal so DELETED doesn't cause it to appear to be
         * NONEXISTENT - but we still need conversations so we can write changes! */
        if (!r) r = mailbox_lock_index_internal(mailbox, LOCK_EXCLUSIVE);
        /* double check just in case a new mailbox with the same name got created
         * in a race condition and isn't deleted! */
        if (!r && (mailbox->i.options & OPT_MAILBOX_DELETED)) {
            mailbox_delete_cleanup(mailbox, mailbox_partition(mailbox), mailbox_name(mailbox),
                                   (mailbox_mbtype(mailbox) & MBTYPE_LEGACY_DIRS) ?
                                   NULL : mailbox_uniqueid(mailbox));
        }
        mailbox_unlock_index(mailbox, NULL);
    }
    else if (!in_shutdown && (mailbox->i.options & MAILBOX_CLEANUP_MASK)) {
        // there's cleanup to do!  Schedule it for after we've replied to the user
        libcyrus_delayed_action(mailbox_meta_fname(mailbox, META_HEADER),
                                _delayed_cleanup, free, xstrdup(mailbox_name(mailbox)));
    }

    mailbox_release_resources(mailbox);

    mboxlist_entry_free(&mailbox->mbentry);
    xzfree(mailbox->h.name);
    xzfree(mailbox->h.uniqueid);
    xzfree(mailbox->h.quotaroot);
    xzfree(mailbox->h.acl);

    for (flag = 0; flag < MAX_USER_FLAGS; flag++) {
        xzfree(mailbox->h.flagname[flag]);
    }

    if (listitem->l) mboxname_release(&listitem->l);

    if (mailbox->local_namespacelock)
        mboxname_release(&mailbox->local_namespacelock);

    remove_listitem(listitem);
}
EXPORTED void mailbox_close(struct mailbox **mailboxptr)
{
    int flag;
    struct mailbox *mailbox = *mailboxptr;
    struct mailboxlist *listitem;

     
    if (!mailbox) return;

    listitem = find_listitem(mailbox_name(mailbox));
    assert(listitem && &listitem->m == mailbox);

    *mailboxptr = NULL;

     
    if (listitem->nopen > 1) {
        listitem->nopen--;
        mailbox_unlock_index(mailbox, NULL);
        return;
    }

    if (mailbox->index_fd != -1) {
         
        mailbox_unlock_index(mailbox, NULL);
    }

    if (mailbox->i.options & OPT_MAILBOX_DELETED) {
        int r = mailbox_mboxlock_reopen(listitem, LOCK_EXCLUSIVE, LOCK_EXCLUSIVE);
        if (!r) r = mailbox_open_index(mailbox);
         
        if (!r) r = mailbox_lock_index_internal(mailbox, LOCK_EXCLUSIVE);
         
        if (!r && (mailbox->i.options & OPT_MAILBOX_DELETED)) {
            mailbox_delete_cleanup(mailbox, mailbox_partition(mailbox), mailbox_name(mailbox),
                                   (mailbox_mbtype(mailbox) & MBTYPE_LEGACY_DIRS) ?
                                   NULL : mailbox_uniqueid(mailbox));
        }
        mailbox_unlock_index(mailbox, NULL);
    }
    else if (!in_shutdown && (mailbox->i.options & MAILBOX_CLEANUP_MASK)) {
         
        libcyrus_delayed_action(mailbox_meta_fname(mailbox, META_HEADER),
                                _delayed_cleanup, free, xstrdup(mailbox_name(mailbox)));
    }

    mailbox_release_resources(mailbox);

    mboxlist_entry_free(&mailbox->mbentry);
    xzfree(mailbox->h.name);
    xzfree(mailbox->h.uniqueid);
    xzfree(mailbox->h.quotaroot);
    xzfree(mailbox->h.acl);

    for (flag = 0; flag < MAX_USER_FLAGS; flag++) {
        xzfree(mailbox->h.flagname[flag]);
    }

    if (listitem->l) mboxname_release(&listitem->l);

    if (mailbox->local_namespacelock)
        mboxname_release(&mailbox->local_namespacelock);

    remove_listitem(listitem);
}