| /* | 
 | http://code.google.com/p/inferno-os/source/browse/libbio/bread.c | 
 |  | 
 | 	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved. | 
 | 	Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).  All rights reserved. | 
 |  | 
 | Permission is hereby granted, free of charge, to any person obtaining a copy | 
 | of this software and associated documentation files (the "Software"), to deal | 
 | in the Software without restriction, including without limitation the rights | 
 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
 | copies of the Software, and to permit persons to whom the Software is | 
 | furnished to do so, subject to the following conditions: | 
 |  | 
 | The above copyright notice and this permission notice shall be included in | 
 | all copies or substantial portions of the Software. | 
 |  | 
 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE | 
 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
 | THE SOFTWARE. | 
 | */ | 
 |  | 
 | #include	<u.h> | 
 | #include	<libc.h> | 
 | #include	<bio.h> | 
 |  | 
 | long | 
 | Bread(Biobuf *bp, void *ap, long count) | 
 | { | 
 | 	long c; | 
 | 	unsigned char *p; | 
 | 	int i, n, ic; | 
 |  | 
 | 	p = ap; | 
 | 	c = count; | 
 | 	ic = bp->icount; | 
 |  | 
 | 	while(c > 0) { | 
 | 		n = -ic; | 
 | 		if(n > c) | 
 | 			n = (int)c; | 
 | 		if(n == 0) { | 
 | 			if(bp->state != Bractive) | 
 | 				break; | 
 | 			i = (int)read(bp->fid, bp->bbuf, (size_t)bp->bsize); | 
 | 			if(i <= 0) { | 
 | 				bp->state = Bracteof; | 
 | 				if(i < 0) | 
 | 					bp->state = Binactive; | 
 | 				break; | 
 | 			} | 
 | 			bp->gbuf = bp->bbuf; | 
 | 			bp->offset += i; | 
 | 			if(i < bp->bsize) { | 
 | 				memmove(bp->ebuf-i, bp->bbuf, (size_t)i); | 
 | 				bp->gbuf = bp->ebuf-i; | 
 | 			} | 
 | 			ic = -i; | 
 | 			continue; | 
 | 		} | 
 | 		memmove(p, bp->ebuf+ic, (size_t)n); | 
 | 		c -= n; | 
 | 		ic += n; | 
 | 		p += n; | 
 | 	} | 
 | 	bp->icount = ic; | 
 | 	return count-c; | 
 | } |