xref: /plan9-contrib/sys/src/cmd/pump.c (revision b45eff48b2b71eae634f2ef40be78636406cc3e8)
192f5376fSDavid du Colombier /* pump - copy through circular buffer */
292f5376fSDavid du Colombier #include <u.h>
392f5376fSDavid du Colombier #include <libc.h>
492f5376fSDavid du Colombier 
592f5376fSDavid du Colombier uchar*	buf;
6649197e1SDavid du Colombier 
7649197e1SDavid du Colombier Lock	arithlock;	/* protect 64-bit accesses: unlikely to be atomic */
8649197e1SDavid du Colombier uvlong	nin;
9649197e1SDavid du Colombier uvlong	nout;
10649197e1SDavid du Colombier 
1192f5376fSDavid du Colombier ulong	kilo;
1292f5376fSDavid du Colombier ulong	max;
1392f5376fSDavid du Colombier long	ssize;
14649197e1SDavid du Colombier vlong	tsize;
1592f5376fSDavid du Colombier int	dsize;
1692f5376fSDavid du Colombier int	done;
1792f5376fSDavid du Colombier int	ibsize;
1892f5376fSDavid du Colombier int	obsize;
1992f5376fSDavid du Colombier int	verb;
20*b45eff48SDavid du Colombier vlong	off;
2192f5376fSDavid du Colombier 
2292f5376fSDavid du Colombier void	doinput(int);
2392f5376fSDavid du Colombier void	dooutput(int);
2492f5376fSDavid du Colombier 
2592f5376fSDavid du Colombier static void
usage(void)2692f5376fSDavid du Colombier usage(void)
2792f5376fSDavid du Colombier {
28*b45eff48SDavid du Colombier 	fprint(2, "usage: pump [-b iando] [-d sleeptime] [-f ofile] "
29*b45eff48SDavid du Colombier 		"[-i ireadsize]\n\t[-k KB-buffer] [-o owritesize] "
30*b45eff48SDavid du Colombier 		"[-s start-KB] [-S seek-offset]\n\t[-t mins] [files]\n");
3192f5376fSDavid du Colombier 	exits("usage");
3292f5376fSDavid du Colombier }
3392f5376fSDavid du Colombier 
3492f5376fSDavid du Colombier void
main(int argc,char * argv[])3592f5376fSDavid du Colombier main(int argc, char *argv[])
3692f5376fSDavid du Colombier {
3792f5376fSDavid du Colombier 	int i, f, fo;
3892f5376fSDavid du Colombier 	char *file;
3992f5376fSDavid du Colombier 
4092f5376fSDavid du Colombier 	kilo = 5000;
4192f5376fSDavid du Colombier 	obsize = ibsize = 8*1024;
4292f5376fSDavid du Colombier 	dsize = 0;
4392f5376fSDavid du Colombier 	fo = 1;
44*b45eff48SDavid du Colombier 	off = 0;
4592f5376fSDavid du Colombier 
4692f5376fSDavid du Colombier 	ARGBEGIN {
4792f5376fSDavid du Colombier 	default:
4892f5376fSDavid du Colombier 		usage();
4992f5376fSDavid du Colombier 	case 'b':
5092f5376fSDavid du Colombier 		obsize = ibsize = atoi(EARGF(usage()));
5192f5376fSDavid du Colombier 		break;
5292f5376fSDavid du Colombier 	case 'd':
5392f5376fSDavid du Colombier 		dsize = atoi(EARGF(usage()));
5492f5376fSDavid du Colombier 		break;
5592f5376fSDavid du Colombier 	case 'f':
5692f5376fSDavid du Colombier 		file = EARGF(usage());
5792f5376fSDavid du Colombier 		fo = create(file, 1, 0666);
5892f5376fSDavid du Colombier 		if(fo < 0)
5992f5376fSDavid du Colombier 			sysfatal("can't create %s: %r", file);
6092f5376fSDavid du Colombier 		break;
6192f5376fSDavid du Colombier 	case 'i':
6292f5376fSDavid du Colombier 		ibsize = atoi(EARGF(usage()));
6392f5376fSDavid du Colombier 		break;
6492f5376fSDavid du Colombier 	case 'k':
6592f5376fSDavid du Colombier 		kilo = atoi(EARGF(usage()));
6692f5376fSDavid du Colombier 		break;
6792f5376fSDavid du Colombier 	case 'o':
6892f5376fSDavid du Colombier 		obsize = atoi(EARGF(usage()));
6992f5376fSDavid du Colombier 		break;
7092f5376fSDavid du Colombier 	case 's':
7192f5376fSDavid du Colombier 		ssize = atoi(EARGF(usage()));
7292f5376fSDavid du Colombier 		if(ssize <= 0)
7392f5376fSDavid du Colombier 			ssize = 800;
7492f5376fSDavid du Colombier 		ssize <<= 10;
7592f5376fSDavid du Colombier 		break;
76*b45eff48SDavid du Colombier 	case 'S':
77*b45eff48SDavid du Colombier 		off = atoll(EARGF(usage()));
78*b45eff48SDavid du Colombier 		if(off < 0)
79*b45eff48SDavid du Colombier 			sysfatal("seek offset %lld must be non-negative", off);
80*b45eff48SDavid du Colombier 		break;
8192f5376fSDavid du Colombier 	case 't':
82649197e1SDavid du Colombier 		tsize = atoll(EARGF(usage()));
8392f5376fSDavid du Colombier 		tsize *= 10584000;		/* minutes */
8492f5376fSDavid du Colombier 		break;
8592f5376fSDavid du Colombier 	} ARGEND
8692f5376fSDavid du Colombier 	kilo <<= 10;
8792f5376fSDavid du Colombier 
8892f5376fSDavid du Colombier 	buf = malloc(kilo);
8992f5376fSDavid du Colombier 	if(buf == nil)
9092f5376fSDavid du Colombier 		sysfatal("no memory: %r");
9192f5376fSDavid du Colombier 	nin = 0;
9292f5376fSDavid du Colombier 	nout = 0;
9392f5376fSDavid du Colombier 	done = 0;
9492f5376fSDavid du Colombier 	max = 0;
9592f5376fSDavid du Colombier 
9692f5376fSDavid du Colombier 	switch(rfork(RFPROC|RFNOWAIT|RFNAMEG|RFMEM)) {
9792f5376fSDavid du Colombier 	default:
9892f5376fSDavid du Colombier 		dooutput(fo);
9992f5376fSDavid du Colombier 		break;
10092f5376fSDavid du Colombier 	case 0:
10192f5376fSDavid du Colombier 		for(i=0; i<argc; i++) {
10292f5376fSDavid du Colombier 			f = open(argv[i], OREAD);
10392f5376fSDavid du Colombier 			if(f < 0) {
10492f5376fSDavid du Colombier 				fprint(2, "%s: can't open %s: %r\n",
10592f5376fSDavid du Colombier 					argv0, argv[i]);
10692f5376fSDavid du Colombier 				break;
10792f5376fSDavid du Colombier 			}
10892f5376fSDavid du Colombier 			doinput(f);
10992f5376fSDavid du Colombier 			close(f);
11092f5376fSDavid du Colombier 		}
11192f5376fSDavid du Colombier 		if(argc == 0)
11292f5376fSDavid du Colombier 			doinput(0);
11392f5376fSDavid du Colombier 		break;
11492f5376fSDavid du Colombier 	case -1:
11592f5376fSDavid du Colombier 		fprint(2, "%s: fork failed: %r\n", argv0);
11692f5376fSDavid du Colombier 		break;
11792f5376fSDavid du Colombier 	}
11892f5376fSDavid du Colombier 	done = 1;
11992f5376fSDavid du Colombier 	exits(0);
12092f5376fSDavid du Colombier }
12192f5376fSDavid du Colombier 
122649197e1SDavid du Colombier /* call with arithlock held */
123649197e1SDavid du Colombier static int
sleepunlocked(long ms)124649197e1SDavid du Colombier sleepunlocked(long ms)
125649197e1SDavid du Colombier {
126649197e1SDavid du Colombier 	int r;
127649197e1SDavid du Colombier 
128649197e1SDavid du Colombier 	unlock(&arithlock);
129649197e1SDavid du Colombier 	r = sleep(ms);
130649197e1SDavid du Colombier 	lock(&arithlock);
131649197e1SDavid du Colombier 	return r;
132649197e1SDavid du Colombier }
133649197e1SDavid du Colombier 
13492f5376fSDavid du Colombier void
dooutput(int f)13592f5376fSDavid du Colombier dooutput(int f)
13692f5376fSDavid du Colombier {
13792f5376fSDavid du Colombier 	long n, l, c;
13892f5376fSDavid du Colombier 
139*b45eff48SDavid du Colombier 	seek(f, off, 0);
140649197e1SDavid du Colombier 	lock(&arithlock);
14192f5376fSDavid du Colombier 	for (;;) {
14292f5376fSDavid du Colombier 		n = nin - nout;
14392f5376fSDavid du Colombier 		if(n == 0) {
14492f5376fSDavid du Colombier 			if(done)
14592f5376fSDavid du Colombier 				break;
146649197e1SDavid du Colombier 			sleepunlocked(dsize);
14792f5376fSDavid du Colombier 			continue;
14892f5376fSDavid du Colombier 		}
14992f5376fSDavid du Colombier 		if(verb && n > max) {
15092f5376fSDavid du Colombier 			fprint(2, "n = %ld\n", n);
15192f5376fSDavid du Colombier 			max = n;
15292f5376fSDavid du Colombier 		}
15392f5376fSDavid du Colombier 		l = nout % kilo;
154649197e1SDavid du Colombier 		unlock(&arithlock);
155649197e1SDavid du Colombier 
15692f5376fSDavid du Colombier 		if(kilo-l < n)
15792f5376fSDavid du Colombier 			n = kilo-l;
15892f5376fSDavid du Colombier 		if(n > obsize)
15992f5376fSDavid du Colombier 			n = obsize;
16092f5376fSDavid du Colombier 		c = write(f, buf+l, n);
161649197e1SDavid du Colombier 
162649197e1SDavid du Colombier 		lock(&arithlock);
16392f5376fSDavid du Colombier 		if(c != n) {
1644d2c0504SDavid du Colombier 			fprint(2, "%s: write error at offset %,lld: %r\n",
1654d2c0504SDavid du Colombier 				argv0, seek(f, 0, 1));
16692f5376fSDavid du Colombier 			break;
16792f5376fSDavid du Colombier 		}
16892f5376fSDavid du Colombier 		nout += c;
16992f5376fSDavid du Colombier 		if(tsize && nout > tsize) {
17092f5376fSDavid du Colombier 			fprint(2, "%s: time limit exceeded\n", argv0);
17192f5376fSDavid du Colombier 			break;
17292f5376fSDavid du Colombier 		}
17392f5376fSDavid du Colombier 	}
174649197e1SDavid du Colombier 	unlock(&arithlock);
17592f5376fSDavid du Colombier }
17692f5376fSDavid du Colombier 
17792f5376fSDavid du Colombier void
doinput(int f)17892f5376fSDavid du Colombier doinput(int f)
17992f5376fSDavid du Colombier {
18092f5376fSDavid du Colombier 	long n, l, c, xnin;
18192f5376fSDavid du Colombier 
182*b45eff48SDavid du Colombier 	seek(f, off, 0);
183649197e1SDavid du Colombier 	lock(&arithlock);
18492f5376fSDavid du Colombier 	if(ssize > 0) {
18592f5376fSDavid du Colombier 		for (xnin = 0; xnin < ssize && !done; xnin += c) {
18692f5376fSDavid du Colombier 			n = kilo - (xnin - nout);
18792f5376fSDavid du Colombier 			if(n == 0)
18892f5376fSDavid du Colombier 				break;
189649197e1SDavid du Colombier 			unlock(&arithlock);
190649197e1SDavid du Colombier 
19192f5376fSDavid du Colombier 			l = xnin % kilo;
19292f5376fSDavid du Colombier 			if(kilo-l < n)
19392f5376fSDavid du Colombier 				n = kilo-l;
19492f5376fSDavid du Colombier 			if(n > ibsize)
19592f5376fSDavid du Colombier 				n = ibsize;
19692f5376fSDavid du Colombier 			c = read(f, buf+l, n);
197649197e1SDavid du Colombier 
198649197e1SDavid du Colombier 			lock(&arithlock);
19992f5376fSDavid du Colombier 			if(c <= 0) {
20092f5376fSDavid du Colombier 				if(c < 0)
20192f5376fSDavid du Colombier 					fprint(2, "%s: read error: %r\n", argv0);
20292f5376fSDavid du Colombier 				break;
20392f5376fSDavid du Colombier 			}
20492f5376fSDavid du Colombier 		}
20592f5376fSDavid du Colombier 		nin = xnin;
20692f5376fSDavid du Colombier 	}
20792f5376fSDavid du Colombier 	while(!done) {
20892f5376fSDavid du Colombier 		n = kilo - (nin - nout);
20992f5376fSDavid du Colombier 		if(n == 0) {
210649197e1SDavid du Colombier 			sleepunlocked(0);
21192f5376fSDavid du Colombier 			continue;
21292f5376fSDavid du Colombier 		}
21392f5376fSDavid du Colombier 		l = nin % kilo;
214649197e1SDavid du Colombier 		unlock(&arithlock);
215649197e1SDavid du Colombier 
21692f5376fSDavid du Colombier 		if(kilo-l < n)
21792f5376fSDavid du Colombier 			n = kilo-l;
21892f5376fSDavid du Colombier 		if(n > ibsize)
21992f5376fSDavid du Colombier 			n = ibsize;
22092f5376fSDavid du Colombier 		c = read(f, buf+l, n);
221649197e1SDavid du Colombier 
222649197e1SDavid du Colombier 		lock(&arithlock);
22392f5376fSDavid du Colombier 		if(c <= 0) {
22492f5376fSDavid du Colombier 			if(c < 0)
22592f5376fSDavid du Colombier 				fprint(2, "%s: read error: %r\n", argv0);
22692f5376fSDavid du Colombier 			break;
22792f5376fSDavid du Colombier 		}
22892f5376fSDavid du Colombier 		nin += c;
22992f5376fSDavid du Colombier 	}
230649197e1SDavid du Colombier 	unlock(&arithlock);
23192f5376fSDavid du Colombier }
232