Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rzsz

A modern Rust rewrite of the classic lrzsz file transfer tool. Transfer files over terminal connections using ZMODEM, XMODEM, and YMODEM protocols.

中文文档

Features

  • Single binary — One zz binary (449KB static), all commands via symlinks
  • Drop-in replacement — Works as rz, sz, rrz, rsz via argv[0] detection
  • Smart modezz file sends, zz receives, no separate commands needed
  • ZMODEM — CRC-16/32, adaptive block sizing, multi-file batch, crash recovery
  • XMODEM — 128B/1K blocks, CRC-16 and checksum modes
  • YMODEM — Batch transfer with file headers, size tracking
  • Secure — Restricted mode by default, path traversal protection, filename sanitization
  • Terminal compatible — Works with Xshell, SecureCRT, iTerm2, MobaXterm
  • Zero dependencies — Static musl build, runs on any Linux (x86_64, aarch64)

Usage

# Unified command (auto-detect mode)
zz file1 file2        # Send files
zz                    # Receive files

# Traditional commands (symlinks to zz)
sz file1 file2        # Send files
rz                    # Receive files

# Common options
zz -r file            # Resume interrupted transfer
zz -p                 # Receive: protect existing files (don't overwrite)
zz -E                 # Receive: rename if file exists (.1, .2, ...)
zz -e file            # Escape all control characters
zz -T file            # Turbo mode (less escaping, faster)
zz -8 file            # Try 8K blocks
zz -q file            # Quiet mode
zz -v file            # Verbose mode
zz --help             # Show all options

File Overwrite Policy

Option Behavior
Default (no flags) Overwrite existing files
-p / --protect Skip existing files with message
-E / --rename Auto-rename (file.1, file.2, ...)

How It Works

zz is a single binary that determines its behavior from how it is invoked:

Invoked as Mode Protocol
zz file Send ZMODEM (default), XMODEM, YMODEM
zz Receive ZMODEM (default), XMODEM, YMODEM
sz / rsz / lsz Send (forced) ZMODEM
rz / rrz / lrz Receive (forced) ZMODEM
sb / rsb Send YMODEM
rb / rrb Receive YMODEM
sx / rsx Send XMODEM
rx / rrx Receive XMODEM

X/YMODEM limitations

X/YMODEM are provided for compatibility. Only ZMODEM mode honors the full option set. On X/YMODEM paths:

  • XMODEM send: -k / -8 selects 1024-byte blocks; other send options are ignored.
  • XMODEM receive: the first non-flag argument is the destination filename (XMODEM has no filename in the protocol). Output is padded to the block boundary.
  • YMODEM receive: -q suppresses the received: line; -p / -y / -E / -r / -R / -U have no effect (files are always overwritten into the current directory with the filename from block 0).

For full option support, use ZMODEM (the default).

Comparison with lrzsz

rzsz lrzsz
Language Rust C
Binary size (static) 449 KB ~200 KB
Binary count 1 (zz) 2 (lsz + lrz)
Unified command zz (auto-detect) No
Memory safety Compile-time guaranteed Manual
Terminal restore RAII (guaranteed on all exit paths) Signal handler (fragile)
Timeout mechanism poll() alarm()/SIGALRM
State management Struct fields 50+ global variables
Protocol state machine Explicit enum + match Implicit goto chains
Path traversal protection Default on Opt-in

Performance (10MB pipe transfer)

Sender Receiver Throughput
C lsz C lrz 116 MB/s
Rust sz C lrz 49 MB/s
C lsz Rust rz 45 MB/s
Rust sz Rust rz 29 MB/s

The Rust version is 2-3x slower in pipe benchmarks due to per-byte escape encoding (vs C's batch zsendline_s). In real-world SSH/serial transfers, network latency dominates and the difference is imperceptible.

Terminal Compatibility

Terminal ZMODEM Support Status
Xshell Built-in Tested
SecureCRT Built-in Compatible
iTerm2 Configurable trigger Compatible
MobaXterm Built-in Compatible
Tabby Plugin Compatible
Windows Terminal None Use scp instead
PuTTY None Use scp instead

Building from Source

git clone https://github.com/kookob/rzsz.git
cd rzsz

# Development build
cargo build

# Release build
cargo build --release

# Static musl build (no runtime dependencies)
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-musl

# Run tests
cargo test
bash tests/interop.sh

Architecture

src/
├── bin/zz.rs           # Unified binary: auto-detect send/receive from argv[0]
├── sender.rs           # ZMODEM send: handshake, file data, adaptive blocks
├── receiver.rs         # ZMODEM receive: ZRINIT negotiation, file write, resume
├── xmodem.rs           # XMODEM: 128B/1K blocks, CRC-16/checksum
├── ymodem.rs           # YMODEM: batch transfer, file headers
├── zmodem/
│   ├── frame.rs        # Frame encoding/decoding (hex/bin16/bin32)
│   ├── session.rs      # Protocol state machine, header parsing
│   ├── crc.rs          # CRC-16 and CRC-32 lookup tables
│   └── escape.rs       # ZDLE escape table
└── serial/
    ├── mod.rs           # ProtocolWriter/StatusWriter (type-safe I/O separation)
    ├── reader.rs        # Buffered modem reader with poll() timeout
    └── terminal.rs      # TerminalGuard (RAII terminal mode restore)

Publishing

See PUBLISHING.md for crates.io and GitHub Release instructions.

License

Apache-2.0

Credits

  • Original rzsz by Chuck Forsberg (Omen Technology)
  • lrzsz maintained by Uwe Ohse
  • ZMODEM protocol specification (1988)

About

Modern rz/sz in Rust — single binary, drop-in lrzsz replacement

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages