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