summaryrefslogtreecommitdiff
path: root/sys/src/libbio
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libbio
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libbio')
-rwxr-xr-xsys/src/libbio/bbuffered.c21
-rwxr-xr-xsys/src/libbio/bfildes.c10
-rwxr-xr-xsys/src/libbio/bflush.c34
-rwxr-xr-xsys/src/libbio/bgetc.c54
-rwxr-xr-xsys/src/libbio/bgetd.c37
-rwxr-xr-xsys/src/libbio/bgetrune.c47
-rwxr-xr-xsys/src/libbio/binit.c136
-rwxr-xr-xsys/src/libbio/boffset.c26
-rwxr-xr-xsys/src/libbio/bprint.c15
-rwxr-xr-xsys/src/libbio/bputc.c21
-rwxr-xr-xsys/src/libbio/bputrune.c23
-rwxr-xr-xsys/src/libbio/brdline.c95
-rwxr-xr-xsys/src/libbio/brdstr.c112
-rwxr-xr-xsys/src/libbio/bread.c48
-rwxr-xr-xsys/src/libbio/bseek.c58
-rwxr-xr-xsys/src/libbio/btestprint.c20
-rwxr-xr-xsys/src/libbio/bvprint.c37
-rwxr-xr-xsys/src/libbio/bwrite.c43
-rwxr-xr-xsys/src/libbio/mkfile32
19 files changed, 869 insertions, 0 deletions
diff --git a/sys/src/libbio/bbuffered.c b/sys/src/libbio/bbuffered.c
new file mode 100755
index 000000000..1b2bdbe09
--- /dev/null
+++ b/sys/src/libbio/bbuffered.c
@@ -0,0 +1,21 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+int
+Bbuffered(Biobufhdr *bp)
+{
+ switch(bp->state) {
+ case Bracteof:
+ case Bractive:
+ return -bp->icount;
+
+ case Bwactive:
+ return bp->bsize + bp->ocount;
+
+ case Binactive:
+ return 0;
+ }
+ fprint(2, "Bbuffered: unknown state %d\n", bp->state);
+ return 0;
+}
diff --git a/sys/src/libbio/bfildes.c b/sys/src/libbio/bfildes.c
new file mode 100755
index 000000000..6b3fd289d
--- /dev/null
+++ b/sys/src/libbio/bfildes.c
@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+int
+Bfildes(Biobufhdr *bp)
+{
+
+ return bp->fid;
+}
diff --git a/sys/src/libbio/bflush.c b/sys/src/libbio/bflush.c
new file mode 100755
index 000000000..d4339eea7
--- /dev/null
+++ b/sys/src/libbio/bflush.c
@@ -0,0 +1,34 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+int
+Bflush(Biobufhdr *bp)
+{
+ int n, c;
+
+ switch(bp->state) {
+ case Bwactive:
+ n = bp->bsize+bp->ocount;
+ if(n == 0)
+ return 0;
+ c = write(bp->fid, bp->bbuf, n);
+ if(n == c) {
+ bp->offset += n;
+ bp->ocount = -bp->bsize;
+ return 0;
+ }
+ bp->state = Binactive;
+ bp->ocount = 0;
+ break;
+
+ case Bracteof:
+ bp->state = Bractive;
+
+ case Bractive:
+ bp->icount = 0;
+ bp->gbuf = bp->ebuf;
+ return 0;
+ }
+ return Beof;
+}
diff --git a/sys/src/libbio/bgetc.c b/sys/src/libbio/bgetc.c
new file mode 100755
index 000000000..1119c4517
--- /dev/null
+++ b/sys/src/libbio/bgetc.c
@@ -0,0 +1,54 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+int
+Bgetc(Biobufhdr *bp)
+{
+ int i;
+
+loop:
+ i = bp->icount;
+ if(i != 0) {
+ bp->icount = i+1;
+ return bp->ebuf[i];
+ }
+ if(bp->state != Bractive) {
+ if(bp->state == Bracteof)
+ bp->state = Bractive;
+ return Beof;
+ }
+ /*
+ * get next buffer, try to keep Bungetsize
+ * characters pre-catenated from the previous
+ * buffer to allow that many ungets.
+ */
+ memmove(bp->bbuf-Bungetsize, bp->ebuf-Bungetsize, Bungetsize);
+ i = read(bp->fid, bp->bbuf, bp->bsize);
+ bp->gbuf = bp->bbuf;
+ if(i <= 0) {
+ bp->state = Bracteof;
+ if(i < 0)
+ bp->state = Binactive;
+ return Beof;
+ }
+ if(i < bp->bsize) {
+ memmove(bp->ebuf-i-Bungetsize, bp->bbuf-Bungetsize, i+Bungetsize);
+ bp->gbuf = bp->ebuf-i;
+ }
+ bp->icount = -i;
+ bp->offset += i;
+ goto loop;
+}
+
+int
+Bungetc(Biobufhdr *bp)
+{
+
+ if(bp->state == Bracteof)
+ bp->state = Bractive;
+ if(bp->state != Bractive)
+ return Beof;
+ bp->icount--;
+ return 1;
+}
diff --git a/sys/src/libbio/bgetd.c b/sys/src/libbio/bgetd.c
new file mode 100755
index 000000000..abede2647
--- /dev/null
+++ b/sys/src/libbio/bgetd.c
@@ -0,0 +1,37 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+struct bgetd
+{
+ Biobufhdr* b;
+ int eof;
+};
+
+static int
+Bgetdf(void *vp)
+{
+ int c;
+ struct bgetd *bg = vp;
+
+ c = Bgetc(bg->b);
+ if(c == Beof)
+ bg->eof = 1;
+ return c;
+}
+
+int
+Bgetd(Biobufhdr *bp, double *dp)
+{
+ double d;
+ struct bgetd b;
+
+ b.b = bp;
+ b.eof = 0;
+ d = charstod(Bgetdf, &b);
+ if(b.eof)
+ return -1;
+ Bungetc(bp);
+ *dp = d;
+ return 1;
+}
diff --git a/sys/src/libbio/bgetrune.c b/sys/src/libbio/bgetrune.c
new file mode 100755
index 000000000..3ba90384e
--- /dev/null
+++ b/sys/src/libbio/bgetrune.c
@@ -0,0 +1,47 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+long
+Bgetrune(Biobufhdr *bp)
+{
+ int c, i;
+ Rune rune;
+ char str[4];
+
+ c = Bgetc(bp);
+ if(c < Runeself) { /* one char */
+ bp->runesize = 1;
+ return c;
+ }
+ str[0] = c;
+
+ for(i=1;;) {
+ c = Bgetc(bp);
+ if(c < 0)
+ return c;
+ str[i++] = c;
+
+ if(fullrune(str, i)) {
+ bp->runesize = chartorune(&rune, str);
+ while(i > bp->runesize) {
+ Bungetc(bp);
+ i--;
+ }
+ return rune;
+ }
+ }
+}
+
+int
+Bungetrune(Biobufhdr *bp)
+{
+
+ if(bp->state == Bracteof)
+ bp->state = Bractive;
+ if(bp->state != Bractive)
+ return Beof;
+ bp->icount -= bp->runesize;
+ bp->runesize = 0;
+ return 1;
+}
diff --git a/sys/src/libbio/binit.c b/sys/src/libbio/binit.c
new file mode 100755
index 000000000..75cee333b
--- /dev/null
+++ b/sys/src/libbio/binit.c
@@ -0,0 +1,136 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static Biobufhdr* wbufs[20];
+static int atexitflag;
+
+static
+void
+batexit(void)
+{
+ Biobufhdr *bp;
+ int i;
+
+ for(i=0; i<nelem(wbufs); i++) {
+ bp = wbufs[i];
+ if(bp != 0) {
+ wbufs[i] = 0;
+ Bflush(bp);
+ }
+ }
+}
+
+static
+void
+deinstall(Biobufhdr *bp)
+{
+ int i;
+
+ for(i=0; i<nelem(wbufs); i++)
+ if(wbufs[i] == bp)
+ wbufs[i] = 0;
+}
+
+static
+void
+install(Biobufhdr *bp)
+{
+ int i;
+
+ deinstall(bp);
+ for(i=0; i<nelem(wbufs); i++)
+ if(wbufs[i] == 0) {
+ wbufs[i] = bp;
+ break;
+ }
+ if(atexitflag == 0) {
+ atexitflag = 1;
+ atexit(batexit);
+ }
+}
+
+int
+Binits(Biobufhdr *bp, int f, int mode, uchar *p, int size)
+{
+
+ p += Bungetsize; /* make room for Bungets */
+ size -= Bungetsize;
+
+ switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) {
+ default:
+ fprint(2, "Binits: unknown mode %d\n", mode);
+ return Beof;
+
+ case OREAD:
+ bp->state = Bractive;
+ bp->ocount = 0;
+ break;
+
+ case OWRITE:
+ install(bp);
+ bp->state = Bwactive;
+ bp->ocount = -size;
+ break;
+ }
+ bp->bbuf = p;
+ bp->ebuf = p+size;
+ bp->bsize = size;
+ bp->icount = 0;
+ bp->gbuf = bp->ebuf;
+ bp->fid = f;
+ bp->flag = 0;
+ bp->rdline = 0;
+ bp->offset = 0;
+ bp->runesize = 0;
+ return 0;
+}
+
+
+int
+Binit(Biobuf *bp, int f, int mode)
+{
+ return Binits(bp, f, mode, bp->b, sizeof(bp->b));
+}
+
+Biobuf*
+Bopen(char *name, int mode)
+{
+ Biobuf *bp;
+ int f;
+
+ switch(mode&~(OCEXEC|ORCLOSE|OTRUNC)) {
+ default:
+ fprint(2, "Bopen: unknown mode %#x\n", mode);
+ return 0;
+ case OREAD:
+ f = open(name, mode);
+ break;
+ case OWRITE:
+ f = create(name, mode, 0666);
+ break;
+ }
+ if(f < 0)
+ return 0;
+ bp = malloc(sizeof(Biobuf));
+ Binits(bp, f, mode, bp->b, sizeof(bp->b));
+ bp->flag = Bmagic; /* mark bp open & malloced */
+ return bp;
+}
+
+int
+Bterm(Biobufhdr *bp)
+{
+ int r;
+
+ deinstall(bp);
+ r = Bflush(bp);
+ if(bp->flag == Bmagic) {
+ bp->flag = 0;
+ close(bp->fid);
+ bp->fid = -1; /* prevent accidents */
+ free(bp);
+ }
+ /* otherwise opened with Binit(s) */
+ return r;
+}
diff --git a/sys/src/libbio/boffset.c b/sys/src/libbio/boffset.c
new file mode 100755
index 000000000..23d74816d
--- /dev/null
+++ b/sys/src/libbio/boffset.c
@@ -0,0 +1,26 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+vlong
+Boffset(Biobufhdr *bp)
+{
+ vlong n;
+
+ switch(bp->state) {
+ default:
+ fprint(2, "Boffset: unknown state %d\n", bp->state);
+ n = Beof;
+ break;
+
+ case Bracteof:
+ case Bractive:
+ n = bp->offset + bp->icount;
+ break;
+
+ case Bwactive:
+ n = bp->offset + (bp->bsize + bp->ocount);
+ break;
+ }
+ return n;
+}
diff --git a/sys/src/libbio/bprint.c b/sys/src/libbio/bprint.c
new file mode 100755
index 000000000..fc016c2be
--- /dev/null
+++ b/sys/src/libbio/bprint.c
@@ -0,0 +1,15 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+int
+Bprint(Biobufhdr *bp, char *fmt, ...)
+{
+ va_list arg;
+ int n;
+
+ va_start(arg, fmt);
+ n = Bvprint(bp, fmt, arg);
+ va_end(arg);
+ return n;
+}
diff --git a/sys/src/libbio/bputc.c b/sys/src/libbio/bputc.c
new file mode 100755
index 000000000..7332c29fd
--- /dev/null
+++ b/sys/src/libbio/bputc.c
@@ -0,0 +1,21 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+int
+Bputc(Biobufhdr *bp, int c)
+{
+ int i;
+
+ for(;;) {
+ i = bp->ocount;
+ if(i) {
+ bp->ebuf[i++] = c;
+ bp->ocount = i;
+ return 0;
+ }
+ if(Bflush(bp) == Beof)
+ break;
+ }
+ return Beof;
+}
diff --git a/sys/src/libbio/bputrune.c b/sys/src/libbio/bputrune.c
new file mode 100755
index 000000000..2a625bd9a
--- /dev/null
+++ b/sys/src/libbio/bputrune.c
@@ -0,0 +1,23 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+int
+Bputrune(Biobufhdr *bp, long c)
+{
+ Rune rune;
+ char str[4];
+ int n;
+
+ rune = c;
+ if(rune < Runeself) {
+ Bputc(bp, rune);
+ return 1;
+ }
+ n = runetochar(str, &rune);
+ if(n == 0)
+ return Bbad;
+ if(Bwrite(bp, str, n) != n)
+ return Beof;
+ return n;
+}
diff --git a/sys/src/libbio/brdline.c b/sys/src/libbio/brdline.c
new file mode 100755
index 000000000..c116e3859
--- /dev/null
+++ b/sys/src/libbio/brdline.c
@@ -0,0 +1,95 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+void*
+Brdline(Biobufhdr *bp, int delim)
+{
+ char *ip, *ep;
+ int i, j;
+
+ i = -bp->icount;
+ if(i == 0) {
+ /*
+ * eof or other error
+ */
+ if(bp->state != Bractive) {
+ if(bp->state == Bracteof)
+ bp->state = Bractive;
+ bp->rdline = 0;
+ bp->gbuf = bp->ebuf;
+ return 0;
+ }
+ }
+
+ /*
+ * first try in remainder of buffer (gbuf doesn't change)
+ */
+ ip = (char*)bp->ebuf - i;
+ ep = memchr(ip, delim, i);
+ if(ep) {
+ j = (ep - ip) + 1;
+ bp->rdline = j;
+ bp->icount += j;
+ return ip;
+ }
+
+ /*
+ * copy data to beginning of buffer
+ */
+ if(i < bp->bsize)
+ memmove(bp->bbuf, ip, i);
+ bp->gbuf = bp->bbuf;
+
+ /*
+ * append to buffer looking for the delim
+ */
+ ip = (char*)bp->bbuf + i;
+ while(i < bp->bsize) {
+ j = read(bp->fid, ip, bp->bsize-i);
+ if(j <= 0) {
+ /*
+ * end of file with no delim
+ */
+ memmove(bp->ebuf-i, bp->bbuf, i);
+ bp->rdline = i;
+ bp->icount = -i;
+ bp->gbuf = bp->ebuf-i;
+ return 0;
+ }
+ bp->offset += j;
+ i += j;
+ ep = memchr(ip, delim, j);
+ if(ep) {
+ /*
+ * found in new piece
+ * copy back up and reset everything
+ */
+ ip = (char*)bp->ebuf - i;
+ if(i < bp->bsize){
+ memmove(ip, bp->bbuf, i);
+ bp->gbuf = (uchar*)ip;
+ }
+ j = (ep - (char*)bp->bbuf) + 1;
+ bp->rdline = j;
+ bp->icount = j - i;
+ return ip;
+ }
+ ip += j;
+ }
+
+ /*
+ * full buffer without finding
+ */
+ bp->rdline = bp->bsize;
+ bp->icount = -bp->bsize;
+ bp->gbuf = bp->bbuf;
+ return 0;
+}
+
+int
+Blinelen(Biobufhdr *bp)
+{
+
+ return bp->rdline;
+}
diff --git a/sys/src/libbio/brdstr.c b/sys/src/libbio/brdstr.c
new file mode 100755
index 000000000..b5727ad2a
--- /dev/null
+++ b/sys/src/libbio/brdstr.c
@@ -0,0 +1,112 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static char*
+badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim)
+{
+ int n;
+
+ n = *np;
+ p = realloc(p, n+ndata+1);
+ if(p){
+ memmove(p+n, data, ndata);
+ n += ndata;
+ if(n>0 && nulldelim && p[n-1]==delim)
+ p[--n] = '\0';
+ else
+ p[n] = '\0';
+ *np = n;
+ }
+ return p;
+}
+
+char*
+Brdstr(Biobufhdr *bp, int delim, int nulldelim)
+{
+ char *ip, *ep, *p;
+ int i, j;
+
+ i = -bp->icount;
+ bp->rdline = 0;
+ if(i == 0) {
+ /*
+ * eof or other error
+ */
+ if(bp->state != Bractive) {
+ if(bp->state == Bracteof)
+ bp->state = Bractive;
+ bp->gbuf = bp->ebuf;
+ return nil;
+ }
+ }
+
+ /*
+ * first try in remainder of buffer (gbuf doesn't change)
+ */
+ ip = (char*)bp->ebuf - i;
+ ep = memchr(ip, delim, i);
+ if(ep) {
+ j = (ep - ip) + 1;
+ bp->icount += j;
+ return badd(nil, &bp->rdline, ip, j, delim, nulldelim);
+ }
+
+ /*
+ * copy data to beginning of buffer
+ */
+ if(i < bp->bsize)
+ memmove(bp->bbuf, ip, i);
+ bp->gbuf = bp->bbuf;
+
+ /*
+ * append to buffer looking for the delim
+ */
+ p = nil;
+ for(;;){
+ ip = (char*)bp->bbuf + i;
+ while(i < bp->bsize) {
+ j = read(bp->fid, ip, bp->bsize-i);
+ if(j <= 0 && i == 0)
+ return p;
+ if(j <= 0 && i > 0){
+ /*
+ * end of file but no delim. pretend we got a delim
+ * by making the delim \0 and smashing it with nulldelim.
+ */
+ j = 1;
+ ep = ip;
+ delim = '\0';
+ nulldelim = 1;
+ *ep = delim; /* there will be room for this */
+ }else{
+ bp->offset += j;
+ ep = memchr(ip, delim, j);
+ }
+ i += j;
+ if(ep) {
+ /*
+ * found in new piece
+ * copy back up and reset everything
+ */
+ ip = (char*)bp->ebuf - i;
+ if(i < bp->bsize){
+ memmove(ip, bp->bbuf, i);
+ bp->gbuf = (uchar*)ip;
+ }
+ j = (ep - (char*)bp->bbuf) + 1;
+ bp->icount = j - i;
+ return badd(p, &bp->rdline, ip, j, delim, nulldelim);
+ }
+ ip += j;
+ }
+
+ /*
+ * full buffer without finding; add to user string and continue
+ */
+ p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0);
+ i = 0;
+ bp->icount = 0;
+ bp->gbuf = bp->ebuf;
+ }
+}
diff --git a/sys/src/libbio/bread.c b/sys/src/libbio/bread.c
new file mode 100755
index 000000000..9780ffac1
--- /dev/null
+++ b/sys/src/libbio/bread.c
@@ -0,0 +1,48 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+long
+Bread(Biobufhdr *bp, void *ap, long count)
+{
+ long c;
+ uchar *p;
+ int i, n, ic;
+
+ p = ap;
+ c = count;
+ ic = bp->icount;
+
+ while(c > 0) {
+ n = -ic;
+ if(n > c)
+ n = c;
+ if(n == 0) {
+ if(bp->state != Bractive)
+ break;
+ i = read(bp->fid, bp->bbuf, 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, i);
+ bp->gbuf = bp->ebuf-i;
+ }
+ ic = -i;
+ continue;
+ }
+ memmove(p, bp->ebuf+ic, n);
+ c -= n;
+ ic += n;
+ p += n;
+ }
+ bp->icount = ic;
+ if(count == c && bp->state == Binactive)
+ return -1;
+ return count-c;
+}
diff --git a/sys/src/libbio/bseek.c b/sys/src/libbio/bseek.c
new file mode 100755
index 000000000..809b09323
--- /dev/null
+++ b/sys/src/libbio/bseek.c
@@ -0,0 +1,58 @@
+#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;
+}
diff --git a/sys/src/libbio/btestprint.c b/sys/src/libbio/btestprint.c
new file mode 100755
index 000000000..69b9c5242
--- /dev/null
+++ b/sys/src/libbio/btestprint.c
@@ -0,0 +1,20 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+void
+main(int argc, char **argv)
+{
+ Biobuf b;
+ char *s;
+ int n;
+
+
+ n = atoi(argv[1]);
+ s = malloc(n+1);
+ memset(s, 'a', n);
+ s[n] = '\0';
+ Binit(&b, 1, OWRITE);
+ Bprint(&b, "%s\n", s);
+ Bflush(&b);
+}
diff --git a/sys/src/libbio/bvprint.c b/sys/src/libbio/bvprint.c
new file mode 100755
index 000000000..4881bee9d
--- /dev/null
+++ b/sys/src/libbio/bvprint.c
@@ -0,0 +1,37 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+static int
+fmtBflush(Fmt *f)
+{
+ Biobufhdr *bp;
+
+ bp = f->farg;
+ bp->ocount = (char*)f->to - (char*)f->stop;
+ if(Bflush(bp) < 0)
+ return 0;
+ f->stop = bp->ebuf;
+ f->to = (char*)f->stop + bp->ocount;
+ f->start = f->to;
+ return 1;
+}
+
+int
+Bvprint(Biobufhdr *bp, char *fmt, va_list arg)
+{
+ int n;
+ Fmt f;
+
+ f.runes = 0;
+ f.stop = bp->ebuf;
+ f.start = (char*)f.stop + bp->ocount;
+ f.to = f.start;
+ f.flush = fmtBflush;
+ f.farg = bp;
+ f.nfmt = 0;
+ f.args = arg;
+ n = dofmt(&f, fmt);
+ bp->ocount = (char*)f.to - (char*)f.stop;
+ return n;
+}
diff --git a/sys/src/libbio/bwrite.c b/sys/src/libbio/bwrite.c
new file mode 100755
index 000000000..ae7a7d97c
--- /dev/null
+++ b/sys/src/libbio/bwrite.c
@@ -0,0 +1,43 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+long
+Bwrite(Biobufhdr *bp, void *ap, long count)
+{
+ long c;
+ uchar *p;
+ int i, n, oc;
+ char errbuf[ERRMAX];
+
+ p = ap;
+ c = count;
+ oc = bp->ocount;
+
+ while(c > 0) {
+ n = -oc;
+ if(n > c)
+ n = c;
+ if(n == 0) {
+ if(bp->state != Bwactive)
+ return Beof;
+ i = write(bp->fid, bp->bbuf, bp->bsize);
+ if(i != bp->bsize) {
+ errstr(errbuf, sizeof errbuf);
+ if(strstr(errbuf, "interrupt") == nil)
+ bp->state = Binactive;
+ errstr(errbuf, sizeof errbuf);
+ return Beof;
+ }
+ bp->offset += i;
+ oc = -bp->bsize;
+ continue;
+ }
+ memmove(bp->ebuf+oc, p, n);
+ oc += n;
+ c -= n;
+ p += n;
+ }
+ bp->ocount = oc;
+ return count-c;
+}
diff --git a/sys/src/libbio/mkfile b/sys/src/libbio/mkfile
new file mode 100755
index 000000000..a8c21dbaa
--- /dev/null
+++ b/sys/src/libbio/mkfile
@@ -0,0 +1,32 @@
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libbio.a
+OFILES=\
+ bbuffered.$O\
+ bfildes.$O\
+ bflush.$O\
+ bgetrune.$O\
+ bgetc.$O\
+ bgetd.$O\
+ binit.$O\
+ boffset.$O\
+ bprint.$O\
+ bputrune.$O\
+ bputc.$O\
+ brdline.$O\
+ brdstr.$O\
+ bread.$O\
+ bseek.$O\
+ bwrite.$O\
+ bvprint.$O\
+
+HFILES=/sys/include/bio.h
+
+UPDATE=\
+ mkfile\
+ $HFILES\
+ ${OFILES:%.$O=%.c}\
+ ${LIB:/$objtype/%=/386/%}\
+
+</sys/src/cmd/mksyslib
+