source: trunk/minix/commands/simple/dd.c@ 10

Last change on this file since 10 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 6.9 KB
Line 
1/* dd - disk dumper */
2
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <signal.h>
6#include <fcntl.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <stdio.h>
11#include <string.h>
12#include <errno.h>
13
14#define EOS '\0'
15#define BOOLEAN int
16#define TRUE 1
17#define FALSE 0
18
19char *pch, *errorp;
20
21_PROTOTYPE(int main, (int argc, char **argv));
22_PROTOTYPE(BOOLEAN is, (char *pc));
23_PROTOTYPE(int num, (void));
24_PROTOTYPE(void puto, (void));
25_PROTOTYPE(void statistics, (void));
26_PROTOTYPE(int ulcase, (int c));
27_PROTOTYPE(void cnull, (int c));
28_PROTOTYPE(void null, (int c));
29_PROTOTYPE(void extra, (void));
30_PROTOTYPE(void over, (int dummy));
31
32BOOLEAN is(pc)
33char *pc;
34{
35 register char *ps = pch;
36
37 while (*ps++ == *pc++)
38 if (*pc == EOS) {
39 pch = ps;
40 return(TRUE);
41 }
42 return(FALSE);
43}
44
45#define BIGNUM 2147483647
46
47int num()
48{
49 long ans;
50 register char *pc;
51
52 pc = pch;
53 ans = 0L;
54 while ((*pc >= '0') && (*pc <= '9'))
55 ans = (long) ((*pc++ - '0') + (ans * 10));
56 while (TRUE) switch (*pc++) {
57 case 'w':
58 ans *= 2L;
59 continue;
60 case 'b':
61 ans *= 512L;
62 continue;
63 case 'k':
64 ans *= 1024L;
65 continue;
66 case 'x':
67 pch = pc;
68 ans *= (long) num();
69 case EOS:
70 if ((ans >= BIGNUM) || (ans < 0)) {
71 fprintf(stderr, "dd: argument %s out of range\n",
72 errorp);
73 exit(1);
74 }
75 return((int) ans);
76 }
77}
78
79#define SWAB 0x0001
80#define LCASE 0x0002
81#define UCASE 0x0004
82#define NOERROR 0x0008
83#define SYNC 0x0010
84#define SILENT 0x0020
85#define BLANK ' '
86#define DEFAULT 512
87
88unsigned cbs, bs, skip, nseek, count;
89int seekseen = FALSE;
90unsigned ibs = DEFAULT;
91unsigned obs = DEFAULT;
92unsigned files = 1;
93char *ifilename = NULL;
94char *ofilename = NULL;
95
96int convflag = 0;
97int flag = 0;
98int ifd, ofd, ibc;
99char *ibuf, *obuf, *op;
100unsigned nifull, nipartial, nofull, nopartial;
101int cbc;
102unsigned ntr, obc;
103int ns;
104char mlen[] = {64, 45, 82, 45, 83, 96, 109, 100, 109, 97, 96, 116, 108, 9};
105
106void puto()
107{
108 int n;
109
110 if (obc == 0) return;
111 if (obc == obs)
112 nofull++;
113 else
114 nopartial++;
115 if ((n = write(ofd, obuf, obc)) != obc) {
116 if (n == -1) {
117 fprintf(stderr, "dd: Write error: %s\n", strerror(errno));
118 } else {
119 fprintf(stderr, "dd: Short write, %d instead of %d\n", n, obc);
120 }
121 exit(1);
122 }
123 obc = 0;
124}
125
126void statistics()
127{
128 if (convflag & SILENT) return;
129 fprintf(stderr, "%u+%u records in\n", nifull, nipartial);
130 fprintf(stderr, "%u+%u records out\n", nofull, nopartial);
131 if (ntr) fprintf(stderr, "%d truncated records\n", ntr);
132}
133
134
135int main(argc, argv)
136int argc;
137char *argv[];
138{
139#ifdef __STDC__
140 void (*convert) (int);
141#else
142 void (*convert) ();
143#endif
144 char *iptr;
145 int i, j;
146
147 convert = null;
148 argc--;
149 argv++;
150 while (argc-- > 0) {
151 pch = *(argv++);
152 if (is("ibs=")) {
153 errorp = pch;
154 ibs = num();
155 continue;
156 }
157 if (is("obs=")) {
158 errorp = pch;
159 obs = num();
160 continue;
161 }
162 if (is("bs=")) {
163 errorp = pch;
164 bs = num();
165 continue;
166 }
167 if (is("if=")) {
168 ifilename = pch;
169 continue;
170 }
171 if (is("of=")) {
172 ofilename = pch;
173 continue;
174 }
175 if (is("skip=")) {
176 errorp = pch;
177 skip = num();
178 continue;
179 }
180 if (is("seek=")) {
181 errorp = pch;
182 nseek = num();
183 seekseen = TRUE;
184 continue;
185 }
186 if (is("count=")) {
187 errorp = pch;
188 count = num();
189 continue;
190 }
191 if (is("files=")) {
192 errorp = pch;
193 files = num();
194 continue;
195 }
196 if (is("length=")) {
197 errorp = pch;
198 for (j = 0; j < 13; j++) mlen[j]++;
199 write(2, mlen, 14);
200 continue;
201 }
202 if (is("conv=")) {
203 while (*pch != EOS) {
204 if (is("lcase")) {
205 convflag |= LCASE;
206 continue;
207 }
208 if (is("ucase")) {
209 convflag |= UCASE;
210 continue;
211 }
212 if (is("noerror")) {
213 convflag |= NOERROR;
214 continue;
215 }
216 if (is("sync")) {
217 convflag |= SYNC;
218 continue;
219 }
220 if (is("swab")) {
221 convflag |= SWAB;
222 continue;
223 }
224 if (is("silent")) {
225 convflag |= SILENT;
226 continue;
227 }
228 if (is(",")) continue;
229 fprintf(stderr, "dd: bad argument: %s\n",
230 pch);
231 exit(1);
232 }
233 if (*pch == EOS) continue;
234 }
235 fprintf(stderr, "dd: bad argument: %s\n", pch);
236 exit(1);
237 }
238 if ((convert == null) && (convflag & (UCASE | LCASE))) convert = cnull;
239 if ((ifd = ((ifilename) ? open(ifilename, O_RDONLY) : dup(0))) < 0) {
240 fprintf(stderr, "dd: Can't open %s: %s\n",
241 (ifilename) ? ifilename : "stdin", strerror(errno));
242 exit(1);
243 }
244 if ((ofd = ((ofilename) ? open(ofilename, seekseen ? O_WRONLY | O_CREAT
245 : O_WRONLY | O_CREAT | O_TRUNC, 0666)
246 : dup(1))) < 0) {
247 fprintf(stderr, "dd: Can't open %s: %s\n",
248 (ofilename) ? ofilename : "stdout", strerror(errno));
249 exit(1);
250 }
251 if (bs) {
252 ibs = obs = bs;
253 if (convert == null) flag++;
254 }
255 if (ibs == 0) {
256 fprintf(stderr, "dd: ibs cannot be zero\n");
257 exit(1);
258 }
259 if (obs == 0) {
260 fprintf(stderr, "dd: obs cannot be zero\n");
261 exit(1);
262 }
263 if ((ibuf = sbrk(ibs)) == (char *) -1) {
264 fprintf(stderr, "dd: not enough memory\n");
265 exit(1);
266 }
267 if ((obuf = (flag) ? ibuf : sbrk(obs)) == (char *) -1) {
268 fprintf(stderr, "dd: not enough memory\n");
269 exit(1);
270 }
271 ibc = obc = cbc = 0;
272 op = obuf;
273 if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, over);
274 if (skip != 0) {
275 struct stat st;
276 if (fstat(ifd,&st) < 0 || !(S_ISREG(st.st_mode) || S_ISBLK(st.st_mode))
277 || lseek(ifd, (off_t) ibs * (off_t) skip, SEEK_SET) == (off_t) -1) {
278 do {
279 if (read(ifd, ibuf, ibs) == -1) {
280 fprintf(stderr,
281 "dd: Error skipping input: %s\n",
282 strerror(errno));
283 exit(1);
284 }
285 } while (--skip != 0);
286 }
287 }
288 if (nseek != 0) {
289 if (lseek(ofd, (off_t) obs * (off_t) nseek, SEEK_SET) == (off_t) -1) {
290 fprintf(stderr, "dd: Seeking on output failed: %s\n",
291 strerror(errno));
292 exit(1);
293 }
294 }
295
296outputall:
297 if (ibc-- == 0) {
298 ibc = 0;
299 if ((count == 0) || ((nifull + nipartial) != count)) {
300 if (convflag & (NOERROR | SYNC))
301 for (iptr = ibuf + ibs; iptr > ibuf;) *--iptr = 0;
302 ibc = read(ifd, ibuf, ibs);
303 }
304 if (ibc == -1) {
305 fprintf(stderr, "dd: Read error: %s\n", strerror(errno));
306 if ((convflag & NOERROR) == 0) {
307 puto();
308 over(0);
309 }
310 ibc = 0;
311 for (i = 0; i < ibs; i++)
312 if (ibuf[i] != 0) ibc = i;
313 statistics();
314 }
315 if ((ibc == 0) && (--files <= 0)) {
316 puto();
317 over(0);
318 }
319 if (ibc != ibs) {
320 nipartial++;
321 if (convflag & SYNC) ibc = ibs;
322 } else
323 nifull++;
324 iptr = ibuf;
325 i = ibc >> 1;
326 if ((convflag & SWAB) && i) do {
327 int temp;
328 temp = *iptr++;
329 iptr[-1] = *iptr;
330 *iptr++ = temp;
331 } while (--i);
332 iptr = ibuf;
333 if (flag) {
334 obc = ibc;
335 puto();
336 ibc = 0;
337 }
338 goto outputall;
339 }
340 i = *iptr++ & 0377;
341 (*convert) (i);
342 goto outputall;
343}
344
345int ulcase(c)
346int c;
347{
348 int ans = c;
349
350 if ((convflag & UCASE) && (c >= 'a') &&
351 (c <= 'z'))
352 ans += 'A' - 'a';
353 if ((convflag & LCASE) && (c >= 'A') &&
354 (c <= 'Z'))
355 ans += 'a' - 'A';
356 return(ans);
357}
358
359void cnull(c)
360int c;
361{
362 c = ulcase(c);
363 null(c);
364}
365
366void null(c)
367int c;
368{
369 *op++ = c;
370 if (++obc >= obs) {
371 puto();
372 op = obuf;
373 }
374}
375
376void extra()
377{
378 if (++cbc >= cbs) {
379 null('\n');
380 cbc = 0;
381 ns = 0;
382 }
383}
384
385void over(sig)
386int sig;
387{
388 statistics();
389 if (sig != 0) {
390 signal(sig, SIG_DFL);
391 raise(sig);
392 }
393 exit(0);
394}
Note: See TracBrowser for help on using the repository browser.