diff options
-rw-r--r-- | util-linux/hexdump.c | 61 | ||||
-rw-r--r-- | util-linux/hexdump_xxd.c | 76 |
2 files changed, 73 insertions, 64 deletions
diff --git a/util-linux/hexdump.c b/util-linux/hexdump.c index 065b83980..2174c3008 100644 --- a/util-linux/hexdump.c +++ b/util-linux/hexdump.c | |||
@@ -15,16 +15,6 @@ | |||
15 | //config: The hexdump utility is used to display binary data in a readable | 15 | //config: The hexdump utility is used to display binary data in a readable |
16 | //config: way that is comparable to the output from most hex editors. | 16 | //config: way that is comparable to the output from most hex editors. |
17 | //config: | 17 | //config: |
18 | //config:config FEATURE_HEXDUMP_REVERSE | ||
19 | //config: bool "Support -R, reverse of 'hexdump -Cv'" | ||
20 | //config: default y | ||
21 | //config: depends on HEXDUMP | ||
22 | //config: help | ||
23 | //config: The hexdump utility is used to display binary data in an ascii | ||
24 | //config: readable way. This option creates binary data from an ascii input. | ||
25 | //config: NB: this option is non-standard. It's unwise to use it in scripts | ||
26 | //config: aimed to be portable. | ||
27 | //config: | ||
28 | //config:config HD | 18 | //config:config HD |
29 | //config: bool "hd (7.8 kb)" | 19 | //config: bool "hd (7.8 kb)" |
30 | //config: default y | 20 | //config: default y |
@@ -38,7 +28,7 @@ | |||
38 | //kbuild:lib-$(CONFIG_HD) += hexdump.o | 28 | //kbuild:lib-$(CONFIG_HD) += hexdump.o |
39 | 29 | ||
40 | //usage:#define hexdump_trivial_usage | 30 | //usage:#define hexdump_trivial_usage |
41 | //usage: "[-bcCdefnosvx" IF_FEATURE_HEXDUMP_REVERSE("R") "] [FILE]..." | 31 | //usage: "[-bcCdefnosvx] [FILE]..." |
42 | //usage:#define hexdump_full_usage "\n\n" | 32 | //usage:#define hexdump_full_usage "\n\n" |
43 | //usage: "Display FILEs (or stdin) in a user specified format\n" | 33 | //usage: "Display FILEs (or stdin) in a user specified format\n" |
44 | //usage: "\n -b 1-byte octal display" | 34 | //usage: "\n -b 1-byte octal display" |
@@ -53,9 +43,6 @@ | |||
53 | // exactly the same help text lines in hexdump and xxd: | 43 | // exactly the same help text lines in hexdump and xxd: |
54 | //usage: "\n -n LENGTH Show only first LENGTH bytes" | 44 | //usage: "\n -n LENGTH Show only first LENGTH bytes" |
55 | //usage: "\n -s OFFSET Skip OFFSET bytes" | 45 | //usage: "\n -s OFFSET Skip OFFSET bytes" |
56 | //usage: IF_FEATURE_HEXDUMP_REVERSE( | ||
57 | //usage: "\n -R Reverse of 'hexdump -Cv'") | ||
58 | // TODO: NONCOMPAT!!! move -R to xxd -r | ||
59 | //usage: | 46 | //usage: |
60 | //usage:#define hd_trivial_usage | 47 | //usage:#define hd_trivial_usage |
61 | //usage: "FILE..." | 48 | //usage: "FILE..." |
@@ -94,7 +81,7 @@ static const char *const add_strings[] = { | |||
94 | 81 | ||
95 | static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; | 82 | static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\""; |
96 | 83 | ||
97 | static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v" IF_FEATURE_HEXDUMP_REVERSE("R"); | 84 | static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v"; |
98 | 85 | ||
99 | int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 86 | int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
100 | int hexdump_main(int argc, char **argv) | 87 | int hexdump_main(int argc, char **argv) |
@@ -102,10 +89,6 @@ int hexdump_main(int argc, char **argv) | |||
102 | dumper_t *dumper = alloc_dumper(); | 89 | dumper_t *dumper = alloc_dumper(); |
103 | const char *p; | 90 | const char *p; |
104 | int ch; | 91 | int ch; |
105 | #if ENABLE_FEATURE_HEXDUMP_REVERSE | ||
106 | FILE *fp; | ||
107 | smallint rdump = 0; | ||
108 | #endif | ||
109 | 92 | ||
110 | if (ENABLE_HD | 93 | if (ENABLE_HD |
111 | && (!ENABLE_HEXDUMP || !applet_name[2]) | 94 | && (!ENABLE_HEXDUMP || !applet_name[2]) |
@@ -153,11 +136,6 @@ int hexdump_main(int argc, char **argv) | |||
153 | if (ch == 'v') { | 136 | if (ch == 'v') { |
154 | dumper->dump_vflag = ALL; | 137 | dumper->dump_vflag = ALL; |
155 | } | 138 | } |
156 | #if ENABLE_FEATURE_HEXDUMP_REVERSE | ||
157 | if (ch == 'R') { | ||
158 | rdump = 1; | ||
159 | } | ||
160 | #endif | ||
161 | } | 139 | } |
162 | 140 | ||
163 | if (!dumper->fshead) { | 141 | if (!dumper->fshead) { |
@@ -167,40 +145,5 @@ int hexdump_main(int argc, char **argv) | |||
167 | 145 | ||
168 | argv += optind; | 146 | argv += optind; |
169 | 147 | ||
170 | #if !ENABLE_FEATURE_HEXDUMP_REVERSE | ||
171 | return bb_dump_dump(dumper, argv); | 148 | return bb_dump_dump(dumper, argv); |
172 | #else | ||
173 | if (!rdump) { | ||
174 | return bb_dump_dump(dumper, argv); | ||
175 | } | ||
176 | |||
177 | /* -R: reverse of 'hexdump -Cv' */ | ||
178 | fp = stdin; | ||
179 | if (!*argv) { | ||
180 | argv--; | ||
181 | goto jump_in; | ||
182 | } | ||
183 | |||
184 | do { | ||
185 | char *buf; | ||
186 | fp = xfopen_for_read(*argv); | ||
187 | jump_in: | ||
188 | while ((buf = xmalloc_fgetline(fp)) != NULL) { | ||
189 | p = buf; | ||
190 | while (1) { | ||
191 | /* skip address or previous byte */ | ||
192 | while (isxdigit(*p)) p++; | ||
193 | while (*p == ' ') p++; | ||
194 | /* '|' char will break the line */ | ||
195 | if (!isxdigit(*p) || sscanf(p, "%x ", &ch) != 1) | ||
196 | break; | ||
197 | putchar(ch); | ||
198 | } | ||
199 | free(buf); | ||
200 | } | ||
201 | fclose(fp); | ||
202 | } while (*++argv); | ||
203 | |||
204 | fflush_stdout_and_exit(EXIT_SUCCESS); | ||
205 | #endif | ||
206 | } | 149 | } |
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c index f2d1ecb2c..d2f4b6ed8 100644 --- a/util-linux/hexdump_xxd.c +++ b/util-linux/hexdump_xxd.c | |||
@@ -50,6 +50,7 @@ | |||
50 | // exactly the same help text lines in hexdump and xxd: | 50 | // exactly the same help text lines in hexdump and xxd: |
51 | //usage: "\n -l LENGTH Show only first LENGTH bytes" | 51 | //usage: "\n -l LENGTH Show only first LENGTH bytes" |
52 | //usage: "\n -s OFFSET Skip OFFSET bytes" | 52 | //usage: "\n -s OFFSET Skip OFFSET bytes" |
53 | //usage: "\n -r Reverse (with -p, assumes no offsets in input)" | ||
53 | // TODO: implement -r (see hexdump -R) | 54 | // TODO: implement -r (see hexdump -R) |
54 | 55 | ||
55 | #include "libbb.h" | 56 | #include "libbb.h" |
@@ -57,6 +58,71 @@ | |||
57 | 58 | ||
58 | /* This is a NOEXEC applet. Be very careful! */ | 59 | /* This is a NOEXEC applet. Be very careful! */ |
59 | 60 | ||
61 | #define OPT_l (1 << 0) | ||
62 | #define OPT_s (1 << 1) | ||
63 | #define OPT_a (1 << 2) | ||
64 | #define OPT_p (1 << 3) | ||
65 | #define OPT_r (1 << 4) | ||
66 | |||
67 | static void reverse(unsigned opt, unsigned cols, const char *filename) | ||
68 | { | ||
69 | FILE *fp; | ||
70 | char *buf; | ||
71 | |||
72 | fp = filename ? xfopen_for_read(filename) : stdin; | ||
73 | |||
74 | while ((buf = xmalloc_fgetline(fp)) != NULL) { | ||
75 | char *p = buf; | ||
76 | unsigned cnt = cols; | ||
77 | |||
78 | if (!(opt & OPT_p)) { | ||
79 | /* skip address */ | ||
80 | while (isxdigit(*p)) p++; | ||
81 | /* NB: for xxd -r, first hex portion is address even without colon */ | ||
82 | /* If it's there, skip it: */ | ||
83 | if (*p == ':') p++; | ||
84 | |||
85 | //TODO: seek (or zero-pad if unseekable) to the address position | ||
86 | //NOTE: -s SEEK value should be added to the address before seeking | ||
87 | } | ||
88 | |||
89 | /* Process hex bytes optionally separated by whitespace */ | ||
90 | do { | ||
91 | uint8_t val, c; | ||
92 | |||
93 | p = skip_whitespace(p); | ||
94 | |||
95 | c = *p++; | ||
96 | if (isdigit(c)) | ||
97 | val = c - '0'; | ||
98 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | ||
99 | val = (c|0x20) - ('a' - 10); | ||
100 | else | ||
101 | break; | ||
102 | val <<= 4; | ||
103 | |||
104 | /* Works the same with xxd V1.10: | ||
105 | * echo "31 09 32 0a" | xxd -r -p | ||
106 | * echo "31 0 9 32 0a" | xxd -r -p | ||
107 | * thus allow whitespace even within the byte: | ||
108 | */ | ||
109 | p = skip_whitespace(p); | ||
110 | |||
111 | c = *p++; | ||
112 | if (isdigit(c)) | ||
113 | val |= c - '0'; | ||
114 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') | ||
115 | val |= (c|0x20) - ('a' - 10); | ||
116 | else | ||
117 | break; | ||
118 | putchar(val); | ||
119 | } while (!(opt & OPT_p) || --cnt != 0); | ||
120 | free(buf); | ||
121 | } | ||
122 | //fclose(fp); | ||
123 | fflush_stdout_and_exit(EXIT_SUCCESS); | ||
124 | } | ||
125 | |||
60 | int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 126 | int xxd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
61 | int xxd_main(int argc UNUSED_PARAM, char **argv) | 127 | int xxd_main(int argc UNUSED_PARAM, char **argv) |
62 | { | 128 | { |
@@ -69,11 +135,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
69 | 135 | ||
70 | dumper = alloc_dumper(); | 136 | dumper = alloc_dumper(); |
71 | 137 | ||
72 | #define OPT_l (1 << 0) | 138 | opt = getopt32(argv, "^" "l:s:aprg:+c:+" "\0" "?1" /* 1 argument max */, |
73 | #define OPT_s (1 << 1) | ||
74 | #define OPT_a (1 << 2) | ||
75 | #define OPT_p (1 << 3) | ||
76 | opt = getopt32(argv, "^" "l:s:apg:+c:+" "\0" "?1" /* 1 argument max */, | ||
77 | &opt_l, &opt_s, &bytes, &cols | 139 | &opt_l, &opt_s, &bytes, &cols |
78 | ); | 140 | ); |
79 | argv += optind; | 141 | argv += optind; |
@@ -107,6 +169,10 @@ int xxd_main(int argc UNUSED_PARAM, char **argv) | |||
107 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " | 169 | bb_dump_add(dumper, "\"%08.8_ax: \""); // "address: " |
108 | } | 170 | } |
109 | 171 | ||
172 | if (opt & OPT_r) { | ||
173 | reverse(opt, cols, argv[0]); | ||
174 | } | ||
175 | |||
110 | if (bytes < 1 || bytes >= cols) { | 176 | if (bytes < 1 || bytes >= cols) { |
111 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx" | 177 | sprintf(buf, "%u/1 \"%%02x\"", cols); // cols * "xx" |
112 | bb_dump_add(dumper, buf); | 178 | bb_dump_add(dumper, buf); |