diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2022-08-22 17:28:43 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2022-08-22 17:28:43 +0200 |
| commit | 5eceafb1f812ec4dca7fdf6896cfcea6783a78b9 (patch) | |
| tree | ac965162ebc73f32e188a6fe84f57ac23c2b533e /util-linux | |
| parent | 0011a6bc2024ec4ee6d8edea203524e758d67833 (diff) | |
| download | busybox-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>
Diffstat (limited to 'util-linux')
| -rw-r--r-- | util-linux/hexdump_xxd.c | 58 |
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 | ||
| 72 | static void reverse(unsigned opt, const char *filename) | 73 | #define fillbuf bb_common_bufsiz1 |
| 74 | |||
| 75 | static 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 | |||
| 86 | static 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) { |
