static int cache_parserecord(struct mappedfile *cachefile, uint64_t cache_offset,
                             struct cacherecord *crec)
{
    const struct buf *buf = mappedfile_buf(cachefile);
    size_t buf_size = mappedfile_size(cachefile);
    const char *cacheitem, *next;
    size_t offset;
    int cache_ent;

    offset = cache_offset;

    for (cache_ent = 0; cache_ent < NUM_CACHE_FIELDS; cache_ent++) {
        cacheitem = buf->s + offset;

        /* bounds checking */
        if (offset >= buf_size) {
            xsyslog(LOG_ERR, "IOERROR: offset greater than cache size",
                             "offset=<" SIZE_T_FMT "> "
                             "buf_size=<" SIZE_T_FMT "> "
                             "cache_ent=<%d>",
                             offset, buf_size, cache_ent);
            return IMAP_IOERROR;
        }

        if (offset + CACHE_ITEM_SIZE_SKIP + CACHE_ITEM_LEN(cacheitem) > buf_size) {
            xsyslog(LOG_ERR, "IOERROR: cache entry truncated",
                             "offset=<" SIZE_T_FMT "> "
                             "length=<%u> "
                             "buf_size=<" SIZE_T_FMT "> "
                             "cache_ent=<%d>",
                             offset, CACHE_ITEM_LEN(cacheitem),
                             buf_size, cache_ent);
            return IMAP_IOERROR;
        }

        /* copy locations */
        crec->item[cache_ent].len = CACHE_ITEM_LEN(cacheitem);
        crec->item[cache_ent].offset = offset + CACHE_ITEM_SIZE_SKIP;

        /* moving on */
        next = CACHE_ITEM_NEXT(cacheitem);
        if (next < cacheitem) {
            xsyslog(LOG_ERR, "IOERROR: cache offset negative", NULL);
            return IMAP_IOERROR;
        }

        offset = next - buf->s;
    }

    /* all fit within the cache, it's gold as far as we can tell */
    crec->buf = buf;
    crec->len = offset - cache_offset;
    crec->offset = cache_offset;

    return 0;
}
static int cache_parserecord(struct mappedfile *cachefile, uint64_t cache_offset,
                             struct cacherecord *crec)
{
    const struct buf *buf = mappedfile_buf(cachefile);
    size_t buf_size = mappedfile_size(cachefile);
    const char *cacheitem, *next;
    size_t offset;
    int cache_ent;

    offset = cache_offset;

    for (cache_ent = 0; cache_ent < NUM_CACHE_FIELDS; cache_ent++) {
        cacheitem = buf->s + offset;

         
        if (offset >= buf_size) {
            xsyslog(LOG_ERR, "IOERROR: offset greater than cache size",
                             "offset=<" SIZE_T_FMT "> "
                             "buf_size=<" SIZE_T_FMT "> "
                             "cache_ent=<%d>",
                             offset, buf_size, cache_ent);
            return IMAP_IOERROR;
        }

        if (offset + CACHE_ITEM_SIZE_SKIP + CACHE_ITEM_LEN(cacheitem) > buf_size) {
            xsyslog(LOG_ERR, "IOERROR: cache entry truncated",
                             "offset=<" SIZE_T_FMT "> "
                             "length=<%u> "
                             "buf_size=<" SIZE_T_FMT "> "
                             "cache_ent=<%d>",
                             offset, CACHE_ITEM_LEN(cacheitem),
                             buf_size, cache_ent);
            return IMAP_IOERROR;
        }

         
        crec->item[cache_ent].len = CACHE_ITEM_LEN(cacheitem);
        crec->item[cache_ent].offset = offset + CACHE_ITEM_SIZE_SKIP;

         
        next = CACHE_ITEM_NEXT(cacheitem);
        if (next < cacheitem) {
            xsyslog(LOG_ERR, "IOERROR: cache offset negative", NULL);
            return IMAP_IOERROR;
        }

        offset = next - buf->s;
    }

     
    crec->buf = buf;
    crec->len = offset - cache_offset;
    crec->offset = cache_offset;

    return 0;
}