13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier
57dd7cddfSDavid du Colombier vlong
Bseek(Biobufhdr * bp,vlong offset,int base)67dd7cddfSDavid du Colombier Bseek(Biobufhdr *bp, vlong offset, int base)
73e12c5d1SDavid du Colombier {
87dd7cddfSDavid du Colombier vlong n, d;
93e12c5d1SDavid du Colombier
103e12c5d1SDavid du Colombier switch(bp->state) {
113e12c5d1SDavid du Colombier default:
123e12c5d1SDavid du Colombier fprint(2, "Bseek: unknown state %d\n", bp->state);
13219b2ee8SDavid du Colombier return Beof;
143e12c5d1SDavid du Colombier
153e12c5d1SDavid du Colombier case Bracteof:
163e12c5d1SDavid du Colombier bp->state = Bractive;
17219b2ee8SDavid du Colombier bp->icount = 0;
18219b2ee8SDavid du Colombier bp->gbuf = bp->ebuf;
193e12c5d1SDavid du Colombier
203e12c5d1SDavid du Colombier case Bractive:
21219b2ee8SDavid du Colombier n = offset;
223e12c5d1SDavid du Colombier if(base == 1) {
23219b2ee8SDavid du Colombier n += Boffset(bp);
243e12c5d1SDavid du Colombier base = 0;
253e12c5d1SDavid du Colombier }
26219b2ee8SDavid du Colombier
27219b2ee8SDavid du Colombier /*
28219b2ee8SDavid du Colombier * try to seek within buffer
29219b2ee8SDavid du Colombier */
30219b2ee8SDavid du Colombier if(base == 0) {
31*58db92f4SDavid du Colombier /*
32*58db92f4SDavid du Colombier * if d is too large for an int, icount may wrap,
33*58db92f4SDavid du Colombier * so we need to ensure that icount hasn't wrapped
34*58db92f4SDavid du Colombier * and points within the buffer's valid data.
35*58db92f4SDavid du Colombier */
36219b2ee8SDavid du Colombier d = n - Boffset(bp);
37219b2ee8SDavid du Colombier bp->icount += d;
38*58db92f4SDavid du Colombier if(d <= bp->bsize && bp->icount <= 0 &&
39*58db92f4SDavid du Colombier bp->ebuf - bp->gbuf >= -bp->icount)
40219b2ee8SDavid du Colombier return n;
41219b2ee8SDavid du Colombier }
42219b2ee8SDavid du Colombier
43219b2ee8SDavid du Colombier /*
44219b2ee8SDavid du Colombier * reset the buffer
45219b2ee8SDavid du Colombier */
46219b2ee8SDavid du Colombier n = seek(bp->fid, n, base);
473e12c5d1SDavid du Colombier bp->icount = 0;
48219b2ee8SDavid du Colombier bp->gbuf = bp->ebuf;
493e12c5d1SDavid du Colombier break;
503e12c5d1SDavid du Colombier
513e12c5d1SDavid du Colombier case Bwactive:
523e12c5d1SDavid du Colombier Bflush(bp);
533e12c5d1SDavid du Colombier n = seek(bp->fid, offset, base);
543e12c5d1SDavid du Colombier break;
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier bp->offset = n;
573e12c5d1SDavid du Colombier return n;
583e12c5d1SDavid du Colombier }
59