Skip to content

fix: handle long hardlink and symlink targets in save archive#134

Merged
mobileoverlord merged 1 commit intomainfrom
lee-eng-1836
May 1, 2026
Merged

fix: handle long hardlink and symlink targets in save archive#134
mobileoverlord merged 1 commit intomainfrom
lee-eng-1836

Conversation

@lee-reinhardt
Copy link
Copy Markdown
Member

@lee-reinhardt lee-reinhardt commented Apr 28, 2026

Problem

avocado save aborts on any volume containing hardlinks whose targets exceed 100 bytes after the avocado-state/volume/ archive prefix is applied. Cargo build artifacts in the SDK volume reliably trigger this:

Error: provided value is too long when setting link name for ./qemux86-64/sdk/aarch64/build/avocado-conn/release/build/anyhow-27218e60227aebdd/build-script-build

Root cause

The save loop cloned each entry's header and called Header::set_link_name directly. The tar crate's header struct has a fixed 100-byte linkname field; set_link_name returns an error rather than emitting a GNU K long-link extension. Re-prefixing the target with avocado-state/volume/ consistently pushes Cargo build paths past the limit.

A latent issue also existed for symlinks with long original targets: the inner archive's K extension was implicitly resolved by Entry::link_name() but header().clone() + append_data would have silently truncated the target on output.

Fix

  • Read targets via Entry::link_name() so GNU/PAX long-name extensions are resolved on read.
  • Write hardlinks and symlinks via Builder::append_link() so the proper long-name extensions are emitted on write.
  • Hardlink targets continue to be re-prefixed for the new archive layout; symlink targets are preserved as-is (filesystem paths, not archive paths).

Test plan

  • cargo build clean
  • cargo fmt --check clean
  • cargo clippy no new warnings
  • cargo test save — 7 existing tests still pass
  • Manual: avocado save --include-src on a built runtimes-dev project (4 GB volume with Cargo artifacts) succeeds and produces a 2 GB archive
  • Manual: round-trip — avocado load on the saved archive into a fresh directory, provision, then sdk run vm dev boots successfully

The previous code called Header::set_link_name directly on a cloned
header, which silently truncates targets longer than 100 bytes.
Combined with the avocado-state/volume/ prefix added to hardlink
targets during re-prefixing, any project with built Cargo artifacts
in the SDK volume (paths like .../build/<crate>-<hash>/...) hit the
limit and aborted save.

- Use Entry::link_name() to resolve through GNU/PAX long-name
  extensions on read.
- Use Builder::append_link() to emit long-name extensions on write
  for both hardlinks and symlinks.
- Hardlink targets continue to be re-prefixed; symlink targets are
  preserved as-is (they reference filesystem paths, not archive
  paths).
@mobileoverlord mobileoverlord merged commit b8d1a18 into main May 1, 2026
5 checks passed
@mobileoverlord mobileoverlord deleted the lee-eng-1836 branch May 1, 2026 19:31
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.

2 participants