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

This commit is contained in:
aiju 2017-05-04 17:42:12 +00:00
parent 414d29e98f
commit f681cf835a
9 changed files with 49 additions and 6 deletions

View file

@ -33,6 +33,7 @@ struct Biobufhdr
uchar* ebuf; /* pointer to end of buffer */ uchar* ebuf; /* pointer to end of buffer */
uchar* gbuf; /* pointer to good data in buf */ uchar* gbuf; /* pointer to good data in buf */
void (*errorf)(char *); /* called on error if not nil */ void (*errorf)(char *); /* called on error if not nil */
int (*iof)(Biobufhdr*, void *, long); /* called to do i/o */
}; };
struct Biobuf struct Biobuf
@ -74,6 +75,7 @@ int Bungetrune(Biobufhdr*);
long Bwrite(Biobufhdr*, void*, long); long Bwrite(Biobufhdr*, void*, long);
void Blethal(Biobufhdr*, void(*)(char*)); void Blethal(Biobufhdr*, void(*)(char*));
void Berror(Biobufhdr*, char*, ...); void Berror(Biobufhdr*, char*, ...);
void Biofn(Biobufhdr*, int(*)(Biobufhdr*, void*, long));
#pragma varargck argpos Bprint 2 #pragma varargck argpos Bprint 2
#pragma varargck argpos Berror 2 #pragma varargck argpos Berror 2

View file

@ -84,6 +84,9 @@ int Bbuffered(Biobufhdr *bp)
.B .B
void Blethal(Biobufhdr *bp, void (*errorf)(char *)) void Blethal(Biobufhdr *bp, void (*errorf)(char *))
.PP .PP
.B
void Biofn(Biobufhdr *bp, int (*iof)(Biohdr *, void *, long))
.PP
.SH DESCRIPTION .SH DESCRIPTION
These routines implement fast buffered I/O. These routines implement fast buffered I/O.
I/O on different file descriptors is independent. I/O on different file descriptors is independent.
@ -338,6 +341,18 @@ to be called in case of an error happening on read/write.
An argument of An argument of
.B nil .B nil
will have the program terminated in case of error. 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 .SH SOURCE
.B /sys/src/libbio .B /sys/src/libbio
.SH SEE ALSO .SH SEE ALSO

View file

@ -12,7 +12,7 @@ Bflush(Biobufhdr *bp)
n = bp->bsize+bp->ocount; n = bp->bsize+bp->ocount;
if(n == 0) if(n == 0)
return 0; return 0;
c = write(bp->fid, bp->bbuf, n); c = bp->iof(bp, bp->bbuf, n);
if(n == c) { if(n == c) {
bp->offset += n; bp->offset += n;
bp->ocount = -bp->bsize; bp->ocount = -bp->bsize;

View file

@ -24,7 +24,7 @@ loop:
* buffer to allow that many ungets. * buffer to allow that many ungets.
*/ */
memmove(bp->bbuf-Bungetsize, bp->ebuf-Bungetsize, Bungetsize); 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; bp->gbuf = bp->bbuf;
if(i <= 0) { if(i <= 0) {
bp->state = Bracteof; bp->state = Bracteof;

View file

@ -50,6 +50,18 @@ install(Biobufhdr *bp)
} }
} }
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 int
Binits(Biobufhdr *bp, int f, int mode, uchar *p, int size) Binits(Biobufhdr *bp, int f, int mode, uchar *p, int size)
{ {
@ -64,12 +76,14 @@ Binits(Biobufhdr *bp, int f, int mode, uchar *p, int size)
case OREAD: case OREAD:
bp->state = Bractive; bp->state = Bractive;
bp->ocount = 0; bp->ocount = 0;
bp->iof = bioread;
break; break;
case OWRITE: case OWRITE:
install(bp); install(bp);
bp->state = Bwactive; bp->state = Bwactive;
bp->ocount = -size; bp->ocount = -size;
bp->iof = biowrite;
break; break;
} }
bp->bbuf = p; bp->bbuf = p;
@ -154,3 +168,15 @@ Bterm(Biobufhdr *bp)
/* otherwise opened with Binit(s) */ /* otherwise opened with Binit(s) */
return r; 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;
}

View file

@ -46,7 +46,7 @@ Brdline(Biobufhdr *bp, int delim)
*/ */
ip = (char*)bp->bbuf + i; ip = (char*)bp->bbuf + i;
while(i < bp->bsize) { while(i < bp->bsize) {
j = read(bp->fid, ip, bp->bsize-i); j = bp->iof(bp, ip, bp->bsize-i);
if(j < 0) if(j < 0)
Berror(bp, "read error: %r"); Berror(bp, "read error: %r");
if(j <= 0) { if(j <= 0) {

View file

@ -69,7 +69,7 @@ Brdstr(Biobufhdr *bp, int delim, int nulldelim)
for(;;){ for(;;){
ip = (char*)bp->bbuf + i; ip = (char*)bp->bbuf + i;
while(i < bp->bsize) { while(i < bp->bsize) {
j = read(bp->fid, ip, bp->bsize-i); j = bp->iof(bp, ip, bp->bsize-i);
if(j < 0) if(j < 0)
Berror(bp, "read error: %r"); Berror(bp, "read error: %r");
if(j <= 0 && i == 0) if(j <= 0 && i == 0)

View file

@ -20,7 +20,7 @@ Bread(Biobufhdr *bp, void *ap, long count)
if(n == 0) { if(n == 0) {
if(bp->state != Bractive) if(bp->state != Bractive)
break; break;
i = read(bp->fid, bp->bbuf, bp->bsize); i = bp->iof(bp, bp->bbuf, bp->bsize);
if(i <= 0) { if(i <= 0) {
bp->state = Bracteof; bp->state = Bracteof;
if(i < 0) { if(i < 0) {

View file

@ -21,7 +21,7 @@ Bwrite(Biobufhdr *bp, void *ap, long count)
if(n == 0) { if(n == 0) {
if(bp->state != Bwactive) if(bp->state != Bwactive)
return Beof; return Beof;
i = write(bp->fid, bp->bbuf, bp->bsize); i = bp->iof(bp, bp->bbuf, bp->bsize);
if(i != bp->bsize) { if(i != bp->bsize) {
errstr(errbuf, sizeof errbuf); errstr(errbuf, sizeof errbuf);
if(strstr(errbuf, "interrupt") == nil) { if(strstr(errbuf, "interrupt") == nil) {