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>
This commit is contained in:
parent
0011a6bc20
commit
5eceafb1f8
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user