diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-27 15:02:00 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-07-27 15:02:00 +0000 |
commit | 75878706174290fbf5faac0215b3b9ae78fa9d6f (patch) | |
tree | 91bc2115d527c840803bec00c4b1aa6b9ffdbef8 /coreutils/dd.c | |
parent | 1d10aaf11617558592b0215fe85bc42fa444e384 (diff) | |
download | busybox-w32-75878706174290fbf5faac0215b3b9ae78fa9d6f.tar.gz busybox-w32-75878706174290fbf5faac0215b3b9ae78fa9d6f.tar.bz2 busybox-w32-75878706174290fbf5faac0215b3b9ae78fa9d6f.zip |
dd: fix bug where we assume count=INT_MAX when count is unspecified;
shrink dd while at it
function old new delta
dd_main 1453 1368 -85
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-85) Total: -85 bytes
text data bss dec hex filename
669216 2668 13616 685500 a75bc busybox_old
669128 2668 13616 685412 a7564 busybox_unstripped
Diffstat (limited to 'coreutils/dd.c')
-rw-r--r-- | coreutils/dd.c | 85 |
1 files changed, 53 insertions, 32 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c index 22ad19287..75cf3732e 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c | |||
@@ -32,6 +32,9 @@ struct globals { | |||
32 | off_t out_full, out_part, in_full, in_part; | 32 | off_t out_full, out_part, in_full, in_part; |
33 | }; | 33 | }; |
34 | #define G (*(struct globals*)&bb_common_bufsiz1) | 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 | |||
35 | 38 | ||
36 | static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal) | 39 | static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal) |
37 | { | 40 | { |
@@ -73,10 +76,11 @@ int dd_main(int argc, char **argv); | |||
73 | int dd_main(int argc, char **argv) | 76 | int dd_main(int argc, char **argv) |
74 | { | 77 | { |
75 | enum { | 78 | enum { |
76 | SYNC_FLAG = 1 << 0, | 79 | FLAG_SYNC = 1 << 0, |
77 | NOERROR = 1 << 1, | 80 | FLAG_NOERROR = 1 << 1, |
78 | TRUNC_FLAG = 1 << 2, | 81 | FLAG_NOTRUNC = 1 << 2, |
79 | TWOBUFS_FLAG = 1 << 3, | 82 | FLAG_TWOBUFS = 1 << 3, |
83 | FLAG_COUNT = 1 << 4, | ||
80 | }; | 84 | }; |
81 | static const char keywords[] = | 85 | static const char keywords[] = |
82 | "bs=\0""count=\0""seek=\0""skip=\0""if=\0""of=\0" | 86 | "bs=\0""count=\0""seek=\0""skip=\0""if=\0""of=\0" |
@@ -100,25 +104,41 @@ int dd_main(int argc, char **argv) | |||
100 | OP_conv_noerror, | 104 | OP_conv_noerror, |
101 | #endif | 105 | #endif |
102 | }; | 106 | }; |
103 | int flags = TRUNC_FLAG; | 107 | size_t ibs = 512, obs = 512; |
104 | size_t oc = 0, ibs = 512, obs = 512; | ||
105 | ssize_t n, w; | 108 | ssize_t n, w; |
106 | off_t seek = 0, skip = 0, count = OFF_T_MAX; | ||
107 | int ifd, ofd; | ||
108 | const char *infile = NULL, *outfile = NULL; | ||
109 | char *ibuf, *obuf; | 109 | char *ibuf, *obuf; |
110 | /* And these are all zeroed at once! */ | ||
111 | struct { | ||
112 | int flags; | ||
113 | int ifd, ofd; | ||
114 | size_t oc; | ||
115 | off_t count; | ||
116 | off_t seek, skip; | ||
117 | const char *infile, *outfile; | ||
118 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING | ||
119 | struct sigaction sigact; | ||
120 | #endif | ||
121 | } Z; | ||
122 | #define flags (Z.flags ) | ||
123 | #define ifd (Z.ifd ) | ||
124 | #define ofd (Z.ofd ) | ||
125 | #define oc (Z.oc ) | ||
126 | #define count (Z.count ) | ||
127 | #define seek (Z.seek ) | ||
128 | #define skip (Z.skip ) | ||
129 | #define infile (Z.infile ) | ||
130 | #define outfile (Z.outfile) | ||
131 | #define sigact (Z.sigact ) | ||
110 | 132 | ||
111 | memset(&G, 0, sizeof(G)); /* because of NOEXEC */ | 133 | memset(&Z, 0, sizeof(Z)); |
112 | 134 | INIT_G(); | |
113 | if (ENABLE_FEATURE_DD_SIGNAL_HANDLING) { | ||
114 | struct sigaction sa; | ||
115 | 135 | ||
116 | memset(&sa, 0, sizeof(sa)); | 136 | #if ENABLE_FEATURE_DD_SIGNAL_HANDLING |
117 | sa.sa_handler = dd_output_status; | 137 | sigact.sa_handler = dd_output_status; |
118 | sa.sa_flags = SA_RESTART; | 138 | sigact.sa_flags = SA_RESTART; |
119 | sigemptyset(&sa.sa_mask); | 139 | sigemptyset(&sigact.sa_mask); |
120 | sigaction(SIGUSR1, &sa, 0); | 140 | sigaction(SIGUSR1, &sigact, NULL); |
121 | } | 141 | #endif |
122 | 142 | ||
123 | for (n = 1; n < argc; n++) { | 143 | for (n = 1; n < argc; n++) { |
124 | smalluint key_len; | 144 | smalluint key_len; |
@@ -162,11 +182,11 @@ int dd_main(int argc, char **argv) | |||
162 | if (what < OP_conv_notrunc) | 182 | if (what < OP_conv_notrunc) |
163 | bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv"); | 183 | bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv"); |
164 | if (what == OP_conv_notrunc) | 184 | if (what == OP_conv_notrunc) |
165 | flags &= ~TRUNC_FLAG; | 185 | flags |= FLAG_NOTRUNC; |
166 | if (what == OP_conv_sync) | 186 | if (what == OP_conv_sync) |
167 | flags |= SYNC_FLAG; | 187 | flags |= FLAG_SYNC; |
168 | if (what == OP_conv_noerror) | 188 | if (what == OP_conv_noerror) |
169 | flags |= NOERROR; | 189 | flags |= FLAG_NOERROR; |
170 | if (!key) /* no ',' left, so this was the last specifier */ | 190 | if (!key) /* no ',' left, so this was the last specifier */ |
171 | break; | 191 | break; |
172 | arg = key + 1; /* skip this keyword and ',' */ | 192 | arg = key + 1; /* skip this keyword and ',' */ |
@@ -180,6 +200,7 @@ int dd_main(int argc, char **argv) | |||
180 | } | 200 | } |
181 | /* These can be large: */ | 201 | /* These can be large: */ |
182 | if (what == OP_count) { | 202 | if (what == OP_count) { |
203 | flags |= FLAG_COUNT; | ||
183 | count = XATOU_SFX(arg, dd_suffixes); | 204 | count = XATOU_SFX(arg, dd_suffixes); |
184 | continue; | 205 | continue; |
185 | } | 206 | } |
@@ -201,24 +222,24 @@ int dd_main(int argc, char **argv) | |||
201 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | 222 | //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever |
202 | ibuf = obuf = xmalloc(ibs); | 223 | ibuf = obuf = xmalloc(ibs); |
203 | if (ibs != obs) { | 224 | if (ibs != obs) { |
204 | flags |= TWOBUFS_FLAG; | 225 | flags |= FLAG_TWOBUFS; |
205 | obuf = xmalloc(obs); | 226 | obuf = xmalloc(obs); |
206 | } | 227 | } |
207 | if (infile != NULL) | 228 | if (infile != NULL) |
208 | ifd = xopen(infile, O_RDONLY); | 229 | ifd = xopen(infile, O_RDONLY); |
209 | else { | 230 | else { |
210 | ifd = STDIN_FILENO; | 231 | /* ifd = STDIN_FILENO; - it's zero and it's already there */ |
211 | infile = bb_msg_standard_input; | 232 | infile = bb_msg_standard_input; |
212 | } | 233 | } |
213 | if (outfile != NULL) { | 234 | if (outfile != NULL) { |
214 | int oflag = O_WRONLY | O_CREAT; | 235 | int oflag = O_WRONLY | O_CREAT; |
215 | 236 | ||
216 | if (!seek && (flags & TRUNC_FLAG)) | 237 | if (!seek && !(flags & FLAG_NOTRUNC)) |
217 | oflag |= O_TRUNC; | 238 | oflag |= O_TRUNC; |
218 | 239 | ||
219 | ofd = xopen(outfile, oflag); | 240 | ofd = xopen(outfile, oflag); |
220 | 241 | ||
221 | if (seek && (flags & TRUNC_FLAG)) { | 242 | if (seek && !(flags & FLAG_NOTRUNC)) { |
222 | if (ftruncate(ofd, seek * obs) < 0) { | 243 | if (ftruncate(ofd, seek * obs) < 0) { |
223 | struct stat st; | 244 | struct stat st; |
224 | 245 | ||
@@ -247,14 +268,14 @@ int dd_main(int argc, char **argv) | |||
247 | goto die_outfile; | 268 | goto die_outfile; |
248 | } | 269 | } |
249 | 270 | ||
250 | while (G.in_full + G.in_part != count) { | 271 | while ((flags & FLAG_COUNT) && (G.in_full + G.in_part != count)) { |
251 | if (flags & NOERROR) /* Pre-zero the buffer when for NOERROR */ | 272 | if (flags & FLAG_NOERROR) /* Pre-zero the buffer if conv=noerror */ |
252 | memset(ibuf, '\0', ibs); | 273 | memset(ibuf, 0, ibs); |
253 | n = safe_read(ifd, ibuf, ibs); | 274 | n = safe_read(ifd, ibuf, ibs); |
254 | if (n == 0) | 275 | if (n == 0) |
255 | break; | 276 | break; |
256 | if (n < 0) { | 277 | if (n < 0) { |
257 | if (flags & NOERROR) { | 278 | if (flags & FLAG_NOERROR) { |
258 | n = ibs; | 279 | n = ibs; |
259 | bb_perror_msg("%s", infile); | 280 | bb_perror_msg("%s", infile); |
260 | } else | 281 | } else |
@@ -264,12 +285,12 @@ int dd_main(int argc, char **argv) | |||
264 | G.in_full++; | 285 | G.in_full++; |
265 | else { | 286 | else { |
266 | G.in_part++; | 287 | G.in_part++; |
267 | if (flags & SYNC_FLAG) { | 288 | if (flags & FLAG_SYNC) { |
268 | memset(ibuf + n, '\0', ibs - n); | 289 | memset(ibuf + n, '\0', ibs - n); |
269 | n = ibs; | 290 | n = ibs; |
270 | } | 291 | } |
271 | } | 292 | } |
272 | if (flags & TWOBUFS_FLAG) { | 293 | if (flags & FLAG_TWOBUFS) { |
273 | char *tmp = ibuf; | 294 | char *tmp = ibuf; |
274 | while (n) { | 295 | while (n) { |
275 | size_t d = obs - oc; | 296 | size_t d = obs - oc; |