diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-08 23:03:54 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-08 23:03:54 +0200 |
commit | 86ba007b84ae1ebe35e88c57e023caac3d2d9903 (patch) | |
tree | 5e80e0d26c2cefec73ba7f2000adccca62641daf | |
parent | d315a77a79817d364a1562f4457c21fbb8174025 (diff) | |
download | busybox-w32-86ba007b84ae1ebe35e88c57e023caac3d2d9903.tar.gz busybox-w32-86ba007b84ae1ebe35e88c57e023caac3d2d9903.tar.bz2 busybox-w32-86ba007b84ae1ebe35e88c57e023caac3d2d9903.zip |
xxd: fix -p -r, closes 13881
function old new delta
xxd_main 893 890 -3
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rwxr-xr-x | testsuite/xxd.tests | 6 | ||||
-rw-r--r-- | util-linux/hexdump_xxd.c | 51 |
2 files changed, 44 insertions, 13 deletions
diff --git a/testsuite/xxd.tests b/testsuite/xxd.tests index 2e80be5fe..76fa96af9 100755 --- a/testsuite/xxd.tests +++ b/testsuite/xxd.tests | |||
@@ -31,4 +31,10 @@ testing 'xxd -p with 31 NULs' \ | |||
31 | '' \ | 31 | '' \ |
32 | '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' | 32 | '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0' |
33 | 33 | ||
34 | testing 'xxd -p -r' \ | ||
35 | 'xxd -p -r' \ | ||
36 | '01234567765432100123456776543210' \ | ||
37 | '' \ | ||
38 | '30313233343536373736353433323130 30313233343536373736353433323130' | ||
39 | |||
34 | exit $FAILCOUNT | 40 | exit $FAILCOUNT |
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index fe78f6242..76dada983 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c | |||
@@ -69,7 +69,7 @@ | |||
69 | #define OPT_c (1 << 7) | 69 | #define OPT_c (1 << 7) |
70 | #define OPT_o (1 << 8) | 70 | #define OPT_o (1 << 8) |
71 | 71 | ||
72 | static void reverse(unsigned opt, unsigned cols, const char *filename) | 72 | static void reverse(unsigned opt, const char *filename) |
73 | { | 73 | { |
74 | FILE *fp; | 74 | FILE *fp; |
75 | char *buf; | 75 | char *buf; |
@@ -77,9 +77,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
77 | fp = filename ? xfopen_for_read(filename) : stdin; | 77 | fp = filename ? xfopen_for_read(filename) : stdin; |
78 | 78 | ||
79 | while ((buf = xmalloc_fgetline(fp)) != NULL) { | 79 | while ((buf = xmalloc_fgetline(fp)) != NULL) { |
80 | char *p = buf; | 80 | char *p; |
81 | unsigned cnt = cols; | ||
82 | 81 | ||
82 | p = buf; | ||
83 | if (!(opt & OPT_p)) { | 83 | if (!(opt & OPT_p)) { |
84 | /* skip address */ | 84 | /* skip address */ |
85 | while (isxdigit(*p)) p++; | 85 | while (isxdigit(*p)) p++; |
@@ -92,9 +92,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | /* Process hex bytes optionally separated by whitespace */ | 94 | /* Process hex bytes optionally separated by whitespace */ |
95 | do { | 95 | for (;;) { |
96 | uint8_t val, c; | 96 | uint8_t val, c; |
97 | 97 | nibble1: | |
98 | p = skip_whitespace(p); | 98 | p = skip_whitespace(p); |
99 | 99 | ||
100 | c = *p++; | 100 | c = *p++; |
@@ -102,8 +102,19 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
102 | val = c - '0'; | 102 | val = c - '0'; |
103 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | 103 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') |
104 | val = (c|0x20) - ('a' - 10); | 104 | val = (c|0x20) - ('a' - 10); |
105 | else | 105 | else { |
106 | /* xxd V1.10 is inconsistent here. | ||
107 | * echo -e "31 !3 0a 0a" | xxd -r -p | ||
108 | * is "10<a0>" (no <cr>) - "!" is ignored, | ||
109 | * but | ||
110 | * echo -e "31 !!343434\n30 0a" | xxd -r -p | ||
111 | * is "10<cr>" - "!!" drops rest of the line. | ||
112 | * We will ignore all invalid chars: | ||
113 | */ | ||
114 | if (c != '\0') | ||
115 | goto nibble1; | ||
106 | break; | 116 | break; |
117 | } | ||
107 | val <<= 4; | 118 | val <<= 4; |
108 | 119 | ||
109 | /* Works the same with xxd V1.10: | 120 | /* Works the same with xxd V1.10: |
@@ -111,6 +122,7 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
111 | * echo "31 0 9 32 0a" | xxd -r -p | 122 | * echo "31 0 9 32 0a" | xxd -r -p |
112 | * thus allow whitespace even within the byte: | 123 | * thus allow whitespace even within the byte: |
113 | */ | 124 | */ |
125 | nibble2: | ||
114 | p = skip_whitespace(p); | 126 | p = skip_whitespace(p); |
115 | 127 | ||
116 | c = *p++; | 128 | c = *p++; |
@@ -118,10 +130,23 @@ static void reverse(unsigned opt, unsigned cols, const char *filename) | |||
118 | val |= c - '0'; | 130 | val |= c - '0'; |
119 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | 131 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') |
120 | val |= (c|0x20) - ('a' - 10); | 132 | val |= (c|0x20) - ('a' - 10); |
121 | else | 133 | else { |
122 | break; | 134 | if (c != '\0') { |
135 | /* "...3<not_hex_char>..." ignores both chars */ | ||
136 | goto nibble1; | ||
137 | } | ||
138 | /* Nibbles can join even through newline: | ||
139 | * echo -e "31 3\n2 0a" | xxd -r -p | ||
140 | * is "12<cr>". | ||
141 | */ | ||
142 | free(buf); | ||
143 | p = buf = xmalloc_fgetline(fp); | ||
144 | if (!buf) | ||
145 | break; | ||
146 | goto nibble2; | ||
147 | } | ||
123 | putchar(val); | 148 | putchar(val); |
124 | } while (!(opt & OPT_p) || --cnt != 0); | 149 | } |
125 | free(buf); | 150 | free(buf); |
126 | } | 151 | } |
127 | //fclose(fp); | 152 | //fclose(fp); |
@@ -174,6 +199,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
174 | //BUGGY for /proc/version (unseekable?) | 199 | //BUGGY for /proc/version (unseekable?) |
175 | } | 200 | } |
176 | 201 | ||
202 | if (opt & OPT_r) { | ||
203 | reverse(opt, argv[0]); | ||
204 | } | ||
205 | |||
177 | if (opt & OPT_o) { | 206 | if (opt & OPT_o) { |
178 | /* -o accepts negative numbers too */ | 207 | /* -o accepts negative numbers too */ |
179 | dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0); | 208 | dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0); |
@@ -194,10 +223,6 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
194 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " | 223 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " |
195 | } | 224 | } |
196 | 225 | ||
197 | if (opt & OPT_r) { | ||
198 | reverse(opt, cols, argv[0]); | ||
199 | } | ||
200 | |||
201 | if (bytes < 1 || bytes >= cols) { | 226 | if (bytes < 1 || bytes >= cols) { |
202 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX" | 227 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX" |
203 | bb_dump_add(dumper, buf); | 228 | bb_dump_add(dumper, buf); |