123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- /* pump - copy through circular buffer */
- #include <u.h>
- #include <libc.h>
- 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;
- void doinput(int);
- void dooutput(int);
- static void
- usage(void)
- {
- fprint(2, "usage: pump [-f ofile] [-k KB-buffer] [-i ireadsize]\n"
- "\t[-o owritesize] [-b iando] [-s start-KB] [-d sleeptime] "
- "[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;
- 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 '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<argc; i++) {
- f = open(argv[i], OREAD);
- if(f < 0) {
- fprint(2, "%s: can't open %s: %r\n",
- argv0, argv[i]);
- break;
- }
- doinput(f);
- close(f);
- }
- if(argc == 0)
- doinput(0);
- break;
- case -1:
- fprint(2, "%s: fork failed: %r\n", argv0);
- break;
- }
- done = 1;
- exits(0);
- }
- /* call with arithlock held */
- static int
- sleepunlocked(long ms)
- {
- int r;
- unlock(&arithlock);
- r = sleep(ms);
- lock(&arithlock);
- return r;
- }
- void
- dooutput(int f)
- {
- long n, l, c;
- lock(&arithlock);
- for (;;) {
- n = nin - nout;
- if(n == 0) {
- if(done)
- break;
- sleepunlocked(dsize);
- continue;
- }
- if(verb && n > 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: %r\n", argv0);
- 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;
- 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);
- }
|