Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/coreutils/dd.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/coreutils/dd.c
r3232 r3621 9 9 */ 10 10 11 //config:config DD 12 //config: bool "dd" 13 //config: default y 14 //config: help 15 //config: dd copies a file (from standard input to standard output, 16 //config: by default) using specific input and output blocksizes, 17 //config: while optionally performing conversions on it. 18 //config: 19 //config:config FEATURE_DD_SIGNAL_HANDLING 20 //config: bool "Enable signal handling for status reporting" 21 //config: default y 22 //config: depends on DD 23 //config: help 24 //config: Sending a SIGUSR1 signal to a running `dd' process makes it 25 //config: print to standard error the number of records read and written 26 //config: so far, then to resume copying. 27 //config: 28 //config: $ dd if=/dev/zero of=/dev/null & 29 //config: $ pid=$!; kill -USR1 $pid; sleep 1; kill $pid 30 //config: 10899206+0 records in 31 //config: 10899206+0 records out 32 //config: 33 //config:config FEATURE_DD_THIRD_STATUS_LINE 34 //config: bool "Enable the third status line upon signal" 35 //config: default y 36 //config: depends on DD && FEATURE_DD_SIGNAL_HANDLING 37 //config: help 38 //config: Displays a coreutils-like third status line with transferred bytes, 39 //config: elapsed time and speed. 40 //config: 41 //config:config FEATURE_DD_IBS_OBS 42 //config: bool "Enable ibs, obs and conv options" 43 //config: default y 44 //config: depends on DD 45 //config: help 46 //config: Enables support for writing a certain number of bytes in and out, 47 //config: at a time, and performing conversions on the data stream. 48 //config: 49 //config:config FEATURE_DD_STATUS 50 //config: bool "Enable status display options" 51 //config: default y 52 //config: depends on DD 53 //config: help 54 //config: Enables support for status=noxfer/none option. 55 11 56 //usage:#define dd_trivial_usage 12 57 //usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" 13 //usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] ")58 //usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes]") 14 59 //usage:#define dd_full_usage "\n\n" 15 60 //usage: "Copy a file with converting and formatting\n" … … 31 76 //usage: "\n conv=sync Pad blocks with zeros" 32 77 //usage: "\n conv=fsync Physically write data out before finishing" 78 //usage: "\n conv=swab Swap every pair of bytes" 79 //usage: "\n iflag=skip_bytes skip=N is in bytes" 80 //usage: ) 81 //usage: IF_FEATURE_DD_STATUS( 82 //usage: "\n status=noxfer Suppress rate output" 83 //usage: "\n status=none Suppress all output" 33 84 //usage: ) 34 85 //usage: "\n" 35 //usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024)," 36 //usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)" 86 //usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G" 37 87 //usage: 38 88 //usage:#define dd_example_usage … … 42 92 43 93 #include "libbb.h" 94 #include "common_bufsiz.h" 44 95 45 96 /* This is a NOEXEC applet. Be very careful! */ … … 49 100 ifd = STDIN_FILENO, 50 101 ofd = STDOUT_FILENO, 51 };52 53 static const struct suffix_mult dd_suffixes[] = {54 { "c", 1 },55 { "w", 2 },56 { "b", 512 },57 { "kD", 1000 },58 { "k", 1024 },59 { "K", 1024 }, /* compat with coreutils dd */60 { "MD", 1000000 },61 { "M", 1048576 },62 { "GD", 1000000000 },63 { "G", 1073741824 },64 { "", 0 }65 102 }; 66 103 … … 71 108 unsigned long long begin_time_us; 72 109 #endif 110 int flags; 73 111 } FIX_ALIASING; 74 #define G (*(struct globals*) &bb_common_bufsiz1)112 #define G (*(struct globals*)bb_common_bufsiz1) 75 113 #define INIT_G() do { \ 114 setup_common_bufsiz(); \ 76 115 /* we have to zero it out because of NOEXEC */ \ 77 116 memset(&G, 0, sizeof(G)); \ 78 117 } while (0) 79 118 119 enum { 120 /* Must be in the same order as OP_conv_XXX! */ 121 /* (see "flags |= (1 << what)" below) */ 122 FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, 123 FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, 124 FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, 125 FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, 126 FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, 127 /* end of conv flags */ 128 /* start of input flags */ 129 FLAG_IFLAG_SHIFT = 5, 130 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 131 /* end of input flags */ 132 FLAG_TWOBUFS = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, 133 FLAG_COUNT = 1 << 7, 134 FLAG_STATUS = 1 << 8, 135 FLAG_STATUS_NONE = 1 << 9, 136 FLAG_STATUS_NOXFER = 1 << 10, 137 }; 80 138 81 139 static void dd_output_status(int UNUSED_PARAM cur_signal) … … 94 152 95 153 #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 154 # if ENABLE_FEATURE_DD_STATUS 155 if (G.flags & FLAG_STATUS_NOXFER) /* status=noxfer active? */ 156 return; 157 //TODO: should status=none make dd stop reacting to USR1 entirely? 158 //So far we react to it (we print the stats), 159 //status=none only suppresses final, non-USR1 generated status message. 160 # endif 96 161 fprintf(stderr, "%llu bytes (%sB) copied, ", 97 162 G.total_bytes, … … 146 211 #endif 147 212 213 #if ENABLE_FEATURE_DD_IBS_OBS 214 static int parse_comma_flags(char *val, const char *words, const char *error_in) 215 { 216 int flags = 0; 217 while (1) { 218 int n; 219 char *arg; 220 /* find ',', replace them with NUL so we can use val for 221 * index_in_strings() without copying. 222 * We rely on val being non-null, else strchr would fault. 223 */ 224 arg = strchr(val, ','); 225 if (arg) 226 *arg = '\0'; 227 n = index_in_strings(words, val); 228 if (n < 0) 229 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, error_in); 230 flags |= (1 << n); 231 if (!arg) /* no ',' left, so this was the last specifier */ 232 break; 233 *arg = ','; /* to preserve ps listing */ 234 val = arg + 1; /* skip this keyword and ',' */ 235 } 236 return flags; 237 } 238 #endif 239 148 240 int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 149 241 int dd_main(int argc UNUSED_PARAM, char **argv) 150 242 { 151 enum {152 /* Must be in the same order as OP_conv_XXX! */153 /* (see "flags |= (1 << what)" below) */154 FLAG_NOTRUNC = 1 << 0,155 FLAG_SYNC = 1 << 1,156 FLAG_NOERROR = 1 << 2,157 FLAG_FSYNC = 1 << 3,158 /* end of conv flags */159 FLAG_TWOBUFS = 1 << 4,160 FLAG_COUNT = 1 << 5,161 };162 243 static const char keywords[] ALIGN1 = 163 "bs\0""count\0""seek\0""skip\0""if\0""of\0" 164 #if ENABLE_FEATURE_DD_IBS_OBS 165 "ibs\0""obs\0""conv\0" 244 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") 245 #if ENABLE_FEATURE_DD_IBS_OBS 246 "ibs\0""obs\0""conv\0""iflag\0" 166 247 #endif 167 248 ; 168 249 #if ENABLE_FEATURE_DD_IBS_OBS 169 250 static const char conv_words[] ALIGN1 = 170 "notrunc\0""sync\0""noerror\0""fsync\0"; 251 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 252 static const char iflag_words[] ALIGN1 = 253 "skip_bytes\0"; 254 #endif 255 #if ENABLE_FEATURE_DD_STATUS 256 static const char status_words[] ALIGN1 = 257 "none\0""noxfer\0"; 171 258 #endif 172 259 enum { … … 177 264 OP_if, 178 265 OP_of, 266 IF_FEATURE_DD_STATUS(OP_status,) 179 267 #if ENABLE_FEATURE_DD_IBS_OBS 180 268 OP_ibs, 181 269 OP_obs, 182 270 OP_conv, 271 OP_iflag, 183 272 /* Must be in the same order as FLAG_XXX! */ 184 273 OP_conv_notrunc = 0, … … 186 275 OP_conv_noerror, 187 276 OP_conv_fsync, 277 OP_conv_swab, 188 278 /* Unimplemented conv=XXX: */ 189 279 //nocreat do not create the output file 190 280 //excl fail if the output file already exists 191 281 //fdatasync physically write output file data before finishing 192 //swab swap every pair of input bytes193 282 //lcase change upper case to lower case 194 283 //ucase change lower case to upper case … … 198 287 //ebcdic from ASCII to EBCDIC 199 288 //ibm from ASCII to alternate EBCDIC 289 /* Partially implemented: */ 290 //swab swap every pair of input bytes: will abort on non-even reads 291 OP_iflag_skip_bytes, 200 292 #endif 201 293 }; 202 int exitcode = EXIT_FAILURE; 203 size_t ibs = 512, obs = 512; 204 ssize_t n, w; 205 char *ibuf, *obuf; 206 /* And these are all zeroed at once! */ 294 smallint exitcode = EXIT_FAILURE; 295 int i; 296 size_t ibs = 512; 297 char *ibuf; 298 #if ENABLE_FEATURE_DD_IBS_OBS 299 size_t obs = 512; 300 char *obuf; 301 #else 302 # define obs ibs 303 # define obuf ibuf 304 #endif 305 /* These are all zeroed at once! */ 207 306 struct { 208 int flags;209 307 size_t oc; 308 ssize_t prev_read_size; /* for detecting swab failure */ 210 309 off_t count; 211 310 off_t seek, skip; 212 311 const char *infile, *outfile; 213 312 } Z; 214 #define flags (Z.flags )215 313 #define oc (Z.oc ) 314 #define prev_read_size (Z.prev_read_size) 216 315 #define count (Z.count ) 217 316 #define seek (Z.seek ) … … 224 323 //fflush_all(); - is this needed because of NOEXEC? 225 324 226 for ( n = 1; argv[n]; n++) {325 for (i = 1; argv[i]; i++) { 227 326 int what; 228 327 char *val; 229 char *arg = argv[ n];328 char *arg = argv[i]; 230 329 231 330 #if ENABLE_DESKTOP … … 247 346 if (what == OP_ibs) { 248 347 /* Must fit into positive ssize_t */ 249 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);348 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 250 349 /*continue;*/ 251 350 } 252 351 if (what == OP_obs) { 253 obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);352 obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 254 353 /*continue;*/ 255 354 } 256 355 if (what == OP_conv) { 257 while (1) { 258 /* find ',', replace them with NUL so we can use val for 259 * index_in_strings() without copying. 260 * We rely on val being non-null, else strchr would fault. 261 */ 262 arg = strchr(val, ','); 263 if (arg) 264 *arg = '\0'; 265 what = index_in_strings(conv_words, val); 266 if (what < 0) 267 bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); 268 flags |= (1 << what); 269 if (!arg) /* no ',' left, so this was the last specifier */ 270 break; 271 /* *arg = ','; - to preserve ps listing? */ 272 val = arg + 1; /* skip this keyword and ',' */ 273 } 274 continue; /* we trashed 'what', can't fall through */ 356 G.flags |= parse_comma_flags(val, conv_words, "conv"); 357 /*continue;*/ 358 } 359 if (what == OP_iflag) { 360 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT; 361 /*continue;*/ 275 362 } 276 363 #endif 277 364 if (what == OP_bs) { 278 ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); 365 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 366 obs = ibs; 279 367 /*continue;*/ 280 368 } 281 369 /* These can be large: */ 282 370 if (what == OP_count) { 283 flags |= FLAG_COUNT;284 count = XATOU_SFX(val, dd_suffixes);371 G.flags |= FLAG_COUNT; 372 count = XATOU_SFX(val, cwbkMG_suffixes); 285 373 /*continue;*/ 286 374 } 287 375 if (what == OP_seek) { 288 seek = XATOU_SFX(val, dd_suffixes);376 seek = XATOU_SFX(val, cwbkMG_suffixes); 289 377 /*continue;*/ 290 378 } 291 379 if (what == OP_skip) { 292 skip = XATOU_SFX(val, dd_suffixes);380 skip = XATOU_SFX(val, cwbkMG_suffixes); 293 381 /*continue;*/ 294 382 } … … 301 389 /*continue;*/ 302 390 } 303 } /* end of "for (argv[n])" */ 391 #if ENABLE_FEATURE_DD_STATUS 392 if (what == OP_status) { 393 int n; 394 n = index_in_strings(status_words, val); 395 if (n < 0) 396 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, "status"); 397 G.flags |= FLAG_STATUS << n; 398 /*continue;*/ 399 } 400 #endif 401 } /* end of "for (argv[i])" */ 304 402 305 403 //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever 306 ibuf = obuf = xmalloc(ibs); 404 ibuf = xmalloc(ibs); 405 obuf = ibuf; 406 #if ENABLE_FEATURE_DD_IBS_OBS 307 407 if (ibs != obs) { 308 flags |= FLAG_TWOBUFS;408 G.flags |= FLAG_TWOBUFS; 309 409 obuf = xmalloc(obs); 310 410 } 411 #endif 311 412 312 413 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING … … 317 418 #endif 318 419 319 if (infile != NULL)420 if (infile) { 320 421 xmove_fd(xopen(infile, O_RDONLY), ifd); 321 else {422 } else { 322 423 infile = bb_msg_standard_input; 323 424 } 324 if (outfile != NULL) {425 if (outfile) { 325 426 int oflag = O_WRONLY | O_CREAT; 326 427 327 if (!seek && !( flags & FLAG_NOTRUNC))428 if (!seek && !(G.flags & FLAG_NOTRUNC)) 328 429 oflag |= O_TRUNC; 329 430 330 431 xmove_fd(xopen(outfile, oflag), ofd); 331 432 332 if (seek && !( flags & FLAG_NOTRUNC)) {433 if (seek && !(G.flags & FLAG_NOTRUNC)) { 333 434 if (ftruncate(ofd, seek * obs) < 0) { 334 435 struct stat st; … … 346 447 } 347 448 if (skip) { 348 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { 349 while (skip-- > 0) { 350 n = safe_read(ifd, ibuf, ibs); 449 size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; 450 if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { 451 do { 452 ssize_t n = safe_read(ifd, ibuf, blocksz); 351 453 if (n < 0) 352 454 goto die_infile; 353 455 if (n == 0) 354 456 break; 355 } 457 } while (--skip != 0); 356 458 } 357 459 } … … 361 463 } 362 464 363 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { 465 while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { 466 ssize_t n; 467 364 468 n = safe_read(ifd, ibuf, ibs); 365 469 if (n == 0) … … 367 471 if (n < 0) { 368 472 /* "Bad block" */ 369 if (!( flags & FLAG_NOERROR))473 if (!(G.flags & FLAG_NOERROR)) 370 474 goto die_infile; 371 475 bb_simple_perror_msg(infile); … … 376 480 n = 0; 377 481 } 482 if (G.flags & FLAG_SWAB) { 483 uint16_t *p16; 484 ssize_t n2; 485 486 /* Our code allows only last read to be odd-sized */ 487 if (prev_read_size & 1) 488 bb_error_msg_and_die("can't swab %lu byte buffer", 489 (unsigned long)prev_read_size); 490 prev_read_size = n; 491 492 /* If n is odd, last byte is not swapped: 493 * echo -n "qwe" | dd conv=swab 494 * prints "wqe". 495 */ 496 p16 = (void*) ibuf; 497 n2 = (n >> 1); 498 while (--n2 >= 0) { 499 *p16 = bswap_16(*p16); 500 p16++; 501 } 502 } 378 503 if ((size_t)n == ibs) 379 504 G.in_full++; 380 505 else { 381 506 G.in_part++; 382 if ( flags & FLAG_SYNC) {507 if (G.flags & FLAG_SYNC) { 383 508 memset(ibuf + n, 0, ibs - n); 384 509 n = ibs; 385 510 } 386 511 } 387 if ( flags & FLAG_TWOBUFS) {512 if (G.flags & FLAG_TWOBUFS) { 388 513 char *tmp = ibuf; 389 514 while (n) { … … 402 527 } 403 528 } 404 } else if (write_and_stats(ibuf, n, obs, outfile)) 405 goto out_status; 406 407 if (flags & FLAG_FSYNC) { 529 } else { 530 if (write_and_stats(ibuf, n, obs, outfile)) 531 goto out_status; 532 } 533 534 if (G.flags & FLAG_FSYNC) { 408 535 if (fsync(ofd) < 0) 409 536 goto die_outfile; … … 412 539 413 540 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 414 w = full_write_or_warn(obuf, oc, outfile); 415 if (w < 0) goto out_status; 416 if (w > 0) G.out_part++; 541 if (write_and_stats(obuf, oc, obs, outfile)) 542 goto out_status; 417 543 } 418 544 if (close(ifd) < 0) { … … 428 554 exitcode = EXIT_SUCCESS; 429 555 out_status: 430 dd_output_status(0); 556 if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) 557 dd_output_status(0); 431 558 432 559 if (ENABLE_FEATURE_CLEAN_UP) { 433 560 free(obuf); 434 if ( flags & FLAG_TWOBUFS)561 if (G.flags & FLAG_TWOBUFS) 435 562 free(ibuf); 436 563 }
Note:
See TracChangeset
for help on using the changeset viewer.