diff --git a/io/io_close.c b/io/io_close.c index af5698a..aa7b1bf 100644 --- a/io/io_close.c +++ b/io/io_close.c @@ -1,4 +1,5 @@ #include +#include #include "io_internal.h" void io_close(int64 d) { @@ -7,6 +8,10 @@ void io_close(int64 d) { e->inuse=0; io_dontwantread(d); io_dontwantwrite(d); + if (e->mmapped) { + munmap(e->mmapped,e->maplen); + e->mmapped=0; + } } close(d); } diff --git a/io/io_sendfile.c b/io/io_sendfile.c index de4c2a5..05a31e7 100644 --- a/io/io_sendfile.c +++ b/io/io_sendfile.c @@ -2,6 +2,8 @@ #include "io_internal.h" #include "havebsdsf.h" +#undef __linux__ + #if defined(HAVE_BSDSENDFILE) #include #include @@ -42,6 +44,7 @@ int64 io_sendfile(int64 s,int64 fd,uint64 off,uint64 n) { #else #include +#include #define BUFSIZE 16384 @@ -50,6 +53,46 @@ int64 io_sendfile(int64 out,int64 in,uint64 off,uint64 bytes) { int n,m; uint64 sent=0; io_entry* e=array_get(&io_fds,sizeof(io_entry),out); + if (e) { + const char* c; + long left; + do { + if (e->mmapped) { + /* did we already map the right chunk? */ + if (off>=e->mapofs && offmapofs+e->maplen) + goto mapok; /* ok; mmapped the right chunk*/ + munmap(e->mmapped,e->maplen); + e->mmapped=0; + } + e->mapofs=off&0xffffffffffff0000ull; + if (e->mapofs+0xffff>off+bytes) + e->maplen=off+bytes-e->mapofs; + else + e->maplen=0xffff; + if ((e->mmapped=mmap(0,e->maplen,PROT_READ,MAP_SHARED,in,e->mapofs))==MAP_FAILED) { + e->mmapped=0; + goto readwrite; + } + mapok: + c=(const char*)(e->mmapped)+(off&0xffff); + left=e->maplen-(off&0xffff); + while (left>0) { + m=write(out,c,left); + if (m==-1) { + e->canwrite=0; + e->next_write=-1; + return errno==EAGAIN?(sent?sent:-1):-3; + } + if (m==0) return sent; + sent+=m; + left-=m; + bytes-=m; + off+=m; + } + } while (bytes); + return sent; + } +readwrite: if (lseek(in,off,SEEK_SET) != off) return -1; while (bytes>0) { diff --git a/io_internal.h b/io_internal.h index cdf7853..5b34940 100644 --- a/io_internal.h +++ b/io_internal.h @@ -25,6 +25,9 @@ typedef struct { long next_read; long next_write; void* cookie; + void* mmapped; + long maplen; + uint64 mapofs; #ifdef __MINGW32__ OVERLAPPED o; HANDLE fd;