aboutsummaryrefslogtreecommitdiffstats
path: root/package/utils/busybox/patches/008-backport-dd-conv-swab.patch
blob: 1e3cd15c93f92aafce6611c496b6726310e09bfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
--- 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 {