Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/coreutils/dd.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/coreutils/dd.c
r821 r1770 9 9 */ 10 10 11 #include <sys/types.h> 12 #include <sys/stat.h> 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <unistd.h> 16 #include <string.h> 17 #include <fcntl.h> 18 #include <signal.h> // For FEATURE_DD_SIGNAL_HANDLING 19 #include "busybox.h" 11 #include <signal.h> /* For FEATURE_DD_SIGNAL_HANDLING */ 12 #include "libbb.h" 13 14 /* This is a NOEXEC applet. Be very careful! */ 15 20 16 21 17 static const struct suffix_mult dd_suffixes[] = { … … 25 21 { "kD", 1000 }, 26 22 { "k", 1024 }, 23 { "K", 1024 }, /* compat with coreutils dd */ 27 24 { "MD", 1000000 }, 28 25 { "M", 1048576 }, 29 26 { "GD", 1000000000 }, 30 27 { "G", 1073741824 }, 31 { NULL, 0}28 { } 32 29 }; 33 30 34 static size_t out_full; 35 static size_t out_part; 36 static size_t in_full; 37 static size_t in_part; 38 39 static void dd_output_status(int cur_signal) 31 struct globals { 32 off_t out_full, out_part, in_full, in_part; 33 }; 34 #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) 40 40 { 41 fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n", 42 (long)in_full, (long)in_part, 43 (long)out_full, (long)out_part); 41 /* Deliberately using %u, not %d */ 42 fprintf(stderr, "%"OFF_FMT"u+%"OFF_FMT"u records in\n" 43 "%"OFF_FMT"u+%"OFF_FMT"u records out\n", 44 G.in_full, G.in_part, 45 G.out_full, G.out_part); 44 46 } 45 47 48 static ssize_t full_write_or_warn(int fd, const void *buf, size_t len, 49 const char *const filename) 50 { 51 ssize_t n = full_write(fd, buf, len); 52 if (n < 0) 53 bb_perror_msg("writing '%s'", filename); 54 return n; 55 } 56 57 static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs, 58 const char *filename) 59 { 60 ssize_t n = full_write_or_warn(fd, buf, len, filename); 61 if (n < 0) 62 return 1; 63 if (n == obs) 64 G.out_full++; 65 else if (n) /* > 0 */ 66 G.out_part++; 67 return 0; 68 } 69 70 #if ENABLE_LFS 71 #define XATOU_SFX xatoull_sfx 72 #else 73 #define XATOU_SFX xatoul_sfx 74 #endif 75 76 int dd_main(int argc, char **argv); 46 77 int dd_main(int argc, char **argv) 47 78 { 48 size_t count = -1, oc = 0, ibs = 512, obs = 512; 49 ssize_t n; 50 off_t seek = 0, skip = 0; 51 int sync_flag = FALSE, noerror = FALSE, trunc_flag = TRUE, twobufs_flag = 0, 52 oflag, ifd, ofd, i; 53 const char *infile = NULL, *outfile = NULL; 79 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, 85 }; 86 static const char keywords[] ALIGN1 = 87 "bs=\0""count=\0""seek=\0""skip=\0""if=\0""of=\0" 88 #if ENABLE_FEATURE_DD_IBS_OBS 89 "ibs=\0""obs=\0""conv=\0""notrunc\0""sync\0""noerror\0" 90 #endif 91 ; 92 enum { 93 OP_bs = 1, 94 OP_count, 95 OP_seek, 96 OP_skip, 97 OP_if, 98 OP_of, 99 #if ENABLE_FEATURE_DD_IBS_OBS 100 OP_ibs, 101 OP_obs, 102 OP_conv, 103 OP_conv_notrunc, 104 OP_conv_sync, 105 OP_conv_noerror, 106 #endif 107 }; 108 size_t ibs = 512, obs = 512; 109 ssize_t n, w; 54 110 char *ibuf, *obuf; 55 56 if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) 57 { 58 struct sigaction sa; 59 60 memset(&sa, 0, sizeof(sa)); 61 sa.sa_handler = dd_output_status; 62 sa.sa_flags = SA_RESTART; 63 sigemptyset(&sa.sa_mask); 64 sigaction(SIGUSR1, &sa, 0); 65 } 66 67 for (i = 1; i < argc; i++) { 68 if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", argv[i], 4)) { 69 ibs = bb_xparse_number(argv[i]+4, dd_suffixes); 70 twobufs_flag++; 71 } else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", argv[i], 4)) { 72 obs = bb_xparse_number(argv[i]+4, dd_suffixes); 73 twobufs_flag++; 74 } else if (!strncmp("bs=", argv[i], 3)) { 75 ibs = obs = bb_xparse_number(argv[i]+3, dd_suffixes); 76 } else if (!strncmp("count=", argv[i], 6)) 77 count = bb_xparse_number(argv[i]+6, dd_suffixes); 78 else if (!strncmp("seek=", argv[i], 5)) 79 seek = bb_xparse_number(argv[i]+5, dd_suffixes); 80 else if (!strncmp("skip=", argv[i], 5)) 81 skip = bb_xparse_number(argv[i]+5, dd_suffixes); 82 else if (!strncmp("if=", argv[i], 3)) 83 infile = argv[i]+3; 84 else if (!strncmp("of=", argv[i], 3)) 85 outfile = argv[i]+3; 86 else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", argv[i], 5)) { 87 ibuf = argv[i]+5; 88 while (1) { 89 if (!strncmp("notrunc", ibuf, 7)) { 90 trunc_flag = FALSE; 91 ibuf += 7; 92 } else if (!strncmp("sync", ibuf, 4)) { 93 sync_flag = TRUE; 94 ibuf += 4; 95 } else if (!strncmp("noerror", ibuf, 7)) { 96 noerror = TRUE; 97 ibuf += 7; 98 } else { 99 bb_error_msg_and_die(bb_msg_invalid_arg, argv[i]+5, "conv"); 111 /* And these are all zeroed at once! */ 112 struct { 113 int flags; 114 int ifd, ofd; 115 size_t oc; 116 off_t count; 117 off_t seek, skip; 118 const char *infile, *outfile; 119 #if ENABLE_FEATURE_DD_SIGNAL_HANDLING 120 struct sigaction sigact; 121 #endif 122 } Z; 123 #define flags (Z.flags ) 124 #define ifd (Z.ifd ) 125 #define ofd (Z.ofd ) 126 #define oc (Z.oc ) 127 #define count (Z.count ) 128 #define seek (Z.seek ) 129 #define skip (Z.skip ) 130 #define infile (Z.infile ) 131 #define outfile (Z.outfile) 132 #define sigact (Z.sigact ) 133 134 memset(&Z, 0, sizeof(Z)); 135 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; 148 char *arg = argv[n]; 149 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) 154 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) 161 bb_show_usage(); 162 arg += key_len; 163 /* Must fit into positive ssize_t */ 164 #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; 168 } 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 ',' */ 100 194 } 101 if (ibuf[0] == '\0') break; 102 if (ibuf[0] == ',') ibuf++; 103 } 104 } else 105 bb_show_usage(); 106 } 107 ibuf = xmalloc(ibs); 108 109 if (twobufs_flag) obuf = xmalloc(obs); 110 else obuf = ibuf; 111 112 if (infile != NULL) { 113 ifd = bb_xopen(infile, O_RDONLY); 114 } else { 115 ifd = STDIN_FILENO; 195 continue; 196 } 197 #endif 198 if (what == OP_bs) { 199 ibs = obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); 200 continue; 201 } 202 /* These can be large: */ 203 if (what == OP_count) { 204 flags |= FLAG_COUNT; 205 count = XATOU_SFX(arg, dd_suffixes); 206 continue; 207 } 208 if (what == OP_seek) { 209 seek = XATOU_SFX(arg, dd_suffixes); 210 continue; 211 } 212 if (what == OP_skip) { 213 skip = XATOU_SFX(arg, dd_suffixes); 214 continue; 215 } 216 if (what == OP_if) { 217 infile = arg; 218 continue; 219 } 220 if (what == OP_of) 221 outfile = arg; 222 } 223 //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever 224 ibuf = obuf = xmalloc(ibs); 225 if (ibs != obs) { 226 flags |= FLAG_TWOBUFS; 227 obuf = xmalloc(obs); 228 } 229 if (infile != NULL) 230 ifd = xopen(infile, O_RDONLY); 231 else { 232 /* ifd = STDIN_FILENO; - it's zero and it's already there */ 116 233 infile = bb_msg_standard_input; 117 234 } 118 119 235 if (outfile != NULL) { 120 oflag = O_WRONLY | O_CREAT;121 122 if (!seek && trunc_flag) {236 int oflag = O_WRONLY | O_CREAT; 237 238 if (!seek && !(flags & FLAG_NOTRUNC)) 123 239 oflag |= O_TRUNC; 124 } 125 126 ofd = bb_xopen3(outfile, oflag, 0666); 127 128 if (seek && trunc_flag) { 240 241 ofd = xopen(outfile, oflag); 242 243 if (seek && !(flags & FLAG_NOTRUNC)) { 129 244 if (ftruncate(ofd, seek * obs) < 0) { 130 245 struct stat st; 131 246 132 if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) || 133 S_ISDIR (st.st_mode)) { 134 bb_perror_msg_and_die("%s", outfile); 135 } 247 if (fstat(ofd, &st) < 0 || S_ISREG(st.st_mode) || 248 S_ISDIR(st.st_mode)) 249 goto die_outfile; 136 250 } 137 251 } … … 140 254 outfile = bb_msg_standard_output; 141 255 } 142 143 256 if (skip) { 144 257 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { … … 146 259 n = safe_read(ifd, ibuf, ibs); 147 260 if (n < 0) 148 bb_perror_msg_and_die("%s", infile);261 goto die_infile; 149 262 if (n == 0) 150 263 break; … … 152 265 } 153 266 } 154 155 267 if (seek) { 156 if (lseek(ofd, seek * obs, SEEK_CUR) < 0) { 157 bb_perror_msg_and_die("%s", outfile); 158 } 159 } 160 161 while (in_full + in_part != count) { 162 if (noerror) { 163 /* Pre-zero the buffer when doing the noerror thing */ 164 memset(ibuf, '\0', ibs); 165 } 166 268 if (lseek(ofd, seek * obs, SEEK_CUR) < 0) 269 goto die_outfile; 270 } 271 272 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); 167 275 n = safe_read(ifd, ibuf, ibs); 168 if (n == 0) {276 if (n == 0) 169 277 break; 170 }171 278 if (n < 0) { 172 if ( noerror) {279 if (flags & FLAG_NOERROR) { 173 280 n = ibs; 174 281 bb_perror_msg("%s", infile); 175 } else { 176 bb_perror_msg_and_die("%s", infile); 177 } 178 } 179 if ((size_t)n == ibs) { 180 in_full++; 181 } else { 182 in_part++; 183 if (sync_flag) { 282 } else 283 goto die_infile; 284 } 285 if ((size_t)n == ibs) 286 G.in_full++; 287 else { 288 G.in_part++; 289 if (flags & FLAG_SYNC) { 184 290 memset(ibuf + n, '\0', ibs - n); 185 291 n = ibs; 186 292 } 187 293 } 188 if ( twobufs_flag) {294 if (flags & FLAG_TWOBUFS) { 189 295 char *tmp = ibuf; 190 296 while (n) { 191 297 size_t d = obs - oc; 192 298 193 if (d > n) d = n; 299 if (d > n) 300 d = n; 194 301 memcpy(obuf + oc, tmp, d); 195 302 n -= d; … … 197 304 oc += d; 198 305 if (oc == obs) { 199 if (bb_full_write(ofd, obuf, obs) < 0) { 200 bb_perror_msg_and_die("%s", outfile); 201 } 202 out_full++; 306 if (write_and_stats(ofd, obuf, obs, obs, outfile)) 307 goto out_status; 203 308 oc = 0; 204 309 } 205 310 } 206 } else { 207 if ((n = bb_full_write(ofd, ibuf, n)) < 0) { 208 bb_perror_msg_and_die("%s", outfile); 209 } 210 if (n == ibs) out_full++; 211 else out_part++; 212 } 213 } 214 311 } else if (write_and_stats(ofd, ibuf, n, obs, outfile)) 312 goto out_status; 313 } 314 215 315 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 216 if (bb_full_write(ofd, obuf, oc) < 0) { 217 bb_perror_msg_and_die("%s", outfile); 218 } 219 out_part++; 220 } 221 if (close (ifd) < 0) { 316 w = full_write_or_warn(ofd, obuf, oc, outfile); 317 if (w < 0) goto out_status; 318 if (w > 0) 319 G.out_part++; 320 } 321 if (close(ifd) < 0) { 322 die_infile: 222 323 bb_perror_msg_and_die("%s", infile); 223 324 } 224 325 225 if (close (ofd) < 0) { 326 if (close(ofd) < 0) { 327 die_outfile: 226 328 bb_perror_msg_and_die("%s", outfile); 227 329 } 228 330 out_status: 229 331 dd_output_status(0); 230 332
Note:
See TracChangeset
for help on using the changeset viewer.