Expand description
Binary deployment for rcpd
This module handles automatic deployment of rcpd binaries to remote hosts. It transfers static rcpd binaries via SSH using base64 encoding, verifies integrity with SHA-256 checksums, and manages cached versions.
§Atomicity and Concurrent Deployment Safety
The deployment mechanism is designed to handle concurrent deployments from multiple rcp instances safely:
§Atomic Operations
-
Unique Temporary Files: Each deployment uses a shell-PID-unique temp file (
.rcpd-{version}.tmp.$$) which ensures concurrent deployments don’t interfere with each other. The$$expands to the shell process PID, guaranteeing uniqueness even when multiple deployments run simultaneously. -
Atomic Rename: The final deployment step uses
mv -fwhich is atomic on POSIX-compliant filesystems. This means:- The binary is either fully present at the final location or not present at all
- No partial writes are visible to readers
- Concurrent renames of the same file complete in a well-defined order
-
Write-Then-Verify: The deployment sequence ensures the binary is:
- Fully written to the temp file
- Marked executable (chmod 700)
- Moved atomically to the final location
- Checksummed after the move completes
§Race Condition Scenarios
Scenario 1: Multiple rcp instances deploying the same version concurrently
- Each uses a unique temp file (
.rcpd-0.22.0.tmp.1234,.rcpd-0.22.0.tmp.5678) - Both successfully write and verify their temp files
- Both attempt
mv -f .rcpd-0.22.0.tmp.$$ rcpd-0.22.0 - The filesystem ensures one wins atomically, the other overwrites atomically
- Result: Final binary is valid (both were identical and checksummed)
Scenario 2: One deployment while another is reading
- Reader opens
rcpd-0.22.0and gets a valid file descriptor - Writer completes deployment and
mv -freplaces the inode - Reader continues reading from the original inode (POSIX semantics)
- Result: Reader gets the old version (but it’s still valid)
Scenario 3: Deployment interrupted (network failure, SIGKILL)
- Temp file may be left in
.cache/rcp/bin/.rcpd-{version}.tmp.* - Final file is either:
- Not present (deployment never completed)
- Present and valid (mv completed before interruption)
- Temp files are hidden (dotfiles) and don’t interfere with discovery
- Result: Safe to retry; old temp files are harmless
§Assumptions
-
POSIX Filesystem Semantics: The deployment assumes the remote filesystem supports atomic
mv(rename) operations. This is true for all POSIX-compliant filesystems (ext4, xfs, btrfs, etc.) but may not hold for network filesystems with relaxed consistency (NFSv3 without proper locking). -
Unique Shell PIDs: The
$$shell variable expands to the process ID, which is assumed to be unique during the lifetime of the deployment. This is guaranteed by the OS but requires PIDs not to wrap around extremely rapidly. -
Checksum Integrity: SHA-256 checksums are assumed to be collision-resistant. If two different binaries produce the same checksum (astronomically unlikely), the deployment would consider them identical.
-
No Malicious Interference: The deployment assumes the remote host is not actively malicious (no adversary replacing files during deployment). Protection against malicious hosts is provided by SSH authentication, not by this module.
§Non-Atomic Operations
The following operations are not atomic and may observe intermediate states:
-
Cleanup of old versions: Uses
ls -t | tail | xargs rmwhich may race with concurrent deployments. This is acceptable because cleanup only removes old versions, never the current version being deployed. Worst case: a version is not cleaned up and remains on disk. -
Directory creation:
mkdir -pmay race with concurrent deployments creating the same directory. This is safe becausemkdir -pis idempotent and succeeds if the directory already exists.
Functions§
- cleanup_
old_ versions - Clean up old rcpd versions on remote host
- deploy_
rcpd - Deploy rcpd binary to remote host
- find_
local_ rcpd_ binary - Find local static rcpd binary suitable for deployment