t40c term[] count fix
[minix.git] / commands / dd / dd.c
blob0f30cdec31b3d378a992b55e6d1aeed9e020fa71
1 /* dd - disk dumper */
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>
14 #define EOS '\0'
15 #define BOOLEAN int
16 #define TRUE 1
17 #define FALSE 0
19 char *pch, *errorp;
21 int main(int argc, char **argv);
22 BOOLEAN is(char *pc);
23 int num(void);
24 void puto(void);
25 void statistics(void);
26 int ulcase(int c);
27 void cnull(int c);
28 void null(int c);
29 void extra(void);
30 void over(int dummy);
32 BOOLEAN is(pc)
33 char *pc;
35 register char *ps = pch;
37 while (*ps++ == *pc++)
38 if (*pc == EOS) {
39 pch = ps;
40 return(TRUE);
42 return(FALSE);
45 #define BIGNUM 2147483647
47 int num()
49 long ans;
50 register char *pc;
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);
75 return((int) ans);
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 NOTRUNC 0x0040
86 #define BLANK ' '
87 #define DEFAULT 512
89 unsigned cbs, bs, skip, nseek, count;
90 int seekseen = FALSE;
91 unsigned ibs = DEFAULT;
92 unsigned obs = DEFAULT;
93 unsigned files = 1;
94 char *ifilename = NULL;
95 char *ofilename = NULL;
97 int convflag = 0;
98 int flag = 0;
99 int ifd, ofd, ibc;
100 char *ibuf, *obuf, *op;
101 unsigned nifull, nipartial, nofull, nopartial;
102 int cbc;
103 unsigned ntr, obc;
104 int ns;
105 char mlen[] = {64, 45, 82, 45, 83, 96, 109, 100, 109, 97, 96, 116, 108, 9};
107 void puto()
109 int n;
111 if (obc == 0) return;
112 if (obc == obs)
113 nofull++;
114 else
115 nopartial++;
116 if ((n = write(ofd, obuf, obc)) != obc) {
117 if (n == -1) {
118 fprintf(stderr, "dd: Write error: %s\n", strerror(errno));
119 } else {
120 fprintf(stderr, "dd: Short write, %d instead of %d\n", n, obc);
122 exit(1);
124 obc = 0;
127 void statistics()
129 if (convflag & SILENT) return;
130 fprintf(stderr, "%u+%u records in\n", nifull, nipartial);
131 fprintf(stderr, "%u+%u records out\n", nofull, nopartial);
132 if (ntr) fprintf(stderr, "%d truncated records\n", ntr);
136 int main(argc, argv)
137 int argc;
138 char *argv[];
140 #ifdef __STDC__
141 void (*convert) (int);
142 #else
143 void (*convert) ();
144 #endif
145 char *iptr;
146 int i, j, oflags;
148 convert = null;
149 argc--;
150 argv++;
151 while (argc-- > 0) {
152 pch = *(argv++);
153 if (is("ibs=")) {
154 errorp = pch;
155 ibs = num();
156 continue;
158 if (is("obs=")) {
159 errorp = pch;
160 obs = num();
161 continue;
163 if (is("bs=")) {
164 errorp = pch;
165 bs = num();
166 continue;
168 if (is("if=")) {
169 ifilename = pch;
170 continue;
172 if (is("of=")) {
173 ofilename = pch;
174 continue;
176 if (is("skip=")) {
177 errorp = pch;
178 skip = num();
179 continue;
181 if (is("seek=")) {
182 errorp = pch;
183 nseek = num();
184 seekseen = TRUE;
185 continue;
187 if (is("count=")) {
188 errorp = pch;
189 count = num();
190 continue;
192 if (is("files=")) {
193 errorp = pch;
194 files = num();
195 continue;
197 if (is("length=")) {
198 errorp = pch;
199 for (j = 0; j < 13; j++) mlen[j]++;
200 write(2, mlen, 14);
201 continue;
203 if (is("conv=")) {
204 while (*pch != EOS) {
205 if (is("lcase")) {
206 convflag |= LCASE;
207 continue;
209 if (is("ucase")) {
210 convflag |= UCASE;
211 continue;
213 if (is("noerror")) {
214 convflag |= NOERROR;
215 continue;
217 if (is("notrunc")) {
218 convflag |= NOTRUNC;
219 continue;
221 if (is("sync")) {
222 convflag |= SYNC;
223 continue;
225 if (is("swab")) {
226 convflag |= SWAB;
227 continue;
229 if (is("silent")) {
230 convflag |= SILENT;
231 continue;
233 if (is(",")) continue;
234 fprintf(stderr, "dd: bad argument: %s\n",
235 pch);
236 exit(1);
238 if (*pch == EOS) continue;
240 fprintf(stderr, "dd: bad argument: %s\n", pch);
241 exit(1);
243 if ((convert == null) && (convflag & (UCASE | LCASE))) convert = cnull;
244 if ((ifd = ((ifilename) ? open(ifilename, O_RDONLY) : dup(0))) < 0) {
245 fprintf(stderr, "dd: Can't open %s: %s\n",
246 (ifilename) ? ifilename : "stdin", strerror(errno));
247 exit(1);
249 oflags = O_WRONLY | O_CREAT;
250 if (!seekseen && (convflag & NOTRUNC) != NOTRUNC)
251 oflags |= O_TRUNC;
252 if ((ofd = ((ofilename) ? open(ofilename, oflags, 0666)
253 : dup(1))) < 0) {
254 fprintf(stderr, "dd: Can't open %s: %s\n",
255 (ofilename) ? ofilename : "stdout", strerror(errno));
256 exit(1);
258 if (bs) {
259 ibs = obs = bs;
260 if (convert == null) flag++;
262 if (ibs == 0) {
263 fprintf(stderr, "dd: ibs cannot be zero\n");
264 exit(1);
266 if (obs == 0) {
267 fprintf(stderr, "dd: obs cannot be zero\n");
268 exit(1);
270 if ((ibuf = sbrk(ibs)) == (char *) -1) {
271 fprintf(stderr, "dd: not enough memory\n");
272 exit(1);
274 if ((obuf = (flag) ? ibuf : sbrk(obs)) == (char *) -1) {
275 fprintf(stderr, "dd: not enough memory\n");
276 exit(1);
278 ibc = obc = cbc = 0;
279 op = obuf;
280 if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, over);
281 if (skip != 0) {
282 struct stat st;
283 if (fstat(ifd,&st) < 0 || !(S_ISREG(st.st_mode) || S_ISBLK(st.st_mode))
284 || lseek(ifd, (off_t) ibs * (off_t) skip, SEEK_SET) == (off_t) -1) {
285 do {
286 if (read(ifd, ibuf, ibs) == -1) {
287 fprintf(stderr,
288 "dd: Error skipping input: %s\n",
289 strerror(errno));
290 exit(1);
292 } while (--skip != 0);
295 if (nseek != 0) {
296 if (lseek(ofd, (off_t) obs * (off_t) nseek, SEEK_SET) == (off_t) -1) {
297 fprintf(stderr, "dd: Seeking on output failed: %s\n",
298 strerror(errno));
299 exit(1);
303 outputall:
304 if (ibc-- == 0) {
305 ibc = 0;
306 if ((count == 0) || ((nifull + nipartial) != count)) {
307 if (convflag & (NOERROR | SYNC))
308 for (iptr = ibuf + ibs; iptr > ibuf;) *--iptr = 0;
309 ibc = read(ifd, ibuf, ibs);
311 if (ibc == -1) {
312 fprintf(stderr, "dd: Read error: %s\n", strerror(errno));
313 if ((convflag & NOERROR) == 0) {
314 puto();
315 over(0);
317 ibc = 0;
318 for (i = 0; i < ibs; i++)
319 if (ibuf[i] != 0) ibc = i;
320 statistics();
322 if ((ibc == 0) && (--files <= 0)) {
323 puto();
324 over(0);
326 if (ibc != ibs) {
327 nipartial++;
328 if (convflag & SYNC) ibc = ibs;
329 } else
330 nifull++;
331 iptr = ibuf;
332 i = ibc >> 1;
333 if ((convflag & SWAB) && i) do {
334 int temp;
335 temp = *iptr++;
336 iptr[-1] = *iptr;
337 *iptr++ = temp;
338 } while (--i);
339 iptr = ibuf;
340 if (flag) {
341 obc = ibc;
342 puto();
343 ibc = 0;
345 goto outputall;
347 i = *iptr++ & 0377;
348 (*convert) (i);
349 goto outputall;
352 int ulcase(c)
353 int c;
355 int ans = c;
357 if ((convflag & UCASE) && (c >= 'a') &&
358 (c <= 'z'))
359 ans += 'A' - 'a';
360 if ((convflag & LCASE) && (c >= 'A') &&
361 (c <= 'Z'))
362 ans += 'a' - 'A';
363 return(ans);
366 void cnull(c)
367 int c;
369 c = ulcase(c);
370 null(c);
373 void null(c)
374 int c;
376 *op++ = c;
377 if (++obc >= obs) {
378 puto();
379 op = obuf;
383 void extra()
385 if (++cbc >= cbs) {
386 null('\n');
387 cbc = 0;
388 ns = 0;
392 void over(sig)
393 int sig;
395 statistics();
396 if (sig != 0) {
397 signal(sig, SIG_DFL);
398 raise(sig);
400 exit(0);