Feature: Preserve symlinks, hard links, and special files (-l, -H, -D) #177

Closed
opened 2026-07-30 18:31:44 +02:00 by TapTap · 0 comments
Owner

Corresponding rsync flags/behavior:

  • -l, --links — copy symlinks as symlinks
  • -H, --hard-links — preserve hard links
  • -D — preserve device and special files (same as --devices --specials)

Current FastSync behavior:
scanner.c:102 uses stat() (not lstat()), so symlinks are followed transparently and never preserved as symlinks. Hard links are not tracked, so each link target is transferred independently. Device/special files are skipped because S_ISDIR/S_ISREG checks only handle directories and regular files.

Proposed changes:

  • CLI flags: -l/--links, -H/--hard-links, -D/--devices --specials
  • Config fields: bool preserve_symlinks, bool preserve_hard_links, bool preserve_devices
  • File type representation:
    • Extend FileMetadata with a file-type field (regular, symlink, directory, device, fifo, socket)
    • Extend protocol: send symlink target as a string; send device major/minor for special files
  • Scanner:
    • Use lstat() when any preserve flag is set
    • For symlinks, store target path instead of content
    • For hard links, maintain an inode map and emit hard-link references
    • For devices, store st_rdev
  • Server:
    • Create symlinks with symlink(), devices with mknod(), and hard links with link()
    • Skip content transfer for symlink/device entries

Priority: high
Rationale: Preserving symlinks and hard links is fundamental for backups, build-artifact sync, and POSIX fidelity. Following symlinks can also be a security risk.

Acceptance criteria:

  • client -l /src /dst recreates symlinks with the correct targets
  • client -H /src /dst transfers a hard-linked file only once and links the rest
  • client -D /src /dst recreates device/special files when running as root
  • Default behavior continues to follow symlinks for backward compatibility
**Corresponding rsync flags/behavior:** - `-l, --links` — copy symlinks as symlinks - `-H, --hard-links` — preserve hard links - `-D` — preserve device and special files (same as `--devices --specials`) **Current FastSync behavior:** `scanner.c:102` uses `stat()` (not `lstat()`), so symlinks are followed transparently and never preserved as symlinks. Hard links are not tracked, so each link target is transferred independently. Device/special files are skipped because `S_ISDIR`/`S_ISREG` checks only handle directories and regular files. **Proposed changes:** - CLI flags: `-l/--links`, `-H/--hard-links`, `-D/--devices --specials` - Config fields: `bool preserve_symlinks`, `bool preserve_hard_links`, `bool preserve_devices` - File type representation: - Extend `FileMetadata` with a file-type field (regular, symlink, directory, device, fifo, socket) - Extend protocol: send symlink target as a string; send device major/minor for special files - Scanner: - Use `lstat()` when any preserve flag is set - For symlinks, store target path instead of content - For hard links, maintain an inode map and emit hard-link references - For devices, store `st_rdev` - Server: - Create symlinks with `symlink()`, devices with `mknod()`, and hard links with `link()` - Skip content transfer for symlink/device entries **Priority:** high **Rationale:** Preserving symlinks and hard links is fundamental for backups, build-artifact sync, and POSIX fidelity. Following symlinks can also be a security risk. **Acceptance criteria:** - [ ] `client -l /src /dst` recreates symlinks with the correct targets - [ ] `client -H /src /dst` transfers a hard-linked file only once and links the rest - [ ] `client -D /src /dst` recreates device/special files when running as root - [ ] Default behavior continues to follow symlinks for backward compatibility
TapTap added the enhancementneeds-triage labels 2026-07-30 18:31:44 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: TapTap/FastSync#177