summaryrefslogtreecommitdiff
path: root/coreutils/dd.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2013-08-27 16:10:53 +0100
committerRon Yorston <rmy@pobox.com>2013-08-27 16:10:53 +0100
commit3fd34651ea72ea1c335d3170f234cb0517fd897f (patch)
tree36e8fc40cffd464ffda4759020777dd3ca23ca31 /coreutils/dd.c
parente3ac39098326de084a805d0dd31db9666b734f20 (diff)
parentd6ae4fb446daedfe3073d67be655942e9fa7eb18 (diff)
downloadbusybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.gz
busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.tar.bz2
busybox-w32-3fd34651ea72ea1c335d3170f234cb0517fd897f.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'coreutils/dd.c')
-rw-r--r--coreutils/dd.c115
1 files changed, 78 insertions, 37 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c
index f6869cb26..db61f665e 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -30,10 +30,10 @@
30//usage: "\n conv=noerror Continue after read errors" 30//usage: "\n conv=noerror Continue after read errors"
31//usage: "\n conv=sync Pad blocks with zeros" 31//usage: "\n conv=sync Pad blocks with zeros"
32//usage: "\n conv=fsync Physically write data out before finishing" 32//usage: "\n conv=fsync Physically write data out before finishing"
33//usage: "\n conv=swab Swap every pair of bytes"
33//usage: ) 34//usage: )
34//usage: "\n" 35//usage: "\n"
35//usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024)," 36//usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G"
36//usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)"
37//usage: 37//usage:
38//usage:#define dd_example_usage 38//usage:#define dd_example_usage
39//usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" 39//usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n"
@@ -151,13 +151,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
151 enum { 151 enum {
152 /* Must be in the same order as OP_conv_XXX! */ 152 /* Must be in the same order as OP_conv_XXX! */
153 /* (see "flags |= (1 << what)" below) */ 153 /* (see "flags |= (1 << what)" below) */
154 FLAG_NOTRUNC = 1 << 0, 154 FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS,
155 FLAG_SYNC = 1 << 1, 155 FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS,
156 FLAG_NOERROR = 1 << 2, 156 FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS,
157 FLAG_FSYNC = 1 << 3, 157 FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS,
158 FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS,
158 /* end of conv flags */ 159 /* end of conv flags */
159 FLAG_TWOBUFS = 1 << 4, 160 FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
160 FLAG_COUNT = 1 << 5, 161 FLAG_COUNT = 1 << 6,
161 }; 162 };
162 static const char keywords[] ALIGN1 = 163 static const char keywords[] ALIGN1 =
163 "bs\0""count\0""seek\0""skip\0""if\0""of\0" 164 "bs\0""count\0""seek\0""skip\0""if\0""of\0"
@@ -167,7 +168,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
167 ; 168 ;
168#if ENABLE_FEATURE_DD_IBS_OBS 169#if ENABLE_FEATURE_DD_IBS_OBS
169 static const char conv_words[] ALIGN1 = 170 static const char conv_words[] ALIGN1 =
170 "notrunc\0""sync\0""noerror\0""fsync\0"; 171 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
171#endif 172#endif
172 enum { 173 enum {
173 OP_bs = 0, 174 OP_bs = 0,
@@ -185,11 +186,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
185 OP_conv_sync, 186 OP_conv_sync,
186 OP_conv_noerror, 187 OP_conv_noerror,
187 OP_conv_fsync, 188 OP_conv_fsync,
189 OP_conv_swab,
188 /* Unimplemented conv=XXX: */ 190 /* Unimplemented conv=XXX: */
189 //nocreat do not create the output file 191 //nocreat do not create the output file
190 //excl fail if the output file already exists 192 //excl fail if the output file already exists
191 //fdatasync physically write output file data before finishing 193 //fdatasync physically write output file data before finishing
192 //swab swap every pair of input bytes
193 //lcase change upper case to lower case 194 //lcase change upper case to lower case
194 //ucase change lower case to upper case 195 //ucase change lower case to upper case
195 //block pad newline-terminated records with spaces to cbs-size 196 //block pad newline-terminated records with spaces to cbs-size
@@ -197,23 +198,34 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
197 //ascii from EBCDIC to ASCII 198 //ascii from EBCDIC to ASCII
198 //ebcdic from ASCII to EBCDIC 199 //ebcdic from ASCII to EBCDIC
199 //ibm from ASCII to alternate EBCDIC 200 //ibm from ASCII to alternate EBCDIC
201 /* Partially implemented: */
202 //swab swap every pair of input bytes: will abort on non-even reads
200#endif 203#endif
201 }; 204 };
202 int exitcode = EXIT_FAILURE; 205 smallint exitcode = EXIT_FAILURE;
203 int devzero = 0; 206 int devzero = 0;
204 size_t ibs = 512, obs = 512; 207 int i;
205 ssize_t n, w; 208 size_t ibs = 512;
206 char *ibuf, *obuf; 209 char *ibuf;
207 /* And these are all zeroed at once! */ 210#if ENABLE_FEATURE_DD_IBS_OBS
211 size_t obs = 512;
212 char *obuf;
213#else
214# define obs ibs
215# define obuf ibuf
216#endif
217 /* These are all zeroed at once! */
208 struct { 218 struct {
209 int flags; 219 int flags;
210 size_t oc; 220 size_t oc;
221 ssize_t prev_read_size; /* for detecting swab failure */
211 off_t count; 222 off_t count;
212 off_t seek, skip; 223 off_t seek, skip;
213 const char *infile, *outfile; 224 const char *infile, *outfile;
214 } Z; 225 } Z;
215#define flags (Z.flags ) 226#define flags (Z.flags )
216#define oc (Z.oc ) 227#define oc (Z.oc )
228#define prev_read_size (Z.prev_read_size)
217#define count (Z.count ) 229#define count (Z.count )
218#define seek (Z.seek ) 230#define seek (Z.seek )
219#define skip (Z.skip ) 231#define skip (Z.skip )
@@ -224,10 +236,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
224 INIT_G(); 236 INIT_G();
225 //fflush_all(); - is this needed because of NOEXEC? 237 //fflush_all(); - is this needed because of NOEXEC?
226 238
227 for (n = 1; argv[n]; n++) { 239 for (i = 1; argv[i]; i++) {
228 int what; 240 int what;
229 char *val; 241 char *val;
230 char *arg = argv[n]; 242 char *arg = argv[i];
231 243
232#if ENABLE_DESKTOP 244#if ENABLE_DESKTOP
233 /* "dd --". NB: coreutils 6.9 will complain if they see 245 /* "dd --". NB: coreutils 6.9 will complain if they see
@@ -256,6 +268,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
256 } 268 }
257 if (what == OP_conv) { 269 if (what == OP_conv) {
258 while (1) { 270 while (1) {
271 int n;
259 /* find ',', replace them with NUL so we can use val for 272 /* find ',', replace them with NUL so we can use val for
260 * index_in_strings() without copying. 273 * index_in_strings() without copying.
261 * We rely on val being non-null, else strchr would fault. 274 * We rely on val being non-null, else strchr would fault.
@@ -263,20 +276,21 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
263 arg = strchr(val, ','); 276 arg = strchr(val, ',');
264 if (arg) 277 if (arg)
265 *arg = '\0'; 278 *arg = '\0';
266 what = index_in_strings(conv_words, val); 279 n = index_in_strings(conv_words, val);
267 if (what < 0) 280 if (n < 0)
268 bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); 281 bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv");
269 flags |= (1 << what); 282 flags |= (1 << n);
270 if (!arg) /* no ',' left, so this was the last specifier */ 283 if (!arg) /* no ',' left, so this was the last specifier */
271 break; 284 break;
272 /* *arg = ','; - to preserve ps listing? */ 285 /* *arg = ','; - to preserve ps listing? */
273 val = arg + 1; /* skip this keyword and ',' */ 286 val = arg + 1; /* skip this keyword and ',' */
274 } 287 }
275 continue; /* we trashed 'what', can't fall through */ 288 /*continue;*/
276 } 289 }
277#endif 290#endif
278 if (what == OP_bs) { 291 if (what == OP_bs) {
279 ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); 292 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes);
293 obs = ibs;
280 /*continue;*/ 294 /*continue;*/
281 } 295 }
282 /* These can be large: */ 296 /* These can be large: */
@@ -301,14 +315,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
301 outfile = val; 315 outfile = val;
302 /*continue;*/ 316 /*continue;*/
303 } 317 }
304 } /* end of "for (argv[n])" */ 318 } /* end of "for (argv[i])" */
305 319
306//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever 320//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
307 ibuf = obuf = xmalloc(ibs); 321 ibuf = xmalloc(ibs);
322 obuf = ibuf;
323#if ENABLE_FEATURE_DD_IBS_OBS
308 if (ibs != obs) { 324 if (ibs != obs) {
309 flags |= FLAG_TWOBUFS; 325 flags |= FLAG_TWOBUFS;
310 obuf = xmalloc(obs); 326 obuf = xmalloc(obs);
311 } 327 }
328#endif
312 329
313#if ENABLE_FEATURE_DD_SIGNAL_HANDLING 330#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
314 signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); 331 signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status);
@@ -317,17 +334,17 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
317 G.begin_time_us = monotonic_us(); 334 G.begin_time_us = monotonic_us();
318#endif 335#endif
319 336
320 if (infile != NULL) 337 if (infile) {
321 if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) { 338 if (ENABLE_PLATFORM_MINGW32 && !strcmp(infile, "/dev/zero")) {
322 flags |= FLAG_NOERROR; 339 flags |= FLAG_NOERROR;
323 devzero = 1; 340 devzero = 1;
324 } 341 } else {
325 else
326 xmove_fd(xopen(infile, O_RDONLY), ifd); 342 xmove_fd(xopen(infile, O_RDONLY), ifd);
327 else { 343 }
344 } else {
328 infile = bb_msg_standard_input; 345 infile = bb_msg_standard_input;
329 } 346 }
330 if (outfile != NULL) { 347 if (outfile) {
331 int oflag = O_WRONLY | O_CREAT; 348 int oflag = O_WRONLY | O_CREAT;
332 349
333 if (!seek && !(flags & FLAG_NOTRUNC)) 350 if (!seek && !(flags & FLAG_NOTRUNC))
@@ -352,13 +369,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
352 } 369 }
353 if (skip && !devzero) { 370 if (skip && !devzero) {
354 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { 371 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
355 while (skip-- > 0) { 372 do {
356 n = safe_read(ifd, ibuf, ibs); 373 ssize_t n = safe_read(ifd, ibuf, ibs);
357 if (n < 0) 374 if (n < 0)
358 goto die_infile; 375 goto die_infile;
359 if (n == 0) 376 if (n == 0)
360 break; 377 break;
361 } 378 } while (--skip != 0);
362 } 379 }
363 } 380 }
364 if (seek) { 381 if (seek) {
@@ -367,6 +384,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
367 } 384 }
368 385
369 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { 386 while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
387 ssize_t n;
388
370 if (devzero) { 389 if (devzero) {
371 memset(ibuf, 0, ibs); 390 memset(ibuf, 0, ibs);
372 n = ibs; 391 n = ibs;
@@ -386,6 +405,27 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
386 * conv=noerror just ignores input bad blocks */ 405 * conv=noerror just ignores input bad blocks */
387 n = 0; 406 n = 0;
388 } 407 }
408 if (flags & FLAG_SWAB) {
409 uint16_t *p16;
410 ssize_t n2;
411
412 /* Our code allows only last read to be odd-sized */
413 if (prev_read_size & 1)
414 bb_error_msg_and_die("can't swab %lu byte buffer",
415 (unsigned long)prev_read_size);
416 prev_read_size = n;
417
418 /* If n is odd, last byte is not swapped:
419 * echo -n "qwe" | dd conv=swab
420 * prints "wqe".
421 */
422 p16 = (void*) ibuf;
423 n2 = (n >> 1);
424 while (--n2 >= 0) {
425 *p16 = bswap_16(*p16);
426 p16++;
427 }
428 }
389 if ((size_t)n == ibs) 429 if ((size_t)n == ibs)
390 G.in_full++; 430 G.in_full++;
391 else { 431 else {
@@ -412,8 +452,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
412 oc = 0; 452 oc = 0;
413 } 453 }
414 } 454 }
415 } else if (write_and_stats(ibuf, n, obs, outfile)) 455 } else {
416 goto out_status; 456 if (write_and_stats(ibuf, n, obs, outfile))
457 goto out_status;
458 }
417 459
418 if (flags & FLAG_FSYNC) { 460 if (flags & FLAG_FSYNC) {
419 if (fsync(ofd) < 0) 461 if (fsync(ofd) < 0)
@@ -422,9 +464,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
422 } 464 }
423 465
424 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 466 if (ENABLE_FEATURE_DD_IBS_OBS && oc) {
425 w = full_write_or_warn(obuf, oc, outfile); 467 if (write_and_stats(obuf, oc, obs, outfile))
426 if (w < 0) goto out_status; 468 goto out_status;
427 if (w > 0) G.out_part++;
428 } 469 }
429 470
430 if (!devzero && close(ifd) < 0) { 471 if (!devzero && close(ifd) < 0) {