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