Skip to content

dd: implement it - #244

Open
metif12 wants to merge 3 commits into
vlang:mainfrom
metif12:dd-implementation
Open

metif12 wants to merge 3 commits into
vlang:mainfrom
metif12:dd-implementation

Conversation

@metif12

@metif12 metif12 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

dd copies a file, converting and formatting according to the operands: if, of, bs, ibs, obs, cbs, count, skip, iseek, seek, status, conv and the iflag/oflag lists.

Operand parsing and the copy live in common/dd; src/dd is a thin main that owns the stderr summary, for the same reason the other recent tools keep their logic in a module — v test <dir> compiles only _test.v files.

skip and seek count blocks unless skip_bytes/seek_bytes make them byte offsets, count counts records unless count_bytes, and conv=sync pads a short final block.

The unit suffixes were measured, not guessed: a bare K is 1024 while KB is 1000, so bs=1K and bs=1KB deliberately read different amounts of the same input. swab exchanges pairs within a block rather than across the whole buffer, which is why bs=1 leaves the data untouched — a distinction the first draft got wrong and the differential test caught.

status=none prints nothing and status=noxfer drops the byte total. The elapsed time and rate are not printed at all, because they are not reproducible and a test that compares them would be comparing noise.

Differential against uutils 0.0.17 on this machine covers the block sizes, both unit conventions, skip and count with and without their _bytes flags, the conversions, status=none, and the failure cases. There is a control run too: making swab a no-op turns the suite red with 0123456789 where the reference gives 1032547698.

Not implemented, and refused rather than faked: the EBCDIC-family conversions, which need cbs; --filter; and the iflag/oflag hints that only mean something on POSIX.

Copies a file, converting and formatting according to the operands: if, of, bs, ibs, obs, cbs, count, skip, iseek, seek, status, conv and the iflag/oflag lists. Operand parsing and the copy live in common/dd; src/dd is a thin main that owns the stderr summary, for the same reason the other recent tools keep their logic in a module. skip and seek count blocks unless skip_bytes/seek_bytes make them byte offsets, count counts records unless count_bytes, and conv=sync pads a short final block. The unit suffixes were measured, not guessed: a bare K is 1024 while KB is 1000, so bs=1K and bs=1KB deliberately read different amounts. swab exchanges pairs within a block rather than across the whole buffer, which is why bs=1 leaves the data untouched. status=none prints nothing and status=noxfer drops the byte total, because the elapsed time and rate are not reproducible and so are not printed at all. Differential against uutils 0.0.17 on this machine covers the block sizes, both unit conventions, skip/count with and without their _bytes flags, the conversions, status=none, and the failure cases. Not implemented and refused rather than faked: the EBCDIC-family conversions, which need cbs; --filter; and the iflag/oflag hints that only make sense on POSIX.
common/dd/dd.v called C.write() directly and declared `fn C.write` in the
same pure .v file. The pinned V rejects that outright:

    common/dd/dd.v:219:4: error: C code will not be allowed in pure .v files,
    please move it to a .c.v file instead

This is the same defect and the same fix as vlang#252 for nohup, which already
landed: the C declaration and the call to it have to sit on opposite sides
of the .c.v boundary. So common/dd/dd.c.v now holds the declaration plus a
pub write_fds wrapper, and dd.v calls that wrapper.

Kept the `unsafe` block at the call site unchanged. It is there for
`data.data`, not for the C call, and moving it would be a behavioural
change this bug fix does not need.

Verified: dd builds and `hello world | dd` still reports 15 bytes copied
through the new wrapper, and v fmt -verify is clean on both files. The
rejection itself is not reproducible on the compiler available here, which
still permits C calls in a .v file; it comes from the pinned CI revision.
@metif12

metif12 commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

This PR does not build as it stands. common/dd/dd.v calls C.write() and declares fn C.write in the same pure .v file, which the pinned V rejects outright:

common/dd/dd.v:219:4: error: C code will not be allowed in pure .v files, please move it to a .c.v file instead
common/dd/dd.v:268:6: error: C code will not be allowed in pure .v files, please move it to a .c.v file instead

Same defect and same fix as #252, which already landed for nohup: the C declaration and the call to it have to sit on opposite sides of the .c.v boundary. So common/dd/dd.c.v now holds the declaration plus a pub fn write_fds wrapper, and dd.v calls that wrapper. The commit is on top of this branch rather than replacing it, so the rest of the PR is unchanged.

The unsafe block at the call site is left as it was. It is there for data.data, not for the C call, and moving it would be a behavioural change this bug fix does not need.

Verified: dd builds, and hello world | dd still reports 15 bytes copied through the new wrapper. v fmt -verify is clean on both files — the formatter caught a missing trailing newline in the new file, which is fixed.

One limit worth stating: the rejection itself is not reproducible with the compiler available on this machine, which still permits C calls in a .v file. The error comes from the revision CI pins, so this is verified against the real compiler only by CI — which is red for the unrelated V bootstrap reason. The fix follows the pattern #252 already established on the same tree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant