summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-12-12 21:06:16 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2014-12-12 21:06:16 +0100
commitaac81cf0701330fff4ff83fc72e9200dc4b1a60c (patch)
tree79e333c54d00b65ec05d39995e53c280578c8bc1
parent651fa5bd50c10a13cc970b9bd0ef1c6ea3c5f62a (diff)
downloadplan9front-aac81cf0701330fff4ff83fc72e9200dc4b1a60c.tar.xz
acme/win: fix fswrite() not assuming iounit < EVENTSIZE
-rw-r--r--acme/bin/source/win/fs.c103
1 files changed, 62 insertions, 41 deletions
diff --git a/acme/bin/source/win/fs.c b/acme/bin/source/win/fs.c
index 6c41eb072..bdfe08204 100644
--- a/acme/bin/source/win/fs.c
+++ b/acme/bin/source/win/fs.c
@@ -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';
- }
- 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);
+ 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;
+ }
+
+ 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);
+ }
}
- partial = nb-i;
- memmove(e[n]->b, tmp, partial);
+
r->ofcall.count = r->ifcall.count;
respond(r, nil);
}