1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
#include <io_internal.h>
#include <iob.h>
#include <unistd.h>
#include <sys/types.h>
#ifdef __MINGW32__
#include <windows.h>
#else
#include <sys/mman.h>
#endif
#include <errno.h>
#include "havepread.h"
#define BUFSIZE 16384
int64 io_mmapwritefile(int64 out,int64 in,uint64 off,uint64 bytes,io_write_callback writecb) {
char buf[BUFSIZE];
ssize_t n,m;
uint64 sent=0;
io_entry* e=iarray_get(&io_fds,out);
if (e) {
const char* c;
unsigned long left;
#ifdef __MINGW32__
if (!e->mh) e->mh=CreateFileMapping(in,0,PAGE_READONLY,0,0,NULL);
if (!e->mh) goto readwrite;
#endif
do {
if (e->mmapped) {
/* did we already map the right chunk? */
if (off>=e->mapofs && off<e->mapofs+e->maplen)
goto mapok; /* ok; mmapped the right chunk*/
#ifdef __MINGW32__
UnmapViewOfFile(e->mmapped);
#else
munmap(e->mmapped,e->maplen);
#endif
}
e->mapofs=off&0xffffffffffff0000ull;
if (e->mapofs+0x10000>off+bytes)
e->maplen=off+bytes-e->mapofs;
else
e->maplen=0x10000;
#ifdef __MINGW32__
if ((e->mmapped=MapViewOfFile(e->mh,FILE_MAP_READ,(DWORD)(e->mapofs>>32),
(DWORD)e->mapofs,e->maplen))==0)
#else
if ((e->mmapped=mmap(0,e->maplen,PROT_READ,MAP_SHARED,in,e->mapofs))==MAP_FAILED)
#endif
{
e->mmapped=0;
goto readwrite;
}
mapok:
c=(const char*)(e->mmapped)+(off&0xffff);
left=e->maplen-(off&0xffff);
if (left>bytes) left=bytes;
while (left>0) {
m=writecb(out,c,left);
if (m<0) {
io_eagain_write(out);
if (errno!=EAGAIN) {
#ifdef __MINGW32__
UnmapViewOfFile(e->mmapped);
#else
munmap(e->mmapped,e->maplen);
#endif
e->mmapped=0;
return -3;
}
return sent?(int64)sent:-1;
}
if (m==0) return sent;
sent+=m;
left-=m;
bytes-=m;
off+=m;
c+=m;
if (e && left>0) {
e->canwrite=0;
e->next_write=-1;
return sent;
}
}
} while (bytes);
if (e->mmapped) {
#ifdef __MINGW32__
UnmapViewOfFile(e->mmapped);
#else
munmap(e->mmapped,e->maplen);
#endif
e->mmapped=0;
}
return sent;
}
readwrite:
#ifndef HAVE_PREAD
if (lseek(in,off,SEEK_SET) != (off_t)off)
return -1;
#endif
while (bytes>0) {
char* tmp=buf;
#ifdef HAVE_PREAD
if ((n=pread(in,tmp,(bytes<BUFSIZE)?bytes:BUFSIZE,off))<=0)
return (sent?(int64)sent:-1);
off+=n;
#else
if ((n=read(in,tmp,(bytes<BUFSIZE)?bytes:BUFSIZE))<=0)
return (sent?(int64)sent:-1);
#endif
while (n>0) {
if ((m=writecb(out,tmp,n))<0) {
if (m==-1) {
if (e) {
e->canwrite=0;
e->next_write=-1;
}
return errno==EAGAIN?(sent?(int64)sent:-1):-3;
}
goto abort;
}
sent+=m;
n-=m;
bytes-=m;
tmp+=m;
if (e && m!=n) {
e->canwrite=0;
e->next_write=-1;
goto abort;
}
}
}
abort:
return sent;
}
|