busybox: backport dd conv=swab from 1.22
[openwrt.git] / package / utils / busybox / patches / 008-backport-dd-conv-swab.patch
1 --- a/coreutils/dd.c
2 +++ b/coreutils/dd.c
3 @@ -10,7 +10,7 @@
4  
5  //usage:#define dd_trivial_usage
6  //usage:       "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n"
7 -//usage:       "       [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]")
8 +//usage:       "       [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync|swab]")
9  //usage:#define dd_full_usage "\n\n"
10  //usage:       "Copy a file with converting and formatting\n"
11  //usage:     "\n       if=FILE         Read from FILE instead of stdin"
12 @@ -30,6 +30,7 @@
13  //usage:     "\n       conv=noerror    Continue after read errors"
14  //usage:     "\n       conv=sync       Pad blocks with zeros"
15  //usage:     "\n       conv=fsync      Physically write data out before finishing"
16 +//usage:     "\n       conv=swab       Swap every pair of bytes"
17  //usage:       )
18  //usage:     "\n"
19  //usage:     "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),"
20 @@ -155,9 +156,10 @@ int dd_main(int argc UNUSED_PARAM, char
21                 FLAG_SYNC    = 1 << 1,
22                 FLAG_NOERROR = 1 << 2,
23                 FLAG_FSYNC   = 1 << 3,
24 +               FLAG_SWAB    = 1 << 4,
25                 /* end of conv flags */
26 -               FLAG_TWOBUFS = 1 << 4,
27 -               FLAG_COUNT   = 1 << 5,
28 +               FLAG_TWOBUFS = 1 << 5,
29 +               FLAG_COUNT   = 1 << 6,
30         };
31         static const char keywords[] ALIGN1 =
32                 "bs\0""count\0""seek\0""skip\0""if\0""of\0"
33 @@ -167,7 +169,7 @@ int dd_main(int argc UNUSED_PARAM, char
34                 ;
35  #if ENABLE_FEATURE_DD_IBS_OBS
36         static const char conv_words[] ALIGN1 =
37 -               "notrunc\0""sync\0""noerror\0""fsync\0";
38 +               "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
39  #endif
40         enum {
41                 OP_bs = 0,
42 @@ -185,11 +187,11 @@ int dd_main(int argc UNUSED_PARAM, char
43                 OP_conv_sync,
44                 OP_conv_noerror,
45                 OP_conv_fsync,
46 +               OP_conv_swab,
47         /* Unimplemented conv=XXX: */
48         //nocreat       do not create the output file
49         //excl          fail if the output file already exists
50         //fdatasync     physically write output file data before finishing
51 -       //swab          swap every pair of input bytes
52         //lcase         change upper case to lower case
53         //ucase         change lower case to upper case
54         //block         pad newline-terminated records with spaces to cbs-size
55 @@ -207,12 +209,14 @@ int dd_main(int argc UNUSED_PARAM, char
56         struct {
57                 int flags;
58                 size_t oc;
59 +               ssize_t prev_read_size; /* for detecting swab failure */
60                 off_t count;
61                 off_t seek, skip;
62                 const char *infile, *outfile;
63         } Z;
64  #define flags   (Z.flags  )
65  #define oc      (Z.oc     )
66 +#define prev_read_size (Z.prev_read_size)
67  #define count   (Z.count  )
68  #define seek    (Z.seek   )
69  #define skip    (Z.skip   )
70 @@ -375,6 +379,27 @@ int dd_main(int argc UNUSED_PARAM, char
71                          * conv=noerror just ignores input bad blocks */
72                         n = 0;
73                 }
74 +               if (flags & FLAG_SWAB) {
75 +                       uint16_t *p16;
76 +                       ssize_t n2;
77 +
78 +                       /* Our code allows only last read to be odd-sized */
79 +                       if (prev_read_size & 1)
80 +                               bb_error_msg_and_die("can't swab %lu byte buffer",
81 +                                               (unsigned long)prev_read_size);
82 +                       prev_read_size = n;
83 +
84 +                       /* If n is odd, last byte is not swapped:
85 +                        *  echo -n "qwe" | dd conv=swab
86 +                        * prints "wqe".
87 +                        */
88 +                       p16 = (void*) ibuf;
89 +                       n2 = (n >> 1);
90 +                       while (--n2 >= 0) {
91 +                               *p16 = bswap_16(*p16);
92 +                               p16++;
93 +                       }
94 +               }
95                 if ((size_t)n == ibs)
96                         G.in_full++;
97                 else {