acme/win: fix fswrite() not assuming iounit < EVENTSIZE

This commit is contained in:
cinap_lenrek 2014-12-12 21:06:16 +01:00
parent 651fa5bd50
commit aac81cf070

View file

@ -46,10 +46,9 @@ fswrite(Req *r)
{ {
static Event *e[4]; static Event *e[4];
Event *ep; Event *ep;
int i, j, ei, nb, wid, pid; int nb, wid, pid;
Rune rune; Rune rune;
char *s; char *s, *se, *d, *p;
char tmp[UTFmax], *t;
static int n, partial; static int n, partial;
if(r->fid->file == devnew){ if(r->fid->file == devnew){
@ -60,58 +59,80 @@ fswrite(Req *r)
s = emalloc(r->ifcall.count+1); s = emalloc(r->ifcall.count+1);
memmove(s, r->ifcall.data, r->ifcall.count); memmove(s, r->ifcall.data, r->ifcall.count);
s[r->ifcall.count] = 0; s[r->ifcall.count] = 0;
pid = strtol(s, &t, 0); pid = strtol(s, &p, 0);
if(*t==' ') if(*p==' ')
t++; p++;
i = newpipewin(pid, t); nb = newpipewin(pid, p);
free(s); free(s);
s = emalloc(32); s = emalloc(32);
sprint(s, "%lud", (ulong)i); sprint(s, "%lud", (ulong)nb);
r->fid->aux = s; r->fid->aux = s;
r->ofcall.count = r->ifcall.count; r->ofcall.count = r->ifcall.count;
respond(r, nil); respond(r, nil);
return; return;
} }
assert(r->fid->file == devcons); if(r->fid->file != devcons){
respond(r, "bug in fswrite");
return;
}
/* init buffer rings */
if(e[0] == nil){ if(e[0] == nil){
for(i=0; i<nelem(e); i++){ for(n=0; n<nelem(e); n++){
e[i] = emalloc(sizeof(Event)); e[n] = emalloc(sizeof(Event));
e[i]->c1 = 'S'; e[n]->c1 = 'S';
} }
} }
ep = e[n]; s = r->ifcall.data;
n = (n+1)%nelem(e); se = s + r->ifcall.count;
assert(r->ifcall.count <= 8192); /* is this guaranteed by lib9p? */
nb = r->ifcall.count; while((nb = (se - s)) > 0){
memmove(ep->b+partial, r->ifcall.data, nb); assert(partial >= 0);
nb += partial; if((partial+nb) > EVENTSIZE)
ep->b[nb] = '\0'; nb = EVENTSIZE - partial;
if(strlen(ep->b) < nb){ /* nulls in data */
t = ep->b; /* fill buffer */
for(i=j=0; i<nb; i++) ep = e[n % nelem(e)];
if(ep->b[i] != '\0') memmove(ep->b+partial, s, nb);
t[j++] = ep->b[i]; partial += nb;
nb = j; s += nb;
t[j] = '\0';
/* check full runes, remove null bytes */
ep->nr = ep->nb = 0;
for(d = p = ep->b; partial > 0; partial -= wid, p += wid){
if(*p == '\0'){
wid = 1;
continue;
} }
ei = nb>8192? 8192 : nb;
/* process bytes into runes, transferring terminal partial runes into next buffer */ if(!fullrune(p, partial))
for(i=j=0; i<ei && fullrune(ep->b+i, ei-i); i+=wid,j++) break;
wid = chartorune(&rune, ep->b+i);
memmove(tmp, ep->b+i, nb-i); wid = chartorune(&rune, p);
partial = nb-i; runetochar(d, &rune);
ep->nb = i; d += wid;
ep->nr = j;
ep->b[i] = '\0'; ep->nr++;
if(i != 0){ ep->nb += wid;
}
/* send buffer when not empty */
if(ep->nb > 0){
ep->b[ep->nb] = '\0';
sendp(win->cevent, ep); sendp(win->cevent, ep);
recvp(writechan); recvp(writechan);
} }
partial = nb-i; n++;
memmove(e[n]->b, tmp, partial);
/* put partial reminder onto next buffer */
if(partial > 0){
ep = e[n % nelem(e)];
memmove(ep->b, p, partial);
}
}
r->ofcall.count = r->ifcall.count; r->ofcall.count = r->ifcall.count;
respond(r, nil); respond(r, nil);
} }