aboutsummaryrefslogtreecommitdiff
path: root/coreutils/dd.c
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2016-02-01 02:17:28 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2016-02-01 02:17:28 +0100
commitc30a5b13731919367ec2d781a107706fd00f21bc (patch)
tree36491cc56ce6a8d7fa7ca0548212deb1e72f529e /coreutils/dd.c
parent40eea690c7eabbf4d12e1e0c30c31f40125ca996 (diff)
downloadbusybox-w32-c30a5b13731919367ec2d781a107706fd00f21bc.tar.gz
busybox-w32-c30a5b13731919367ec2d781a107706fd00f21bc.tar.bz2
busybox-w32-c30a5b13731919367ec2d781a107706fd00f21bc.zip
dd: support iflag=skip_bytes
It allows specifying amount of bytes directly (not only amount of blocks) is also supported by GNU's Coreutils. function old new delta parse_comma_flags - 93 +93 static.iflag_words - 12 +12 dd_main 1569 1580 +11 packed_usage 30591 30600 +9 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 2/0 up/down: 125/0) Total: 125 bytes Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
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 6a5288da1..0c0ea07b9 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;
@@ -315,24 +351,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
315 /*continue;*/ 351 /*continue;*/
316 } 352 }
317 if (what == OP_conv) { 353 if (what == OP_conv) {
318 while (1) { 354 G.flags |= parse_comma_flags(val, conv_words, "conv");
319 int n; 355 /*continue;*/
320 /* find ',', replace them with NUL so we can use val for 356 }
321 * index_in_strings() without copying. 357 if (what == OP_iflag) {
322 * We rely on val being non-null, else strchr would fault. 358 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT;
323 */
324 arg = strchr(val, ',');
325 if (arg)
326 *arg = '\0';
327 n = index_in_strings(conv_words, val);
328 if (n < 0)
329 bb_error_msg_and_die(bb_msg_invalid_arg_to, val, "conv");
330 G.flags |= (1 << n);
331 if (!arg) /* no ',' left, so this was the last specifier */
332 break;
333 /* *arg = ','; - to preserve ps listing? */
334 val = arg + 1; /* skip this keyword and ',' */
335 }
336 /*continue;*/ 359 /*continue;*/
337 } 360 }
338#endif 361#endif
@@ -421,9 +444,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
421 outfile = bb_msg_standard_output; 444 outfile = bb_msg_standard_output;
422 } 445 }
423 if (skip) { 446 if (skip) {
424 if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { 447 size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs;
448 if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) {
425 do { 449 do {
426 ssize_t n = safe_read(ifd, ibuf, ibs); 450 ssize_t n = safe_read(ifd, ibuf, blocksz);
427 if (n < 0) 451 if (n < 0)
428 goto die_infile; 452 goto die_infile;
429 if (n == 0) 453 if (n == 0)