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)"
|
//usage: "\n -r Reverse (with -p, assumes no offsets in input)"
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
#include "common_bufsiz.h"
|
||||||
#include "dump.h"
|
#include "dump.h"
|
||||||
|
|
||||||
/* This is a NOEXEC applet. Be very careful! */
|
/* This is a NOEXEC applet. Be very careful! */
|
||||||
@ -69,10 +70,32 @@
|
|||||||
#define OPT_c (1 << 7)
|
#define OPT_c (1 << 7)
|
||||||
#define OPT_o (1 << 8)
|
#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;
|
FILE *fp;
|
||||||
char *buf;
|
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;
|
fp = filename ? xfopen_for_read(filename) : stdin;
|
||||||
|
|
||||||
@ -82,15 +105,31 @@ static void reverse(unsigned opt, const char *filename)
|
|||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
if (!(opt & OPT_p)) {
|
if (!(opt & OPT_p)) {
|
||||||
|
char *end;
|
||||||
|
off_t ofs;
|
||||||
skip_address:
|
skip_address:
|
||||||
p = skip_whitespace(p);
|
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 */
|
/* NB: for xxd -r, first hex portion is address even without colon */
|
||||||
/* If it's there, skip it: */
|
/* But if colon is there, skip it: */
|
||||||
if (*p == ':') p++;
|
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process hex bytes optionally separated by whitespace */
|
/* Process hex bytes optionally separated by whitespace */
|
||||||
@ -168,6 +207,7 @@ static void reverse(unsigned opt, const char *filename)
|
|||||||
goto nibble2;
|
goto nibble2;
|
||||||
}
|
}
|
||||||
putchar(val);
|
putchar(val);
|
||||||
|
cur++;
|
||||||
} /* for(;;) */
|
} /* for(;;) */
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
@ -195,6 +235,8 @@ int xxd_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
unsigned opt;
|
unsigned opt;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
setup_common_bufsiz();
|
||||||
|
|
||||||
dumper = alloc_dumper();
|
dumper = alloc_dumper();
|
||||||
|
|
||||||
opt = getopt32(argv, "^" "l:s:apirg:+c:+o:" "\0" "?1" /* 1 argument max */,
|
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) {
|
if (opt & OPT_r) {
|
||||||
reverse(opt, argv[0]);
|
reverse(opt, argv[0], opt_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt & OPT_o) {
|
if (opt & OPT_o) {
|
||||||
|
Loading…
Reference in New Issue
Block a user