diff options
author | aldot <aldot@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-04 14:01:23 +0000 |
---|---|---|
committer | aldot <aldot@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-04 14:01:23 +0000 |
commit | e7afc91560feabfaf16db9bc5e30661cd6ecf0c0 (patch) | |
tree | aa59c9f272cdc8883516460fcf7874352dde1f51 | |
parent | 5063ac0a267b08feab2573bb6e5796b94145adfd (diff) | |
download | busybox-w32-e7afc91560feabfaf16db9bc5e30661cd6ecf0c0.tar.gz busybox-w32-e7afc91560feabfaf16db9bc5e30661cd6ecf0c0.tar.bz2 busybox-w32-e7afc91560feabfaf16db9bc5e30661cd6ecf0c0.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
git-svn-id: svn://busybox.net/trunk/busybox@18322 69ca8d6d-28ef-0310-b511-8ec308f3f277
-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; |