/* pump - copy through circular buffer */ #include #include uchar* buf; Lock arithlock; /* protect 64-bit accesses: unlikely to be atomic */ uvlong nin; uvlong nout; ulong kilo; ulong max; long ssize; vlong tsize; int dsize; int done; int ibsize; int obsize; int verb; vlong off; void doinput(int); void dooutput(int); static void usage(void) { fprint(2, "usage: pump [-b iando] [-d sleeptime] [-f ofile] " "[-i ireadsize]\n\t[-k KB-buffer] [-o owritesize] " "[-s start-KB] [-S seek-offset]\n\t[-t mins] [files]\n"); exits("usage"); } void main(int argc, char *argv[]) { int i, f, fo; char *file; kilo = 5000; obsize = ibsize = 8*1024; dsize = 0; fo = 1; off = 0; ARGBEGIN { default: usage(); case 'b': obsize = ibsize = atoi(EARGF(usage())); break; case 'd': dsize = atoi(EARGF(usage())); break; case 'f': file = EARGF(usage()); fo = create(file, 1, 0666); if(fo < 0) sysfatal("can't create %s: %r", file); break; case 'i': ibsize = atoi(EARGF(usage())); break; case 'k': kilo = atoi(EARGF(usage())); break; case 'o': obsize = atoi(EARGF(usage())); break; case 's': ssize = atoi(EARGF(usage())); if(ssize <= 0) ssize = 800; ssize <<= 10; break; case 'S': off = atoll(EARGF(usage())); if(off < 0) sysfatal("seek offset %lld must be non-negative", off); break; case 't': tsize = atoll(EARGF(usage())); tsize *= 10584000; /* minutes */ break; } ARGEND kilo <<= 10; buf = malloc(kilo); if(buf == nil) sysfatal("no memory: %r"); nin = 0; nout = 0; done = 0; max = 0; switch(rfork(RFPROC|RFNOWAIT|RFNAMEG|RFMEM)) { default: dooutput(fo); break; case 0: for(i=0; i max) { fprint(2, "n = %ld\n", n); max = n; } l = nout % kilo; unlock(&arithlock); if(kilo-l < n) n = kilo-l; if(n > obsize) n = obsize; c = write(f, buf+l, n); lock(&arithlock); if(c != n) { fprint(2, "%s: write error at offset %,lld: %r\n", argv0, seek(f, 0, 1)); break; } nout += c; if(tsize && nout > tsize) { fprint(2, "%s: time limit exceeded\n", argv0); break; } } unlock(&arithlock); } void doinput(int f) { long n, l, c, xnin; seek(f, off, 0); lock(&arithlock); if(ssize > 0) { for (xnin = 0; xnin < ssize && !done; xnin += c) { n = kilo - (xnin - nout); if(n == 0) break; unlock(&arithlock); l = xnin % kilo; if(kilo-l < n) n = kilo-l; if(n > ibsize) n = ibsize; c = read(f, buf+l, n); lock(&arithlock); if(c <= 0) { if(c < 0) fprint(2, "%s: read error: %r\n", argv0); break; } } nin = xnin; } while(!done) { n = kilo - (nin - nout); if(n == 0) { sleepunlocked(0); continue; } l = nin % kilo; unlock(&arithlock); if(kilo-l < n) n = kilo-l; if(n > ibsize) n = ibsize; c = read(f, buf+l, n); lock(&arithlock); if(c <= 0) { if(c < 0) fprint(2, "%s: read error: %r\n", argv0); break; } nin += c; } unlock(&arithlock); }