sharkdp / hexyl

A command-line hex viewer
Apache License 2.0
8.92k stars 227 forks source link

Argument `--display-offset` does not accept negative numbers, contrary to its helptext description. #112

Open eth-p opened 3 years ago

eth-p commented 3 years ago

The hexyl --help description for the --block-size argument goes as follows:

    -o, --display-offset <N>    Add N bytes to the displayed file position. The
                                N argument can also include a unit (see
                                `--length` for details)
                                A negative value is valid and calculates an
                                offset relative to the end of the file.

However, when I attempt to run dd if=/dev/urandom bs=16 count=32 2>/dev/null | hexyl --skip=0xFF --display-offset=-0x2F, hexyl prints the following error:

Error: failed to parse `--display-offset` arg "-0x2F" as byte count

Caused by:
    negative offset specified, but only positive offsets (counts) are accepted in this context

Note: I'm doing a class assignment regarding creating tests (from scratch) for an open-source command line program, and I chose hexyl for it. You might have a couple more of these on the way, depending on what the assignment brings to light :)

sharkdp commented 3 years ago

@ErichDonGubler Do you remember how this was intended to work?

ErichDonGubler commented 3 years ago

Disclaimer: I'm interested in resolving this. Right now, I'm just going to triage things, but I hope to have a solution after I finish researching and put in my vote for my elections as a US resident.

There's a misunderstanding what's governing this failure here, and I don't think that that's your fault, @eth-p -- the diagnostic isn't giving you enough information IMO. Negative offsets don't work on streams, because they're not seekable. But if you put the output of the command you're piping into a file and then try to do what you're doing:

$ dd if=/dev/urandom bs=16 count=32 2>/dev/null > file

$ hexyl --skip=0xFF --display-offset=-0x2F file
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│000000ff│ 78 99 4d 53 97 58 d1 04 ┊ d8 fc 70 0e 8f a7 e2 f9 │x×MS×Xו┊××p•××××│
│0000010f│ bd 0e 3d 41 50 19 6c 8c ┊ 97 eb 4d 9b f2 0b 23 24 │ו=AP•l×┊××M×ו#$│
│0000011f│ d0 15 05 a8 c1 d3 71 cb ┊ 2d bd 8c 6f 2f 17 0f 49 │ו•×××q×┊-××o/••I│
│0000012f│ b9 82 64 7e 57 dc 23 3a ┊ 7a 9e cf 82 11 62 71 c4 │××d~W×#:┊z××וbq×│
│0000013f│ a5 02 a8 1e 7c 6a 81 32 ┊ 50 fc 5d 03 df a1 51 1a │וו|j×2┊P×]•××Q•│
│0000014f│ 09 8e 2b 4b 66 09 c9 92 ┊ 03 54 e7 27 46 1e 66 62 │_×+Kf_××┊•T×'F•fb│
│0000015f│ c5 dd 8a 14 4b 71 82 0f ┊ 79 94 1e 57 5c 31 7e 49 │××וKqו┊yוW\1~I│
│0000016f│ 6c f5 17 84 0d 46 18 8e ┊ 02 a5 4f bc 7a 8e 71 d4 │lו×_F•×┊•×O×z×q×│
│0000017f│ af ad 45 6d f8 5d ea 39 ┊ fe c0 24 ce 60 a2 27 d4 │××Em×]×9┊××$×`×'×│
│0000018f│ 7b 8c 8a db 6e 22 31 53 ┊ 3b e1 2d 46 1f 5b ea 64 │{×××n"1S┊;×-F•[×d│
│0000019f│ b4 ca 0e 65 77 cf 85 11 ┊ 9f 6a 97 4e 04 f1 ea e3 │×וew×ו┊×j×N•×××│
│000001af│ 75 89 bc ac e1 04 d3 68 ┊ f2 14 e8 8f b5 2e 26 00 │u×××ו×h┊ו×××.&0│
│000001bf│ 72 f1 c9 9b 7d ae 96 7b ┊ 51 2b c7 c4 5e f1 86 61 │r×××}××{┊Q+××^××a│
│000001cf│ 26 d0 99 a6 84 bc 7a c3 ┊ 20 88 b2 a6 c1 a1 9d 24 │&×××××z×┊ ××××××$│
│000001df│ 3b 50 f7 b3 54 a6 5d 7b ┊ 98 0d 5d 23 31 d3 34 9a │;P××T×]{┊×_]#1×4×│
│000001ef│ ed 15 ff 7a c4 72 5f de ┊ df 30 cd 94 2b 7e e3 9a │ו×z×r_×┊×0××+~××│
│000001ff│ 6d                      ┊                         │m       ┊        │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘

The reason for this is fundamentally that stdin is essentially a ring buffer on most platforms -- seeking operations are not implemented for them, only reads, and after a read is performed the read region is discarded.

sharkdp commented 3 years ago

Thanks @ErichDonGubler. That was my guess as well, but I wasn't sure. In this case, I think we should simply provide a more detailed error message.

sharkdp commented 1 year ago

Even on files, this does not seem to work anymore

▶ hexyl --skip=0xFF --display-offset=-0xff /usr/bin/grep
Error: failed to parse `--display-offset` arg "-0xff" as byte count

Caused by:
    negative offset specified, but only positive offsets (counts) are accepted in this context

So what do we do here? remove the "A negative value is valid and will seek from the end of the file." part?