Skip to content

feat(transfer): wire --info=SYMSAFE emission (3.4.1 parity)#4119

Merged
oferchen merged 1 commit into
masterfrom
feat/info-symsafe-emission-2163
May 16, 2026
Merged

feat(transfer): wire --info=SYMSAFE emission (3.4.1 parity)#4119
oferchen merged 1 commit into
masterfrom
feat/info-symsafe-emission-2163

Conversation

@oferchen
Copy link
Copy Markdown
Owner

Summary

  • Wire --info=SYMSAFE producer emissions across the sender, local-copy, and cross-device backup paths so the flag finally fires under INFO_GTE(SYMSAFE, 1) (upstream flist.c:217 and backup.c:292).
  • Three call sites mirror upstream byte-for-byte: crates/transfer/src/generator/file_list/walk.rs for the sender push path, crates/engine/src/local_copy/executor/special/symlink.rs for the local-copy dereference branch, and crates/engine/src/local_copy/context_impl/state.rs for the cross-device backup fallback that refuses to recreate unsafe symlinks under --safe-links.
  • Roll SYMSAFE from Stub to Match in docs/audits/info-flags-audit.md and remove it from the parity-gap summary.

Test plan

  • cargo nextest run -p transfer --all-features -E 'test(symsafe)' covers the sender-side wording and the gated-when-disabled case.
  • cargo nextest run -p engine --all-features -E 'test(symsafe)' covers both the local-copy --copy-unsafe-links integration test (real symlink dereference through LocalCopyPlan) and the byte-for-byte backup wording test.
  • Visual inspection against target/interop/upstream-src/rsync-3.4.1/{flist.c:217,backup.c:292} confirms copying unsafe symlink "<path>" -> "<target>" and not backing up unsafe symlink "<dest>" -> "<target>" are emitted exactly.
  • Full CI (fmt+clippy, nextest stable, Windows stable, macOS stable, Linux musl stable).

Closes #2163

SYMSAFE sits at upstream's `INFO_GTE(SYMSAFE, 1)` gate and is part of
`info_verbosity[1]` (options.c:241), so it fires once `-v` (or any
explicit `--info=SYMSAFE`) raises the level above zero. Upstream emits
two distinct messages:

  flist.c:217   - `copying unsafe symlink "<path>" -> "<target>"`
                  fired by `readlink_stat()` when
                  `copy_unsafe_links && unsafe_symlink(...)` triggers
                  a dereference into a regular entry.
  backup.c:292  - `not backing up unsafe symlink "<fname>" -> "<sl>"`
                  fired by `make_backup()` when `safe_symlinks &&
                  unsafe_symlink(...)` refuses to recreate the symlink
                  at the backup location.

oc-rsync had the flag wired through CLI parsing and the level table
(symsafe=1 at -v) but no producer. The audit doc flagged this as
"Stub" with the note: "Our symlink-safety code in `crates/filters` and
`crates/transfer/src/file_list/*` does not gate on the flag."

Wire three emission sites that cover every transfer mode:

1. crates/transfer/src/generator/file_list/walk.rs - the sender path
   for daemon/SSH push. Both `resolve_symlink_metadata` and the
   batched-stat fixup in `process_dir_entries_batched` emit the
   upstream wording before dereferencing an unsafe symlink.

2. crates/engine/src/local_copy/executor/special/symlink.rs - the
   local-copy path. `copy_symlink` emits the same notice when
   `copy_unsafe_links_enabled()` triggers the dereference branch.

3. crates/engine/src/local_copy/context_impl/state.rs - the
   cross-device backup fallback. `backup_existing_entry` emits the
   `not backing up unsafe symlink` notice when `safe_links_enabled()`
   refuses to recreate the symlink at the backup location and
   bails out (mirroring upstream's `ret = 2`).

Five new tests assert byte-for-byte upstream wording and confirm the
notices are suppressed at the default verbosity. The audit doc rolls
SYMSAFE from Stub to Match and removes it from the parity-gap summary
list.

Closes #2163.
@github-actions github-actions Bot added the enhancement New feature or request label May 16, 2026
@oferchen oferchen merged commit 1d5fdc0 into master May 16, 2026
26 of 28 checks passed
@oferchen oferchen deleted the feat/info-symsafe-emission-2163 branch May 16, 2026 02:55
oferchen added a commit that referenced this pull request May 18, 2026
SYMSAFE sits at upstream's `INFO_GTE(SYMSAFE, 1)` gate and is part of
`info_verbosity[1]` (options.c:241), so it fires once `-v` (or any
explicit `--info=SYMSAFE`) raises the level above zero. Upstream emits
two distinct messages:

  flist.c:217   - `copying unsafe symlink "<path>" -> "<target>"`
                  fired by `readlink_stat()` when
                  `copy_unsafe_links && unsafe_symlink(...)` triggers
                  a dereference into a regular entry.
  backup.c:292  - `not backing up unsafe symlink "<fname>" -> "<sl>"`
                  fired by `make_backup()` when `safe_symlinks &&
                  unsafe_symlink(...)` refuses to recreate the symlink
                  at the backup location.

oc-rsync had the flag wired through CLI parsing and the level table
(symsafe=1 at -v) but no producer. The audit doc flagged this as
"Stub" with the note: "Our symlink-safety code in `crates/filters` and
`crates/transfer/src/file_list/*` does not gate on the flag."

Wire three emission sites that cover every transfer mode:

1. crates/transfer/src/generator/file_list/walk.rs - the sender path
   for daemon/SSH push. Both `resolve_symlink_metadata` and the
   batched-stat fixup in `process_dir_entries_batched` emit the
   upstream wording before dereferencing an unsafe symlink.

2. crates/engine/src/local_copy/executor/special/symlink.rs - the
   local-copy path. `copy_symlink` emits the same notice when
   `copy_unsafe_links_enabled()` triggers the dereference branch.

3. crates/engine/src/local_copy/context_impl/state.rs - the
   cross-device backup fallback. `backup_existing_entry` emits the
   `not backing up unsafe symlink` notice when `safe_links_enabled()`
   refuses to recreate the symlink at the backup location and
   bails out (mirroring upstream's `ret = 2`).

Five new tests assert byte-for-byte upstream wording and confirm the
notices are suppressed at the default verbosity. The audit doc rolls
SYMSAFE from Stub to Match and removes it from the parity-gap summary
list.

Closes #2163.
oferchen added a commit that referenced this pull request May 18, 2026
SYMSAFE sits at upstream's `INFO_GTE(SYMSAFE, 1)` gate and is part of
`info_verbosity[1]` (options.c:241), so it fires once `-v` (or any
explicit `--info=SYMSAFE`) raises the level above zero. Upstream emits
two distinct messages:

  flist.c:217   - `copying unsafe symlink "<path>" -> "<target>"`
                  fired by `readlink_stat()` when
                  `copy_unsafe_links && unsafe_symlink(...)` triggers
                  a dereference into a regular entry.
  backup.c:292  - `not backing up unsafe symlink "<fname>" -> "<sl>"`
                  fired by `make_backup()` when `safe_symlinks &&
                  unsafe_symlink(...)` refuses to recreate the symlink
                  at the backup location.

oc-rsync had the flag wired through CLI parsing and the level table
(symsafe=1 at -v) but no producer. The audit doc flagged this as
"Stub" with the note: "Our symlink-safety code in `crates/filters` and
`crates/transfer/src/file_list/*` does not gate on the flag."

Wire three emission sites that cover every transfer mode:

1. crates/transfer/src/generator/file_list/walk.rs - the sender path
   for daemon/SSH push. Both `resolve_symlink_metadata` and the
   batched-stat fixup in `process_dir_entries_batched` emit the
   upstream wording before dereferencing an unsafe symlink.

2. crates/engine/src/local_copy/executor/special/symlink.rs - the
   local-copy path. `copy_symlink` emits the same notice when
   `copy_unsafe_links_enabled()` triggers the dereference branch.

3. crates/engine/src/local_copy/context_impl/state.rs - the
   cross-device backup fallback. `backup_existing_entry` emits the
   `not backing up unsafe symlink` notice when `safe_links_enabled()`
   refuses to recreate the symlink at the backup location and
   bails out (mirroring upstream's `ret = 2`).

Five new tests assert byte-for-byte upstream wording and confirm the
notices are suppressed at the default verbosity. The audit doc rolls
SYMSAFE from Stub to Match and removes it from the parity-gap summary
list.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant