From c6cb9445e288f24f69eaf44de99c52543f1aebc5 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 3 May 2022 09:33:58 -0700 Subject: [PATCH] xxd -r: don't seek unnecessarily on the output stream. Also add a dup() to fix a double close() noticed in strace when looking at the lseek() issue... Fixes: https://github.com/landley/toybox/issues/338 --- tests/xxd.test | 4 ++++ toys/other/xxd.c | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/xxd.test b/tests/xxd.test index e9ec81ed..37061e89 100755 --- a/tests/xxd.test +++ b/tests/xxd.test @@ -50,4 +50,8 @@ testing "-r -p long" \ "echo '40404040404040404040404040404040404040404040404040404040404040404040404040404040' | xxd -r -p -" \ "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" "" "" +testing "-r unnecessary output seeks" \ + "echo '00000000: 0100 0000 0000 0000 0000 0000 0000 00ff deadbeef........' | xxd -r | xxd" \ + "00000000: 0100 0000 0000 0000 0000 0000 0000 00ff ................\n" "" "" + rm file1 file2 diff --git a/toys/other/xxd.c b/toys/other/xxd.c index 3a070dff..fba78bca 100644 --- a/toys/other/xxd.c +++ b/toys/other/xxd.c @@ -104,7 +104,8 @@ static int dehex(char ch) static void do_xxd_reverse(int fd, char *name) { - FILE *fp = xfdopen(fd, "r"); + FILE *fp = xfdopen(xdup(fd), "r"); + long long current_pos = 0; int tmp; // -ri is a very easy special case. @@ -118,7 +119,7 @@ static void do_xxd_reverse(int fd, char *name) long long pos; if (fscanf(fp, "%llx: ", &pos) == 1) { - if (fseek(stdout, pos, SEEK_SET) != 0) { + if (pos != current_pos && fseek(stdout, pos, SEEK_SET) != 0) { // TODO: just write out zeros if non-seekable? perror_exit("%s: seek failed", name); } @@ -141,6 +142,7 @@ static void do_xxd_reverse(int fd, char *name) fputc((n1 << 4) | (n2 & 0xf), stdout); col++; + current_pos++; // Is there any grouping going on? Ignore a single space. tmp = fgetc(fp); -- 2.39.2