180ee5cbfSDavid du Colombier #include <u.h> 280ee5cbfSDavid du Colombier #include <libc.h> 380ee5cbfSDavid du Colombier #include <httpd.h> 480ee5cbfSDavid du Colombier 580ee5cbfSDavid du Colombier static char hstates[] = "nrewE"; 680ee5cbfSDavid du Colombier static char hxfers[] = " x"; 780ee5cbfSDavid du Colombier 880ee5cbfSDavid du Colombier int 980ee5cbfSDavid du Colombier hinit(Hio *h, int fd, int mode) 1080ee5cbfSDavid du Colombier { 1180ee5cbfSDavid du Colombier if(fd == -1 || mode != Hread && mode != Hwrite) 1280ee5cbfSDavid du Colombier return -1; 1380ee5cbfSDavid du Colombier h->hh = nil; 1480ee5cbfSDavid du Colombier h->fd = fd; 1580ee5cbfSDavid du Colombier h->seek = 0; 1680ee5cbfSDavid du Colombier h->state = mode; 1780ee5cbfSDavid du Colombier h->start = h->buf + 16; /* leave space for chunk length */ 1880ee5cbfSDavid du Colombier h->stop = h->pos = h->start; 1980ee5cbfSDavid du Colombier if(mode == Hread){ 2080ee5cbfSDavid du Colombier h->bodylen = ~0UL; 2180ee5cbfSDavid du Colombier *h->pos = '\0'; 2280ee5cbfSDavid du Colombier }else 2380ee5cbfSDavid du Colombier h->stop = h->start + Hsize; 2480ee5cbfSDavid du Colombier return 0; 2580ee5cbfSDavid du Colombier } 2680ee5cbfSDavid du Colombier 2780ee5cbfSDavid du Colombier int 2880ee5cbfSDavid du Colombier hiserror(Hio *h) 2980ee5cbfSDavid du Colombier { 3080ee5cbfSDavid du Colombier return h->state == Herr; 3180ee5cbfSDavid du Colombier } 3280ee5cbfSDavid du Colombier 3380ee5cbfSDavid du Colombier int 3480ee5cbfSDavid du Colombier hgetc(Hio *h) 3580ee5cbfSDavid du Colombier { 3680ee5cbfSDavid du Colombier uchar *p; 3780ee5cbfSDavid du Colombier 3880ee5cbfSDavid du Colombier p = h->pos; 3980ee5cbfSDavid du Colombier if(p < h->stop){ 4080ee5cbfSDavid du Colombier h->pos = p + 1; 4180ee5cbfSDavid du Colombier return *p; 4280ee5cbfSDavid du Colombier } 4380ee5cbfSDavid du Colombier p -= UTFmax; 4480ee5cbfSDavid du Colombier if(p < h->start) 4580ee5cbfSDavid du Colombier p = h->start; 4680ee5cbfSDavid du Colombier if(!hreadbuf(h, p) || h->pos == h->stop) 4780ee5cbfSDavid du Colombier return -1; 4880ee5cbfSDavid du Colombier return *h->pos++; 4980ee5cbfSDavid du Colombier } 5080ee5cbfSDavid du Colombier 5180ee5cbfSDavid du Colombier int 5280ee5cbfSDavid du Colombier hungetc(Hio *h) 5380ee5cbfSDavid du Colombier { 5480ee5cbfSDavid du Colombier if(h->state == Hend) 5580ee5cbfSDavid du Colombier h->state = Hread; 5680ee5cbfSDavid du Colombier else if(h->state == Hread) 5780ee5cbfSDavid du Colombier h->pos--; 5880ee5cbfSDavid du Colombier if(h->pos < h->start || h->state != Hread){ 5980ee5cbfSDavid du Colombier h->state = Herr; 6080ee5cbfSDavid du Colombier h->pos = h->stop; 6180ee5cbfSDavid du Colombier return -1; 6280ee5cbfSDavid du Colombier } 6380ee5cbfSDavid du Colombier return 0; 6480ee5cbfSDavid du Colombier } 6580ee5cbfSDavid du Colombier 6680ee5cbfSDavid du Colombier /* 6780ee5cbfSDavid du Colombier * fill the buffer, saving contents from vsave onwards. 6880ee5cbfSDavid du Colombier * nothing is saved if vsave is nil. 6980ee5cbfSDavid du Colombier * returns the beginning of the buffer. 7080ee5cbfSDavid du Colombier * 7180ee5cbfSDavid du Colombier * understands message body sizes and chunked transfer encoding 7280ee5cbfSDavid du Colombier */ 7380ee5cbfSDavid du Colombier void * 7480ee5cbfSDavid du Colombier hreadbuf(Hio *h, void *vsave) 7580ee5cbfSDavid du Colombier { 7680ee5cbfSDavid du Colombier Hio *hh; 7780ee5cbfSDavid du Colombier uchar *save; 7880ee5cbfSDavid du Colombier int c, in, cpy, dpos; 7980ee5cbfSDavid du Colombier 8080ee5cbfSDavid du Colombier save = vsave; 8180ee5cbfSDavid du Colombier if(save && (save < h->start || save > h->stop) 8280ee5cbfSDavid du Colombier || h->state != Hread && h->state != Hend){ 8380ee5cbfSDavid du Colombier h->state = Herr; 8480ee5cbfSDavid du Colombier h->pos = h->stop; 8580ee5cbfSDavid du Colombier return nil; 8680ee5cbfSDavid du Colombier } 8780ee5cbfSDavid du Colombier 8880ee5cbfSDavid du Colombier dpos = 0; 8980ee5cbfSDavid du Colombier if(save && h->pos > save) 9080ee5cbfSDavid du Colombier dpos = h->pos - save; 9180ee5cbfSDavid du Colombier cpy = 0; 9280ee5cbfSDavid du Colombier if(save){ 9380ee5cbfSDavid du Colombier cpy = h->stop - save; 9480ee5cbfSDavid du Colombier memmove(h->start, save, cpy); 9580ee5cbfSDavid du Colombier } 9680ee5cbfSDavid du Colombier h->seek += h->stop - h->start - cpy; 9780ee5cbfSDavid du Colombier h->pos = h->start + dpos; 9880ee5cbfSDavid du Colombier 9980ee5cbfSDavid du Colombier in = Hsize - cpy; 10080ee5cbfSDavid du Colombier if(h->state == Hend) 10180ee5cbfSDavid du Colombier in = 0; 10280ee5cbfSDavid du Colombier else if(in > h->bodylen) 10380ee5cbfSDavid du Colombier in = h->bodylen; 10480ee5cbfSDavid du Colombier 10580ee5cbfSDavid du Colombier /* 10680ee5cbfSDavid du Colombier * for chunked encoding, fill buffer, 10780ee5cbfSDavid du Colombier * then read in new chunk length and wipe out that line 10880ee5cbfSDavid du Colombier */ 10980ee5cbfSDavid du Colombier hh = h->hh; 11080ee5cbfSDavid du Colombier if(hh != nil){ 11180ee5cbfSDavid du Colombier if(!in && h->xferenc && h->state != Hend){ 11280ee5cbfSDavid du Colombier if(h->xferenc == 2){ 11380ee5cbfSDavid du Colombier c = hgetc(hh); 11480ee5cbfSDavid du Colombier if(c == '\r') 11580ee5cbfSDavid du Colombier c = hgetc(hh); 11680ee5cbfSDavid du Colombier if(c != '\n'){ 11780ee5cbfSDavid du Colombier h->pos = h->stop; 11880ee5cbfSDavid du Colombier h->state = Herr; 11980ee5cbfSDavid du Colombier return nil; 12080ee5cbfSDavid du Colombier } 12180ee5cbfSDavid du Colombier } 12280ee5cbfSDavid du Colombier h->xferenc = 2; 12380ee5cbfSDavid du Colombier in = 0; 12480ee5cbfSDavid du Colombier while((c = hgetc(hh)) != '\n'){ 12580ee5cbfSDavid du Colombier if(c >= '0' && c <= '9') 12680ee5cbfSDavid du Colombier c -= '0'; 12780ee5cbfSDavid du Colombier else if(c >= 'a' && c <= 'f') 12880ee5cbfSDavid du Colombier c -= 'a' - 10; 12980ee5cbfSDavid du Colombier else if(c >= 'A' && c <= 'F') 13080ee5cbfSDavid du Colombier c -= 'A' - 10; 13180ee5cbfSDavid du Colombier else 13280ee5cbfSDavid du Colombier break; 13380ee5cbfSDavid du Colombier in = in * 16 + c; 13480ee5cbfSDavid du Colombier } 13580ee5cbfSDavid du Colombier while(c != '\n'){ 13680ee5cbfSDavid du Colombier if(c < 0){ 13780ee5cbfSDavid du Colombier h->pos = h->stop; 13880ee5cbfSDavid du Colombier h->state = Herr; 13980ee5cbfSDavid du Colombier return nil; 14080ee5cbfSDavid du Colombier } 14180ee5cbfSDavid du Colombier c = hgetc(hh); 14280ee5cbfSDavid du Colombier } 14380ee5cbfSDavid du Colombier h->bodylen = in; 14480ee5cbfSDavid du Colombier 14580ee5cbfSDavid du Colombier in = Hsize - cpy; 14680ee5cbfSDavid du Colombier if(in > h->bodylen) 14780ee5cbfSDavid du Colombier in = h->bodylen; 14880ee5cbfSDavid du Colombier } 14980ee5cbfSDavid du Colombier if(in){ 15080ee5cbfSDavid du Colombier while(hh->pos + in > hh->stop){ 15180ee5cbfSDavid du Colombier if(hreadbuf(hh, hh->pos) == nil){ 15280ee5cbfSDavid du Colombier h->pos = h->stop; 15380ee5cbfSDavid du Colombier h->state = Herr; 15480ee5cbfSDavid du Colombier return nil; 15580ee5cbfSDavid du Colombier } 15680ee5cbfSDavid du Colombier } 15780ee5cbfSDavid du Colombier memmove(h->start + cpy, hh->pos, in); 15880ee5cbfSDavid du Colombier hh->pos += in; 15980ee5cbfSDavid du Colombier } 16080ee5cbfSDavid du Colombier }else if(in && (in = read(h->fd, h->start + cpy, in)) < 0){ 16180ee5cbfSDavid du Colombier h->state = Herr; 16280ee5cbfSDavid du Colombier h->pos = h->stop; 16380ee5cbfSDavid du Colombier return nil; 16480ee5cbfSDavid du Colombier } 16580ee5cbfSDavid du Colombier if(in == 0) 16680ee5cbfSDavid du Colombier h->state = Hend; 16780ee5cbfSDavid du Colombier 16880ee5cbfSDavid du Colombier h->bodylen -= in; 16980ee5cbfSDavid du Colombier 17080ee5cbfSDavid du Colombier h->stop = h->start + cpy + in; 17180ee5cbfSDavid du Colombier *h->stop = '\0'; 17280ee5cbfSDavid du Colombier if(h->pos == h->stop) 17380ee5cbfSDavid du Colombier return nil; 17480ee5cbfSDavid du Colombier return h->start; 17580ee5cbfSDavid du Colombier } 17680ee5cbfSDavid du Colombier 17780ee5cbfSDavid du Colombier int 17880ee5cbfSDavid du Colombier hbuflen(Hio *h, void *p) 17980ee5cbfSDavid du Colombier { 18080ee5cbfSDavid du Colombier return h->stop - (uchar*)p; 18180ee5cbfSDavid du Colombier } 18280ee5cbfSDavid du Colombier 18380ee5cbfSDavid du Colombier /* 18480ee5cbfSDavid du Colombier * prepare to receive a message body 18580ee5cbfSDavid du Colombier * len is the content length (~0 => unspecified) 18680ee5cbfSDavid du Colombier * te is the transfer encoding 18780ee5cbfSDavid du Colombier * returns < 0 if setup failed 18880ee5cbfSDavid du Colombier */ 18980ee5cbfSDavid du Colombier Hio* 19080ee5cbfSDavid du Colombier hbodypush(Hio *hh, ulong len, HFields *te) 19180ee5cbfSDavid du Colombier { 19280ee5cbfSDavid du Colombier Hio *h; 19380ee5cbfSDavid du Colombier int xe; 19480ee5cbfSDavid du Colombier 19580ee5cbfSDavid du Colombier if(hh->state != Hread) 19680ee5cbfSDavid du Colombier return nil; 19780ee5cbfSDavid du Colombier xe = 0; 19880ee5cbfSDavid du Colombier if(te != nil){ 19980ee5cbfSDavid du Colombier if(te->params != nil || te->next != nil) 20080ee5cbfSDavid du Colombier return nil; 20180ee5cbfSDavid du Colombier if(cistrcmp(te->s, "chunked") == 0){ 20280ee5cbfSDavid du Colombier xe = 1; 20380ee5cbfSDavid du Colombier len = 0; 2049a747e4fSDavid du Colombier }else if(cistrcmp(te->s, "identity") == 0){ 20580ee5cbfSDavid du Colombier ; 2069a747e4fSDavid du Colombier }else 20780ee5cbfSDavid du Colombier return nil; 20880ee5cbfSDavid du Colombier } 20980ee5cbfSDavid du Colombier 21080ee5cbfSDavid du Colombier h = malloc(sizeof *h); 21180ee5cbfSDavid du Colombier if(h == nil) 21280ee5cbfSDavid du Colombier return nil; 21380ee5cbfSDavid du Colombier 21480ee5cbfSDavid du Colombier h->hh = hh; 21580ee5cbfSDavid du Colombier h->fd = -1; 21680ee5cbfSDavid du Colombier h->seek = 0; 21780ee5cbfSDavid du Colombier h->state = Hread; 21880ee5cbfSDavid du Colombier h->xferenc = xe; 21980ee5cbfSDavid du Colombier h->start = h->buf + 16; /* leave space for chunk length */ 22080ee5cbfSDavid du Colombier h->stop = h->pos = h->start; 22180ee5cbfSDavid du Colombier *h->pos = '\0'; 22280ee5cbfSDavid du Colombier h->bodylen = len; 22380ee5cbfSDavid du Colombier return h; 22480ee5cbfSDavid du Colombier } 22580ee5cbfSDavid du Colombier 22680ee5cbfSDavid du Colombier /* 22780ee5cbfSDavid du Colombier * dump the state of the io buffer into a string 22880ee5cbfSDavid du Colombier */ 22980ee5cbfSDavid du Colombier char * 23080ee5cbfSDavid du Colombier hunload(Hio *h) 23180ee5cbfSDavid du Colombier { 23280ee5cbfSDavid du Colombier uchar *p, *t, *stop, *buf; 23380ee5cbfSDavid du Colombier int ne, n, c; 23480ee5cbfSDavid du Colombier 23580ee5cbfSDavid du Colombier stop = h->stop; 23680ee5cbfSDavid du Colombier ne = 0; 23780ee5cbfSDavid du Colombier for(p = h->pos; p < stop; p++){ 23880ee5cbfSDavid du Colombier c = *p; 23980ee5cbfSDavid du Colombier if(c == 0x80) 24080ee5cbfSDavid du Colombier ne++; 24180ee5cbfSDavid du Colombier } 24280ee5cbfSDavid du Colombier p = h->pos; 24380ee5cbfSDavid du Colombier 24480ee5cbfSDavid du Colombier n = (stop - p) + ne + 3; 24580ee5cbfSDavid du Colombier buf = mallocz(n, 1); 24680ee5cbfSDavid du Colombier if(buf == nil) 24780ee5cbfSDavid du Colombier return nil; 24880ee5cbfSDavid du Colombier buf[0] = hstates[h->state]; 24980ee5cbfSDavid du Colombier buf[1] = hxfers[h->xferenc]; 25080ee5cbfSDavid du Colombier 25180ee5cbfSDavid du Colombier t = &buf[2]; 25280ee5cbfSDavid du Colombier for(; p < stop; p++){ 25380ee5cbfSDavid du Colombier c = *p; 25480ee5cbfSDavid du Colombier if(c == 0 || c == 0x80){ 25580ee5cbfSDavid du Colombier *t++ = 0x80; 25680ee5cbfSDavid du Colombier if(c == 0x80) 25780ee5cbfSDavid du Colombier *t++ = 0x80; 25880ee5cbfSDavid du Colombier }else 25980ee5cbfSDavid du Colombier *t++ = c; 26080ee5cbfSDavid du Colombier } 26180ee5cbfSDavid du Colombier *t++ = '\0'; 26280ee5cbfSDavid du Colombier if(t != buf + n) 26380ee5cbfSDavid du Colombier return nil; 26480ee5cbfSDavid du Colombier return (char*)buf; 26580ee5cbfSDavid du Colombier } 26680ee5cbfSDavid du Colombier 26780ee5cbfSDavid du Colombier /* 26880ee5cbfSDavid du Colombier * read the io buffer state from a string 26980ee5cbfSDavid du Colombier */ 27080ee5cbfSDavid du Colombier int 27180ee5cbfSDavid du Colombier hload(Hio *h, char *buf) 27280ee5cbfSDavid du Colombier { 27380ee5cbfSDavid du Colombier uchar *p, *t, *stop; 27480ee5cbfSDavid du Colombier char *s; 27580ee5cbfSDavid du Colombier int c; 27680ee5cbfSDavid du Colombier 27780ee5cbfSDavid du Colombier s = strchr(hstates, buf[0]); 27880ee5cbfSDavid du Colombier if(s == nil) 27980ee5cbfSDavid du Colombier return 0; 28080ee5cbfSDavid du Colombier h->state = s - hstates; 28180ee5cbfSDavid du Colombier 28280ee5cbfSDavid du Colombier s = strchr(hxfers, buf[1]); 28380ee5cbfSDavid du Colombier if(s == nil) 28480ee5cbfSDavid du Colombier return 0; 28580ee5cbfSDavid du Colombier h->xferenc = s - hxfers; 28680ee5cbfSDavid du Colombier 28780ee5cbfSDavid du Colombier t = h->start; 28880ee5cbfSDavid du Colombier stop = t + Hsize; 28980ee5cbfSDavid du Colombier for(p = (uchar*)&buf[2]; c = *p; p++){ 29080ee5cbfSDavid du Colombier if(c == 0x80){ 29180ee5cbfSDavid du Colombier if(p[1] != 0x80) 29280ee5cbfSDavid du Colombier c = 0; 29380ee5cbfSDavid du Colombier else 2949a747e4fSDavid du Colombier p++; 29580ee5cbfSDavid du Colombier } 29680ee5cbfSDavid du Colombier *t++ = c; 29780ee5cbfSDavid du Colombier if(t >= stop) 29880ee5cbfSDavid du Colombier return 0; 29980ee5cbfSDavid du Colombier } 30080ee5cbfSDavid du Colombier *t = '\0'; 30180ee5cbfSDavid du Colombier h->pos = h->start; 30280ee5cbfSDavid du Colombier h->stop = t; 30380ee5cbfSDavid du Colombier h->seek = 0; 30480ee5cbfSDavid du Colombier return 1; 30580ee5cbfSDavid du Colombier } 30680ee5cbfSDavid du Colombier 30780ee5cbfSDavid du Colombier void 30880ee5cbfSDavid du Colombier hclose(Hio *h) 30980ee5cbfSDavid du Colombier { 31080ee5cbfSDavid du Colombier if(h->fd >= 0){ 3119a747e4fSDavid du Colombier if(h->state == Hwrite) 31280ee5cbfSDavid du Colombier hxferenc(h, 0); 31380ee5cbfSDavid du Colombier close(h->fd); 31480ee5cbfSDavid du Colombier } 31580ee5cbfSDavid du Colombier h->stop = h->pos = nil; 31680ee5cbfSDavid du Colombier h->fd = -1; 31780ee5cbfSDavid du Colombier } 31880ee5cbfSDavid du Colombier 31980ee5cbfSDavid du Colombier /* 32080ee5cbfSDavid du Colombier * flush the buffer and possibly change encoding modes 32180ee5cbfSDavid du Colombier */ 32280ee5cbfSDavid du Colombier int 32380ee5cbfSDavid du Colombier hxferenc(Hio *h, int on) 32480ee5cbfSDavid du Colombier { 32580ee5cbfSDavid du Colombier if(h->xferenc && !on && h->pos != h->start) 32680ee5cbfSDavid du Colombier hflush(h); 32780ee5cbfSDavid du Colombier if(hflush(h) < 0) 32880ee5cbfSDavid du Colombier return -1; 32980ee5cbfSDavid du Colombier h->xferenc = !!on; 33080ee5cbfSDavid du Colombier return 0; 33180ee5cbfSDavid du Colombier } 33280ee5cbfSDavid du Colombier 33380ee5cbfSDavid du Colombier int 33480ee5cbfSDavid du Colombier hputc(Hio *h, int c) 33580ee5cbfSDavid du Colombier { 33680ee5cbfSDavid du Colombier uchar *p; 33780ee5cbfSDavid du Colombier 33880ee5cbfSDavid du Colombier p = h->pos; 33980ee5cbfSDavid du Colombier if(p < h->stop){ 34080ee5cbfSDavid du Colombier h->pos = p + 1; 34180ee5cbfSDavid du Colombier return *p = c; 34280ee5cbfSDavid du Colombier } 34380ee5cbfSDavid du Colombier if(hflush(h) < 0) 34480ee5cbfSDavid du Colombier return -1; 34580ee5cbfSDavid du Colombier return *h->pos++ = c; 34680ee5cbfSDavid du Colombier } 34780ee5cbfSDavid du Colombier 348*3ff48bf5SDavid du Colombier static int 3499a747e4fSDavid du Colombier fmthflush(Fmt *f) 3509a747e4fSDavid du Colombier { 3519a747e4fSDavid du Colombier Hio *h; 3529a747e4fSDavid du Colombier 3539a747e4fSDavid du Colombier h = f->farg; 3549a747e4fSDavid du Colombier h->pos = f->to; 3559a747e4fSDavid du Colombier if(hflush(h) < 0) 3569a747e4fSDavid du Colombier return 0; 3579a747e4fSDavid du Colombier f->stop = h->stop; 3589a747e4fSDavid du Colombier f->to = h->pos; 3599a747e4fSDavid du Colombier f->start = h->pos; 3609a747e4fSDavid du Colombier return 1; 3619a747e4fSDavid du Colombier } 3629a747e4fSDavid du Colombier 3639a747e4fSDavid du Colombier int 3649a747e4fSDavid du Colombier hvprint(Hio *h, char *fmt, va_list args) 3659a747e4fSDavid du Colombier { 3669a747e4fSDavid du Colombier int n; 3679a747e4fSDavid du Colombier Fmt f; 3689a747e4fSDavid du Colombier 3699a747e4fSDavid du Colombier f.runes = 0; 3709a747e4fSDavid du Colombier f.stop = h->stop; 3719a747e4fSDavid du Colombier f.to = h->pos; 3729a747e4fSDavid du Colombier f.start = h->pos; 3739a747e4fSDavid du Colombier f.flush = fmthflush; 3749a747e4fSDavid du Colombier f.farg = h; 3759a747e4fSDavid du Colombier f.nfmt = 0; 3769a747e4fSDavid du Colombier f.args = args; 3779a747e4fSDavid du Colombier n = dofmt(&f, fmt); 3789a747e4fSDavid du Colombier h->pos = f.to; 3799a747e4fSDavid du Colombier return n; 3809a747e4fSDavid du Colombier } 3819a747e4fSDavid du Colombier 3829a747e4fSDavid du Colombier int 38380ee5cbfSDavid du Colombier hprint(Hio *h, char *fmt, ...) 38480ee5cbfSDavid du Colombier { 38580ee5cbfSDavid du Colombier int n; 38680ee5cbfSDavid du Colombier va_list arg; 38780ee5cbfSDavid du Colombier 38880ee5cbfSDavid du Colombier va_start(arg, fmt); 3899a747e4fSDavid du Colombier n = hvprint(h, fmt, arg); 39080ee5cbfSDavid du Colombier va_end(arg); 39180ee5cbfSDavid du Colombier return n; 39280ee5cbfSDavid du Colombier } 39380ee5cbfSDavid du Colombier 39480ee5cbfSDavid du Colombier int 39580ee5cbfSDavid du Colombier hflush(Hio *h) 39680ee5cbfSDavid du Colombier { 39780ee5cbfSDavid du Colombier uchar *s; 39880ee5cbfSDavid du Colombier int w; 39980ee5cbfSDavid du Colombier 40080ee5cbfSDavid du Colombier if(h->state != Hwrite){ 40180ee5cbfSDavid du Colombier h->state = Herr; 40280ee5cbfSDavid du Colombier h->stop = h->pos; 40380ee5cbfSDavid du Colombier return -1; 40480ee5cbfSDavid du Colombier } 40580ee5cbfSDavid du Colombier s = h->start; 40680ee5cbfSDavid du Colombier w = h->pos - s; 40780ee5cbfSDavid du Colombier if(h->xferenc){ 40880ee5cbfSDavid du Colombier *--s = '\n'; 40980ee5cbfSDavid du Colombier *--s = '\r'; 41080ee5cbfSDavid du Colombier do{ 41180ee5cbfSDavid du Colombier *--s = "0123456789abcdef"[w & 0xf]; 41280ee5cbfSDavid du Colombier w >>= 4; 41380ee5cbfSDavid du Colombier }while(w); 41480ee5cbfSDavid du Colombier h->pos[0] = '\r'; 41580ee5cbfSDavid du Colombier h->pos[1] = '\n'; 41680ee5cbfSDavid du Colombier w = &h->pos[2] - s; 41780ee5cbfSDavid du Colombier } 41880ee5cbfSDavid du Colombier if(write(h->fd, s, w) != w){ 41980ee5cbfSDavid du Colombier h->state = Herr; 42080ee5cbfSDavid du Colombier h->stop = h->pos; 42180ee5cbfSDavid du Colombier return -1; 42280ee5cbfSDavid du Colombier } 42380ee5cbfSDavid du Colombier h->seek += w; 42480ee5cbfSDavid du Colombier h->pos = h->start; 42580ee5cbfSDavid du Colombier return 0; 42680ee5cbfSDavid du Colombier } 42780ee5cbfSDavid du Colombier 42880ee5cbfSDavid du Colombier int 42980ee5cbfSDavid du Colombier hwrite(Hio *h, void *vbuf, int len) 43080ee5cbfSDavid du Colombier { 43180ee5cbfSDavid du Colombier uchar *pos, *buf; 43280ee5cbfSDavid du Colombier int n, m; 43380ee5cbfSDavid du Colombier 43480ee5cbfSDavid du Colombier buf = vbuf; 43580ee5cbfSDavid du Colombier n = len; 43680ee5cbfSDavid du Colombier if(n < 0 || h->state != Hwrite){ 43780ee5cbfSDavid du Colombier h->state = Herr; 43880ee5cbfSDavid du Colombier h->stop = h->pos; 43980ee5cbfSDavid du Colombier return -1; 44080ee5cbfSDavid du Colombier } 44180ee5cbfSDavid du Colombier pos = h->pos; 44280ee5cbfSDavid du Colombier if(pos + n >= h->stop){ 44380ee5cbfSDavid du Colombier m = pos - h->start; 44480ee5cbfSDavid du Colombier if(m){ 44580ee5cbfSDavid du Colombier m = Hsize - m; 44680ee5cbfSDavid du Colombier if(m){ 44780ee5cbfSDavid du Colombier memmove(pos, buf, m); 44880ee5cbfSDavid du Colombier buf += m; 44980ee5cbfSDavid du Colombier n -= m; 45080ee5cbfSDavid du Colombier } 45180ee5cbfSDavid du Colombier if(write(h->fd, h->start, Hsize) != Hsize){ 45280ee5cbfSDavid du Colombier h->state = Herr; 45380ee5cbfSDavid du Colombier h->stop = h->pos; 45480ee5cbfSDavid du Colombier return -1; 45580ee5cbfSDavid du Colombier } 45680ee5cbfSDavid du Colombier h->seek += Hsize; 45780ee5cbfSDavid du Colombier } 45880ee5cbfSDavid du Colombier m = n % Hsize; 45980ee5cbfSDavid du Colombier n -= m; 460b7b24591SDavid du Colombier if(n != 0 && write(h->fd, buf, n) != n){ 46180ee5cbfSDavid du Colombier h->state = Herr; 46280ee5cbfSDavid du Colombier h->stop = h->pos; 46380ee5cbfSDavid du Colombier return -1; 46480ee5cbfSDavid du Colombier } 46580ee5cbfSDavid du Colombier h->seek += n; 46680ee5cbfSDavid du Colombier buf += n; 46780ee5cbfSDavid du Colombier pos = h->pos = h->start; 46880ee5cbfSDavid du Colombier n = m; 46980ee5cbfSDavid du Colombier } 47080ee5cbfSDavid du Colombier memmove(pos, buf, n); 47180ee5cbfSDavid du Colombier h->pos = pos + n; 47280ee5cbfSDavid du Colombier return len; 47380ee5cbfSDavid du Colombier } 474