diff options
Diffstat (limited to 'src/base/bufio/init.c')
-rw-r--r-- | src/base/bufio/init.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/base/bufio/init.c b/src/base/bufio/init.c new file mode 100644 index 0000000..7e6dcee --- /dev/null +++ b/src/base/bufio/init.c @@ -0,0 +1,102 @@ +#include "internal.h" + +#define MAXHEADERS 20 +static io·Header *tracked[MAXHEADERS]; +static int doexit; + +static void +untrackall(void *arg) +{ + int i; + io·Header *it; + + for(i=0; i < MAXHEADERS; i++){ + it = tracked[i]; + if(it){ + tracked[i] = nil; + bio·flush(it); + } + } +} + +static void +untrack(io·Header *io) +{ + int i; + + for(i=0; i<arrlen(tracked); i++){ + if(tracked[i] == io) + tracked[i] = nil; + } +} + +static void +track(io·Header *io) +{ + int i; + + untrack(io); + for(i=0; i<arrlen(tracked); i++){ + if(!tracked[i]){ + tracked[i] = io; + break; + } + } + + if(!doexit){ + doexit = 1; + rt·atexit(untrackall, nil); + } +} + +int +bio·initcap(io·Header *io, int fd, int mode, int cap, uchar *buf) +{ + buf += io·BufUngets; + cap += io·BufUngets; + + switch(mode & ~(sys·OCloseExec|sys·OTrunc)){ + default: + fmt·fprint(2, "initcap: unknown mode %d\n" , mode); + return io·BufErr; + case sys·ORead: + io->state = io·BufRdr; + io->olen = 0; + break; + case sys·OWrite: + track(io); + io->state = io·BufWtr; + io->olen = -cap; + break; + } + + io->b = buf; + io->e = buf+cap; + io->g = io->e; + io->fd = fd; + io->cap = cap; + io->pos = io->runesz = io->flag = io->ilen = io->line = 0; + return 0; +} + +int +bio·init(io·Buffer *io, int fd, int mode) +{ + return bio·initcap(header(io), fd, mode, io·BufLen + io·BufUngets, io->b); +} + +int +bio·close(io·Header *io) +{ + int err; + + untrack(io); + + err = bio·flush(io); + if(io->flag == io·BufMagic){ + io->flag = 0; + if((err=sys·close(io->fd))) + return err; + } + return 0; +} |