SIGN IN SIGN UP

fix(head/tail): read file arguments byte-clean, not UTF-8 (#264)

* fix(head/tail): read file arguments byte-clean, not UTF-8

head/tail read file arguments via `ctx.fs.readFile`, which UTF-8-decodes
the content. For binary (or any non-ASCII) files this corrupts the data:
`-c` slices by codepoint instead of byte, and high/invalid bytes are
re-encoded (e.g. 0xFF -> U+FFFD, 3 bytes), so `head -c 50000` on binary
could emit 150000 bytes.

The stdin path was already byte-clean (latin1FromBytes(ctx.stdin)); the
file-argument path was missed in the 3.0.0 stdin byte/utf8 overhaul. Read
files via byte-preserving `readBytesFrom` and mark stdout `binary` (like
`cat`) so redirects/pipes don't double-encode. `-c` byte counts and `-n`
line splits (on 0x0A, UTF-8-transparent) are byte-safe over the latin1 view.

Adds regression tests for UTF-8 byte counting and raw high-byte round-trip
through a redirect for both head and tail.

* fix(head/tail): UTF-8 encode filename headers in binary output

The byte-clean fix marks head/tail stdout as binary so raw file bytes
round-trip through redirects/pipes. But headers (-v or multiple files)
carry the filename as a JS Unicode string, and the binary glue writes
each char as one latin1 byte. A non-ASCII filename like café.txt was
written as caf\xe9.txt (latin1) instead of caf\xc3\xa9.txt (UTF-8),
corrupting the header on redirect.

Encode the header text to its byte-shaped (UTF-8) form before mixing it
with the raw file bytes. One spot in the shared helper covers both
head and tail. Adds regression tests asserting the redirected header
bytes are UTF-8.
H
Harry Nguyen committed
9481331f54fdcbfa1b81b313d756cd7f541d7018
Parent: 75d8dfd
Committed by GitHub <noreply@github.com> on 6/4/2026, 5:30:57 PM