aboutsummaryrefslogtreecommitdiff
path: root/coreutils/dd.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-02-22 10:00:45 +0000
committerRon Yorston <rmy@pobox.com>2016-02-22 10:00:45 +0000
commit371c20c008254a36e7157df6c13dc2e4cf87d6fd (patch)
treea214c03f6617dffa60df2192b312a46c93b7c19f /coreutils/dd.c
parentab879a41ab674129ef1593cda181cc8b64d0dadf (diff)
parent3a5cc989025eefe03fda0552b253a4a8f015a761 (diff)
downloadbusybox-w32-371c20c008254a36e7157df6c13dc2e4cf87d6fd.tar.gz
busybox-w32-371c20c008254a36e7157df6c13dc2e4cf87d6fd.tar.bz2
busybox-w32-371c20c008254a36e7157df6c13dc2e4cf87d6fd.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'coreutils/dd.c')
-rw-r--r--coreutils/dd.c78
1 files changed, 51 insertions, 27 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c
index ccb91f69d..7bd3e2084 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -55,7 +55,7 @@
55 55
56//usage:#define dd_trivial_usage 56//usage:#define dd_trivial_usage
57//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" 57//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n"
58//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") 58//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes]")
59//usage:#define dd_full_usage "\n\n" 59//usage:#define dd_full_usage "\n\n"
60//usage: "Copy a file with converting and formatting\n" 60//usage: "Copy a file with converting and formatting\n"
61//usage: "\n if=FILE Read from FILE instead of stdin" 61//usage: "\n if=FILE Read from FILE instead of stdin"
@@ -76,6 +76,7 @@
76//usage: "\n conv=sync Pad blocks with zeros" 76//usage: "\n conv=sync Pad blocks with zeros"
77//usage: "\n conv=fsync Physically write data out before finishing" 77//usage: "\n conv=fsync Physically write data out before finishing"
78//usage: "\n conv=swab Swap every pair of bytes" 78//usage: "\n conv=swab Swap every pair of bytes"
79//usage: "\n iflag=skip_bytes skip=N is in bytes"
79//usage: ) 80//usage: )
80//usage: IF_FEATURE_DD_STATUS( 81//usage: IF_FEATURE_DD_STATUS(
81//usage: "\n status=noxfer Suppress rate output" 82//usage: "\n status=noxfer Suppress rate output"
@@ -122,11 +123,15 @@ enum {
122 FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, 123 FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS,
123 FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, 124 FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS,
124 /* end of conv flags */ 125 /* end of conv flags */
125 FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 126 /* start of input flags */
126 FLAG_COUNT = 1 << 6, 127 FLAG_IFLAG_SHIFT = 5,
127 FLAG_STATUS = 1 << 7, 128 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
128 FLAG_STATUS_NONE = 1 << 7, 129 /* end of input flags */
129 FLAG_STATUS_NOXFER = 1 << 8, 130 FLAG_TWOBUFS = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
131 FLAG_COUNT = 1 << 7,
132 FLAG_STATUS = 1 << 8,
133 FLAG_STATUS_NONE = 1 << 9,
134 FLAG_STATUS_NOXFER = 1 << 10,
130}; 135};
131 136
132static void dd_output_status(int UNUSED_PARAM cur_signal) 137static void dd_output_status(int UNUSED_PARAM cur_signal)
@@ -203,18 +208,47 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
203# define XATOU_SFX xatoul_sfx 208# define XATOU_SFX xatoul_sfx
204#endif 209#endif
205 210
211#if ENABLE_FEATURE_DD_IBS_OBS
212static int parse_comma_flags(char *val, const char *words, const char *error_in)
213{
214 int flags = 0;
215 while (1) {
216 int n;
217 char *arg;
218 /* find ',', replace them with NUL so we can use val for
219 * index_in_strings() without copying.
220 * We rely on val being non-null, else strchr would fault.
221 */
222 arg = strchr(val, ',');
223 if (arg)
224 *arg = '\0';
225 n = index_in_strings(words, val);
226 if (n < 0)
227 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, error_in);
228 flags |= (1 << n);
229 if (!arg) /* no ',' left, so this was the last specifier */
230 break;
231 *arg = ','; /* to preserve ps listing */
232 val = arg + 1; /* skip this keyword and ',' */
233 }
234 return flags;
235}
236#endif
237
206int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 238int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
207int dd_main(int argc UNUSED_PARAM, char **argv) 239int dd_main(int argc UNUSED_PARAM, char **argv)
208{ 240{
209 static const char keywords[] ALIGN1 = 241 static const char keywords[] ALIGN1 =
210 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") 242 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0")
211#if ENABLE_FEATURE_DD_IBS_OBS 243#if ENABLE_FEATURE_DD_IBS_OBS
212 "ibs\0""obs\0""conv\0" 244 "ibs\0""obs\0""conv\0""iflag\0"
213#endif 245#endif
214 ; 246 ;
215#if ENABLE_FEATURE_DD_IBS_OBS 247#if ENABLE_FEATURE_DD_IBS_OBS
216 static const char conv_words[] ALIGN1 = 248 static const char conv_words[] ALIGN1 =
217 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 249 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
250 static const char iflag_words[] ALIGN1 =
251 "skip_bytes\0";
218#endif 252#endif
219#if ENABLE_FEATURE_DD_STATUS 253#if ENABLE_FEATURE_DD_STATUS
220 static const char status_words[] ALIGN1 = 254 static const char status_words[] ALIGN1 =
@@ -232,6 +266,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
232 OP_ibs, 266 OP_ibs,
233 OP_obs, 267 OP_obs,
234 OP_conv, 268 OP_conv,
269 OP_iflag,
235 /* Must be in the same order as FLAG_XXX! */ 270 /* Must be in the same order as FLAG_XXX! */
236 OP_conv_notrunc = 0, 271 OP_conv_notrunc = 0,
237 OP_conv_sync, 272 OP_conv_sync,
@@ -251,6 +286,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
251 //ibm from ASCII to alternate EBCDIC 286 //ibm from ASCII to alternate EBCDIC
252 /* Partially implemented: */ 287 /* Partially implemented: */
253 //swab swap every pair of input bytes: will abort on non-even reads 288 //swab swap every pair of input bytes: will abort on non-even reads
289 OP_iflag_skip_bytes,
254#endif 290#endif
255 }; 291 };
256 smallint exitcode = EXIT_FAILURE; 292 smallint exitcode = EXIT_FAILURE;
@@ -316,24 +352,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
316 /*continue;*/ 352 /*continue;*/
317 } 353 }
318 if (what == OP_conv) { 354 if (what == OP_conv) {
319 while (1) { 355 G.flags |= parse_comma_flags(val, conv_words, "conv");
320 int n; 356 /*continue;*/
321 /* find ',', replace them with NUL so we can use val for 357 }
322 * index_in_strings() without copying. 358 if (what == OP_iflag) {
323 * We rely on val being non-null, else strchr would fault. 359 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT;
324 */
325 arg = strchr(val, ',');
326 if (arg)
327 *arg = '\0';
328 n = index_in_strings(conv_words, val);
329 if (n < 0)
330 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, "conv");
331 G.flags |= (1 << n);
332 if (!arg) /* no ',' left, so this was the last specifier */
333 break;
334 /* *arg = ','; - to preserve ps listing? */
335 val = arg + 1; /* skip this keyword and ',' */
336 }
337 /*continue;*/ 360 /*continue;*/
338 } 361 }
339#endif 362#endif
@@ -427,9 +450,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
427 outfile = bb_msg_standard_output; 450 outfile = bb_msg_standard_output;
428 } 451 }
429 if (skip && !devzero) { 452 if (skip && !devzero) {
430 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { 453 size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs;
454 if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) {
431 do { 455 do {
432 ssize_t n = safe_read(ifd, ibuf, ibs); 456 ssize_t n = safe_read(ifd, ibuf, blocksz);
433 if (n < 0) 457 if (n < 0)
434 goto die_infile; 458 goto die_infile;
435 if (n == 0) 459 if (n == 0)