feat(pull,push): work on devices without SFTP - #14
Merged
Conversation
ares-push and ares-pull opened SFTP directly, so a device set to "files": "stream" failed with "request subsystem failed". Only ares-install went through the FileTransfer fallback. Add Transfer, an open transport that picks SFTP or a stream over exec channels once and keeps it. Copying many files now costs one SFTP handshake instead of one per file, where FileTransfer opens a session per call. Transfer also gains what the path rules need: stat, which answers dir, file, other or missing, and read_dir. The stream side asks a POSIX shell, checked against busybox ash and dash, so the device needs no find. mkdir now makes missing parents over SFTP too, matching what the stream side already did with mkdir -p. TransferError names the SFTP status instead of printing "Sftp error code 3", and is_permission_denied lets a caller suggest another path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #13.
ares-pushandares-pullopened SFTP directly, so a deviceset to
"files": "stream"failed withrequest subsystem failed.ares-installwas the only tool that used the
FileTransferfallback.Transfer
FileTransferopens a transport per call, andSession::sftp()is a fullsftp_new+sftp_initround trip. Pushing 500 files meant 500 handshakes.The new
Transferpicks SFTP or a stream over exec channels once and keepsit for its whole life.
FileTransfernow delegates to it, so there is oneimplementation, and
ares-installis unchanged apart from a&mutthat wasnever needed.
It also gains what the #13 path rules need:
stat→ dir/file/other/missingsftp_stat[ -d ] / [ -f ] / [ -e ] || [ -L ]read_dirsftp_readdir, re-stat for symlinksfor f in * .*with the same testsmkdirmkdir -p, unchangedThe stream side needs only a POSIX shell, so the device needs no
find, which@webosose/ares-clishells out to. It reads one directory per command ratherthan one
findfor the tree, so a deep pull costs more round trips.Transfer::openalso falls back to streaming when a device claims SFTP but thesession will not start.
Errors
TransferErrornow names the SFTP status — "permission denied" instead ofSftp error code 3— andis_permission_denied()letsares-pushsuggestanother path.
Test: unit
cargo test --workspace— 77 tests, including the new listing and path-kindparsers.
Test: against a real SSH server
A sandboxed
sshdon127.0.0.1:2222and a scratch device list, 30 checks pertransport covering every row of the #13 path table, names with spaces, made
parents, the refusal cases, and
-i:sftp— all passstream— all passexercises the stream path and the automatic fallback
The same server made the
mainbuild fail:Test: every busybox LG ships
The busybox version per firmware comes from
packages.jsonincompat-checker-rs (webOS 7 and
up rename the package to
lib32-busybox):Both snippets were run under all eight, plus 1.27.2, 1.33.1, 1.37.0, dash
and bash. 1.20.2 through 1.29.2 were built from source as an ash-only static
binary, the rest came from the
busyboximages. Every one passes:🤖 Generated with Claude Code