EXPORTED int mailbox_expunge_cleanup(struct mailbox *mailbox, time_t expunge_mark,
                            unsigned *ndeleted)
{
    int dirty = 0;
    unsigned numdeleted = 0;
    const message_t *msg;
    time_t first_expunged = 0;
    int r = 0;

    /* run the actual expunge phase */
    struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, 0);
    while ((msg = mailbox_iter_step(iter))) {
        const struct index_record *record = msg_record(msg);
        /* already unlinked, skip it (but dirty so we mark a repack is needed) */
        if (record->internal_flags & FLAG_INTERNAL_UNLINKED) {
            dirty = 1;
            continue;
        }

        /* not actually expunged, skip it */
        if (!(record->internal_flags & FLAG_INTERNAL_EXPUNGED))
            continue;

        /* not stale enough yet, skip it - but track the updated time
         * so we know when to run again */
        if (record->last_updated > expunge_mark) {
            if (!first_expunged || (first_expunged > record->last_updated))
                first_expunged = record->last_updated;
            continue;
        }

        dirty = 1;

        numdeleted++;

        struct index_record copyrecord = *record;
        copyrecord.internal_flags |= FLAG_INTERNAL_UNLINKED;
        copyrecord.silentupdate = 1;
        copyrecord.ignorelimits = 1;
        if (mailbox_rewrite_index_record(mailbox, &copyrecord)) {
            xsyslog(LOG_ERR, "IOERROR: failed to mark unlinked",
                             "mailbox=<%s> uid=<%u> recno=<%u>",
                             mailbox_name(mailbox), copyrecord.uid, copyrecord.recno);
            break;
        }
    }
    mailbox_iter_done(&iter);

    if (dirty) {
        mailbox_index_dirty(mailbox);
        mailbox->i.options |= OPT_MAILBOX_NEEDS_REPACK;
        mailbox->i.first_expunged = first_expunged;
    }

    if (ndeleted) *ndeleted = numdeleted;

    return r;
}
EXPORTED int mailbox_expunge_cleanup(struct mailbox *mailbox, time_t expunge_mark,
                            unsigned *ndeleted)
{
    int dirty = 0;
    unsigned numdeleted = 0;
    const message_t *msg;
    time_t first_expunged = 0;
    int r = 0;

     
    struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, 0);
    while ((msg = mailbox_iter_step(iter))) {
        const struct index_record *record = msg_record(msg);
         
        if (record->internal_flags & FLAG_INTERNAL_UNLINKED) {
            dirty = 1;
            continue;
        }

         
        if (!(record->internal_flags & FLAG_INTERNAL_EXPUNGED))
            continue;

         
        if (record->last_updated > expunge_mark) {
            if (!first_expunged || (first_expunged > record->last_updated))
                first_expunged = record->last_updated;
            continue;
        }

        dirty = 1;

        numdeleted++;

        struct index_record copyrecord = *record;
        copyrecord.internal_flags |= FLAG_INTERNAL_UNLINKED;
        copyrecord.silentupdate = 1;
        copyrecord.ignorelimits = 1;
        if (mailbox_rewrite_index_record(mailbox, &copyrecord)) {
            xsyslog(LOG_ERR, "IOERROR: failed to mark unlinked",
                             "mailbox=<%s> uid=<%u> recno=<%u>",
                             mailbox_name(mailbox), copyrecord.uid, copyrecord.recno);
            break;
        }
    }
    mailbox_iter_done(&iter);

    if (dirty) {
        mailbox_index_dirty(mailbox);
        mailbox->i.options |= OPT_MAILBOX_NEEDS_REPACK;
        mailbox->i.first_expunged = first_expunged;
    }

    if (ndeleted) *ndeleted = numdeleted;

    return r;
}