aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2022-08-22 17:28:43 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2022-08-22 17:28:43 +0200
commit5eceafb1f812ec4dca7fdf6896cfcea6783a78b9 (patch)
treeac965162ebc73f32e188a6fe84f57ac23c2b533e
parent0011a6bc2024ec4ee6d8edea203524e758d67833 (diff)
downloadbusybox-w32-5eceafb1f812ec4dca7fdf6896cfcea6783a78b9.tar.gz
busybox-w32-5eceafb1f812ec4dca7fdf6896cfcea6783a78b9.tar.bz2
busybox-w32-5eceafb1f812ec4dca7fdf6896cfcea6783a78b9.zip
xxd -r: handle offsets
function old new delta xxd_main 1076 1439 +363 .rodata 105239 105251 +12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 375/0) Total: 375 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--util-linux/hexdump_xxd.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/util-linux/hexdump_xxd.c b/util-linux/hexdump_xxd.c
index dbda34bc5..6629407de 100644
--- a/util-linux/hexdump_xxd.c
+++ b/util-linux/hexdump_xxd.c
@@ -55,6 +55,7 @@
55//usage: "\n -r Reverse (with -p, assumes no offsets in input)" 55//usage: "\n -r Reverse (with -p, assumes no offsets in input)"
56 56
57#include "libbb.h" 57#include "libbb.h"
58#include "common_bufsiz.h"
58#include "dump.h" 59#include "dump.h"
59 60
60/* This is a NOEXEC applet. Be very careful! */ 61/* This is a NOEXEC applet. Be very careful! */
@@ -69,10 +70,32 @@
69#define OPT_c (1 << 7) 70#define OPT_c (1 << 7)
70#define OPT_o (1 << 8) 71#define OPT_o (1 << 8)
71 72
72static void reverse(unsigned opt, const char *filename) 73#define fillbuf bb_common_bufsiz1
74
75static void write_zeros(off_t count)
76{
77 errno = 0;
78 do {
79 unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE;
80 if (fwrite(fillbuf, 1, sz, stdout) != sz)
81 bb_perror_msg_and_die("write error");
82 count -= sz;
83 } while (count != 0);
84}
85
86static void reverse(unsigned opt, const char *filename, char *opt_s)
73{ 87{
74 FILE *fp; 88 FILE *fp;
75 char *buf; 89 char *buf;
90 off_t cur, opt_s_ofs;
91
92 memset(fillbuf, 0, COMMON_BUFSIZE);
93 opt_s_ofs = cur = 0;
94 if (opt_s) {
95 opt_s_ofs = BB_STRTOOFF(opt_s, NULL, 0);
96 if (errno || opt_s_ofs < 0)
97 bb_error_msg_and_die("invalid number '%s'", opt_s);
98 }
76 99
77 fp = filename ? xfopen_for_read(filename) : stdin; 100 fp = filename ? xfopen_for_read(filename) : stdin;
78 101
@@ -82,15 +105,31 @@ static void reverse(unsigned opt, const char *filename)
82 105
83 p = buf; 106 p = buf;
84 if (!(opt & OPT_p)) { 107 if (!(opt & OPT_p)) {
108 char *end;
109 off_t ofs;
85 skip_address: 110 skip_address:
86 p = skip_whitespace(p); 111 p = skip_whitespace(p);
87 while (isxdigit(*p)) p++; 112 ofs = BB_STRTOOFF(p, &end, 16);
113 if ((errno && errno != EINVAL)
114 || ofs < 0
115 /* -s SEEK value should be added before seeking */
116 || (ofs += opt_s_ofs) < 0
117 ) {
118 bb_error_msg_and_die("invalid number '%s'", p);
119 }
120 if (ofs != cur) {
121 if (fseeko(stdout, ofs, SEEK_SET) != 0) {
122 if (ofs < cur)
123 bb_perror_msg_and_die("cannot seek");
124 write_zeros(ofs - cur);
125 }
126 cur = ofs;
127 }
128 p = end;
88 /* NB: for xxd -r, first hex portion is address even without colon */ 129 /* NB: for xxd -r, first hex portion is address even without colon */
89 /* If it's there, skip it: */ 130 /* But if colon is there, skip it: */
90 if (*p == ':') p++; 131 if (*p == ':')
91 132 p++;
92//TODO: seek (or zero-pad if unseekable) to the address position
93//NOTE: -s SEEK value should be added to the address before seeking
94 } 133 }
95 134
96 /* Process hex bytes optionally separated by whitespace */ 135 /* Process hex bytes optionally separated by whitespace */
@@ -168,6 +207,7 @@ static void reverse(unsigned opt, const char *filename)
168 goto nibble2; 207 goto nibble2;
169 } 208 }
170 putchar(val); 209 putchar(val);
210 cur++;
171 } /* for(;;) */ 211 } /* for(;;) */
172 free(buf); 212 free(buf);
173 } 213 }
@@ -195,6 +235,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
195 unsigned opt; 235 unsigned opt;
196 int r; 236 int r;
197 237
238 setup_common_bufsiz();
239
198 dumper = alloc_dumper(); 240 dumper = alloc_dumper();
199 241
200 opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */, 242 opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */,
@@ -222,7 +264,7 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
222 } 264 }
223 265
224 if (opt & OPT_r) { 266 if (opt & OPT_r) {
225 reverse(opt, argv[0]); 267 reverse(opt, argv[0], opt_s);
226 } 268 }
227 269
228 if (opt & OPT_o) { 270 if (opt & OPT_o) {