ref: 3345ce88f43cae566eabcc164d5587baf666ca8b
parent: 0e7f9e241586c40c1d88b387b706d12fc28e811f
author: qwx <[email protected]>
date: Thu Nov 24 23:12:06 EST 2022
fix ^ and simplify reading/writing buffers from/to files
--- a/cmd.c
+++ b/cmd.c
@@ -65,7 +65,7 @@
}
static void
-recalcsize(void)
+assertsize(void)
{
Chunk *c;
@@ -289,7 +289,8 @@
bp += Δ;
m -= Δ;
}
- *boff = n;
+ if(boff != nil)
+ *boff = n;
return scratch;
}
@@ -445,35 +446,38 @@
static Chunk *
readintochunks(int fd)
{
- int n, m;
- usize off;
+ int n;
+ usize m;
Chunk *rc, *c, *nc;
- rc = newchunk(Iochunksz);
- for(off=0, m=0, c=rc;; m+=n, off+=n){
- if(off + Ioreadsz > Iochunksz){
- if(off != Iochunksz)
- resizechunk(c, off);
- c->bufsz = off;
- nc = newchunk(Iochunksz);
+ for(m=0, rc=c=nil;; m+=n){
+ nc = newchunk(Iochunksz);
+ if(rc == nil)
+ rc = nc;
+ else
linkchunk(c, nc);
- c = nc;
- off = 0;
- }
- if((n = read(fd, c->buf+off, Ioreadsz)) <= 0)
+ c = nc;
+ if((n = readn(fd, c->buf, Iochunksz)) < Iochunksz)
break;
+ yield();
}
close(fd);
- if(n < 0 || m == 0){
- fprint(2, "readintochunks: nothing read\n");
- if(m == 0){
- freechunk(rc);
+ if(n < 0)
+ fprint(2, "readintochunks: %r\n");
+ else if(n == 0){
+ if(c != rc)
+ unlinkchunk(c);
+ freechunk(c);
+ if(c == rc){
+ werrstr("readintochunks: nothing read");
return nil;
}
+ }else if(n > 0 && n < Iochunksz){
+ resizechunk(c, n);
+ /* kludge! first chunk still unlinked */
+ if(m < Iochunksz)
+ totalsz += Iochunksz - c->bufsz;
}
- resizechunk(c, off);
- if(m < Iochunksz) /* kludge! >:( */
- totalsz += Iochunksz - c->bufsz;
return rc;
}
@@ -495,24 +499,29 @@
static int
writebuf(int fd)
{
- usize n, m;
+ int nio;
+ usize n, m, c, k;
uchar *p;
Dot d;
d.pos = d.from.pos = dot.from.pos;
d.to.pos = dot.to.pos;
- for(m=d.to.pos-d.from.pos; m>0;){
- n = sizeof plentyofroom < m ? sizeof plentyofroom : m;
- if((p = getbuf(d, n, plentyofroom, &n)) == nil){
- fprint(2, "writebuf: getbuf won't feed\n");
+ if((nio = iounit(fd)) == 0)
+ nio = 8192;
+ nio = MIN(nio, sizeof plentyofroom);
+ for(m=d.to.pos-d.from.pos, c=0; m>0;){
+ k = nio < m ? nio : m;
+ if((p = getbuf(d, k, plentyofroom, &k)) == nil){
+ fprint(2, "writebuf: couldn\'t get a buffer: %r\n");
return -1;
}
- if((n = write(fd, p, n)) != n){
- fprint(2, "writebuf: short write not %zd\n", n);
+ if((n = write(fd, p, k)) != k){
+ fprint(2, "writebuf: short write not %zd: %r\n", k);
return -1;
}
m -= n;
d.pos += n;
+ c += n;
}
write(fd, plentyofroom, 0); /* close pipe */
return 0;
@@ -521,35 +530,59 @@
static void
rc(void *s)
{
+ close(epfd[1]);
dup(epfd[0], 0);
- dup(epfd[1], 1);
+ dup(epfd[0], 1);
close(epfd[0]);
- close(epfd[1]);
procexecl(nil, "/bin/rc", "rc", "-c", s, nil);
sysfatal("procexec: %r");
}
-static int
-pipeline(char *arg, int rr, int wr)
+static void
+wproc(void *efd)
{
+ int fd;
+
+ fd = (intptr)efd;
+ writebuf(fd);
+ close(fd);
+ threadexits(nil);
+}
+static void
+rthread(void *efd)
+{
+ int fd;
Chunk *c;
+ fd = (intptr)efd;
+ if((c = readintochunks(fd)) == nil)
+ threadexits("readintochunks: %r");
+ close(fd);
+ paste(nil, c);
+ assertsize();
+ redraw(0);
+ threadexits(nil);
+}
+
+static int
+pipeline(char *arg, int rr, int wr)
+{
+ assertsize();
if(pipe(epfd) < 0)
sysfatal("pipe: %r");
if(procrfork(rc, arg, mainstacksize, RFFDG|RFNOTEG|RFNAMEG) < 0)
sysfatal("procrfork: %r");
- if(wr)
- writebuf(epfd[1]);
- close(epfd[1]);
- if(rr){
- if((c = readintochunks(epfd[0])) == nil){
- close(epfd[0]);
- return -1;
- }
- paste(nil, c);
- }
close(epfd[0]);
- return 1;
+ if(wr && procrfork(wproc, (int*)dup(epfd[1], -1), mainstacksize, RFFDG) < 0){
+ fprint(2, "threadcreate: %r\n");
+ return -1;
+ }
+ if(rr && threadcreate(rthread, (int*)dup(epfd[1], -1), mainstacksize) < 0){
+ fprint(2, "threadcreate: %r\n");
+ return -1;
+ }
+ close(epfd[1]);
+ return 0;
}
static int
@@ -565,11 +598,9 @@
}
static int
-pipethrough(char *)
+pipethrough(char *arg)
{
- werrstr("pipethrough disabled due to pebcak");
- return -1;
- //return pipeline(arg, 1, 1);
+ return pipeline(arg, 1, 1);
}
/* the entire string is treated as the filename, ie.
@@ -612,7 +643,7 @@
break;
s += n;
}
- recalcsize();
+ assertsize();
switch(r){
case '<': return pipefrom(s);
case '^': return pipethrough(s);
--- a/dat.h
+++ b/dat.h
@@ -9,7 +9,6 @@
Sampsz = 2 * 2,
Outsz = WriteDelay * Sampsz,
Iochunksz = 4*1024*1024, /* ≈ 24 sec. at 44.1 kHz */
- Ioreadsz = 64*1024,
};
struct Chunk{
uchar *buf;