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];
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
|
||||||
|
/* put partial reminder onto next buffer */
|
||||||
|
if(partial > 0){
|
||||||
|
ep = e[n % nelem(e)];
|
||||||
|
memmove(ep->b, p, partial);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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){
|
|
||||||
sendp(win->cevent, ep);
|
|
||||||
recvp(writechan);
|
|
||||||
}
|
|
||||||
partial = nb-i;
|
|
||||||
memmove(e[n]->b, tmp, partial);
|
|
||||||
r->ofcall.count = r->ifcall.count;
|
r->ofcall.count = r->ifcall.count;
|
||||||
respond(r, nil);
|
respond(r, nil);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue