Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.busybox.net/busybox.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2022-08-22 18:28:43 +0300
committerDenys Vlasenko <vda.linux@googlemail.com>2022-08-22 18:28:43 +0300
commit5eceafb1f812ec4dca7fdf6896cfcea6783a78b9 (patch)
treeac965162ebc73f32e188a6fe84f57ac23c2b533e /util-linux
parent0011a6bc2024ec4ee6d8edea203524e758d67833 (diff)
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.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 @@
//usage: "\n -r Reverse (with -p, assumes no offsets in input)"
#include "libbb.h"
+#include "common_bufsiz.h"
#include "dump.h"
/* This is a NOEXEC applet. Be very careful! */
@@ -69,10 +70,32 @@
#define OPT_c (1 << 7)
#define OPT_o (1 << 8)
-static void reverse(unsigned opt, const char *filename)
+#define fillbuf bb_common_bufsiz1
+
+static void write_zeros(off_t count)
+{
+ errno = 0;
+ do {
+ unsigned sz = count < COMMON_BUFSIZE ? (unsigned)count : COMMON_BUFSIZE;
+ if (fwrite(fillbuf, 1, sz, stdout) != sz)
+ bb_perror_msg_and_die("write error");
+ count -= sz;
+ } while (count != 0);
+}
+
+static void reverse(unsigned opt, const char *filename, char *opt_s)
{
FILE *fp;
char *buf;
+ off_t cur, opt_s_ofs;
+
+ memset(fillbuf, 0, COMMON_BUFSIZE);
+ opt_s_ofs = cur = 0;
+ if (opt_s) {
+ opt_s_ofs = BB_STRTOOFF(opt_s, NULL, 0);
+ if (errno || opt_s_ofs < 0)
+ bb_error_msg_and_die("invalid number '%s'", opt_s);
+ }
fp = filename ? xfopen_for_read(filename) : stdin;
@@ -82,15 +105,31 @@ static void reverse(unsigned opt, const char *filename)
p = buf;
if (!(opt & OPT_p)) {
+ char *end;
+ off_t ofs;
skip_address:
p = skip_whitespace(p);
- while (isxdigit(*p)) p++;
+ ofs = BB_STRTOOFF(p, &end, 16);
+ if ((errno && errno != EINVAL)
+ || ofs < 0
+ /* -s SEEK value should be added before seeking */
+ || (ofs += opt_s_ofs) < 0
+ ) {
+ bb_error_msg_and_die("invalid number '%s'", p);
+ }
+ if (ofs != cur) {
+ if (fseeko(stdout, ofs, SEEK_SET) != 0) {
+ if (ofs < cur)
+ bb_perror_msg_and_die("cannot seek");
+ write_zeros(ofs - cur);
+ }
+ cur = ofs;
+ }
+ p = end;
/* NB: for xxd -r, first hex portion is address even without colon */
- /* If it's there, skip it: */
- if (*p == ':') p++;
-
-//TODO: seek (or zero-pad if unseekable) to the address position
-//NOTE: -s SEEK value should be added to the address before seeking
+ /* But if colon is there, skip it: */
+ if (*p == ':')
+ p++;
}
/* Process hex bytes optionally separated by whitespace */
@@ -168,6 +207,7 @@ static void reverse(unsigned opt, const char *filename)
goto nibble2;
}
putchar(val);
+ cur++;
} /* for(;;) */
free(buf);
}
@@ -195,6 +235,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
unsigned opt;
int r;
+ setup_common_bufsiz();
+
dumper = alloc_dumper();
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)
}
if (opt & OPT_r) {
- reverse(opt, argv[0]);
+ reverse(opt, argv[0], opt_s);
}
if (opt & OPT_o) {