Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include        <u.h>
#include        <libc.h>
#include        <bio.h>

vlong
Bseek(Biobufhdr *bp, vlong offset, int base)
{
        vlong n, d;

        switch(bp->state) {
        default:
                fprint(2, "Bseek: unknown state %d\n", bp->state);
                return Beof;

        case Bracteof:
                bp->state = Bractive;
                bp->icount = 0;
                bp->gbuf = bp->ebuf;

        case Bractive:
                n = offset;
                if(base == 1) {
                        n += Boffset(bp);
                        base = 0;
                }

                /*
                 * try to seek within buffer
                 */
                if(base == 0) {
                        /*
                         * if d is too large for an int, icount may wrap,
                         * so we need to ensure that icount hasn't wrapped
                         * and points within the buffer's valid data.
                         */
                        d = n - Boffset(bp);
                        bp->icount += d;
                        if(d <= bp->bsize && bp->icount <= 0 &&
                            bp->ebuf - bp->gbuf >= -bp->icount)
                                return n;
                }

                /*
                 * reset the buffer
                 */
                n = seek(bp->fid, n, base);
                bp->icount = 0;
                bp->gbuf = bp->ebuf;
                break;

        case Bwactive:
                Bflush(bp);
                n = seek(bp->fid, offset, base);
                break;
        }
        bp->offset = n;
        return n;
}