diff --git a/CHANGES b/CHANGES index 14ed007..94766a5 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,8 @@ #include in io/io_sendfile.c (broken OpenBSD, thx Rob) add scan_urlencoded2 (like scan_urlencoded but will not convert '+' to ' '; needed for web servers, so they can serve libstdc++.tar.gz) + fix iob_write to handle failure properly + document that the iob_write callback should limit itself 0.21: errno cleanup and man page updates (Rolf Eike Beer) diff --git a/io/iob_write.3 b/io/iob_write.3 index 90e4e6d..62a3639 100644 --- a/io/iob_write.3 +++ b/io/iob_write.3 @@ -25,5 +25,13 @@ writable, and then calling iob_write until it returns 0, -1 or -3. If it returns 0, terminate the loop (everything was written OK). If it returns -1, call io_wait again. If it returned -3, signal an error. + +.SH NOTE +iob_write will continue to call your callback until it returns an error. +So if you are in a state machine, for example a web server using this +for SSL support, make sure to write at most n bytes at a time (e.g. 64k) +and the next time you are called return -1. Otherwise iob_write might +not return until the whole file is served. + .SH "SEE ALSO" iob_send(3) diff --git a/io/iob_write.c b/io/iob_write.c index 025762d..d4cba7d 100644 --- a/io/iob_write.c +++ b/io/iob_write.c @@ -18,16 +18,14 @@ int64 iob_write(int64 s,io_batch* b,io_write_callback cb) { sent=io_mmapwritefile(s,e[i].fd,e[i].offset,e[i].n,cb); else sent=cb(s,e[i].buf+e[i].offset,e[i].n); - if (sent > e[i].n) sent=e[i].n; /* can't happen */ + if (sent>0 && sent>e[i].n) sent=e[i].n; /* can't happen */ thatsit=(sent != e[i].n); - if (sent==-1 && errno!=EAGAIN) - sent=-3; - if (sent>0) { - e[i].offset+=sent; - e[i].n-=sent; - total+=sent; - } else + if (sent<=0) return total?total:sent; + e[i].offset+=sent; + e[i].n-=sent; + total+=sent; + b->bytesleft-=sent; if (thatsit) break; } if (total == b->bytesleft) diff --git a/t.c b/t.c index 90398d2..8714ce2 100644 --- a/t.c +++ b/t.c @@ -19,22 +19,43 @@ #include #include #include -#include +#include "errmsg.h" +#include "iob.h" #define rdtscl(low) \ __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx") +int64 writecb(int64 fd,const void* buf,uint64 n) { +#if 0 + int r; + int todo=n>=65536?65536:n; + r=write(fd,buf,todo); + if (r==-1 && r!=EAGAIN) r=-3; + return r; +#endif + return -1; +} + int main(int argc,char* argv[]) { + static io_batch b; + int64 fd=open("t.c",0); + iob_addbuf(&b,"fnord",5); + iob_addfile_close(&b,fd,0,7365); + iob_write(1,&b,writecb); +#if 0 char dest[1024]; unsigned long len; scan_urlencoded2("libstdc++.tar.gz",dest,&len); buffer_putmflush(buffer_1,dest,"\n"); +#endif #if 0 static stralloc sa; stralloc_copym(&sa,"foo ","bar ","baz.\n"); write(1,sa.s,sa.len); #endif +#if 0 buffer_putmflush(buffer_1,"foo ","bar ","baz.\n"); +#endif #if 0 char* c="fnord"; int fd=open_read(c);