shithub: riscv

Download patch

ref: f681cf835af1e5c9e016e5245c24165b029a5e38
parent: 414d29e98f8d5242cc68161e61b66b7171e96634
author: aiju <devnull@localhost>
date: Thu May 4 13:42:12 EDT 2017

bio: add support for custom I/O handler via Biofn

--- a/sys/include/bio.h
+++ b/sys/include/bio.h
@@ -33,6 +33,7 @@
 	uchar*	ebuf;		/* pointer to end of buffer */
 	uchar*	gbuf;		/* pointer to good data in buf */
 	void	(*errorf)(char *);	/* called on error if not nil */
+	int	(*iof)(Biobufhdr*, void *, long);	/* called to do i/o */
 };
 
 struct	Biobuf
@@ -74,6 +75,7 @@
 long	Bwrite(Biobufhdr*, void*, long);
 void	Blethal(Biobufhdr*, void(*)(char*));
 void	Berror(Biobufhdr*, char*, ...);
+void	Biofn(Biobufhdr*, int(*)(Biobufhdr*, void*, long));
 
 #pragma	varargck	argpos	Bprint	2
 #pragma	varargck	argpos	Berror	2
--- a/sys/man/2/bio
+++ b/sys/man/2/bio
@@ -84,6 +84,9 @@
 .B
 void	Blethal(Biobufhdr *bp, void (*errorf)(char *))
 .PP
+.B
+void	Biofn(Biobufhdr *bp, int (*iof)(Biohdr *, void *, long))
+.PP
 .SH DESCRIPTION
 These routines implement fast buffered I/O.
 I/O on different file descriptors is independent.
@@ -338,6 +341,18 @@
 An argument of
 .B nil
 will have the program terminated in case of error.
+.PP
+If
+.I Biofn
+is called with a non-nil
+.I iof
+function, then that function is called for I/O in lieu of
+.IR read (2)
+and
+.IR write (2).
+A nil argument for
+.I iof
+restores normal behaviour.
 .SH SOURCE
 .B /sys/src/libbio
 .SH SEE ALSO
--- a/sys/src/libbio/bflush.c
+++ b/sys/src/libbio/bflush.c
@@ -12,7 +12,7 @@
 		n = bp->bsize+bp->ocount;
 		if(n == 0)
 			return 0;
-		c = write(bp->fid, bp->bbuf, n);
+		c = bp->iof(bp, bp->bbuf, n);
 		if(n == c) {
 			bp->offset += n;
 			bp->ocount = -bp->bsize;
--- a/sys/src/libbio/bgetc.c
+++ b/sys/src/libbio/bgetc.c
@@ -24,7 +24,7 @@
 	 * buffer to allow that many ungets.
 	 */
 	memmove(bp->bbuf-Bungetsize, bp->ebuf-Bungetsize, Bungetsize);
-	i = read(bp->fid, bp->bbuf, bp->bsize);
+	i = bp->iof(bp, bp->bbuf, bp->bsize);
 	bp->gbuf = bp->bbuf;
 	if(i <= 0) {
 		bp->state = Bracteof;
--- a/sys/src/libbio/binit.c
+++ b/sys/src/libbio/binit.c
@@ -50,6 +50,18 @@
 	}
 }
 
+static int
+bioread(Biobufhdr *bp, void *v, long n)
+{
+	return read(bp->fid, v, n);
+}
+
+static int
+biowrite(Biobufhdr *bp, void *v, long n)
+{
+	return write(bp->fid, v, n);
+}
+
 int
 Binits(Biobufhdr *bp, int f, int mode, uchar *p, int size)
 {
@@ -64,6 +76,7 @@
 	case OREAD:
 		bp->state = Bractive;
 		bp->ocount = 0;
+		bp->iof = bioread;
 		break;
 
 	case OWRITE:
@@ -70,6 +83,7 @@
 		install(bp);
 		bp->state = Bwactive;
 		bp->ocount = -size;
+		bp->iof = biowrite;
 		break;
 	}
 	bp->bbuf = p;
@@ -153,4 +167,16 @@
 	}
 	/* otherwise opened with Binit(s) */
 	return r;
+}
+
+void
+Biofn(Biobufhdr *bp, int (*f)(Biobufhdr *, void *, long))
+{
+	if(f == nil)
+		if(bp->state == Bwactive)
+			bp->iof = biowrite;
+		else
+			bp->iof = bioread;
+	else
+		bp->iof = f;
 }
--- a/sys/src/libbio/brdline.c
+++ b/sys/src/libbio/brdline.c
@@ -46,7 +46,7 @@
 	 */
 	ip = (char*)bp->bbuf + i;
 	while(i < bp->bsize) {
-		j = read(bp->fid, ip, bp->bsize-i);
+		j = bp->iof(bp, ip, bp->bsize-i);
 		if(j < 0)
 			Berror(bp, "read error: %r");
 		if(j <= 0) {
--- a/sys/src/libbio/brdstr.c
+++ b/sys/src/libbio/brdstr.c
@@ -69,7 +69,7 @@
 	for(;;){
 		ip = (char*)bp->bbuf + i;
 		while(i < bp->bsize) {
-			j = read(bp->fid, ip, bp->bsize-i);
+			j = bp->iof(bp, ip, bp->bsize-i);
 			if(j < 0)
 				Berror(bp, "read error: %r");
 			if(j <= 0 && i == 0)
--- a/sys/src/libbio/bread.c
+++ b/sys/src/libbio/bread.c
@@ -20,7 +20,7 @@
 		if(n == 0) {
 			if(bp->state != Bractive)
 				break;
-			i = read(bp->fid, bp->bbuf, bp->bsize);
+			i = bp->iof(bp, bp->bbuf, bp->bsize);
 			if(i <= 0) {
 				bp->state = Bracteof;
 				if(i < 0) {
--- a/sys/src/libbio/bwrite.c
+++ b/sys/src/libbio/bwrite.c
@@ -21,7 +21,7 @@
 		if(n == 0) {
 			if(bp->state != Bwactive)
 				return Beof;
-			i = write(bp->fid, bp->bbuf, bp->bsize);
+			i = bp->iof(bp, bp->bbuf, bp->bsize);
 			if(i != bp->bsize) {
 				errstr(errbuf, sizeof errbuf);
 				if(strstr(errbuf, "interrupt") == nil) {