xref: /inferno-os/libbio/bseek.c (revision 72335078034e3cd7edcb1739556b405a3e1e9bf8)
1 #include	"lib9.h"
2 #include	<bio.h>
3 
4 vlong
Bseek(Biobuf * bp,vlong offset,int base)5 Bseek(Biobuf *bp, vlong offset, int base)
6 {
7 	vlong n, d;
8 
9 	switch(bp->state) {
10 	default:
11 		fprint(2, "Bseek: unknown state %d\n", bp->state);
12 		return Beof;
13 
14 	case Bracteof:
15 		bp->state = Bractive;
16 		bp->icount = 0;
17 		bp->gbuf = bp->ebuf;
18 
19 	case Bractive:
20 		n = offset;
21 		if(base == 1) {
22 			n += Boffset(bp);
23 			base = 0;
24 		}
25 
26 		/*
27 		 * try to seek within buffer
28 		 */
29 		if(base == 0) {
30 			/*
31 			 * if d is too large for an int, icount may wrap,
32 			 * so we need to ensure that icount hasn't wrapped
33 			 * and points within the buffer's valid data.
34 			 */
35 			d = n - Boffset(bp);
36 			bp->icount += d;
37 			if(d <= bp->bsize && bp->icount <= 0 &&
38 			    bp->ebuf - bp->gbuf >= -bp->icount)
39 				return n;
40 		}
41 
42 		/*
43 		 * reset the buffer
44 		 */
45 		n = seek(bp->fid, n, base);
46 		bp->icount = 0;
47 		bp->gbuf = bp->ebuf;
48 		break;
49 
50 	case Bwactive:
51 		Bflush(bp);
52 		n = seek(bp->fid, offset, base);
53 		break;
54 	}
55 	bp->offset = n;
56 	return n;
57 }
58