aboutsummaryrefslogtreecommitdiff
path: root/coreutils/dd.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-07-27 15:02:00 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-07-27 15:02:00 +0000
commit75878706174290fbf5faac0215b3b9ae78fa9d6f (patch)
tree91bc2115d527c840803bec00c4b1aa6b9ffdbef8 /coreutils/dd.c
parent1d10aaf11617558592b0215fe85bc42fa444e384 (diff)
downloadbusybox-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.c85
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
36static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal) 39static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal)
37{ 40{
@@ -73,10 +76,11 @@ int dd_main(int argc, char **argv);
73int dd_main(int argc, char **argv) 76int 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;