acme/win: fix fswrite() not assuming iounit < EVENTSIZE
This commit is contained in:
parent
651fa5bd50
commit
aac81cf070
1 changed files with 62 additions and 41 deletions
|
@ -46,10 +46,9 @@ fswrite(Req *r)
|
|||
{
|
||||
static Event *e[4];
|
||||
Event *ep;
|
||||
int i, j, ei, nb, wid, pid;
|
||||
int nb, wid, pid;
|
||||
Rune rune;
|
||||
char *s;
|
||||
char tmp[UTFmax], *t;
|
||||
char *s, *se, *d, *p;
|
||||
static int n, partial;
|
||||
|
||||
if(r->fid->file == devnew){
|
||||
|
@ -60,58 +59,80 @@ fswrite(Req *r)
|
|||
s = emalloc(r->ifcall.count+1);
|
||||
memmove(s, r->ifcall.data, r->ifcall.count);
|
||||
s[r->ifcall.count] = 0;
|
||||
pid = strtol(s, &t, 0);
|
||||
if(*t==' ')
|
||||
t++;
|
||||
i = newpipewin(pid, t);
|
||||
pid = strtol(s, &p, 0);
|
||||
if(*p==' ')
|
||||
p++;
|
||||
nb = newpipewin(pid, p);
|
||||
free(s);
|
||||
s = emalloc(32);
|
||||
sprint(s, "%lud", (ulong)i);
|
||||
sprint(s, "%lud", (ulong)nb);
|
||||
r->fid->aux = s;
|
||||
r->ofcall.count = r->ifcall.count;
|
||||
respond(r, nil);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(r->fid->file == devcons);
|
||||
if(r->fid->file != devcons){
|
||||
respond(r, "bug in fswrite");
|
||||
return;
|
||||
}
|
||||
|
||||
/* init buffer rings */
|
||||
if(e[0] == nil){
|
||||
for(i=0; i<nelem(e); i++){
|
||||
e[i] = emalloc(sizeof(Event));
|
||||
e[i]->c1 = 'S';
|
||||
for(n=0; n<nelem(e); n++){
|
||||
e[n] = emalloc(sizeof(Event));
|
||||
e[n]->c1 = 'S';
|
||||
}
|
||||
}
|
||||
|
||||
ep = e[n];
|
||||
n = (n+1)%nelem(e);
|
||||
assert(r->ifcall.count <= 8192); /* is this guaranteed by lib9p? */
|
||||
nb = r->ifcall.count;
|
||||
memmove(ep->b+partial, r->ifcall.data, nb);
|
||||
nb += partial;
|
||||
ep->b[nb] = '\0';
|
||||
if(strlen(ep->b) < nb){ /* nulls in data */
|
||||
t = ep->b;
|
||||
for(i=j=0; i<nb; i++)
|
||||
if(ep->b[i] != '\0')
|
||||
t[j++] = ep->b[i];
|
||||
nb = j;
|
||||
t[j] = '\0';
|
||||
s = r->ifcall.data;
|
||||
se = s + r->ifcall.count;
|
||||
|
||||
while((nb = (se - s)) > 0){
|
||||
assert(partial >= 0);
|
||||
if((partial+nb) > EVENTSIZE)
|
||||
nb = EVENTSIZE - partial;
|
||||
|
||||
/* fill buffer */
|
||||
ep = e[n % nelem(e)];
|
||||
memmove(ep->b+partial, s, nb);
|
||||
partial += nb;
|
||||
s += nb;
|
||||
|
||||
/* 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 */
|
||||
for(i=j=0; i<ei && fullrune(ep->b+i, ei-i); i+=wid,j++)
|
||||
wid = chartorune(&rune, ep->b+i);
|
||||
memmove(tmp, ep->b+i, nb-i);
|
||||
partial = nb-i;
|
||||
ep->nb = i;
|
||||
ep->nr = j;
|
||||
ep->b[i] = '\0';
|
||||
if(i != 0){
|
||||
|
||||
if(!fullrune(p, partial))
|
||||
break;
|
||||
|
||||
wid = chartorune(&rune, p);
|
||||
runetochar(d, &rune);
|
||||
d += wid;
|
||||
|
||||
ep->nr++;
|
||||
ep->nb += wid;
|
||||
}
|
||||
|
||||
/* send buffer when not empty */
|
||||
if(ep->nb > 0){
|
||||
ep->b[ep->nb] = '\0';
|
||||
sendp(win->cevent, ep);
|
||||
recvp(writechan);
|
||||
}
|
||||
partial = nb-i;
|
||||
memmove(e[n]->b, tmp, partial);
|
||||
n++;
|
||||
|
||||
/* 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;
|
||||
respond(r, nil);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue