z_off64_t ZEXPORT gzseek64()

in zlibWrapper/gzlib.c [369:443]


z_off64_t ZEXPORT gzseek64(file, offset, whence)
    gzFile file;
    z_off64_t offset;
    int whence;
{
    unsigned n;
    z_off64_t ret;
    gz_statep state;

    /* get internal structure and check integrity */
    if (file == NULL)
        return -1;
    state.file = file;
    if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
        return -1;

    /* check that there's no error */
    if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
        return -1;

    /* can only seek from start or relative to current position */
    if (whence != SEEK_SET && whence != SEEK_CUR)
        return -1;

    /* normalize offset to a SEEK_CUR specification */
    if (whence == SEEK_SET)
        offset -= state.state->x.pos;
    else if (state.state->seek)
        offset += state.state->skip;
    state.state->seek = 0;

    /* if within raw area while reading, just go there */
    if (state.state->mode == GZ_READ && state.state->how == COPY &&
            state.state->x.pos + offset >= 0) {
        ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);
        if (ret == -1)
            return -1;
        state.state->x.have = 0;
        state.state->eof = 0;
        state.state->past = 0;
        state.state->seek = 0;
        gz_error(state, Z_OK, NULL);
        state.state->strm.avail_in = 0;
        state.state->x.pos += offset;
        return state.state->x.pos;
    }

    /* calculate skip amount, rewinding if needed for back seek when reading */
    if (offset < 0) {
        if (state.state->mode != GZ_READ)         /* writing -- can't go backwards */
            return -1;
        offset += state.state->x.pos;
        if (offset < 0)                     /* before start of file! */
            return -1;
        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
            return -1;
    }

    /* if reading, skip what's in output buffer (one less gzgetc() check) */
    if (state.state->mode == GZ_READ) {
        n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?
            (unsigned)offset : state.state->x.have;
        state.state->x.have -= n;
        state.state->x.next += n;
        state.state->x.pos += n;
        offset -= n;
    }

    /* request skip (if not zero) */
    if (offset) {
        state.state->seek = 1;
        state.state->skip = offset;
    }
    return state.state->x.pos + offset;
}