You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/package/utils/busybox/patches/008-backport-dd-conv-swab.p...

98 lines
3.2 KiB
Diff

--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -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|swab]")
//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,7 @@
//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 conv=swab Swap every pair of bytes"
//usage: )
//usage: "\n"
//usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),"
@@ -155,9 +156,10 @@ int dd_main(int argc UNUSED_PARAM, char
FLAG_SYNC = 1 << 1,
FLAG_NOERROR = 1 << 2,
FLAG_FSYNC = 1 << 3,
+ FLAG_SWAB = 1 << 4,
/* end of conv flags */
- FLAG_TWOBUFS = 1 << 4,
- FLAG_COUNT = 1 << 5,
+ FLAG_TWOBUFS = 1 << 5,
+ FLAG_COUNT = 1 << 6,
};
static const char keywords[] ALIGN1 =
"bs\0""count\0""seek\0""skip\0""if\0""of\0"
@@ -167,7 +169,7 @@ int dd_main(int argc UNUSED_PARAM, char
;
#if ENABLE_FEATURE_DD_IBS_OBS
static const char conv_words[] ALIGN1 =
- "notrunc\0""sync\0""noerror\0""fsync\0";
+ "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
#endif
enum {
OP_bs = 0,
@@ -185,11 +187,11 @@ int dd_main(int argc UNUSED_PARAM, char
OP_conv_sync,
OP_conv_noerror,
OP_conv_fsync,
+ OP_conv_swab,
/* Unimplemented conv=XXX: */
//nocreat do not create the output file
//excl fail if the output file already exists
//fdatasync physically write output file data before finishing
- //swab swap every pair of input bytes
//lcase change upper case to lower case
//ucase change lower case to upper case
//block pad newline-terminated records with spaces to cbs-size
@@ -207,12 +209,14 @@ int dd_main(int argc UNUSED_PARAM, char
struct {
int flags;
size_t oc;
+ ssize_t prev_read_size; /* for detecting swab failure */
off_t count;
off_t seek, skip;
const char *infile, *outfile;
} Z;
#define flags (Z.flags )
#define oc (Z.oc )
+#define prev_read_size (Z.prev_read_size)
#define count (Z.count )
#define seek (Z.seek )
#define skip (Z.skip )
@@ -375,6 +379,27 @@ int dd_main(int argc UNUSED_PARAM, char
* conv=noerror just ignores input bad blocks */
n = 0;
}
+ if (flags & FLAG_SWAB) {
+ uint16_t *p16;
+ ssize_t n2;
+
+ /* Our code allows only last read to be odd-sized */
+ if (prev_read_size & 1)
+ bb_error_msg_and_die("can't swab %lu byte buffer",
+ (unsigned long)prev_read_size);
+ prev_read_size = n;
+
+ /* If n is odd, last byte is not swapped:
+ * echo -n "qwe" | dd conv=swab
+ * prints "wqe".
+ */
+ p16 = (void*) ibuf;
+ n2 = (n >> 1);
+ while (--n2 >= 0) {
+ *p16 = bswap_16(*p16);
+ p16++;
+ }
+ }
if ((size_t)n == ibs)
G.in_full++;
else {