diff options
author | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2013-08-27 16:10:53 +0100 |
commit | 3fd34651ea72ea1c335d3170f234cb0517fd897f (patch) | |
tree | 36e8fc40cffd464ffda4759020777dd3ca23ca31 /coreutils/dd.c | |
parent | e3ac39098326de084a805d0dd31db9666b734f20 (diff) | |
parent | d6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff) | |
download | busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.gz busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.bz2 busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'coreutils/dd.c')
-rw-r--r-- | coreutils/dd.c | 115 |
1 files changed, 78 insertions, 37 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c index f6869cb26..db61f665e 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -30,10 +30,10 @@ | |||
30 | //usage: "\n conv=noerror Continue after read errors" | 30 | //usage: "\n conv=noerror Continue after read errors" |
31 | //usage: "\n conv=sync Pad blocks with zeros" | 31 | //usage: "\n conv=sync Pad blocks with zeros" |
32 | //usage: "\n conv=fsync Physically write data out before finishing" | 32 | //usage: "\n conv=fsync Physically write data out before finishing" |
33 | //usage: "\n conv=swab Swap every pair of bytes" | ||
33 | //usage: ) | 34 | //usage: ) |
34 | //usage: "\n" | 35 | //usage: "\n" |
35 | //usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024)," | 36 | //usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G" |
36 | //usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)" | ||
37 | //usage: | 37 | //usage: |
38 | //usage:#define dd_example_usage | 38 | //usage:#define dd_example_usage |
39 | //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" | 39 | //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" |
@@ -151,13 +151,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
151 | enum { | 151 | enum { |
152 | /* Must be in the same order as OP_conv_XXX! */ | 152 | /* Must be in the same order as OP_conv_XXX! */ |
153 | /* (see "flags |= (1 << what)" below) */ | 153 | /* (see "flags |= (1 << what)" below) */ |
154 | FLAG_NOTRUNC = 1 << 0, | 154 | FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, |
155 | FLAG_SYNC = 1 << 1, | 155 | FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, |
156 | FLAG_NOERROR = 1 << 2, | 156 | FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, |
157 | FLAG_FSYNC = 1 << 3, | 157 | FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, |
158 | FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, | ||
158 | /* end of conv flags */ | 159 | /* end of conv flags */ |
159 | FLAG_TWOBUFS = 1 << 4, | 160 | FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, |
160 | FLAG_COUNT = 1 << 5, | 161 | FLAG_COUNT = 1 << 6, |
161 | }; | 162 | }; |
162 | static const char keywords[] ALIGN1 = | 163 | static const char keywords[] ALIGN1 = |
163 | "bs\0""count\0""seek\0""skip\0""if\0""of\0" | 164 | "bs\0""count\0""seek\0""skip\0""if\0""of\0" |
@@ -167,7 +168,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
167 | ; | 168 | ; |
168 | #if ENABLE_FEATURE_DD_IBS_OBS | 169 | #if ENABLE_FEATURE_DD_IBS_OBS |
169 | static const char conv_words[] ALIGN1 = | 170 | static const char conv_words[] ALIGN1 = |
170 | "notrunc\0""sync\0""noerror\0""fsync\0"; | 171 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; |
171 | #endif | 172 | #endif |
172 | enum { | 173 | enum { |
173 | OP_bs = 0, | 174 | OP_bs = 0, |
@@ -185,11 +186,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
185 | OP_conv_sync, | 186 | OP_conv_sync, |
186 | OP_conv_noerror, | 187 | OP_conv_noerror, |
187 | OP_conv_fsync, | 188 | OP_conv_fsync, |
189 | OP_conv_swab, | ||
188 | /* Unimplemented conv=XXX: */ | 190 | /* Unimplemented conv=XXX: */ |
189 | //nocreat do not create the output file | 191 | //nocreat do not create the output file |
190 | //excl fail if the output file already exists | 192 | //excl fail if the output file already exists |
191 | //fdatasync physically write output file data before finishing | 193 | //fdatasync physically write output file data before finishing |
192 | //swab swap every pair of input bytes | ||
193 | //lcase change upper case to lower case | 194 | //lcase change upper case to lower case |
194 | //ucase change lower case to upper case | 195 | //ucase change lower case to upper case |
195 | //block pad newline-terminated records with spaces to cbs-size | 196 | //block pad newline-terminated records with spaces to cbs-size |
@@ -197,23 +198,34 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
197 | //ascii from EBCDIC to ASCII | 198 | //ascii from EBCDIC to ASCII |
198 | //ebcdic from ASCII to EBCDIC | 199 | //ebcdic from ASCII to EBCDIC |
199 | //ibm from ASCII to alternate EBCDIC | 200 | //ibm from ASCII to alternate EBCDIC |
201 | /* Partially implemented: */ | ||
202 | //swab swap every pair of input bytes: will abort on non-even reads | ||
200 | #endif | 203 | #endif |
201 | }; | 204 | }; |
202 | int exitcode = EXIT_FAILURE; | 205 | smallint exitcode = EXIT_FAILURE; |
203 | int devzero = 0; | 206 | int devzero = 0; |
204 | size_t ibs = 512, obs = 512; | 207 | int i; |
205 | ssize_t n, w; | 208 | size_t ibs = 512; |
206 | char *ibuf, *obuf; | 209 | char *ibuf; |
207 | /* And these are all zeroed at once! */ | 210 | #if ENABLE_FEATURE_DD_IBS_OBS |
211 | size_t obs = 512; | ||
212 | char *obuf; | ||
213 | #else | ||
214 | # define obs ibs | ||
215 | # define obuf ibuf | ||
216 | #endif | ||
217 | /* These are all zeroed at once! */ | ||
208 | struct { | 218 | struct { |
209 | int flags; | 219 | int flags; |
210 | size_t oc; | 220 | size_t oc; |
221 | ssize_t prev_read_size; /* for detecting swab failure */ | ||
211 | off_t count; | 222 | off_t count; |
212 | off_t seek, skip; | 223 | off_t seek, skip; |
213 | const char *infile, *outfile; | 224 | const char *infile, *outfile; |
214 | } Z; | 225 | } Z; |
215 | #define flags (Z.flags ) | 226 | #define flags (Z.flags ) |
216 | #define oc (Z.oc ) | 227 | #define oc (Z.oc ) |
228 | #define prev_read_size (Z.prev_read_size) | ||
217 | #define count (Z.count ) | 229 | #define count (Z.count ) |
218 | #define seek (Z.seek ) | 230 | #define seek (Z.seek ) |
219 | #define skip (Z.skip ) | 231 | #define skip (Z.skip ) |
@@ -224,10 +236,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
224 | INIT_G(); | 236 | INIT_G(); |
225 | //fflush_all(); - is this needed because of NOEXEC? | 237 | //fflush_all(); - is this needed because of NOEXEC? |
226 | 238 | ||
227 | for (n = 1; argv[n]; n++) { | 239 | for (i = 1; argv[i]; i++) { |
228 | int what; | 240 | int what; |
229 | char *val; | 241 | char *val; |
230 | char *arg = argv[n]; | 242 | char *arg = argv[i]; |
231 | 243 | ||
232 | #if ENABLE_DESKTOP | 244 | #if ENABLE_DESKTOP |
233 | /* "dd --". NB: coreutils 6.9 will complain if they see | 245 | /* "dd --". NB: coreutils 6.9 will complain if they see |
@@ -256,6 +268,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
256 | } | 268 | } |
257 | if (what == OP_conv) { | 269 | if (what == OP_conv) { |
258 | while (1) { | 270 | while (1) { |
271 | int n; | ||
259 | /* find ',', replace them with NUL so we can use val for | 272 | /* find ',', replace them with NUL so we can use val for |
260 | * index_in_strings() without copying. | 273 | * index_in_strings() without copying. |
261 | * We rely on val being non-null, else strchr would fault. | 274 | * We rely on val being non-null, else strchr would fault. |
@@ -263,20 +276,21 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
263 | arg = strchr(val, ','); | 276 | arg = strchr(val, ','); |
264 | if (arg) | 277 | if (arg) |
265 | *arg = '\0'; | 278 | *arg = '\0'; |
266 | what = index_in_strings(conv_words, val); | 279 | n = index_in_strings(conv_words, val); |
267 | if (what < 0) | 280 | if (n < 0) |
268 | bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); | 281 | bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); |
269 | flags |= (1 << what); | 282 | flags |= (1 << n); |
270 | if (!arg) /* no ',' left, so this was the last specifier */ | 283 | if (!arg) /* no ',' left, so this was the last specifier */ |
271 | break; | 284 | break; |
272 | /* *arg = ','; - to preserve ps listing? */ | 285 | /* *arg = ','; - to preserve ps listing? */ |
273 | val = arg + 1; /* skip this keyword and ',' */ | 286 | val = arg + 1; /* skip this keyword and ',' */ |
274 | } | 287 | } |
275 | continue; /* we trashed 'what', can't fall through */ | 288 | /*continue;*/ |
276 | } | 289 | } |
277 | #endif | 290 | #endif |
278 | if (what == OP_bs) { | 291 | if (what == OP_bs) { |
279 | ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); | 292 | ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); |
293 | obs = ibs; | ||
280 | /*continue;*/ | 294 | /*continue;*/ |
281 | } | 295 | } |
282 | /* These can be large: */ | 296 | /* These can be large: */ |
@@ -301,14 +315,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
301 | outfile = val; | 315 | outfile = val; |
302 | /*continue;*/ | 316 | /*continue;*/ |
303 | } | 317 | } |
304 | } /* end of "for (argv[n])" */ | 318 | } /* end of "for (argv[i])" */ |
305 | 319 | ||
306 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | 320 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever |
307 | ibuf = obuf = xmalloc(ibs); | 321 | ibuf = xmalloc(ibs); |
322 | obuf = ibuf; | ||
323 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
308 | if (ibs != obs) { | 324 | if (ibs != obs) { |
309 | flags |= FLAG_TWOBUFS; | 325 | flags |= FLAG_TWOBUFS; |
310 | obuf = xmalloc(obs); | 326 | obuf = xmalloc(obs); |
311 | } | 327 | } |
328 | #endif | ||
312 | 329 | ||
313 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING | 330 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING |
314 | signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); | 331 | signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); |
@@ -317,17 +334,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
317 | G.begin_time_us = monotonic_us(); | 334 | G.begin_time_us = monotonic_us(); |
318 | #endif | 335 | #endif |
319 | 336 | ||
320 | if (infile != NULL) | 337 | if (infile) { |
321 | if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) { | 338 | if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) { |
322 | flags |= FLAG_NOERROR; | 339 | flags |= FLAG_NOERROR; |
323 | devzero = 1; | 340 | devzero = 1; |
324 | } | 341 | } else { |
325 | else | ||
326 | xmove_fd(xopen(infile, O_RDONLY), ifd); | 342 | xmove_fd(xopen(infile, O_RDONLY), ifd); |
327 | else { | 343 | } |
344 | } else { | ||
328 | infile = bb_msg_standard_input; | 345 | infile = bb_msg_standard_input; |
329 | } | 346 | } |
330 | if (outfile != NULL) { | 347 | if (outfile) { |
331 | int oflag = O_WRONLY | O_CREAT; | 348 | int oflag = O_WRONLY | O_CREAT; |
332 | 349 | ||
333 | if (!seek && !(flags & FLAG_NOTRUNC)) | 350 | if (!seek && !(flags & FLAG_NOTRUNC)) |
@@ -352,13 +369,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
352 | } | 369 | } |
353 | if (skip && !devzero) { | 370 | if (skip && !devzero) { |
354 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { | 371 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { |
355 | while (skip-- > 0) { | 372 | do { |
356 | n = safe_read(ifd, ibuf, ibs); | 373 | ssize_t n = safe_read(ifd, ibuf, ibs); |
357 | if (n < 0) | 374 | if (n < 0) |
358 | goto die_infile; | 375 | goto die_infile; |
359 | if (n == 0) | 376 | if (n == 0) |
360 | break; | 377 | break; |
361 | } | 378 | } while (--skip != 0); |
362 | } | 379 | } |
363 | } | 380 | } |
364 | if (seek) { | 381 | if (seek) { |
@@ -367,6 +384,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
367 | } | 384 | } |
368 | 385 | ||
369 | while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { | 386 | while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { |
387 | ssize_t n; | ||
388 | |||
370 | if (devzero) { | 389 | if (devzero) { |
371 | memset(ibuf, 0, ibs); | 390 | memset(ibuf, 0, ibs); |
372 | n = ibs; | 391 | n = ibs; |
@@ -386,6 +405,27 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
386 | * conv=noerror just ignores input bad blocks */ | 405 | * conv=noerror just ignores input bad blocks */ |
387 | n = 0; | 406 | n = 0; |
388 | } | 407 | } |
408 | if (flags & FLAG_SWAB) { | ||
409 | uint16_t *p16; | ||
410 | ssize_t n2; | ||
411 | |||
412 | /* Our code allows only last read to be odd-sized */ | ||
413 | if (prev_read_size & 1) | ||
414 | bb_error_msg_and_die("can't swab %lu byte buffer", | ||
415 | (unsigned long)prev_read_size); | ||
416 | prev_read_size = n; | ||
417 | |||
418 | /* If n is odd, last byte is not swapped: | ||
419 | * echo -n "qwe" | dd conv=swab | ||
420 | * prints "wqe". | ||
421 | */ | ||
422 | p16 = (void*) ibuf; | ||
423 | n2 = (n >> 1); | ||
424 | while (--n2 >= 0) { | ||
425 | *p16 = bswap_16(*p16); | ||
426 | p16++; | ||
427 | } | ||
428 | } | ||
389 | if ((size_t)n == ibs) | 429 | if ((size_t)n == ibs) |
390 | G.in_full++; | 430 | G.in_full++; |
391 | else { | 431 | else { |
@@ -412,8 +452,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
412 | oc = 0; | 452 | oc = 0; |
413 | } | 453 | } |
414 | } | 454 | } |
415 | } else if (write_and_stats(ibuf, n, obs, outfile)) | 455 | } else { |
416 | goto out_status; | 456 | if (write_and_stats(ibuf, n, obs, outfile)) |
457 | goto out_status; | ||
458 | } | ||
417 | 459 | ||
418 | if (flags & FLAG_FSYNC) { | 460 | if (flags & FLAG_FSYNC) { |
419 | if (fsync(ofd) < 0) | 461 | if (fsync(ofd) < 0) |
@@ -422,9 +464,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
422 | } | 464 | } |
423 | 465 | ||
424 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { | 466 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { |
425 | w = full_write_or_warn(obuf, oc, outfile); | 467 | if (write_and_stats(obuf, oc, obs, outfile)) |
426 | if (w < 0) goto out_status; | 468 | goto out_status; |
427 | if (w > 0) G.out_part++; | ||
428 | } | 469 | } |
429 | 470 | ||
430 | if (!devzero && close(ifd) < 0) { | 471 | if (!devzero && close(ifd) < 0) { |