xxd: fix -p -r, closes 13881
function old new delta xxd_main 893 890 -3 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
d315a77a79
commit
86ba007b84
@ -31,4 +31,10 @@ testing 'xxd -p with 31 NULs' \
|
|||||||
'' \
|
'' \
|
||||||
'\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'
|
'\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'
|
||||||
|
|
||||||
|
testing 'xxd -p -r' \
|
||||||
|
'xxd -p -r' \
|
||||||
|
'01234567765432100123456776543210' \
|
||||||
|
'' \
|
||||||
|
'30313233343536373736353433323130 30313233343536373736353433323130'
|
||||||
|
|
||||||
exit $FAILCOUNT
|
exit $FAILCOUNT
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
#define OPT_c (1 << 7)
|
#define OPT_c (1 << 7)
|
||||||
#define OPT_o (1 << 8)
|
#define OPT_o (1 << 8)
|
||||||
|
|
||||||
static void reverse(unsigned opt, unsigned cols, const char *filename)
|
static void reverse(unsigned opt, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -77,9 +77,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
|
|||||||
fp = filename ? xfopen_for_read(filename) : stdin;
|
fp = filename ? xfopen_for_read(filename) : stdin;
|
||||||
|
|
||||||
while ((buf = xmalloc_fgetline(fp)) != NULL) {
|
while ((buf = xmalloc_fgetline(fp)) != NULL) {
|
||||||
char *p = buf;
|
char *p;
|
||||||
unsigned cnt = cols;
|
|
||||||
|
|
||||||
|
p = buf;
|
||||||
if (!(opt & OPT_p)) {
|
if (!(opt & OPT_p)) {
|
||||||
/* skip address */
|
/* skip address */
|
||||||
while (isxdigit(*p)) p++;
|
while (isxdigit(*p)) p++;
|
||||||
@ -92,9 +92,9 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Process hex bytes optionally separated by whitespace */
|
/* Process hex bytes optionally separated by whitespace */
|
||||||
do {
|
for (;;) {
|
||||||
uint8_t val, c;
|
uint8_t val, c;
|
||||||
|
nibble1:
|
||||||
p = skip_whitespace(p);
|
p = skip_whitespace(p);
|
||||||
|
|
||||||
c = *p++;
|
c = *p++;
|
||||||
@ -102,8 +102,19 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
|
|||||||
val = c - '0';
|
val = c - '0';
|
||||||
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
||||||
val = (c|0x20) - ('a' - 10);
|
val = (c|0x20) - ('a' - 10);
|
||||||
else
|
else {
|
||||||
|
/* xxd V1.10 is inconsistent here.
|
||||||
|
* echo -e "31 !3 0a 0a" | xxd -r -p
|
||||||
|
* is "10<a0>" (no <cr>) - "!" is ignored,
|
||||||
|
* but
|
||||||
|
* echo -e "31 !!343434\n30 0a" | xxd -r -p
|
||||||
|
* is "10<cr>" - "!!" drops rest of the line.
|
||||||
|
* We will ignore all invalid chars:
|
||||||
|
*/
|
||||||
|
if (c != '\0')
|
||||||
|
goto nibble1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
val <<= 4;
|
val <<= 4;
|
||||||
|
|
||||||
/* Works the same with xxd V1.10:
|
/* Works the same with xxd V1.10:
|
||||||
@ -111,6 +122,7 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
|
|||||||
* echo "31 0 9 32 0a" | xxd -r -p
|
* echo "31 0 9 32 0a" | xxd -r -p
|
||||||
* thus allow whitespace even within the byte:
|
* thus allow whitespace even within the byte:
|
||||||
*/
|
*/
|
||||||
|
nibble2:
|
||||||
p = skip_whitespace(p);
|
p = skip_whitespace(p);
|
||||||
|
|
||||||
c = *p++;
|
c = *p++;
|
||||||
@ -118,10 +130,23 @@ static void reverse(unsigned opt, unsigned cols, const char *filename)
|
|||||||
val |= c - '0';
|
val |= c - '0';
|
||||||
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
|
||||||
val |= (c|0x20) - ('a' - 10);
|
val |= (c|0x20) - ('a' - 10);
|
||||||
else
|
else {
|
||||||
|
if (c != '\0') {
|
||||||
|
/* "...3<not_hex_char>..." ignores both chars */
|
||||||
|
goto nibble1;
|
||||||
|
}
|
||||||
|
/* Nibbles can join even through newline:
|
||||||
|
* echo -e "31 3\n2 0a" | xxd -r -p
|
||||||
|
* is "12<cr>".
|
||||||
|
*/
|
||||||
|
free(buf);
|
||||||
|
p = buf = xmalloc_fgetline(fp);
|
||||||
|
if (!buf)
|
||||||
break;
|
break;
|
||||||
|
goto nibble2;
|
||||||
|
}
|
||||||
putchar(val);
|
putchar(val);
|
||||||
} while (!(opt & OPT_p) || --cnt != 0);
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
//fclose(fp);
|
//fclose(fp);
|
||||||
@ -174,6 +199,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
//BUGGY for /proc/version (unseekable?)
|
//BUGGY for /proc/version (unseekable?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt & OPT_r) {
|
||||||
|
reverse(opt, argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (opt & OPT_o) {
|
if (opt & OPT_o) {
|
||||||
/* -o accepts negative numbers too */
|
/* -o accepts negative numbers too */
|
||||||
dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0);
|
dumper->xxd_displayoff = xstrtoll(opt_o, /*base:*/ 0);
|
||||||
@ -194,10 +223,6 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: "
|
bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: "
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt & OPT_r) {
|
|
||||||
reverse(opt, cols, argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes < 1 || bytes >= cols) {
|
if (bytes < 1 || bytes >= cols) {
|
||||||
sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX"
|
sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "XX"
|
||||||
bb_dump_add(dumper, buf);
|
bb_dump_add(dumper, buf);
|
||||||
|
Loading…
Reference in New Issue
Block a user