diff options
| author | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2007-04-04 14:01:23 +0000 |
|---|---|---|
| committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2007-04-04 14:01:23 +0000 |
| commit | 2a47dea263afdb98e1d545da3c48e829883974ef (patch) | |
| tree | aa59c9f272cdc8883516460fcf7874352dde1f51 /coreutils | |
| parent | 3a60244ae94782a1a4065685cf6e7867cc306a25 (diff) | |
| download | busybox-w32-2a47dea263afdb98e1d545da3c48e829883974ef.tar.gz busybox-w32-2a47dea263afdb98e1d545da3c48e829883974ef.tar.bz2 busybox-w32-2a47dea263afdb98e1d545da3c48e829883974ef.zip | |
- remove bss users. Shrinkage while at it. See XXX for further, pre-existing bugs
text data bss dec hex filename
1969 0 32 2001 7d1 dd.o.oorig
1941 0 0 1941 795 dd.o
Diffstat (limited to 'coreutils')
| -rw-r--r-- | coreutils/dd.c | 204 |
1 files changed, 130 insertions, 74 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c index 4a094e81a..518c5fed2 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
| @@ -17,7 +17,7 @@ static const struct suffix_mult dd_suffixes[] = { | |||
| 17 | { "b", 512 }, | 17 | { "b", 512 }, |
| 18 | { "kD", 1000 }, | 18 | { "kD", 1000 }, |
| 19 | { "k", 1024 }, | 19 | { "k", 1024 }, |
| 20 | { "K", 1024 }, // compat with coreutils dd | 20 | { "K", 1024 }, /* compat with coreutils dd */ |
| 21 | { "MD", 1000000 }, | 21 | { "MD", 1000000 }, |
| 22 | { "M", 1048576 }, | 22 | { "M", 1048576 }, |
| 23 | { "GD", 1000000000 }, | 23 | { "GD", 1000000000 }, |
| @@ -25,18 +25,21 @@ static const struct suffix_mult dd_suffixes[] = { | |||
| 25 | { NULL, 0 } | 25 | { NULL, 0 } |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | static off_t out_full, out_part, in_full, in_part; | 28 | struct globals { |
| 29 | off_t out_full, out_part, in_full, in_part; | ||
| 30 | }; | ||
| 31 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
| 29 | 32 | ||
| 30 | static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal) | 33 | static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal) |
| 31 | { | 34 | { |
| 32 | fprintf(stderr, "%"OFF_FMT"d+%"OFF_FMT"d records in\n" | 35 | fprintf(stderr, "%"OFF_FMT"d+%"OFF_FMT"d records in\n" |
| 33 | "%"OFF_FMT"d+%"OFF_FMT"d records out\n", | 36 | "%"OFF_FMT"d+%"OFF_FMT"d records out\n", |
| 34 | in_full, in_part, | 37 | G.in_full, G.in_part, |
| 35 | out_full, out_part); | 38 | G.out_full, G.out_part); |
| 36 | } | 39 | } |
| 37 | 40 | ||
| 38 | static ssize_t full_write_or_warn(int fd, const void *buf, size_t len, | 41 | static ssize_t full_write_or_warn(int fd, const void *buf, size_t len, |
| 39 | const char* filename) | 42 | const char * const filename) |
| 40 | { | 43 | { |
| 41 | ssize_t n = full_write(fd, buf, len); | 44 | ssize_t n = full_write(fd, buf, len); |
| 42 | if (n < 0) | 45 | if (n < 0) |
| @@ -44,6 +47,19 @@ static ssize_t full_write_or_warn(int fd, const void *buf, size_t len, | |||
| 44 | return n; | 47 | return n; |
| 45 | } | 48 | } |
| 46 | 49 | ||
| 50 | static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs, | ||
| 51 | const char * const filename) | ||
| 52 | { | ||
| 53 | ssize_t n = full_write_or_warn(fd, buf, len, filename); | ||
| 54 | if (n < 0) | ||
| 55 | return 1; | ||
| 56 | if (n == obs) | ||
| 57 | G.out_full++; | ||
| 58 | else if (n > 0) | ||
| 59 | G.out_part++; | ||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 47 | #if ENABLE_LFS | 63 | #if ENABLE_LFS |
| 48 | #define XATOU_SFX xatoull_sfx | 64 | #define XATOU_SFX xatoull_sfx |
| 49 | #else | 65 | #else |
| @@ -59,11 +75,31 @@ int dd_main(int argc, char **argv) | |||
| 59 | trunc_flag = 1 << 2, | 75 | trunc_flag = 1 << 2, |
| 60 | twobufs_flag = 1 << 3, | 76 | twobufs_flag = 1 << 3, |
| 61 | }; | 77 | }; |
| 78 | const char * const keywords[] = { | ||
| 79 | "bs=", "count=", "seek=", "skip=", "if=", "of=", | ||
| 80 | #if ENABLE_FEATURE_DD_IBS_OBS | ||
| 81 | "ibs=", "obs=", "conv=", "notrunc", "sync", "noerror", | ||
| 82 | #endif | ||
| 83 | NULL | ||
| 84 | }; | ||
| 85 | #define OP_bs 0 + 1 | ||
| 86 | #define OP_count OP_bs + 1 | ||
| 87 | #define OP_seek OP_count + 1 | ||
| 88 | #define OP_skip OP_seek + 1 | ||
| 89 | #define OP_if OP_skip + 1 | ||
| 90 | #define OP_of OP_if + 1 | ||
| 91 | #define OP_ibs OP_of + ENABLE_FEATURE_DD_IBS_OBS | ||
| 92 | #define OP_obs OP_ibs + ENABLE_FEATURE_DD_IBS_OBS | ||
| 93 | #define OP_conv OP_obs + ENABLE_FEATURE_DD_IBS_OBS | ||
| 94 | #define OP_conv_notrunc OP_conv + ENABLE_FEATURE_DD_IBS_OBS | ||
| 95 | #define OP_conv_sync OP_conv_notrunc + ENABLE_FEATURE_DD_IBS_OBS | ||
| 96 | #define OP_conv_noerror OP_conv_sync + ENABLE_FEATURE_DD_IBS_OBS | ||
| 97 | |||
| 62 | int flags = trunc_flag; | 98 | int flags = trunc_flag; |
| 63 | size_t oc = 0, ibs = 512, obs = 512; | 99 | size_t oc = 0, ibs = 512, obs = 512; |
| 64 | ssize_t n, w; | 100 | ssize_t n, w; |
| 65 | off_t seek = 0, skip = 0, count = OFF_T_MAX; | 101 | off_t seek = 0, skip = 0, count = OFF_T_MAX; |
| 66 | int oflag, ifd, ofd; | 102 | int ifd, ofd; |
| 67 | const char *infile = NULL, *outfile = NULL; | 103 | const char *infile = NULL, *outfile = NULL; |
| 68 | char *ibuf, *obuf; | 104 | char *ibuf, *obuf; |
| 69 | 105 | ||
| @@ -78,63 +114,96 @@ int dd_main(int argc, char **argv) | |||
| 78 | } | 114 | } |
| 79 | 115 | ||
| 80 | for (n = 1; n < argc; n++) { | 116 | for (n = 1; n < argc; n++) { |
| 117 | smalluint key_len, what; | ||
| 118 | char *key; | ||
| 81 | char *arg = argv[n]; | 119 | char *arg = argv[n]; |
| 120 | |||
| 121 | //XXX:FIXME: we reject plain "dd --" This would cost ~20 bytes, so.. | ||
| 122 | //if (*arg == '-' && *++arg == '-' && !*++arg) continue; | ||
| 123 | key = strstr(arg, "="); | ||
| 124 | if (key == NULL) | ||
| 125 | bb_show_usage(); | ||
| 126 | key_len = key - arg + 1; | ||
| 127 | key = xstrndup(arg, key_len); | ||
| 128 | what = index_in_str_array(keywords, key) + 1; | ||
| 129 | if (ENABLE_FEATURE_CLEAN_UP) | ||
| 130 | free(key); | ||
| 131 | if (what == 0) | ||
| 132 | bb_show_usage(); | ||
| 133 | arg += key_len; | ||
| 82 | /* Must fit into positive ssize_t */ | 134 | /* Must fit into positive ssize_t */ |
| 83 | if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("ibs=", arg, 4)) | 135 | if (ENABLE_FEATURE_DD_IBS_OBS) { |
| 84 | ibs = xatoul_range_sfx(arg+4, 0, ((size_t)-1L)/2, dd_suffixes); | 136 | if (what == OP_ibs) { |
| 85 | else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("obs=", arg, 4)) | 137 | ibs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); |
| 86 | obs = xatoul_range_sfx(arg+4, 0, ((size_t)-1L)/2, dd_suffixes); | 138 | continue; |
| 87 | else if (!strncmp("bs=", arg, 3)) | 139 | } |
| 88 | ibs = obs = xatoul_range_sfx(arg+3, 0, ((size_t)-1L)/2, dd_suffixes); | 140 | if (what == OP_obs) { |
| 89 | /* These can be large: */ | 141 | obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); |
| 90 | else if (!strncmp("count=", arg, 6)) | 142 | continue; |
| 91 | count = XATOU_SFX(arg+6, dd_suffixes); | 143 | } |
| 92 | else if (!strncmp("seek=", arg, 5)) | 144 | if (what == OP_conv) { |
| 93 | seek = XATOU_SFX(arg+5, dd_suffixes); | 145 | while (1) { |
| 94 | else if (!strncmp("skip=", arg, 5)) | 146 | /* find ',', replace them with nil so we can use arg for |
| 95 | skip = XATOU_SFX(arg+5, dd_suffixes); | 147 | * index_in_str_array without copying. |
| 96 | 148 | * We rely on arg being non-null, else strstr would fault. | |
| 97 | else if (!strncmp("if=", arg, 3)) | 149 | */ |
| 98 | infile = arg+3; | 150 | key = strstr(arg, ","); |
| 99 | else if (!strncmp("of=", arg, 3)) | 151 | if (key) |
| 100 | outfile = arg+3; | 152 | *key = '\0'; |
| 101 | else if (ENABLE_FEATURE_DD_IBS_OBS && !strncmp("conv=", arg, 5)) { | 153 | what = index_in_str_array(keywords, arg) + 1; |
| 102 | arg += 5; | 154 | if (what < OP_conv_notrunc) |
| 103 | while (1) { | 155 | bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv"); |
| 104 | if (!strncmp("notrunc", arg, 7)) { | 156 | if (what == OP_conv_notrunc) |
| 105 | flags &= ~trunc_flag; | 157 | flags &= ~trunc_flag; |
| 106 | arg += 7; | 158 | if (what == OP_conv_sync) |
| 107 | } else if (!strncmp("sync", arg, 4)) { | 159 | flags |= sync_flag; |
| 108 | flags |= sync_flag; | 160 | if (what == OP_conv_noerror) |
| 109 | arg += 4; | 161 | flags |= noerror; |
| 110 | } else if (!strncmp("noerror", arg, 7)) { | 162 | if (!key) /* no ',' left, so this was the last specifier */ |
| 111 | flags |= noerror; | 163 | break; |
| 112 | arg += 7; | 164 | arg += key - arg + 1; /* skip this keyword plus ',' */ |
| 113 | } else { | ||
| 114 | bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv"); | ||
| 115 | } | 165 | } |
| 116 | if (arg[0] == '\0') break; | 166 | continue; |
| 117 | if (*arg++ != ',') bb_show_usage(); | ||
| 118 | } | 167 | } |
| 119 | } else | 168 | } |
| 120 | bb_show_usage(); | 169 | if (what == OP_bs) { |
| 170 | ibs = obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); | ||
| 171 | continue; | ||
| 172 | } | ||
| 173 | /* These can be large: */ | ||
| 174 | if (what == OP_count) { | ||
| 175 | count = XATOU_SFX(arg, dd_suffixes); | ||
| 176 | continue; | ||
| 177 | } | ||
| 178 | if (what == OP_seek) { | ||
| 179 | seek = XATOU_SFX(arg, dd_suffixes); | ||
| 180 | continue; | ||
| 181 | } | ||
| 182 | if (what == skip) { | ||
| 183 | skip = XATOU_SFX(arg, dd_suffixes); | ||
| 184 | continue; | ||
| 185 | } | ||
| 186 | if (what == OP_if) { | ||
| 187 | infile = arg; | ||
| 188 | continue; | ||
| 189 | } | ||
| 190 | if (what == OP_of) | ||
| 191 | outfile = arg; | ||
| 121 | } | 192 | } |
| 122 | 193 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | |
| 123 | ibuf = obuf = xmalloc(ibs); | 194 | ibuf = obuf = xmalloc(ibs); |
| 124 | if (ibs != obs) { | 195 | if (ibs != obs) { |
| 125 | flags |= twobufs_flag; | 196 | flags |= twobufs_flag; |
| 126 | obuf = xmalloc(obs); | 197 | obuf = xmalloc(obs); |
| 127 | } | 198 | } |
| 128 | |||
| 129 | if (infile != NULL) | 199 | if (infile != NULL) |
| 130 | ifd = xopen(infile, O_RDONLY); | 200 | ifd = xopen(infile, O_RDONLY); |
| 131 | else { | 201 | else { |
| 132 | ifd = STDIN_FILENO; | 202 | ifd = STDIN_FILENO; |
| 133 | infile = bb_msg_standard_input; | 203 | infile = bb_msg_standard_input; |
| 134 | } | 204 | } |
| 135 | |||
| 136 | if (outfile != NULL) { | 205 | if (outfile != NULL) { |
| 137 | oflag = O_WRONLY | O_CREAT; | 206 | int oflag = O_WRONLY | O_CREAT; |
| 138 | 207 | ||
| 139 | if (!seek && (flags & trunc_flag)) | 208 | if (!seek && (flags & trunc_flag)) |
| 140 | oflag |= O_TRUNC; | 209 | oflag |= O_TRUNC; |
| @@ -154,30 +223,25 @@ int dd_main(int argc, char **argv) | |||
| 154 | ofd = STDOUT_FILENO; | 223 | ofd = STDOUT_FILENO; |
| 155 | outfile = bb_msg_standard_output; | 224 | outfile = bb_msg_standard_output; |
| 156 | } | 225 | } |
| 157 | |||
| 158 | if (skip) { | 226 | if (skip) { |
| 159 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { | 227 | if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { |
| 160 | while (skip-- > 0) { | 228 | while (skip-- > 0) { |
| 161 | n = safe_read(ifd, ibuf, ibs); | 229 | n = safe_read(ifd, ibuf, ibs); |
| 162 | if (n < 0) | 230 | if (n < 0) |
| 163 | bb_perror_msg_and_die("%s", infile); | 231 | goto die_infile; |
| 164 | if (n == 0) | 232 | if (n == 0) |
| 165 | break; | 233 | break; |
| 166 | } | 234 | } |
| 167 | } | 235 | } |
| 168 | } | 236 | } |
| 169 | |||
| 170 | if (seek) { | 237 | if (seek) { |
| 171 | if (lseek(ofd, seek * obs, SEEK_CUR) < 0) | 238 | if (lseek(ofd, seek * obs, SEEK_CUR) < 0) |
| 172 | goto die_outfile; | 239 | goto die_outfile; |
| 173 | } | 240 | } |
| 174 | 241 | ||
| 175 | while (in_full + in_part != count) { | 242 | while (G.in_full + G.in_part != count) { |
| 176 | if (flags & noerror) { | 243 | if (flags & noerror) /* Pre-zero the buffer when for noerror */ |
| 177 | /* Pre-zero the buffer when doing the noerror thing */ | ||
| 178 | memset(ibuf, '\0', ibs); | 244 | memset(ibuf, '\0', ibs); |
| 179 | } | ||
| 180 | |||
| 181 | n = safe_read(ifd, ibuf, ibs); | 245 | n = safe_read(ifd, ibuf, ibs); |
| 182 | if (n == 0) | 246 | if (n == 0) |
| 183 | break; | 247 | break; |
| @@ -186,12 +250,12 @@ int dd_main(int argc, char **argv) | |||
| 186 | n = ibs; | 250 | n = ibs; |
| 187 | bb_perror_msg("%s", infile); | 251 | bb_perror_msg("%s", infile); |
| 188 | } else | 252 | } else |
| 189 | bb_perror_msg_and_die("%s", infile); | 253 | goto die_infile; |
| 190 | } | 254 | } |
| 191 | if ((size_t)n == ibs) | 255 | if ((size_t)n == ibs) |
| 192 | in_full++; | 256 | G.in_full++; |
| 193 | else { | 257 | else { |
| 194 | in_part++; | 258 | G.in_part++; |
| 195 | if (flags & sync_flag) { | 259 | if (flags & sync_flag) { |
| 196 | memset(ibuf + n, '\0', ibs - n); | 260 | memset(ibuf + n, '\0', ibs - n); |
| 197 | n = ibs; | 261 | n = ibs; |
| @@ -209,40 +273,32 @@ int dd_main(int argc, char **argv) | |||
| 209 | tmp += d; | 273 | tmp += d; |
| 210 | oc += d; | 274 | oc += d; |
| 211 | if (oc == obs) { | 275 | if (oc == obs) { |
| 212 | w = full_write_or_warn(ofd, obuf, obs, outfile); | 276 | if (write_and_stats(ofd, obuf, obs, obs, outfile)) |
| 213 | if (w < 0) goto out_status; | 277 | goto out_status; |
| 214 | if (w == obs) | ||
| 215 | out_full++; | ||
| 216 | else if (w > 0) | ||
| 217 | out_part++; | ||
| 218 | oc = 0; | 278 | oc = 0; |
| 219 | } | 279 | } |
| 220 | } | 280 | } |
| 221 | } else { | 281 | } else |
| 222 | w = full_write_or_warn(ofd, ibuf, n, outfile); | 282 | if (write_and_stats(ofd, ibuf, n, obs, outfile)) |
| 223 | if (w < 0) goto out_status; | 283 | goto out_status; |
| 224 | if (w == obs) | ||
| 225 | out_full++; | ||
| 226 | else if (w > 0) | ||
| 227 | out_part++; | ||
| 228 | } | ||
| 229 | } | 284 | } |
| 230 | 285 | ||
| 231 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { | 286 | if (ENABLE_FEATURE_DD_IBS_OBS && oc) { |
| 232 | w = full_write_or_warn(ofd, obuf, oc, outfile); | 287 | w = full_write_or_warn(ofd, obuf, oc, outfile); |
| 233 | if (w < 0) goto out_status; | 288 | if (w < 0) goto out_status; |
| 234 | if (w > 0) | 289 | if (w > 0) |
| 235 | out_part++; | 290 | G.out_part++; |
| 236 | } | 291 | } |
| 237 | if (close(ifd) < 0) { | 292 | if (close(ifd) < 0) { |
| 293 | die_infile: | ||
| 238 | bb_perror_msg_and_die("%s", infile); | 294 | bb_perror_msg_and_die("%s", infile); |
| 239 | } | 295 | } |
| 240 | 296 | ||
| 241 | if (close(ofd) < 0) { | 297 | if (close(ofd) < 0) { |
| 242 | die_outfile: | 298 | die_outfile: |
| 243 | bb_perror_msg_and_die("%s", outfile); | 299 | bb_perror_msg_and_die("%s", outfile); |
| 244 | } | 300 | } |
| 245 | out_status: | 301 | out_status: |
| 246 | dd_output_status(0); | 302 | dd_output_status(0); |
| 247 | 303 | ||
| 248 | return EXIT_SUCCESS; | 304 | return EXIT_SUCCESS; |
