]> git.lizzy.rs Git - plan9front.git/commitdiff
acme/win: fix fswrite() not assuming iounit < EVENTSIZE
authorcinap_lenrek <cinap_lenrek@felloff.net>
Fri, 12 Dec 2014 20:06:16 +0000 (21:06 +0100)
committercinap_lenrek <cinap_lenrek@felloff.net>
Fri, 12 Dec 2014 20:06:16 +0000 (21:06 +0100)
acme/bin/source/win/fs.c

index 6c41eb072b70838a81a2ab1af47192a8d99575d4..bdfe0820424a3967d7aca45b01e6bce33b437f1e 100644 (file)
@@ -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);
 }