diff -ru busybox-1.21.0.orig/coreutils/dd.c busybox-1.21.0/coreutils/dd.c
--- busybox-1.21.0.orig/coreutils/dd.c	2017-11-28 14:36:41.329460259 +0100
+++ busybox-1.21.0/coreutils/dd.c	2017-11-28 14:36:53.557566521 +0100
@@ -10,7 +10,7 @@
 
 //usage:#define dd_trivial_usage
 //usage:       "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n"
-//usage:       "	[seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]")
+//usage:       "	[seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes,count_bytes] [oflag=seek_bytes] |status=none/noxfer]")
 //usage:#define dd_full_usage "\n\n"
 //usage:       "Copy a file with converting and formatting\n"
 //usage:     "\n	if=FILE		Read from FILE instead of stdin"
@@ -30,6 +30,11 @@
 //usage:     "\n	conv=noerror	Continue after read errors"
 //usage:     "\n	conv=sync	Pad blocks with zeros"
 //usage:     "\n	conv=fsync	Physically write data out before finishing"
+//usage:     "\n	iflag=skip_bytes	skip=N is in bytes"
+//usage:     "\n	iflag=count_bytes	count=N is in bytes"
+//usage:     "\n	oflag=seek_bytes	seek=N is in bytes"
+//usage:     "\n	status=noxfer	Suppress rate output"
+//usage:     "\n	status=none	Suppress all output"
 //usage:	)
 //usage:     "\n"
 //usage:     "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),"
@@ -70,6 +75,7 @@
 	unsigned long long total_bytes;
 	unsigned long long begin_time_us;
 #endif
+	int flags;
 } FIX_ALIASING;
 #define G (*(struct globals*)&bb_common_bufsiz1)
 #define INIT_G() do { \
@@ -77,6 +83,32 @@
 	memset(&G, 0, sizeof(G)); \
 } while (0)
 
+enum {
+	/* Must be in the same order as OP_conv_XXX! */
+	/* (see "flags |= (1 << what)" below) */
+	FLAG_NOTRUNC = 1 << 0,
+	FLAG_SYNC    = 1 << 1,
+	FLAG_NOERROR = 1 << 2,
+	FLAG_FSYNC   = 1 << 3,
+	/* end of conv flags */
+
+	/* start of input flags */
+	FLAG_IFLAG_SHIFT = 5,
+	FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
+	FLAG_COUNT_BYTES = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
+	/* end of input flags */
+
+	/* start of output flags */
+	FLAG_OFLAG_SHIFT = 7,
+	FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
+	/* end of output flags */
+
+	FLAG_TWOBUFS = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
+	FLAG_COUNT   = 1 << 9,
+	FLAG_STATUS  = 1 << 10,
+	FLAG_STATUS_NONE = 1 << 11,
+	FLAG_STATUS_NOXFER = 1 << 12,
+};
 
 static void dd_output_status(int UNUSED_PARAM cur_signal)
 {
@@ -93,6 +125,9 @@
 			G.out_full, G.out_part);
 
 #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
+	if (G.flags & FLAG_STATUS_NOXFER) /* status=noxfer active? */
+		return;
+
 	fprintf(stderr, "%llu bytes (%sB) copied, ",
 			G.total_bytes,
 			/* show fractional digit, use suffixes */
@@ -139,6 +174,34 @@
 	return 0;
 }
 
+#if ENABLE_FEATURE_DD_IBS_OBS
+static int parse_comma_flags(char *val, const char *words, const char *error_in)
+{
+	int flags = 0;
+	while (1) {
+		int n;
+		char *arg;
+		/* find ',', replace them with NUL so we can use val for
+		 * index_in_strings() without copying.
+		 * We rely on val being non-null, else strchr would fault.
+		 */
+		arg = strchr(val, ',');
+		if (arg)
+			*arg = '\0';
+		n = index_in_strings(words, val);
+		if (n < 0)
+			bb_error_msg_and_die(bb_msg_invalid_arg, val, error_in);
+		flags |= (1 << n);
+		if (!arg) /* no ',' left, so this was the last specifier */
+			break;
+		/* *arg = ','; - to preserve ps listing? */
+		val = arg + 1; /* skip this keyword and ',' */
+	}
+	return flags;
+}
+#endif
+
+
 #if ENABLE_LFS
 # define XATOU_SFX xatoull_sfx
 #else
@@ -148,26 +211,21 @@
 int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int dd_main(int argc UNUSED_PARAM, char **argv)
 {
-	enum {
-		/* Must be in the same order as OP_conv_XXX! */
-		/* (see "flags |= (1 << what)" below) */
-		FLAG_NOTRUNC = 1 << 0,
-		FLAG_SYNC    = 1 << 1,
-		FLAG_NOERROR = 1 << 2,
-		FLAG_FSYNC   = 1 << 3,
-		/* end of conv flags */
-		FLAG_TWOBUFS = 1 << 4,
-		FLAG_COUNT   = 1 << 5,
-	};
 	static const char keywords[] ALIGN1 =
 		"bs\0""count\0""seek\0""skip\0""if\0""of\0"
 #if ENABLE_FEATURE_DD_IBS_OBS
-		"ibs\0""obs\0""conv\0"
+		"ibs\0""obs\0""conv\0""iflag\0""oflag\0""status\0"
 #endif
 		;
 #if ENABLE_FEATURE_DD_IBS_OBS
 	static const char conv_words[] ALIGN1 =
 		"notrunc\0""sync\0""noerror\0""fsync\0";
+	static const char iflag_words[] ALIGN1 =
+		"skip_bytes\0""count_bytes\0";
+	static const char oflag_words[] ALIGN1 =
+		"seek_bytes\0";
+	static const char status_words[] ALIGN1 =
+		"none\0""noxfer\0";
 #endif
 	enum {
 		OP_bs = 0,
@@ -180,6 +238,9 @@
 		OP_ibs,
 		OP_obs,
 		OP_conv,
+		OP_iflag,
+		OP_oflag,
+		OP_status,
 		/* Must be in the same order as FLAG_XXX! */
 		OP_conv_notrunc = 0,
 		OP_conv_sync,
@@ -197,6 +258,9 @@
 	//ascii         from EBCDIC to ASCII
 	//ebcdic        from ASCII to EBCDIC
 	//ibm           from ASCII to alternate EBCDIC
+		OP_iflag_skip_bytes,
+		OP_iflag_count_bytes,
+		OP_oflag_seek_bytes,
 #endif
 	};
 	int exitcode = EXIT_FAILURE;
@@ -205,13 +269,11 @@
 	char *ibuf, *obuf;
 	/* And these are all zeroed at once! */
 	struct {
-		int flags;
 		size_t oc;
 		off_t count;
 		off_t seek, skip;
 		const char *infile, *outfile;
 	} Z;
-#define flags   (Z.flags  )
 #define oc      (Z.oc     )
 #define count   (Z.count  )
 #define seek    (Z.seek   )
@@ -254,24 +316,18 @@
 			/*continue;*/
 		}
 		if (what == OP_conv) {
-			while (1) {
-				/* find ',', replace them with NUL so we can use val for
-				 * index_in_strings() without copying.
-				 * We rely on val being non-null, else strchr would fault.
-				 */
-				arg = strchr(val, ',');
-				if (arg)
-					*arg = '\0';
-				what = index_in_strings(conv_words, val);
-				if (what < 0)
-					bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv");
-				flags |= (1 << what);
-				if (!arg) /* no ',' left, so this was the last specifier */
-					break;
-				/* *arg = ','; - to preserve ps listing? */
-				val = arg + 1; /* skip this keyword and ',' */
-			}
-			continue; /* we trashed 'what', can't fall through */
+			G.flags |= parse_comma_flags(val, conv_words, "conv");
+			/*continue;*/
+		}
+		if (what == OP_iflag) {
+			G.flags |= parse_comma_flags(val, iflag_words, "iflag") <<
+				FLAG_IFLAG_SHIFT;
+			/*continue;*/
+		}
+		if (what == OP_oflag) {
+			G.flags |= parse_comma_flags(val, oflag_words, "oflag") <<
+				FLAG_OFLAG_SHIFT;
+			/*continue;*/
 		}
 #endif
 		if (what == OP_bs) {
@@ -280,7 +336,7 @@
 		}
 		/* These can be large: */
 		if (what == OP_count) {
-			flags |= FLAG_COUNT;
+			G.flags |= FLAG_COUNT;
 			count = XATOU_SFX(val, dd_suffixes);
 			/*continue;*/
 		}
@@ -300,12 +356,22 @@
 			outfile = val;
 			/*continue;*/
 		}
+#if ENABLE_FEATURE_DD_IBS_OBS
+		if (what == OP_status) {
+			int ni;
+			ni = index_in_strings(status_words, val);
+			if (ni < 0)
+				bb_error_msg_and_die(bb_msg_invalid_arg, val, "status");
+			G.flags |= FLAG_STATUS_NONE << ni;
+			/*continue;*/
+		}
+#endif
 	} /* end of "for (argv[n])" */
 
 //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever
 	ibuf = obuf = xmalloc(ibs);
 	if (ibs != obs) {
-		flags |= FLAG_TWOBUFS;
+		G.flags |= FLAG_TWOBUFS;
 		obuf = xmalloc(obs);
 	}
 
@@ -324,13 +390,16 @@
 	if (outfile != NULL) {
 		int oflag = O_WRONLY | O_CREAT;
 
-		if (!seek && !(flags & FLAG_NOTRUNC))
+		if (!seek && !(G.flags & FLAG_NOTRUNC))
 			oflag |= O_TRUNC;
 
 		xmove_fd(xopen(outfile, oflag), ofd);
 
-		if (seek && !(flags & FLAG_NOTRUNC)) {
-			if (ftruncate(ofd, seek * obs) < 0) {
+		if (seek && !(G.flags & FLAG_NOTRUNC)) {
+			size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
+			ssize_t trunc_size = seek * blocksz;
+
+			if (ftruncate(ofd, trunc_size) < 0) {
 				struct stat st;
 
 				if (fstat(ofd, &st) < 0
@@ -345,9 +414,10 @@
 		outfile = bb_msg_standard_output;
 	}
 	if (skip) {
-		if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) {
+		size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs;
+		if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) {
 			while (skip-- > 0) {
-				n = safe_read(ifd, ibuf, ibs);
+				n = safe_read(ifd, ibuf, blocksz);
 				if (n < 0)
 					goto die_infile;
 				if (n == 0)
@@ -356,17 +426,34 @@
 		}
 	}
 	if (seek) {
-		if (lseek(ofd, seek * obs, SEEK_CUR) < 0)
+		size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
+		if (lseek(ofd, seek * blocksz, SEEK_CUR) < 0)
 			goto die_outfile;
 	}
 
-	while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
-		n = safe_read(ifd, ibuf, ibs);
+	while (1) {
+		ssize_t to_read = ibs;
+
+		if (G.flags & FLAG_COUNT) {
+			if (!(G.flags & FLAG_COUNT_BYTES)) {
+				if ((G.in_full + G.in_part == count))
+					break;
+			} else {
+				if (count <= 0)
+					break;
+
+				if (to_read > count)
+					to_read = count;
+				count -= to_read;
+			}
+		}
+
+		n = safe_read(ifd, ibuf, to_read);
 		if (n == 0)
 			break;
 		if (n < 0) {
 			/* "Bad block" */
-			if (!(flags & FLAG_NOERROR))
+			if (!(G.flags & FLAG_NOERROR))
 				goto die_infile;
 			bb_simple_perror_msg(infile);
 			/* GNU dd with conv=noerror skips over bad blocks */
@@ -379,12 +466,12 @@
 			G.in_full++;
 		else {
 			G.in_part++;
-			if (flags & FLAG_SYNC) {
+			if (G.flags & FLAG_SYNC) {
 				memset(ibuf + n, 0, ibs - n);
 				n = ibs;
 			}
 		}
-		if (flags & FLAG_TWOBUFS) {
+		if (G.flags & FLAG_TWOBUFS) {
 			char *tmp = ibuf;
 			while (n) {
 				size_t d = obs - oc;
@@ -404,7 +491,7 @@
 		} else if (write_and_stats(ibuf, n, obs, outfile))
 			goto out_status;
 
-		if (flags & FLAG_FSYNC) {
+		if (G.flags & FLAG_FSYNC) {
 			if (fsync(ofd) < 0)
 				goto die_outfile;
 		}
@@ -427,11 +514,12 @@
 
 	exitcode = EXIT_SUCCESS;
  out_status:
-	dd_output_status(0);
+	if (!(G.flags & FLAG_STATUS_NONE))
+		dd_output_status(0);
 
 	if (ENABLE_FEATURE_CLEAN_UP) {
 		free(obuf);
-		if (flags & FLAG_TWOBUFS)
+		if (G.flags & FLAG_TWOBUFS)
 			free(ibuf);
 	}
 
