/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* 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 voidusage(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");} voidmain(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 intsleepunlocked(long ms){ int r; unlock(&arithlock); r = sleep(ms); lock(&arithlock); return r;} voiddooutput(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 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);} voiddoinput(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);}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
/* 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 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;
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);
}