EXPORTED int mailbox_append_index_record(struct mailbox *mailbox,
                                struct index_record *record)
{
    int r;
    struct utimbuf settime;
    uint32_t changeflags = CHANGE_ISAPPEND;

    assert(mailbox_index_islocked(mailbox, 1));

    /* Append MUST be a higher UID than any we've yet seen */
    assert(record->uid > mailbox->i.last_uid);

    /* Append MUST have a message with data */
    assert(record->size);

    /* GUID must not be null */
    assert(!message_guid_isnull(&record->guid));

    /* Check mailbox type size limits */
    if (mailbox->i.exists && !record->ignorelimits) {
        if (mailbox_mbtype(mailbox) & MBTYPE_ADDRESSBOOK) {
            int limit = config_getint(IMAPOPT_MAILBOX_MAXMESSAGES_ADDRESSBOOK);
            if (limit > 0 && limit <= (int)mailbox->i.exists) {
                xsyslog(LOG_ERR, "IOERROR: client hit per-addressbook exists limit",
                                 "mailbox=<%s>",
                                 mailbox_name(mailbox));
                return IMAP_NO_OVERQUOTA;
            }
        }
        else if (mailbox_mbtype(mailbox) & MBTYPE_CALENDAR) {
            int limit = config_getint(IMAPOPT_MAILBOX_MAXMESSAGES_CALENDAR);
            if (limit > 0 && limit <= (int)mailbox->i.exists) {
                xsyslog(LOG_ERR, "IOERROR: client hit per-calendar exists limit",
                                 "mailbox=<%s>",
                                 mailbox_name(mailbox));
                return IMAP_NO_OVERQUOTA;
            }
        }
        else if (!mailbox_mbtype(mailbox)) { // default == email
            int limit = config_getint(IMAPOPT_MAILBOX_MAXMESSAGES_EMAIL);
            if (limit > 0 && limit <= (int)mailbox->i.exists) {
                xsyslog(LOG_ERR, "IOERROR: client hit per-mailbox exists limit",
                                 "mailbox=<%s>",
                                 mailbox_name(mailbox));
                return IMAP_NO_OVERQUOTA;
            }
        }
        else {
            /* no limits for other types defined yet */
        }
    }

    /* belt AND suspenders - check the previous record too */
    if (mailbox->i.num_records) {
        struct index_record prev;
        r = mailbox_read_index_record(mailbox, mailbox->i.num_records, &prev);
        if (r) return r;
        assert(prev.uid <= mailbox->i.last_uid);
        if (message_guid_equal(&prev.guid, &record->guid)) {
            syslog(LOG_INFO, "%s: same message appears twice %u %u",
                   mailbox_name(mailbox), prev.uid, record->uid);
            /* but it's OK, we won't reject it */
        }
    }

    if (!record->internaldate)
        record->internaldate = time(NULL);
    if (!record->gmtime)
        record->gmtime = record->internaldate;
    if (!record->sentdate) {
        struct tm *tm = localtime(&record->internaldate);
        /* truncate to the day */
        tm->tm_sec = 0;
        tm->tm_min = 0;
        tm->tm_hour = 0;
        record->sentdate = mktime(tm);
    }

    /* update the highestmodseq if needed */
    if (record->silentupdate) {
        mailbox_index_dirty(mailbox);
    }
    else {
        mailbox_modseq_dirty(mailbox);
        record->modseq = mailbox->i.highestmodseq;
        if (!record->createdmodseq || record->createdmodseq > record->modseq)
            record->createdmodseq = record->modseq;
        record->last_updated = mailbox->last_updated;
        if (!record->savedate) {
            // store the time of actual append if requested
            record->savedate = mailbox->last_updated;
        }
    }

    int object_storage_enabled = 0 ;
#if defined ENABLE_OBJECTSTORE
    object_storage_enabled = config_getswitch(IMAPOPT_OBJECT_STORAGE_ENABLED) ;
#endif

    if (!(record->internal_flags & FLAG_INTERNAL_UNLINKED)) {
        /* make the file timestamp correct */
        settime.actime = settime.modtime = record->internaldate;
        if (!(object_storage_enabled && (record->internal_flags & FLAG_INTERNAL_ARCHIVED)))  // mabe there is no file in directory.
            if (utime(mailbox_record_fname(mailbox, record), &settime) == -1)
                return IMAP_IOERROR;

        /* write the cache record before buffering the message, it
         * will set the cache_offset field. */
        r = mailbox_append_cache(mailbox, record);
        if (r) return r;
    }

    r = mailbox_update_indexes(mailbox, NULL, record);
    if (r) return r;

    record->recno = mailbox->i.num_records + 1;

    mailbox->i.last_uid = record->uid;
    mailbox->i.num_records = record->recno;

    r = _store_change(mailbox, record, changeflags);
    if (r) return r;

    /* expunged tracking */
    if ((record->internal_flags & FLAG_INTERNAL_EXPUNGED) && (!mailbox->i.first_expunged || mailbox->i.first_expunged > record->last_updated))
        mailbox->i.first_expunged = record->last_updated;

    return 0;
}
EXPORTED int mailbox_append_index_record(struct mailbox *mailbox,
                                struct index_record *record)
{
    int r;
    struct utimbuf settime;
    uint32_t changeflags = CHANGE_ISAPPEND;

    assert(mailbox_index_islocked(mailbox, 1));

     
    assert(record->uid > mailbox->i.last_uid);

     
    assert(record->size);

     
    assert(!message_guid_isnull(&record->guid));

     
    if (mailbox->i.exists && !record->ignorelimits) {
        if (mailbox_mbtype(mailbox) & MBTYPE_ADDRESSBOOK) {
            int limit = config_getint(IMAPOPT_MAILBOX_MAXMESSAGES_ADDRESSBOOK);
            if (limit > 0 && limit <= (int)mailbox->i.exists) {
                xsyslog(LOG_ERR, "IOERROR: client hit per-addressbook exists limit",
                                 "mailbox=<%s>",
                                 mailbox_name(mailbox));
                return IMAP_NO_OVERQUOTA;
            }
        }
        else if (mailbox_mbtype(mailbox) & MBTYPE_CALENDAR) {
            int limit = config_getint(IMAPOPT_MAILBOX_MAXMESSAGES_CALENDAR);
            if (limit > 0 && limit <= (int)mailbox->i.exists) {
                xsyslog(LOG_ERR, "IOERROR: client hit per-calendar exists limit",
                                 "mailbox=<%s>",
                                 mailbox_name(mailbox));
                return IMAP_NO_OVERQUOTA;
            }
        }
        else if (!mailbox_mbtype(mailbox)) {  
            int limit = config_getint(IMAPOPT_MAILBOX_MAXMESSAGES_EMAIL);
            if (limit > 0 && limit <= (int)mailbox->i.exists) {
                xsyslog(LOG_ERR, "IOERROR: client hit per-mailbox exists limit",
                                 "mailbox=<%s>",
                                 mailbox_name(mailbox));
                return IMAP_NO_OVERQUOTA;
            }
        }
        else {
             
        }
    }

     
    if (mailbox->i.num_records) {
        struct index_record prev;
        r = mailbox_read_index_record(mailbox, mailbox->i.num_records, &prev);
        if (r) return r;
        assert(prev.uid <= mailbox->i.last_uid);
        if (message_guid_equal(&prev.guid, &record->guid)) {
            syslog(LOG_INFO, "%s: same message appears twice %u %u",
                   mailbox_name(mailbox), prev.uid, record->uid);
             
        }
    }

    if (!record->internaldate)
        record->internaldate = time(NULL);
    if (!record->gmtime)
        record->gmtime = record->internaldate;
    if (!record->sentdate) {
        struct tm *tm = localtime(&record->internaldate);
         
        tm->tm_sec = 0;
        tm->tm_min = 0;
        tm->tm_hour = 0;
        record->sentdate = mktime(tm);
    }

     
    if (record->silentupdate) {
        mailbox_index_dirty(mailbox);
    }
    else {
        mailbox_modseq_dirty(mailbox);
        record->modseq = mailbox->i.highestmodseq;
        if (!record->createdmodseq || record->createdmodseq > record->modseq)
            record->createdmodseq = record->modseq;
        record->last_updated = mailbox->last_updated;
        if (!record->savedate) {
             
            record->savedate = mailbox->last_updated;
        }
    }

    int object_storage_enabled = 0 ;
#if defined ENABLE_OBJECTSTORE
    object_storage_enabled = config_getswitch(IMAPOPT_OBJECT_STORAGE_ENABLED) ;
#endif

    if (!(record->internal_flags & FLAG_INTERNAL_UNLINKED)) {
         
        settime.actime = settime.modtime = record->internaldate;
        if (!(object_storage_enabled && (record->internal_flags & FLAG_INTERNAL_ARCHIVED)))   
            if (utime(mailbox_record_fname(mailbox, record), &settime) == -1)
                return IMAP_IOERROR;

         
        r = mailbox_append_cache(mailbox, record);
        if (r) return r;
    }

    r = mailbox_update_indexes(mailbox, NULL, record);
    if (r) return r;

    record->recno = mailbox->i.num_records + 1;

    mailbox->i.last_uid = record->uid;
    mailbox->i.num_records = record->recno;

    r = _store_change(mailbox, record, changeflags);
    if (r) return r;

     
    if ((record->internal_flags & FLAG_INTERNAL_EXPUNGED) && (!mailbox->i.first_expunged || mailbox->i.first_expunged > record->last_updated))
        mailbox->i.first_expunged = record->last_updated;

    return 0;
}