Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* pump - copy through circular buffer */
2
#include <u.h>
3
#include <libc.h>
4
 
5
uchar*	buf;
6
 
7
Lock	arithlock;	/* protect 64-bit accesses: unlikely to be atomic */
8
uvlong	nin;
9
uvlong	nout;
10
 
11
ulong	kilo;
12
ulong	max;
13
long	ssize;
14
vlong	tsize;
15
int	dsize;
16
int	done;
17
int	ibsize;
18
int	obsize;
19
int	verb;
20
vlong	off;
21
 
22
void	doinput(int);
23
void	dooutput(int);
24
 
25
static void
26
usage(void)
27
{
28
	fprint(2, "usage: pump [-b iando] [-d sleeptime] [-f ofile] "
29
		"[-i ireadsize]\n\t[-k KB-buffer] [-o owritesize] "
30
		"[-s start-KB] [-S seek-offset]\n\t[-t mins] [files]\n");
31
	exits("usage");
32
}
33
 
34
void
35
main(int argc, char *argv[])
36
{
37
	int i, f, fo;
38
	char *file;
39
 
40
	kilo = 5000;
41
	obsize = ibsize = 8*1024;
42
	dsize = 0;
43
	fo = 1;
44
	off = 0;
45
 
46
	ARGBEGIN {
47
	default:
48
		usage();
49
	case 'b':
50
		obsize = ibsize = atoi(EARGF(usage()));
51
		break;
52
	case 'd':
53
		dsize = atoi(EARGF(usage()));
54
		break;
55
	case 'f':
56
		file = EARGF(usage());
57
		fo = create(file, 1, 0666);
58
		if(fo < 0)
59
			sysfatal("can't create %s: %r", file);
60
		break;
61
	case 'i':
62
		ibsize = atoi(EARGF(usage()));
63
		break;
64
	case 'k':
65
		kilo = atoi(EARGF(usage()));
66
		break;
67
	case 'o':
68
		obsize = atoi(EARGF(usage()));
69
		break;
70
	case 's':
71
		ssize = atoi(EARGF(usage()));
72
		if(ssize <= 0)
73
			ssize = 800;
74
		ssize <<= 10;
75
		break;
76
	case 'S':
77
		off = atoll(EARGF(usage()));
78
		if(off < 0)
79
			sysfatal("seek offset %lld must be non-negative", off);
80
		break;
81
	case 't':
82
		tsize = atoll(EARGF(usage()));
83
		tsize *= 10584000;		/* minutes */
84
		break;
85
	} ARGEND
86
	kilo <<= 10;
87
 
88
	buf = malloc(kilo);
89
	if(buf == nil)
90
		sysfatal("no memory: %r");
91
	nin = 0;
92
	nout = 0;
93
	done = 0;
94
	max = 0;
95
 
96
	switch(rfork(RFPROC|RFNOWAIT|RFNAMEG|RFMEM)) {
97
	default:
98
		dooutput(fo);
99
		break;
100
	case 0:
101
		for(i=0; i<argc; i++) {
102
			f = open(argv[i], OREAD);
103
			if(f < 0) {
104
				fprint(2, "%s: can't open %s: %r\n",
105
					argv0, argv[i]);
106
				break;
107
			}
108
			doinput(f);
109
			close(f);
110
		}
111
		if(argc == 0)
112
			doinput(0);
113
		break;
114
	case -1:
115
		fprint(2, "%s: fork failed: %r\n", argv0);
116
		break;
117
	}
118
	done = 1;
119
	exits(0);
120
}
121
 
122
/* call with arithlock held */
123
static int
124
sleepunlocked(long ms)
125
{
126
	int r;
127
 
128
	unlock(&arithlock);
129
	r = sleep(ms);
130
	lock(&arithlock);
131
	return r;
132
}
133
 
134
void
135
dooutput(int f)
136
{
137
	long n, l, c;
138
 
139
	seek(f, off, 0);
140
	lock(&arithlock);
141
	for (;;) {
142
		n = nin - nout;
143
		if(n == 0) {
144
			if(done)
145
				break;
146
			sleepunlocked(dsize);
147
			continue;
148
		}
149
		if(verb && n > max) {
150
			fprint(2, "n = %ld\n", n);
151
			max = n;
152
		}
153
		l = nout % kilo;
154
		unlock(&arithlock);
155
 
156
		if(kilo-l < n)
157
			n = kilo-l;
158
		if(n > obsize)
159
			n = obsize;
160
		c = write(f, buf+l, n);
161
 
162
		lock(&arithlock);
163
		if(c != n) {
164
			fprint(2, "%s: write error at offset %,lld: %r\n",
165
				argv0, seek(f, 0, 1));
166
			break;
167
		}
168
		nout += c;
169
		if(tsize && nout > tsize) {
170
			fprint(2, "%s: time limit exceeded\n", argv0);
171
			break;
172
		}
173
	}
174
	unlock(&arithlock);
175
}
176
 
177
void
178
doinput(int f)
179
{
180
	long n, l, c, xnin;
181
 
182
	seek(f, off, 0);
183
	lock(&arithlock);
184
	if(ssize > 0) {
185
		for (xnin = 0; xnin < ssize && !done; xnin += c) {
186
			n = kilo - (xnin - nout);
187
			if(n == 0)
188
				break;
189
			unlock(&arithlock);
190
 
191
			l = xnin % kilo;
192
			if(kilo-l < n)
193
				n = kilo-l;
194
			if(n > ibsize)
195
				n = ibsize;
196
			c = read(f, buf+l, n);
197
 
198
			lock(&arithlock);
199
			if(c <= 0) {
200
				if(c < 0)
201
					fprint(2, "%s: read error: %r\n", argv0);
202
				break;
203
			}
204
		}
205
		nin = xnin;
206
	}
207
	while(!done) {
208
		n = kilo - (nin - nout);
209
		if(n == 0) {
210
			sleepunlocked(0);
211
			continue;
212
		}
213
		l = nin % kilo;
214
		unlock(&arithlock);
215
 
216
		if(kilo-l < n)
217
			n = kilo-l;
218
		if(n > ibsize)
219
			n = ibsize;
220
		c = read(f, buf+l, n);
221
 
222
		lock(&arithlock);
223
		if(c <= 0) {
224
			if(c < 0)
225
				fprint(2, "%s: read error: %r\n", argv0);
226
			break;
227
		}
228
		nin += c;
229
	}
230
	unlock(&arithlock);
231
}