diff options
author | Eric Andersen <andersen@codepoet.org> | 1999-10-05 16:24:54 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 1999-10-05 16:24:54 +0000 |
commit | cc8ed39b240180b58810784f844e253263594ac3 (patch) | |
tree | 15feebbb4be9a9168209609f48f0b100f9364420 /dd.c | |
download | busybox-w32-0_29alpha2.tar.gz busybox-w32-0_29alpha2.tar.bz2 busybox-w32-0_29alpha2.zip |
Initial revision0_29alpha2
Diffstat (limited to '')
-rw-r--r-- | dd.c | 307 |
1 files changed, 307 insertions, 0 deletions
@@ -0,0 +1,307 @@ | |||
1 | /* | ||
2 | * Copyright (c) 1999 by David I. Bell | ||
3 | * Permission is granted to use, distribute, or modify this source, | ||
4 | * provided that this copyright notice remains intact. | ||
5 | * | ||
6 | * The "dd" command, originally taken from sash. | ||
7 | * | ||
8 | * Permission to distribute this code under the GPL has been granted. | ||
9 | * Majorly modified, and bugs fixed for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com> | ||
10 | */ | ||
11 | |||
12 | #include "internal.h" | ||
13 | #ifdef BB_DD | ||
14 | |||
15 | const char dd_usage[] = | ||
16 | "Copy a file, converting and formatting according to options\n\ | ||
17 | \n\ | ||
18 | usage: [if=name] [of=name] [bs=n] [count=n]\n\ | ||
19 | \tif=FILE\tread from FILE instead of stdin\n\ | ||
20 | \tof=FILE\twrite to FILE instead of stout\n\ | ||
21 | \tbs=n\tread and write N bytes at a time\n\ | ||
22 | \tcount=n\tcopy only n input blocks\n\ | ||
23 | \n\ | ||
24 | BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n"; | ||
25 | |||
26 | |||
27 | #include <stdio.h> | ||
28 | #include <dirent.h> | ||
29 | #include <errno.h> | ||
30 | #include <fcntl.h> | ||
31 | #include <signal.h> | ||
32 | #include <time.h> | ||
33 | |||
34 | |||
35 | #define PAR_NONE 0 | ||
36 | #define PAR_IF 1 | ||
37 | #define PAR_OF 2 | ||
38 | #define PAR_BS 3 | ||
39 | #define PAR_COUNT 4 | ||
40 | |||
41 | |||
42 | typedef struct | ||
43 | { | ||
44 | const char * name; | ||
45 | int value; | ||
46 | } PARAM; | ||
47 | |||
48 | |||
49 | static const PARAM params[] = | ||
50 | { | ||
51 | {"if", PAR_IF}, | ||
52 | {"of", PAR_OF}, | ||
53 | {"bs", PAR_BS}, | ||
54 | {"count", PAR_COUNT}, | ||
55 | {NULL, PAR_NONE} | ||
56 | }; | ||
57 | |||
58 | |||
59 | static long getNum(const char * cp); | ||
60 | |||
61 | extern int | ||
62 | dd_main (struct FileInfo *unused, int argc, char **argv) | ||
63 | { | ||
64 | const char * str; | ||
65 | const PARAM * par; | ||
66 | const char * inFile; | ||
67 | const char * outFile; | ||
68 | char * cp; | ||
69 | int inFd; | ||
70 | int outFd; | ||
71 | int inCc=0; | ||
72 | int outCc; | ||
73 | int blockSize; | ||
74 | long count; | ||
75 | long intotal; | ||
76 | long outTotal; | ||
77 | unsigned char* buf; | ||
78 | unsigned char localBuf[BUF_SIZE]; | ||
79 | |||
80 | inFile = NULL; | ||
81 | outFile = NULL; | ||
82 | blockSize = 512; | ||
83 | count = 1; | ||
84 | |||
85 | |||
86 | while (--argc > 0) | ||
87 | { | ||
88 | str = *++argv; | ||
89 | cp = strchr(str, '='); | ||
90 | |||
91 | if (cp == NULL) | ||
92 | { | ||
93 | fprintf(stderr, "Bad dd argument\n"); | ||
94 | goto usage; | ||
95 | } | ||
96 | |||
97 | *cp++ = '\0'; | ||
98 | |||
99 | for (par = params; par->name; par++) | ||
100 | { | ||
101 | if (strcmp(str, par->name) == 0) | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | switch (par->value) | ||
106 | { | ||
107 | case PAR_IF: | ||
108 | if (inFile) | ||
109 | { | ||
110 | fprintf(stderr, "Multiple input files illegal\n"); | ||
111 | goto usage; | ||
112 | } | ||
113 | |||
114 | //fprintf(stderr, "if=%s\n", cp); | ||
115 | inFile = cp; | ||
116 | break; | ||
117 | |||
118 | case PAR_OF: | ||
119 | if (outFile) | ||
120 | { | ||
121 | fprintf(stderr, "Multiple output files illegal\n"); | ||
122 | goto usage; | ||
123 | } | ||
124 | |||
125 | //fprintf(stderr, "of=%s\n", cp); | ||
126 | outFile = cp; | ||
127 | break; | ||
128 | |||
129 | case PAR_BS: | ||
130 | blockSize = getNum(cp); | ||
131 | //fprintf(stderr, "bs=%d\n", blockSize); | ||
132 | |||
133 | if (blockSize <= 0) | ||
134 | { | ||
135 | fprintf(stderr, "Bad block size value\n"); | ||
136 | goto usage; | ||
137 | } | ||
138 | |||
139 | break; | ||
140 | |||
141 | case PAR_COUNT: | ||
142 | count = getNum(cp); | ||
143 | //fprintf(stderr, "count=%ld\n", count); | ||
144 | |||
145 | if (count < 0) | ||
146 | { | ||
147 | fprintf(stderr, "Bad count value\n"); | ||
148 | goto usage; | ||
149 | } | ||
150 | |||
151 | break; | ||
152 | |||
153 | default: | ||
154 | goto usage; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | buf = localBuf; | ||
159 | |||
160 | if (blockSize > sizeof(localBuf)) | ||
161 | { | ||
162 | buf = malloc(blockSize); | ||
163 | |||
164 | if (buf == NULL) | ||
165 | { | ||
166 | fprintf(stderr, "Cannot allocate buffer\n"); | ||
167 | return 1; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | intotal = 0; | ||
172 | outTotal = 0; | ||
173 | |||
174 | if (inFile == NULL) | ||
175 | inFd = STDIN; | ||
176 | else | ||
177 | inFd = open(inFile, 0); | ||
178 | |||
179 | if (inFd < 0) | ||
180 | { | ||
181 | perror(inFile); | ||
182 | |||
183 | if (buf != localBuf) | ||
184 | free(buf); | ||
185 | |||
186 | return 1; | ||
187 | } | ||
188 | |||
189 | if (outFile == NULL) | ||
190 | outFd = STDOUT; | ||
191 | else | ||
192 | outFd = creat(outFile, 0666); | ||
193 | |||
194 | if (outFd < 0) | ||
195 | { | ||
196 | perror(outFile); | ||
197 | close(inFd); | ||
198 | |||
199 | if (buf != localBuf) | ||
200 | free(buf); | ||
201 | |||
202 | return 1; | ||
203 | } | ||
204 | |||
205 | while ( outTotal < count*blockSize ) | ||
206 | { | ||
207 | inCc = read(inFd, buf, blockSize); | ||
208 | if (inCc < 0) { | ||
209 | perror(inFile); | ||
210 | goto cleanup; | ||
211 | } | ||
212 | //fprintf(stderr, "read in =%d\n", inCc); | ||
213 | intotal += inCc; | ||
214 | cp = buf; | ||
215 | |||
216 | |||
217 | while ( intotal > outTotal ) | ||
218 | { | ||
219 | if (outTotal+inCc > count*blockSize) | ||
220 | inCc=count*blockSize-outTotal; | ||
221 | outCc = write(outFd, cp, inCc); | ||
222 | if (outCc < 0) | ||
223 | { | ||
224 | perror(outFile); | ||
225 | goto cleanup; | ||
226 | } | ||
227 | //fprintf(stderr, "wrote out =%d\n", outCc); | ||
228 | |||
229 | inCc -= outCc; | ||
230 | cp += outCc; | ||
231 | outTotal += outCc; | ||
232 | //fprintf(stderr, "outTotal=%ld\n", outTotal); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if (inCc < 0) | ||
237 | perror(inFile); | ||
238 | |||
239 | cleanup: | ||
240 | close(inFd); | ||
241 | |||
242 | if (close(outFd) < 0) | ||
243 | perror(outFile); | ||
244 | |||
245 | if (buf != localBuf) | ||
246 | free(buf); | ||
247 | |||
248 | printf("%ld+%d records in\n", intotal / blockSize, | ||
249 | (intotal % blockSize) != 0); | ||
250 | |||
251 | printf("%ld+%d records out\n", outTotal / blockSize, | ||
252 | (outTotal % blockSize) != 0); | ||
253 | return 0; | ||
254 | usage: | ||
255 | |||
256 | fprintf(stderr, "%s", dd_usage); | ||
257 | return 1; | ||
258 | } | ||
259 | |||
260 | |||
261 | /* | ||
262 | * Read a number with a possible multiplier. | ||
263 | * Returns -1 if the number format is illegal. | ||
264 | */ | ||
265 | static long | ||
266 | getNum(const char * cp) | ||
267 | { | ||
268 | long value; | ||
269 | |||
270 | if (!isDecimal(*cp)) | ||
271 | return -1; | ||
272 | |||
273 | value = 0; | ||
274 | |||
275 | while (isDecimal(*cp)) | ||
276 | value = value * 10 + *cp++ - '0'; | ||
277 | |||
278 | switch (*cp++) | ||
279 | { | ||
280 | case 'k': | ||
281 | value *= 1024; | ||
282 | break; | ||
283 | |||
284 | case 'b': | ||
285 | value *= 512; | ||
286 | break; | ||
287 | |||
288 | case 'w': | ||
289 | value *= 2; | ||
290 | break; | ||
291 | |||
292 | case '\0': | ||
293 | return value; | ||
294 | |||
295 | default: | ||
296 | return -1; | ||
297 | } | ||
298 | |||
299 | if (*cp) | ||
300 | return -1; | ||
301 | |||
302 | return value; | ||
303 | } | ||
304 | |||
305 | #endif | ||
306 | /* END CODE */ | ||
307 | |||