Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/coreutils/dd.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/coreutils/dd.c
r1765 r2725 6 6 * Copyright (C) 2000,2001 Matt Kraai 7 7 * 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 9 */ 10 10 11 #include <signal.h> /* For FEATURE_DD_SIGNAL_HANDLING */12 11 #include "libbb.h" 13 12 14 13 /* This is a NOEXEC applet. Be very careful! */ 15 14 15 16 enum { 17 ifd = STDIN_FILENO, 18 ofd = STDOUT_FILENO, 19 }; 16 20 17 21 static const struct suffix_mult dd_suffixes[] = { … … 21 25 { "kD", 1000 }, 22 26 { "k", 1024 }, 23 { "K", 1024 }, 27 { "K", 1024 }, /* compat with coreutils dd */ 24 28 { "MD", 1000000 }, 25 29 { "M", 1048576 }, 26 30 { "GD", 1000000000 }, 27 31 { "G", 1073741824 }, 28 { }32 { "", 0 } 29 33 }; 30 34 31 35 struct globals { 32 36 off_t out_full, out_part, in_full, in_part; 33 }; 37 #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 38 unsigned long long total_bytes; 39 unsigned long long begin_time_us; 40 #endif 41 } FIX_ALIASING; 34 42 #define G (*(struct globals*)&bb_common_bufsiz1) 35 /* We have to zero it out because of NOEXEC */ 36 #define INIT_G() memset(&G, 0, sizeof(G)) 37 38 39 static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal) 43 #define INIT_G() do { \ 44 /* we have to zero it out because of NOEXEC */ \ 45 memset(&G, 0, sizeof(G)); \ 46 } while (0) 47 48 49 static void dd_output_status(int UNUSED_PARAM cur_signal) 40 50 { 51 #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 52 double seconds; 53 unsigned long long bytes_sec; 54 unsigned long long now_us = monotonic_us(); /* before fprintf */ 55 #endif 56 41 57 /* Deliberately using %u, not %d */ 42 58 fprintf(stderr, "%"OFF_FMT"u+%"OFF_FMT"u records in\n" … … 44 60 G.in_full, G.in_part, 45 61 G.out_full, G.out_part); 62 63 #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 64 fprintf(stderr, "%llu bytes (%sB) copied, ", 65 G.total_bytes, 66 /* show fractional digit, use suffixes */ 67 make_human_readable_str(G.total_bytes, 1, 0) 68 ); 69 /* Corner cases: 70 * ./busybox dd </dev/null >/dev/null 71 * ./busybox dd bs=1M count=2000 </dev/zero >/dev/null 72 * (echo DONE) | ./busybox dd >/dev/null 73 * (sleep 1; echo DONE) | ./busybox dd >/dev/null 74 */ 75 seconds = (now_us - G.begin_time_us) / 1000000.0; 76 bytes_sec = G.total_bytes / seconds; 77 fprintf(stderr, "%f seconds, %sB/s\n", 78 seconds, 79 /* show fractional digit, use suffixes */ 80 make_human_readable_str(bytes_sec, 1, 0) 81 ); 82 #endif 46 83 } 47 84 48 static ssize_t full_write_or_warn( int fd,const void *buf, size_t len,85 static ssize_t full_write_or_warn(const void *buf, size_t len, 49 86 const char *const filename) 50 87 { 51 ssize_t n = full_write( fd, buf, len);88 ssize_t n = full_write(ofd, buf, len); 52 89 if (n < 0) 53 90 bb_perror_msg("writing '%s'", filename); … … 55 92 } 56 93 57 static bool write_and_stats( int fd,const void *buf, size_t len, size_t obs,94 static bool write_and_stats(const void *buf, size_t len, size_t obs, 58 95 const char *filename) 59 96 { 60 ssize_t n = full_write_or_warn( fd,buf, len, filename);97 ssize_t n = full_write_or_warn(buf, len, filename); 61 98 if (n < 0) 62 99 return 1; 63 if ( n == obs)100 if ((size_t)n == obs) 64 101 G.out_full++; 65 102 else if (n) /* > 0 */ 66 103 G.out_part++; 104 #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 105 G.total_bytes += n; 106 #endif 67 107 return 0; 68 108 } 69 109 70 110 #if ENABLE_LFS 71 # define XATOU_SFX xatoull_sfx111 # define XATOU_SFX xatoull_sfx 72 112 #else 73 # define XATOU_SFX xatoul_sfx74 #endif 75 76 int dd_main(int argc, char **argv) ;77 int dd_main(int argc , char **argv)113 # define XATOU_SFX xatoul_sfx 114 #endif 115 116 int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 117 int dd_main(int argc UNUSED_PARAM, char **argv) 78 118 { 79 119 enum { 80 FLAG_SYNC = 1 << 0, 81 FLAG_NOERROR = 1 << 1, 82 FLAG_NOTRUNC = 1 << 2, 83 FLAG_TWOBUFS = 1 << 3, 84 FLAG_COUNT = 1 << 4, 120 /* Must be in the same order as OP_conv_XXX! */ 121 /* (see "flags |= (1 << what)" below) */ 122 FLAG_NOTRUNC = 1 << 0, 123 FLAG_SYNC = 1 << 1, 124 FLAG_NOERROR = 1 << 2, 125 FLAG_FSYNC = 1 << 3, 126 /* end of conv flags */ 127 FLAG_TWOBUFS = 1 << 4, 128 FLAG_COUNT = 1 << 5, 85 129 }; 86 130 static const char keywords[] ALIGN1 = 87 "bs =\0""count=\0""seek=\0""skip=\0""if=\0""of=\0"131 "bs\0""count\0""seek\0""skip\0""if\0""of\0" 88 132 #if ENABLE_FEATURE_DD_IBS_OBS 89 "ibs =\0""obs=\0""conv=\0""notrunc\0""sync\0""noerror\0"133 "ibs\0""obs\0""conv\0" 90 134 #endif 91 135 ; 136 #if ENABLE_FEATURE_DD_IBS_OBS 137 static const char conv_words[] ALIGN1 = 138 "notrunc\0""sync\0""noerror\0""fsync\0"; 139 #endif 92 140 enum { 93 OP_bs = 1,141 OP_bs = 0, 94 142 OP_count, 95 143 OP_seek, … … 101 149 OP_obs, 102 150 OP_conv, 103 OP_conv_notrunc, 151 /* Must be in the same order as FLAG_XXX! */ 152 OP_conv_notrunc = 0, 104 153 OP_conv_sync, 105 154 OP_conv_noerror, 155 OP_conv_fsync, 156 /* Unimplemented conv=XXX: */ 157 //nocreat do not create the output file 158 //excl fail if the output file already exists 159 //fdatasync physically write output file data before finishing 160 //swab swap every pair of input bytes 161 //lcase change upper case to lower case 162 //ucase change lower case to upper case 163 //block pad newline-terminated records with spaces to cbs-size 164 //unblock replace trailing spaces in cbs-size records with newline 165 //ascii from EBCDIC to ASCII 166 //ebcdic from ASCII to EBCDIC 167 //ibm from ASCII to alternate EBCDIC 106 168 #endif 107 169 }; 170 int exitcode = EXIT_FAILURE; 108 171 size_t ibs = 512, obs = 512; 109 172 ssize_t n, w; … … 112 175 struct { 113 176 int flags; 114 int ifd, ofd;115 177 size_t oc; 116 178 off_t count; 117 179 off_t seek, skip; 118 180 const char *infile, *outfile; 119 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING120 struct sigaction sigact;121 #endif122 181 } Z; 123 182 #define flags (Z.flags ) 124 #define ifd (Z.ifd )125 #define ofd (Z.ofd )126 183 #define oc (Z.oc ) 127 184 #define count (Z.count ) … … 130 187 #define infile (Z.infile ) 131 188 #define outfile (Z.outfile) 132 #define sigact (Z.sigact )133 189 134 190 memset(&Z, 0, sizeof(Z)); 135 191 INIT_G(); 136 137 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING 138 sigact.sa_handler = dd_output_status; 139 sigact.sa_flags = SA_RESTART; 140 sigemptyset(&sigact.sa_mask); 141 sigaction(SIGUSR1, &sigact, NULL); 142 #endif 143 144 for (n = 1; n < argc; n++) { 145 smalluint key_len; 146 smalluint what; 147 char *key; 192 //fflush_all(); - is this needed because of NOEXEC? 193 194 for (n = 1; argv[n]; n++) { 195 int what; 196 char *val; 148 197 char *arg = argv[n]; 149 198 150 //XXX:FIXME: we reject plain "dd --" This would cost ~20 bytes, so.. 151 //if (*arg == '-' && *++arg == '-' && !*++arg) continue; 152 key = strstr(arg, "="); 153 if (key == NULL) 199 #if ENABLE_DESKTOP 200 /* "dd --". NB: coreutils 6.9 will complain if they see 201 * more than one of them. We wouldn't. */ 202 if (arg[0] == '-' && arg[1] == '-' && arg[2] == '\0') 203 continue; 204 #endif 205 val = strchr(arg, '='); 206 if (val == NULL) 154 207 bb_show_usage(); 155 key_len = key - arg + 1; 156 key = xstrndup(arg, key_len); 157 what = index_in_strings(keywords, key) + 1; 158 if (ENABLE_FEATURE_CLEAN_UP) 159 free(key); 160 if (what == 0) 208 *val = '\0'; 209 what = index_in_strings(keywords, arg); 210 if (what < 0) 161 211 bb_show_usage(); 162 arg += key_len;163 /* Must fit into positive ssize_t */212 /* *val = '='; - to preserve ps listing? */ 213 val++; 164 214 #if ENABLE_FEATURE_DD_IBS_OBS 165 if (what == OP_ibs) { 166 ibs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); 167 continue; 215 if (what == OP_ibs) { 216 /* Must fit into positive ssize_t */ 217 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); 218 /*continue;*/ 219 } 220 if (what == OP_obs) { 221 obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); 222 /*continue;*/ 223 } 224 if (what == OP_conv) { 225 while (1) { 226 /* find ',', replace them with NUL so we can use val for 227 * index_in_strings() without copying. 228 * We rely on val being non-null, else strchr would fault. 229 */ 230 arg = strchr(val, ','); 231 if (arg) 232 *arg = '\0'; 233 what = index_in_strings(conv_words, val); 234 if (what < 0) 235 bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); 236 flags |= (1 << what); 237 if (!arg) /* no ',' left, so this was the last specifier */ 238 break; 239 /* *arg = ','; - to preserve ps listing? */ 240 val = arg + 1; /* skip this keyword and ',' */ 168 241 } 169 if (what == OP_obs) { 170 obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); 171 continue; 172 } 173 if (what == OP_conv) { 174 while (1) { 175 /* find ',', replace them with nil so we can use arg for 176 * index_in_strings() without copying. 177 * We rely on arg being non-null, else strchr would fault. 178 */ 179 key = strchr(arg, ','); 180 if (key) 181 *key = '\0'; 182 what = index_in_strings(keywords, arg) + 1; 183 if (what < OP_conv_notrunc) 184 bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv"); 185 if (what == OP_conv_notrunc) 186 flags |= FLAG_NOTRUNC; 187 if (what == OP_conv_sync) 188 flags |= FLAG_SYNC; 189 if (what == OP_conv_noerror) 190 flags |= FLAG_NOERROR; 191 if (!key) /* no ',' left, so this was the last specifier */ 192 break; 193 arg = key + 1; /* skip this keyword and ',' */ 194 } 195 continue; 196 } 242 continue; /* we trashed 'what', can't fall through */ 243 } 197 244 #endif 198 245 if (what == OP_bs) { 199 ibs = obs = xatoul_range_sfx( arg, 1, ((size_t)-1L)/2, dd_suffixes);200 continue;246 ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); 247 /*continue;*/ 201 248 } 202 249 /* These can be large: */ 203 250 if (what == OP_count) { 204 251 flags |= FLAG_COUNT; 205 count = XATOU_SFX( arg, dd_suffixes);206 continue;252 count = XATOU_SFX(val, dd_suffixes); 253 /*continue;*/ 207 254 } 208 255 if (what == OP_seek) { 209 seek = XATOU_SFX( arg, dd_suffixes);210 continue;256 seek = XATOU_SFX(val, dd_suffixes); 257 /*continue;*/ 211 258 } 212 259 if (what == OP_skip) { 213 skip = XATOU_SFX( arg, dd_suffixes);214 continue;260 skip = XATOU_SFX(val, dd_suffixes); 261 /*continue;*/ 215 262 } 216 263 if (what == OP_if) { 217 infile = arg; 218 continue; 219 } 220 if (what == OP_of) 221 outfile = arg; 222 } 264 infile = val; 265 /*continue;*/ 266 } 267 if (what == OP_of) { 268 outfile = val; 269 /*continue;*/ 270 } 271 } /* end of "for (argv[n])" */ 272 223 273 //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever 224 274 ibuf = obuf = xmalloc(ibs); … … 227 277 obuf = xmalloc(obs); 228 278 } 279 280 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING 281 signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); 282 #endif 283 #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 284 G.begin_time_us = monotonic_us(); 285 #endif 286 229 287 if (infile != NULL) 230 ifd = xopen(infile, O_RDONLY);288 xmove_fd(xopen(infile, O_RDONLY), ifd); 231 289 else { 232 /* ifd = STDIN_FILENO; - it's zero and it's already there */233 290 infile = bb_msg_standard_input; 234 291 } … … 239 296 oflag |= O_TRUNC; 240 297 241 ofd = xopen(outfile, oflag);298 xmove_fd(xopen(outfile, oflag), ofd); 242 299 243 300 if (seek && !(flags & FLAG_NOTRUNC)) { … … 245 302 struct stat st; 246 303 247 if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) || 248 S_ISDIR(st.st_mode)) 304 if (fstat(ofd, &st) < 0 305 || S_ISREG(st.st_mode) 306 || S_ISDIR(st.st_mode) 307 ) { 249 308 goto die_outfile; 309 } 250 310 } 251 311 } 252 312 } else { 253 ofd = STDOUT_FILENO;254 313 outfile = bb_msg_standard_output; 255 314 } … … 271 330 272 331 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { 273 if (flags & FLAG_NOERROR) /* Pre-zero the buffer if conv=noerror */274 memset(ibuf, 0, ibs);275 332 n = safe_read(ifd, ibuf, ibs); 276 333 if (n == 0) 277 334 break; 278 335 if (n < 0) { 279 if (flags & FLAG_NOERROR) { 280 n = ibs; 281 bb_perror_msg("%s", infile); 282 } else 336 /* "Bad block" */ 337 if (!(flags & FLAG_NOERROR)) 283 338 goto die_infile; 339 bb_simple_perror_msg(infile); 340 /* GNU dd with conv=noerror skips over bad blocks */ 341 xlseek(ifd, ibs, SEEK_CUR); 342 /* conv=noerror,sync writes NULs, 343 * conv=noerror just ignores input bad blocks */ 344 n = 0; 284 345 } 285 346 if ((size_t)n == ibs) … … 288 349 G.in_part++; 289 350 if (flags & FLAG_SYNC) { 290 memset(ibuf + n, '\0', ibs - n);351 memset(ibuf + n, 0, ibs - n); 291 352 n = ibs; 292 353 } … … 297 358 size_t d = obs - oc; 298 359 299 if (d > n)360 if (d > (size_t)n) 300 361 d = n; 301 362 memcpy(obuf + oc, tmp, d); … … 304 365 oc += d; 305 366 if (oc == obs) { 306 if (write_and_stats(o fd, obuf, obs, obs, outfile))367 if (write_and_stats(obuf, obs, obs, outfile)) 307 368 goto out_status; 308 369 oc = 0; 309 370 } 310 371 } 311 } else if (write_and_stats( ofd,ibuf, n, obs, outfile))372 } else if (write_and_stats(ibuf, n, obs, outfile)) 312 373 goto out_status; 374 375 if (flags & FLAG_FSYNC) { 376 if (fsync(ofd) < 0) 377 goto die_outfile; 378 } 313 379 } 314 380 315 381 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 316 w = full_write_or_warn(o fd, obuf, oc, outfile);382 w = full_write_or_warn(obuf, oc, outfile); 317 383 if (w < 0) goto out_status; 318 if (w > 0) 319 G.out_part++; 384 if (w > 0) G.out_part++; 320 385 } 321 386 if (close(ifd) < 0) { 322 387 die_infile: 323 bb_ perror_msg_and_die("%s",infile);388 bb_simple_perror_msg_and_die(infile); 324 389 } 325 390 326 391 if (close(ofd) < 0) { 327 392 die_outfile: 328 bb_perror_msg_and_die("%s", outfile); 329 } 393 bb_simple_perror_msg_and_die(outfile); 394 } 395 396 exitcode = EXIT_SUCCESS; 330 397 out_status: 331 398 dd_output_status(0); 332 399 333 return EXIT_SUCCESS;400 return exitcode; 334 401 }
Note:
See TracChangeset
for help on using the changeset viewer.