Add an untested SFTP implementation of Yama Wormfiles
This commit is contained in:
		
							parent
							
								
									1fe4d9d2f3
								
							
						
					
					
						commit
						a5d6bf3085
					
				
							
								
								
									
										559
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										559
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -2,6 +2,12 @@ | |||||||
| # It is not intended for manual editing. | # It is not intended for manual editing. | ||||||
| version = 3 | version = 3 | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "Inflector" | ||||||
|  | version = "0.11.4" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "adler" | name = "adler" | ||||||
| version = "1.0.2" | version = "1.0.2" | ||||||
| @ -43,6 +49,12 @@ dependencies = [ | |||||||
|  "memchr", |  "memchr", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "aliasable" | ||||||
|  | version = "0.1.3" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "ambient-authority" | name = "ambient-authority" | ||||||
| version = "0.0.1" | version = "0.0.1" | ||||||
| @ -67,6 +79,18 @@ dependencies = [ | |||||||
|  "serde", |  "serde", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "arc-swap" | ||||||
|  | version = "1.6.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "array-init" | ||||||
|  | version = "2.1.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "async-trait" | name = "async-trait" | ||||||
| version = "0.1.68" | version = "0.1.68" | ||||||
| @ -84,7 +108,7 @@ version = "0.2.14" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "hermit-abi", |  "hermit-abi 0.1.19", | ||||||
|  "libc", |  "libc", | ||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| @ -95,6 +119,22 @@ version = "1.1.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "awaitable" | ||||||
|  | version = "0.4.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "70af449c9a763cb655c6a1e5338b42d99c67190824ff90658c1e30be844c0775" | ||||||
|  | dependencies = [ | ||||||
|  |  "awaitable-error", | ||||||
|  |  "cfg-if 1.0.0", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "awaitable-error" | ||||||
|  | version = "0.1.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d5b3469636cdf8543cceab175efca534471f36eee12fb8374aba00eb5e7e7f8a" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "bare-metrics-core" | name = "bare-metrics-core" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| @ -136,6 +176,12 @@ version = "1.3.2" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "bitflags" | ||||||
|  | version = "2.0.2" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "blake" | name = "blake" | ||||||
| version = "2.0.2" | version = "2.0.2" | ||||||
| @ -166,7 +212,7 @@ checksum = "e54b86398b5852ddd45784b1d9b196b98beb39171821bad4b8b44534a1e87927" | |||||||
| dependencies = [ | dependencies = [ | ||||||
|  "cap-primitives", |  "cap-primitives", | ||||||
|  "cap-std", |  "cap-std", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -177,13 +223,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||||
| checksum = "fb8fca3e81fae1d91a36e9784ca22a39ef623702b5f7904d89dc31f10184a178" | checksum = "fb8fca3e81fae1d91a36e9784ca22a39ef623702b5f7904d89dc31f10184a178" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "ambient-authority", |  "ambient-authority", | ||||||
|  "errno", |  "errno 0.2.8", | ||||||
|  "fs-set-times", |  "fs-set-times", | ||||||
|  "io-extras", |  "io-extras", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "ipnet", |  "ipnet", | ||||||
|  "maybe-owned", |  "maybe-owned", | ||||||
|  "rustix", |  "rustix 0.33.7", | ||||||
|  "winapi", |  "winapi", | ||||||
|  "winapi-util", |  "winapi-util", | ||||||
|  "winx", |  "winx", | ||||||
| @ -197,9 +243,9 @@ checksum = "2247568946095c7765ad2b441a56caffc08027734c634a6d5edda648f04e32eb" | |||||||
| dependencies = [ | dependencies = [ | ||||||
|  "cap-primitives", |  "cap-primitives", | ||||||
|  "io-extras", |  "io-extras", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "ipnet", |  "ipnet", | ||||||
|  "rustix", |  "rustix 0.33.7", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| @ -243,7 +289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||||
| checksum = "1df386a2d0f35bdefc0642fd8bcb2cd28243959f028abfd22fbade6f7d30980e" | checksum = "1df386a2d0f35bdefc0642fd8bcb2cd28243959f028abfd22fbade6f7d30980e" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "atty", |  "atty", | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "clap_derive", |  "clap_derive", | ||||||
|  "clap_lex", |  "clap_lex", | ||||||
|  "indexmap", |  "indexmap", | ||||||
| @ -287,6 +333,19 @@ dependencies = [ | |||||||
|  "unicode-width", |  "unicode-width", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "concurrent_arena" | ||||||
|  | version = "0.1.7" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "24bfeb060a299f86521bb3940344800fc861cc506356e44a273a42cb552afde5" | ||||||
|  | dependencies = [ | ||||||
|  |  "arc-swap", | ||||||
|  |  "array-init", | ||||||
|  |  "const_fn_assert", | ||||||
|  |  "parking_lot", | ||||||
|  |  "triomphe", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "console" | name = "console" | ||||||
| version = "0.15.0" | version = "0.15.0" | ||||||
| @ -324,6 +383,12 @@ dependencies = [ | |||||||
|  "tiny-keccak", |  "tiny-keccak", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "const_fn_assert" | ||||||
|  | version = "0.1.2" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "27d614f23f34f7b5165a77dc1591f497e2518f9cec4b4f4b92bfc4dc6cf7a190" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "crc32fast" | name = "crc32fast" | ||||||
| version = "1.3.2" | version = "1.3.2" | ||||||
| @ -384,7 +449,7 @@ version = "0.23.2" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" | checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "crossterm_winapi", |  "crossterm_winapi", | ||||||
|  "libc", |  "libc", | ||||||
|  "mio", |  "mio", | ||||||
| @ -461,6 +526,26 @@ dependencies = [ | |||||||
|  "syn 1.0.96", |  "syn 1.0.96", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "derive_destructure2" | ||||||
|  | version = "0.1.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "35cb7e5875e1028a73e551747d6d0118f25c3d6dbba2dadf97cc0f4d0c53f2f5" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "syn 1.0.96", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "dirs" | ||||||
|  | version = "4.0.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" | ||||||
|  | dependencies = [ | ||||||
|  |  "dirs-sys", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "dirs-next" | name = "dirs-next" | ||||||
| version = "2.0.0" | version = "2.0.0" | ||||||
| @ -471,6 +556,17 @@ dependencies = [ | |||||||
|  "dirs-sys-next", |  "dirs-sys-next", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "dirs-sys" | ||||||
|  | version = "0.3.7" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" | ||||||
|  | dependencies = [ | ||||||
|  |  "libc", | ||||||
|  |  "redox_users", | ||||||
|  |  "winapi", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "dirs-sys-next" | name = "dirs-sys-next" | ||||||
| version = "0.1.2" | version = "0.1.2" | ||||||
| @ -533,6 +629,17 @@ dependencies = [ | |||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "errno" | ||||||
|  | version = "0.3.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" | ||||||
|  | dependencies = [ | ||||||
|  |  "errno-dragonfly", | ||||||
|  |  "libc", | ||||||
|  |  "windows-sys 0.45.0", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "errno-dragonfly" | name = "errno-dragonfly" | ||||||
| version = "0.1.2" | version = "0.1.2" | ||||||
| @ -561,6 +668,15 @@ version = "1.0.6" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "861d7b3427fbf3e06300b4aca5c430a2e263b7a7b6821faff8b200d3dc4a61cb" | checksum = "861d7b3427fbf3e06300b4aca5c430a2e263b7a7b6821faff8b200d3dc4a61cb" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "fastrand" | ||||||
|  | version = "1.9.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" | ||||||
|  | dependencies = [ | ||||||
|  |  "instant", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "flate2" | name = "flate2" | ||||||
| version = "1.0.24" | version = "1.0.24" | ||||||
| @ -577,8 +693,8 @@ version = "0.15.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "7df62ee66ee2d532ea8d567b5a3f0d03ecd64636b98bad5be1e93dcc918b92aa" | checksum = "7df62ee66ee2d532ea8d567b5a3f0d03ecd64636b98bad5be1e93dcc918b92aa" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "rustix", |  "rustix 0.33.7", | ||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -592,6 +708,18 @@ dependencies = [ | |||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "futures-core" | ||||||
|  | version = "0.3.28" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "futures-sink" | ||||||
|  | version = "0.3.28" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "fxhash" | name = "fxhash" | ||||||
| version = "0.2.1" | version = "0.2.1" | ||||||
| @ -671,6 +799,12 @@ dependencies = [ | |||||||
|  "libc", |  "libc", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "hermit-abi" | ||||||
|  | version = "0.3.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "hostname" | name = "hostname" | ||||||
| version = "0.3.1" | version = "0.3.1" | ||||||
| @ -719,13 +853,22 @@ dependencies = [ | |||||||
|  "regex", |  "regex", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "instant" | ||||||
|  | version = "0.1.12" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" | ||||||
|  | dependencies = [ | ||||||
|  |  "cfg-if 1.0.0", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "io-extras" | name = "io-extras" | ||||||
| version = "0.13.2" | version = "0.13.2" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "d0c937cc9891c12eaa8c63ad347e4a288364b1328b924886970b47a14ab8f8f8" | checksum = "d0c937cc9891c12eaa8c63ad347e4a288364b1328b924886970b47a14ab8f8f8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "os_pipe", |  "os_pipe", | ||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| @ -739,6 +882,17 @@ dependencies = [ | |||||||
|  "os_pipe", |  "os_pipe", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "io-lifetimes" | ||||||
|  | version = "1.0.9" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" | ||||||
|  | dependencies = [ | ||||||
|  |  "hermit-abi 0.3.1", | ||||||
|  |  "libc", | ||||||
|  |  "windows-sys 0.45.0", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "io-streams" | name = "io-streams" | ||||||
| version = "0.11.0" | version = "0.11.0" | ||||||
| @ -747,11 +901,11 @@ checksum = "fba6685e8e5efa7bd0ce8c4e92ac113b3b059b2e18bd1bf51f7cfab0f61b4b19" | |||||||
| dependencies = [ | dependencies = [ | ||||||
|  "duplex", |  "duplex", | ||||||
|  "io-extras", |  "io-extras", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "memchr", |  "memchr", | ||||||
|  "os_pipe", |  "os_pipe", | ||||||
|  "parking", |  "parking", | ||||||
|  "rustix", |  "rustix 0.33.7", | ||||||
|  "system-interface", |  "system-interface", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -802,9 +956,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "libc" | name = "libc" | ||||||
| version = "0.2.126" | version = "0.2.140" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" | checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "libsodium-sys" | name = "libsodium-sys" | ||||||
| @ -834,6 +988,12 @@ version = "0.0.42" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" | checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "linux-raw-sys" | ||||||
|  | version = "0.3.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "lock_api" | name = "lock_api" | ||||||
| version = "0.4.7" | version = "0.4.7" | ||||||
| @ -920,14 +1080,14 @@ dependencies = [ | |||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "mio" | name = "mio" | ||||||
| version = "0.8.3" | version = "0.8.6" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "libc", |  "libc", | ||||||
|  "log", |  "log", | ||||||
|  "wasi 0.11.0+wasi-snapshot-preview1", |  "wasi 0.11.0+wasi-snapshot-preview1", | ||||||
|  "windows-sys 0.36.1", |  "windows-sys 0.45.0", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| @ -936,7 +1096,7 @@ version = "0.17.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" | checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "cc", |  "cc", | ||||||
|  "cfg-if 0.1.10", |  "cfg-if 0.1.10", | ||||||
|  "libc", |  "libc", | ||||||
| @ -949,7 +1109,7 @@ version = "0.19.1" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" | checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "cc", |  "cc", | ||||||
|  "cfg-if 1.0.0", |  "cfg-if 1.0.0", | ||||||
|  "libc", |  "libc", | ||||||
| @ -965,6 +1125,17 @@ dependencies = [ | |||||||
|  "minimal-lexical", |  "minimal-lexical", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "num-derive" | ||||||
|  | version = "0.3.3" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "syn 1.0.96", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "num-integer" | name = "num-integer" | ||||||
| version = "0.1.45" | version = "0.1.45" | ||||||
| @ -990,7 +1161,7 @@ version = "1.13.1" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "hermit-abi", |  "hermit-abi 0.1.19", | ||||||
|  "libc", |  "libc", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -1012,6 +1183,95 @@ version = "1.12.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" | checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "openssh" | ||||||
|  | version = "0.9.9" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "8ca6c277973fb549b36dd8980941b5ea3ecebea026f5b1f0060acde74d893c22" | ||||||
|  | dependencies = [ | ||||||
|  |  "dirs", | ||||||
|  |  "libc", | ||||||
|  |  "once_cell", | ||||||
|  |  "shell-escape", | ||||||
|  |  "tempfile", | ||||||
|  |  "thiserror", | ||||||
|  |  "tokio", | ||||||
|  |  "tokio-pipe", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "openssh-sftp-client" | ||||||
|  | version = "0.12.2" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "f4fa8e5f26e549bd266d9bcd9e5b4fd344729985ef1a7f5ac3e51f3f96a4a620" | ||||||
|  | dependencies = [ | ||||||
|  |  "bytes", | ||||||
|  |  "derive_destructure2", | ||||||
|  |  "once_cell", | ||||||
|  |  "openssh-sftp-client-lowlevel", | ||||||
|  |  "openssh-sftp-error", | ||||||
|  |  "scopeguard", | ||||||
|  |  "tokio", | ||||||
|  |  "tokio-io-utility", | ||||||
|  |  "tokio-util", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "openssh-sftp-client-lowlevel" | ||||||
|  | version = "0.4.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "406bf41d8372365497d5645e802a8dfe22008b8183edbe6c79e4b75614431daa" | ||||||
|  | dependencies = [ | ||||||
|  |  "awaitable", | ||||||
|  |  "bytes", | ||||||
|  |  "concurrent_arena", | ||||||
|  |  "derive_destructure2", | ||||||
|  |  "openssh-sftp-error", | ||||||
|  |  "openssh-sftp-protocol", | ||||||
|  |  "pin-project", | ||||||
|  |  "tokio", | ||||||
|  |  "tokio-io-utility", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "openssh-sftp-error" | ||||||
|  | version = "0.3.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "3d836b428ead150165d1178ed0aa672791c13b3ae9616ea1e34d13730a2cb486" | ||||||
|  | dependencies = [ | ||||||
|  |  "awaitable-error", | ||||||
|  |  "openssh-sftp-protocol-error", | ||||||
|  |  "ssh_format_error", | ||||||
|  |  "thiserror", | ||||||
|  |  "tokio", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "openssh-sftp-protocol" | ||||||
|  | version = "0.24.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "bf38532d784978966f95d241226223823f351d5bb2a4bebcf6b20b9cb1e393e0" | ||||||
|  | dependencies = [ | ||||||
|  |  "bitflags 2.0.2", | ||||||
|  |  "num-derive", | ||||||
|  |  "num-traits", | ||||||
|  |  "openssh-sftp-protocol-error", | ||||||
|  |  "serde", | ||||||
|  |  "ssh_format", | ||||||
|  |  "vec-strings", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "openssh-sftp-protocol-error" | ||||||
|  | version = "0.1.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "0719269eb3f037866ae07ec89cb44ed2c1d63b72b2390cef8e1aa3016a956ff8" | ||||||
|  | dependencies = [ | ||||||
|  |  "serde", | ||||||
|  |  "thiserror", | ||||||
|  |  "vec-strings", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "os_pipe" | name = "os_pipe" | ||||||
| version = "1.0.1" | version = "1.0.1" | ||||||
| @ -1028,6 +1288,29 @@ version = "6.1.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" | checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "ouroboros" | ||||||
|  | version = "0.15.6" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e1358bd1558bd2a083fed428ffeda486fbfb323e698cdda7794259d592ca72db" | ||||||
|  | dependencies = [ | ||||||
|  |  "aliasable", | ||||||
|  |  "ouroboros_macro", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "ouroboros_macro" | ||||||
|  | version = "0.15.6" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" | ||||||
|  | dependencies = [ | ||||||
|  |  "Inflector", | ||||||
|  |  "proc-macro-error", | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "syn 1.0.96", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "parking" | name = "parking" | ||||||
| version = "2.0.0" | version = "2.0.0" | ||||||
| @ -1052,11 +1335,31 @@ checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" | |||||||
| dependencies = [ | dependencies = [ | ||||||
|  "cfg-if 1.0.0", |  "cfg-if 1.0.0", | ||||||
|  "libc", |  "libc", | ||||||
|  "redox_syscall", |  "redox_syscall 0.2.13", | ||||||
|  "smallvec", |  "smallvec", | ||||||
|  "windows-sys 0.36.1", |  "windows-sys 0.36.1", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "pin-project" | ||||||
|  | version = "1.0.12" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" | ||||||
|  | dependencies = [ | ||||||
|  |  "pin-project-internal", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "pin-project-internal" | ||||||
|  | version = "1.0.12" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "syn 1.0.96", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "pin-project-lite" | name = "pin-project-lite" | ||||||
| version = "0.2.9" | version = "0.2.9" | ||||||
| @ -1189,7 +1492,16 @@ version = "0.2.13" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" | checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "redox_syscall" | ||||||
|  | version = "0.3.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" | ||||||
|  | dependencies = [ | ||||||
|  |  "bitflags 1.3.2", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| @ -1198,7 +1510,7 @@ version = "0.1.2" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" | checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "redox_syscall", |  "redox_syscall 0.2.13", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| @ -1208,7 +1520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||||
| checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "getrandom", |  "getrandom", | ||||||
|  "redox_syscall", |  "redox_syscall 0.2.13", | ||||||
|  "thiserror", |  "thiserror", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -1235,7 +1547,7 @@ version = "0.24.2" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "d5f38ee71cbab2c827ec0ac24e76f82eca723cee92c509a65f67dee393c25112" | checksum = "d5f38ee71cbab2c827ec0ac24e76f82eca723cee92c509a65f67dee393c25112" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "fallible-iterator", |  "fallible-iterator", | ||||||
|  "fallible-streaming-iterator", |  "fallible-streaming-iterator", | ||||||
|  "hashlink", |  "hashlink", | ||||||
| @ -1250,16 +1562,30 @@ version = "0.33.7" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "938a344304321a9da4973b9ff4f9f8db9caf4597dfd9dda6a60b523340a0fff0" | checksum = "938a344304321a9da4973b9ff4f9f8db9caf4597dfd9dda6a60b523340a0fff0" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "errno", |  "errno 0.2.8", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "itoa", |  "itoa", | ||||||
|  "libc", |  "libc", | ||||||
|  "linux-raw-sys", |  "linux-raw-sys 0.0.42", | ||||||
|  "once_cell", |  "once_cell", | ||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "rustix" | ||||||
|  | version = "0.37.6" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d097081ed288dfe45699b72f5b5d648e5f15d64d900c7080273baa20c16a6849" | ||||||
|  | dependencies = [ | ||||||
|  |  "bitflags 1.3.2", | ||||||
|  |  "errno 0.3.0", | ||||||
|  |  "io-lifetimes 1.0.9", | ||||||
|  |  "libc", | ||||||
|  |  "linux-raw-sys 0.3.1", | ||||||
|  |  "windows-sys 0.45.0", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "rustversion" | name = "rustversion" | ||||||
| version = "1.0.6" | version = "1.0.6" | ||||||
| @ -1272,7 +1598,7 @@ version = "7.1.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "8227301bfc717136f0ecbd3d064ba8199e44497a0bdd46bb01ede4387cfd2cec" | checksum = "8227301bfc717136f0ecbd3d064ba8199e44497a0bdd46bb01ede4387cfd2cec" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "cfg-if 1.0.0", |  "cfg-if 1.0.0", | ||||||
|  "dirs-next", |  "dirs-next", | ||||||
|  "fs2", |  "fs2", | ||||||
| @ -1357,6 +1683,12 @@ dependencies = [ | |||||||
|  "serde", |  "serde", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "shell-escape" | ||||||
|  | version = "0.1.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "signal-hook" | name = "signal-hook" | ||||||
| version = "0.3.14" | version = "0.3.14" | ||||||
| @ -1399,6 +1731,16 @@ version = "1.8.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" | checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "socket2" | ||||||
|  | version = "0.4.9" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" | ||||||
|  | dependencies = [ | ||||||
|  |  "libc", | ||||||
|  |  "winapi", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "socketpair" | name = "socketpair" | ||||||
| version = "0.14.0" | version = "0.14.0" | ||||||
| @ -1406,8 +1748,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||||
| checksum = "2f0c0b3fc17356799222affc5a40345b7cc25b548c489c5a31eca0888ee2404c" | checksum = "2f0c0b3fc17356799222affc5a40345b7cc25b548c489c5a31eca0888ee2404c" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "io-extras", |  "io-extras", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "rustix", |  "rustix 0.33.7", | ||||||
|  "uuid", |  "uuid", | ||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| @ -1424,6 +1766,32 @@ dependencies = [ | |||||||
|  "serde", |  "serde", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "ssh_format" | ||||||
|  | version = "0.14.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "24ab31081d1c9097c327ec23550858cb5ffb4af6b866c1ef4d728455f01f3304" | ||||||
|  | dependencies = [ | ||||||
|  |  "bytes", | ||||||
|  |  "serde", | ||||||
|  |  "ssh_format_error", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "ssh_format_error" | ||||||
|  | version = "0.1.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "be3c6519de7ca611f71ef7e8a56eb57aa1c818fecb5242d0a0f39c83776c210c" | ||||||
|  | dependencies = [ | ||||||
|  |  "serde", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "stable_deref_trait" | ||||||
|  | version = "1.2.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "static_assertions" | name = "static_assertions" | ||||||
| version = "1.1.0" | version = "1.1.0" | ||||||
| @ -1484,11 +1852,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||||
| checksum = "1e09bb3fb4e02ec4b87e182ea9718fadbc0fa3e50085b40a9af9690572b67f9e" | checksum = "1e09bb3fb4e02ec4b87e182ea9718fadbc0fa3e50085b40a9af9690572b67f9e" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "atty", |  "atty", | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "cap-fs-ext", |  "cap-fs-ext", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "os_pipe", |  "os_pipe", | ||||||
|  "rustix", |  "rustix 0.33.7", | ||||||
|  "socketpair", |  "socketpair", | ||||||
|  "winapi", |  "winapi", | ||||||
|  "winx", |  "winx", | ||||||
| @ -1500,6 +1868,19 @@ version = "0.1.11" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "af547b166dd1ea4b472165569fc456cfb6818116f854690b0ff205e636523dab" | checksum = "af547b166dd1ea4b472165569fc456cfb6818116f854690b0ff205e636523dab" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "tempfile" | ||||||
|  | version = "3.5.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" | ||||||
|  | dependencies = [ | ||||||
|  |  "cfg-if 1.0.0", | ||||||
|  |  "fastrand", | ||||||
|  |  "redox_syscall 0.3.5", | ||||||
|  |  "rustix 0.37.6", | ||||||
|  |  "windows-sys 0.45.0", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "termcolor" | name = "termcolor" | ||||||
| version = "1.1.3" | version = "1.1.3" | ||||||
| @ -1527,7 +1908,7 @@ checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" | |||||||
| dependencies = [ | dependencies = [ | ||||||
|  "libc", |  "libc", | ||||||
|  "numtoa", |  "numtoa", | ||||||
|  "redox_syscall", |  "redox_syscall 0.2.13", | ||||||
|  "redox_termios", |  "redox_termios", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -1538,23 +1919,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||||
| checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" | checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "thiserror" | name = "thin-vec" | ||||||
| version = "1.0.31" | version = "0.2.12" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" | checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "thiserror" | ||||||
|  | version = "1.0.40" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "thiserror-impl", |  "thiserror-impl", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "thiserror-impl" | name = "thiserror-impl" | ||||||
| version = "1.0.31" | version = "1.0.40" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
|  "quote", |  "quote", | ||||||
|  "syn 1.0.96", |  "syn 2.0.13", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| @ -1585,10 +1972,59 @@ checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" | |||||||
| dependencies = [ | dependencies = [ | ||||||
|  "autocfg", |  "autocfg", | ||||||
|  "bytes", |  "bytes", | ||||||
|  |  "libc", | ||||||
|  |  "mio", | ||||||
|  "pin-project-lite", |  "pin-project-lite", | ||||||
|  |  "signal-hook-registry", | ||||||
|  |  "socket2", | ||||||
|  |  "tokio-macros", | ||||||
|  "windows-sys 0.45.0", |  "windows-sys 0.45.0", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "tokio-io-utility" | ||||||
|  | version = "0.7.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "6948d15bb5da6f565846828025df4d7b503df3890f0fcdb9a667de1c81bc1976" | ||||||
|  | dependencies = [ | ||||||
|  |  "bytes", | ||||||
|  |  "tokio", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "tokio-macros" | ||||||
|  | version = "2.0.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "syn 2.0.13", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "tokio-pipe" | ||||||
|  | version = "0.2.12" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "f213a84bffbd61b8fa0ba8a044b4bbe35d471d0b518867181e82bd5c15542784" | ||||||
|  | dependencies = [ | ||||||
|  |  "libc", | ||||||
|  |  "tokio", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "tokio-util" | ||||||
|  | version = "0.7.7" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" | ||||||
|  | dependencies = [ | ||||||
|  |  "bytes", | ||||||
|  |  "futures-core", | ||||||
|  |  "futures-sink", | ||||||
|  |  "pin-project-lite", | ||||||
|  |  "tokio", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "toml" | name = "toml" | ||||||
| version = "0.5.9" | version = "0.5.9" | ||||||
| @ -1598,6 +2034,17 @@ dependencies = [ | |||||||
|  "serde", |  "serde", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "triomphe" | ||||||
|  | version = "0.1.8" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db" | ||||||
|  | dependencies = [ | ||||||
|  |  "arc-swap", | ||||||
|  |  "serde", | ||||||
|  |  "stable_deref_trait", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "twox-hash" | name = "twox-hash" | ||||||
| version = "1.6.3" | version = "1.6.3" | ||||||
| @ -1657,6 +2104,16 @@ version = "0.2.15" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "vec-strings" | ||||||
|  | version = "0.4.8" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "c8509489e2a7ee219522238ad45fd370bec6808811ac15ac6b07453804e77659" | ||||||
|  | dependencies = [ | ||||||
|  |  "serde", | ||||||
|  |  "thin-vec", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "version_check" | name = "version_check" | ||||||
| version = "0.9.4" | version = "0.9.4" | ||||||
| @ -1838,8 +2295,8 @@ version = "0.31.0" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "08d5973cb8cd94a77d03ad7e23bbe14889cb29805da1cec0e4aff75e21aebded" | checksum = "08d5973cb8cd94a77d03ad7e23bbe14889cb29805da1cec0e4aff75e21aebded" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "bitflags", |  "bitflags 1.3.2", | ||||||
|  "io-lifetimes", |  "io-lifetimes 0.5.3", | ||||||
|  "winapi", |  "winapi", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -1903,6 +2360,16 @@ version = "0.1.0" | |||||||
| [[package]] | [[package]] | ||||||
| name = "yama_wormfile_sftp" | name = "yama_wormfile_sftp" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "async-trait", | ||||||
|  |  "openssh", | ||||||
|  |  "openssh-sftp-client", | ||||||
|  |  "ouroboros", | ||||||
|  |  "rand", | ||||||
|  |  "thiserror", | ||||||
|  |  "tokio", | ||||||
|  |  "yama_wormfile", | ||||||
|  | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "zstd" | name = "zstd" | ||||||
|  | |||||||
| @ -1,4 +1,5 @@ | |||||||
| use std::borrow::Borrow; | use std::borrow::Borrow; | ||||||
|  | use std::fmt::{Debug, Formatter}; | ||||||
| 
 | 
 | ||||||
| /// Simplified version of `Path` for use in WormFile situations.
 | /// Simplified version of `Path` for use in WormFile situations.
 | ||||||
| /// The Path is guaranteed to remain within the root and does not contain any `.` or `..` elements.
 | /// The Path is guaranteed to remain within the root and does not contain any `.` or `..` elements.
 | ||||||
| @ -7,6 +8,12 @@ pub struct WormPath { | |||||||
|     inner: str, |     inner: str, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl Debug for WormPath { | ||||||
|  |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         write!(f, "<{}>", &self.inner) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl WormPath { | impl WormPath { | ||||||
|     pub fn new(path_str: &str) -> Option<&WormPath> { |     pub fn new(path_str: &str) -> Option<&WormPath> { | ||||||
|         if path_str |         if path_str | ||||||
| @ -70,6 +77,12 @@ pub struct WormPathBuf { | |||||||
|     inner: String, |     inner: String, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl Debug for WormPathBuf { | ||||||
|  |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         write!(f, "<{}>", self.inner) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl WormPathBuf { | impl WormPathBuf { | ||||||
|     pub fn new(path_string: String) -> Option<WormPathBuf> { |     pub fn new(path_string: String) -> Option<WormPathBuf> { | ||||||
|         if path_string |         if path_string | ||||||
|  | |||||||
| @ -6,3 +6,12 @@ edition = "2021" | |||||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
|  | yama_wormfile = { version = "0.1.0", path = "../yama_wormfile" } | ||||||
|  | 
 | ||||||
|  | ouroboros = "0.15.6" | ||||||
|  | openssh = "0.9.9" | ||||||
|  | openssh-sftp-client = "0.12.2" | ||||||
|  | async-trait = "0.1.68" | ||||||
|  | tokio = { version = "1.27.0", features = ["io-std"] } | ||||||
|  | rand = "0.8.5" | ||||||
|  | thiserror = "1.0.40" | ||||||
| @ -0,0 +1,463 @@ | |||||||
|  | extern crate core; | ||||||
|  | 
 | ||||||
|  | use async_trait::async_trait; | ||||||
|  | use openssh::{KnownHosts, RemoteChild, Session, Stdio}; | ||||||
|  | use openssh_sftp_client::error::SftpErrorKind; | ||||||
|  | use openssh_sftp_client::file::TokioCompatFile; | ||||||
|  | use openssh_sftp_client::fs::Fs; | ||||||
|  | use openssh_sftp_client::Error::SftpError; | ||||||
|  | use openssh_sftp_client::Sftp; | ||||||
|  | use ouroboros::self_referencing; | ||||||
|  | use std::fmt::{Debug, Formatter}; | ||||||
|  | use std::io; | ||||||
|  | use std::io::{ErrorKind, SeekFrom}; | ||||||
|  | use std::path::{Path, PathBuf}; | ||||||
|  | use std::pin::Pin; | ||||||
|  | use std::sync::Arc; | ||||||
|  | use std::task::{Context, Poll}; | ||||||
|  | use thiserror::Error; | ||||||
|  | use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite, AsyncWriteExt, ReadBuf}; | ||||||
|  | use yama_wormfile::paths::{WormPath, WormPathBuf}; | ||||||
|  | use yama_wormfile::{WormFileProvider, WormFileReader, WormFileWriter}; | ||||||
|  | 
 | ||||||
|  | /// WormFileProvider that uses an SFTP connection, in a given root directory.
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct SftpWormFilesystem { | ||||||
|  |     conn: Arc<SftpConn>, | ||||||
|  | 
 | ||||||
|  |     /// The root directory.
 | ||||||
|  |     root_dir: PathBuf, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[self_referencing] | ||||||
|  | struct SftpConn { | ||||||
|  |     /// The SSH session.
 | ||||||
|  |     ssh: Session, | ||||||
|  | 
 | ||||||
|  |     /// The SSH child process
 | ||||||
|  |     #[borrows(ssh)] | ||||||
|  |     #[covariant] | ||||||
|  |     ssh_child: RemoteChild<'this>, | ||||||
|  | 
 | ||||||
|  |     /// The SFTP client.
 | ||||||
|  |     #[borrows(mut ssh_child)] | ||||||
|  |     sftp: Sftp, | ||||||
|  | 
 | ||||||
|  |     root_dir: PathBuf, | ||||||
|  |     // #[borrows(sftp)]
 | ||||||
|  |     // #[covariant]
 | ||||||
|  |     // fs: Fs<'this>,
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[self_referencing] | ||||||
|  | struct FileWithSftpConn { | ||||||
|  |     conn: Arc<SftpConn>, | ||||||
|  |     #[borrows(conn)] | ||||||
|  |     #[covariant] | ||||||
|  |     file: Option<TokioCompatFile<'this>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl SftpConn { | ||||||
|  |     pub async fn create(ssh_connect: &str, root_dir: impl Into<PathBuf>) -> YWSResult<Self> { | ||||||
|  |         let root_dir = root_dir.into(); | ||||||
|  |         let session = Session::connect(ssh_connect, KnownHosts::Strict).await?; | ||||||
|  | 
 | ||||||
|  |         let res = SftpConnAsyncTryBuilder { | ||||||
|  |             ssh: session, | ||||||
|  |             ssh_child_builder: |ssh| { | ||||||
|  |                 Box::pin(async move { | ||||||
|  |                     ssh.subsystem("sftp") | ||||||
|  |                         .stdin(Stdio::piped()) | ||||||
|  |                         .stdout(Stdio::piped()) | ||||||
|  |                         .spawn() | ||||||
|  |                         .await | ||||||
|  |                         .map_err(SftpWormFileError::from) | ||||||
|  |                 }) | ||||||
|  |             }, | ||||||
|  |             sftp_builder: |ssh_child| { | ||||||
|  |                 Box::pin(async move { | ||||||
|  |                     Sftp::new( | ||||||
|  |                         ssh_child.stdin().take().unwrap(), | ||||||
|  |                         ssh_child.stdout().take().unwrap(), | ||||||
|  |                         Default::default(), | ||||||
|  |                     ) | ||||||
|  |                     .await | ||||||
|  |                     .map_err(SftpWormFileError::from) | ||||||
|  |                 }) | ||||||
|  |             }, | ||||||
|  |             // fs_builder: |sftp| Box::pin(async move {
 | ||||||
|  |             //     let mut fs = sftp.fs();
 | ||||||
|  |             //     fs.set_cwd(&root_dir);
 | ||||||
|  |             //     Ok(fs)
 | ||||||
|  |             // })
 | ||||||
|  |             root_dir, | ||||||
|  |         } | ||||||
|  |         .try_build() | ||||||
|  |         .await?; | ||||||
|  |         Ok(res) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_fs(&self) -> Fs<'_> { | ||||||
|  |         let mut fs = self.borrow_sftp().fs(); | ||||||
|  |         fs.set_cwd(&self.borrow_root_dir()); | ||||||
|  |         fs | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn create_dir_all(&self, worm_path_as_pathbuf: PathBuf) -> YWSResult<()> { | ||||||
|  |         let mut fs = self.get_fs(); | ||||||
|  |         let mut stack = vec![]; | ||||||
|  | 
 | ||||||
|  |         let mut at = Some(worm_path_as_pathbuf); | ||||||
|  |         while let Some(at_path) = at { | ||||||
|  |             match fs.metadata(&at_path).await { | ||||||
|  |                 Ok(_) => { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 Err(SftpError(SftpErrorKind::NoSuchFile, _)) => { | ||||||
|  |                     at = at_path.parent().map(Path::to_owned); | ||||||
|  |                     stack.push(at_path); | ||||||
|  |                 } | ||||||
|  |                 Err(sftp_err) => { | ||||||
|  |                     return Err(SftpWormFileError::SftpError(sftp_err)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         while let Some(path) = stack.pop() { | ||||||
|  |             fs.create_dir(path).await?; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Debug for SftpConn { | ||||||
|  |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         write!(f, "<SftpConn>") | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Error)] | ||||||
|  | pub enum SftpWormFileError { | ||||||
|  |     #[error("ssh error: {0:?}")] | ||||||
|  |     SshError(#[from] openssh::Error), | ||||||
|  | 
 | ||||||
|  |     #[error("sftp error: {0:?}")] | ||||||
|  |     SftpError(#[from] openssh_sftp_client::Error), | ||||||
|  | 
 | ||||||
|  |     #[error("error: {0}")] | ||||||
|  |     Message(String), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type YWSResult<T> = Result<T, SftpWormFileError>; | ||||||
|  | 
 | ||||||
|  | impl SftpWormFilesystem { | ||||||
|  |     pub async fn new( | ||||||
|  |         ssh_connect: &str, | ||||||
|  |         root_dir: impl Into<PathBuf>, | ||||||
|  |     ) -> YWSResult<SftpWormFilesystem> { | ||||||
|  |         let root_dir = root_dir.into(); | ||||||
|  | 
 | ||||||
|  |         let conn = Arc::new(SftpConn::create(ssh_connect, &root_dir).await?); | ||||||
|  | 
 | ||||||
|  |         if !conn | ||||||
|  |             .get_fs() | ||||||
|  |             .metadata(".") | ||||||
|  |             .await? | ||||||
|  |             .file_type() | ||||||
|  |             .unwrap() | ||||||
|  |             .is_dir() | ||||||
|  |         { | ||||||
|  |             return Err(SftpWormFileError::Message(format!( | ||||||
|  |                 "{root_dir:?} is not a dir on SFTP remote." | ||||||
|  |             ))); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Ok(SftpWormFilesystem { conn, root_dir }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_fs(&self) -> Fs<'_> { | ||||||
|  |         let mut fs = self.conn.borrow_sftp().fs(); | ||||||
|  |         fs.set_cwd(&self.root_dir); | ||||||
|  |         fs | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[async_trait] | ||||||
|  | impl WormFileProvider for SftpWormFilesystem { | ||||||
|  |     type WormFileReader = SftpWormReader; | ||||||
|  |     type WormFileWriter = SftpWormWriter; | ||||||
|  |     type Error = SftpWormFileError; | ||||||
|  | 
 | ||||||
|  |     async fn is_dir(&self, path: impl AsRef<WormPath> + Send) -> Result<bool, Self::Error> { | ||||||
|  |         let path = path.as_ref().as_str(); | ||||||
|  |         let mut fs = self.get_fs(); | ||||||
|  |         match fs.metadata(path).await { | ||||||
|  |             Ok(meta) => Ok(meta.file_type().unwrap().is_dir()), | ||||||
|  |             Err(SftpError(SftpErrorKind::NoSuchFile, _)) => Ok(false), | ||||||
|  |             Err(sftp_err) => Err(SftpWormFileError::SftpError(sftp_err)), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn is_regular_file( | ||||||
|  |         &self, | ||||||
|  |         path: impl AsRef<WormPath> + Send, | ||||||
|  |     ) -> Result<bool, Self::Error> { | ||||||
|  |         let path = path.as_ref().as_str(); | ||||||
|  |         let mut fs = self.get_fs(); | ||||||
|  |         match fs.metadata(path).await { | ||||||
|  |             Ok(meta) => Ok(meta.file_type().unwrap().is_file()), | ||||||
|  |             Err(SftpError(SftpErrorKind::NoSuchFile, _)) => Ok(false), | ||||||
|  |             Err(sftp_err) => Err(SftpWormFileError::SftpError(sftp_err)), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn list( | ||||||
|  |         &self, | ||||||
|  |         path: impl AsRef<WormPath> + Send, | ||||||
|  |     ) -> Result<Vec<WormPathBuf>, Self::Error> { | ||||||
|  |         let worm_path = path.as_ref(); | ||||||
|  |         let path = worm_path.as_str(); | ||||||
|  |         let mut fs = self.get_fs(); | ||||||
|  | 
 | ||||||
|  |         let mut remote_dir = fs.open_dir(path).await?; | ||||||
|  |         let dir_reader = remote_dir.read_dir().await?; | ||||||
|  | 
 | ||||||
|  |         Ok(dir_reader | ||||||
|  |             .iter() | ||||||
|  |             .filter_map(|entry| { | ||||||
|  |                 if let Some(name_str) = entry.filename().as_os_str().to_str() { | ||||||
|  |                     if name_str.is_empty() || name_str == "." || name_str == ".." { | ||||||
|  |                         None | ||||||
|  |                     } else { | ||||||
|  |                         Some(worm_path.join(name_str).expect("pre-checked")) | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     None | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |             .collect()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn read( | ||||||
|  |         &self, | ||||||
|  |         path: impl AsRef<WormPath> + Send, | ||||||
|  |     ) -> Result<Self::WormFileReader, Self::Error> { | ||||||
|  |         let real_path = self.root_dir.join(path.as_ref().as_str()); | ||||||
|  | 
 | ||||||
|  |         let real_path2 = real_path.clone(); | ||||||
|  |         // the `Send` in the below line is very important...
 | ||||||
|  |         let file_with_conn: FileWithSftpConn = FileWithSftpConnAsyncSendTryBuilder { | ||||||
|  |             conn: self.conn.clone(), | ||||||
|  |             file_builder: |conn| { | ||||||
|  |                 Box::pin(async move { | ||||||
|  |                     let file = conn | ||||||
|  |                         .borrow_sftp() | ||||||
|  |                         .open(real_path) | ||||||
|  |                         .await | ||||||
|  |                         .map_err(SftpWormFileError::from)?; | ||||||
|  |                     Ok::<_, SftpWormFileError>(Some(TokioCompatFile::new(file))) | ||||||
|  |                 }) | ||||||
|  |             }, | ||||||
|  |         } | ||||||
|  |         .try_build() | ||||||
|  |         .await?; | ||||||
|  | 
 | ||||||
|  |         Ok(SftpWormReader { | ||||||
|  |             path: real_path2, | ||||||
|  |             file_with_conn, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     async fn write(&self) -> Result<Self::WormFileWriter, Self::Error> { | ||||||
|  |         // let tmp_dir = self.root_dir.join("tmp");
 | ||||||
|  |         // if !tokio::fs::try_exists(&tmp_dir).await? {
 | ||||||
|  |         //     tokio::fs::create_dir(&tmp_dir).await?;
 | ||||||
|  |         // }
 | ||||||
|  |         //
 | ||||||
|  |         // let (tmp_path, file) = loop {
 | ||||||
|  |         //     let rand_num: u32 = rand::random();
 | ||||||
|  |         //     let pid = std::process::id();
 | ||||||
|  |         //
 | ||||||
|  |         //     let try_fn = format!("pid{pid}-{rand_num:08X}.writing");
 | ||||||
|  |         //     let try_path = tmp_dir.join(try_fn);
 | ||||||
|  |         //     match OpenOptions::new().create_new(true).open(&try_path).await {
 | ||||||
|  |         //         Ok(file) => break (try_path, file),
 | ||||||
|  |         //         Err(err) => {
 | ||||||
|  |         //             if err.kind() == ErrorKind::AlreadyExists {
 | ||||||
|  |         //                 continue;
 | ||||||
|  |         //             } else {
 | ||||||
|  |         //                 return Err(err);
 | ||||||
|  |         //             }
 | ||||||
|  |         //         }
 | ||||||
|  |         //     }
 | ||||||
|  |         // };
 | ||||||
|  |         //
 | ||||||
|  |         // Ok(SftpWormWriter {
 | ||||||
|  |         //     temp_path: tmp_path,
 | ||||||
|  |         //     file,
 | ||||||
|  |         //     root_dir: self.root_dir.clone(),
 | ||||||
|  |         // })
 | ||||||
|  |         todo!() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct SftpWormReader { | ||||||
|  |     path: PathBuf, | ||||||
|  |     file_with_conn: FileWithSftpConn, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Debug for SftpWormReader { | ||||||
|  |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         write!(f, "FileWormReader({:?})", self.path) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl AsyncRead for SftpWormReader { | ||||||
|  |     fn poll_read( | ||||||
|  |         mut self: Pin<&mut Self>, | ||||||
|  |         cx: &mut Context<'_>, | ||||||
|  |         buf: &mut ReadBuf<'_>, | ||||||
|  |     ) -> Poll<io::Result<()>> { | ||||||
|  |         self.file_with_conn | ||||||
|  |             .with_file_mut(|file| Pin::new(file.as_mut().unwrap()).poll_read(cx, buf)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl AsyncSeek for SftpWormReader { | ||||||
|  |     fn start_seek(mut self: Pin<&mut Self>, position: SeekFrom) -> io::Result<()> { | ||||||
|  |         self.file_with_conn | ||||||
|  |             .with_file_mut(|file| Pin::new(file.as_mut().unwrap()).start_seek(position)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> { | ||||||
|  |         self.file_with_conn | ||||||
|  |             .with_file_mut(|file| Pin::new(file.as_mut().unwrap()).poll_complete(cx)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl WormFileReader for SftpWormReader {} | ||||||
|  | 
 | ||||||
|  | pub struct SftpWormWriter { | ||||||
|  |     temp_path: PathBuf, | ||||||
|  |     file_with_conn: FileWithSftpConn, | ||||||
|  |     root_dir: PathBuf, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Debug for SftpWormWriter { | ||||||
|  |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         write!(f, "FileWormWriter({:?})", self.temp_path) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl AsyncWrite for SftpWormWriter { | ||||||
|  |     fn poll_write( | ||||||
|  |         mut self: Pin<&mut Self>, | ||||||
|  |         cx: &mut Context<'_>, | ||||||
|  |         buf: &[u8], | ||||||
|  |     ) -> Poll<Result<usize, io::Error>> { | ||||||
|  |         self.file_with_conn | ||||||
|  |             .with_file_mut(|file| Pin::new(file.as_mut().unwrap()).poll_write(cx, buf)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { | ||||||
|  |         self.file_with_conn | ||||||
|  |             .with_file_mut(|file| Pin::new(file.as_mut().unwrap()).poll_flush(cx)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn poll_shutdown( | ||||||
|  |         mut self: Pin<&mut Self>, | ||||||
|  |         cx: &mut Context<'_>, | ||||||
|  |     ) -> Poll<Result<(), io::Error>> { | ||||||
|  |         self.file_with_conn | ||||||
|  |             .with_file_mut(|file| Pin::new(file.as_mut().unwrap()).poll_shutdown(cx)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[async_trait] | ||||||
|  | impl WormFileWriter for SftpWormWriter { | ||||||
|  |     async fn finalise(mut self, target_path: &WormPath, replace: bool) -> io::Result<()> { | ||||||
|  |         self.flush().await?; | ||||||
|  | 
 | ||||||
|  |         let SftpWormWriter { | ||||||
|  |             root_dir, | ||||||
|  |             temp_path, | ||||||
|  |             mut file_with_conn, | ||||||
|  |             .. | ||||||
|  |         } = self; | ||||||
|  | 
 | ||||||
|  |         let file = file_with_conn.with_file_mut(|file| file.take().unwrap()); | ||||||
|  |         file.close() | ||||||
|  |             .await | ||||||
|  |             .map_err(|e| io::Error::new(ErrorKind::Other, e))?; | ||||||
|  | 
 | ||||||
|  |         let conn: Arc<SftpConn> = file_with_conn.into_heads().conn; | ||||||
|  |         let mut fs = conn.get_fs(); | ||||||
|  | 
 | ||||||
|  |         let worm_path = target_path; | ||||||
|  | 
 | ||||||
|  |         // Directories will be created as needed.
 | ||||||
|  |         if let Some(parent) = PathBuf::from(worm_path.as_str()).parent() { | ||||||
|  |             conn.create_dir_all(parent.to_owned()) | ||||||
|  |                 .await | ||||||
|  |                 .map_err(|e| io::Error::new(ErrorKind::Other, e))?; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Avoid allowing a replacement if not intended.
 | ||||||
|  |         // But this is currently not atomic, so it's just a sanity check rather than a foolproof
 | ||||||
|  |         // safeguard!
 | ||||||
|  |         if !replace { | ||||||
|  |             match fs.metadata(worm_path.as_str()).await { | ||||||
|  |                 Ok(_) => { | ||||||
|  |                     return Err(io::Error::new( | ||||||
|  |                         ErrorKind::AlreadyExists, | ||||||
|  |                         "finalise()ing a writer: dest already exists and replace = false", | ||||||
|  |                     )); | ||||||
|  |                 } | ||||||
|  |                 Err(SftpError(SftpErrorKind::NoSuchFile, _)) => { | ||||||
|  |                     // ideal. nop.
 | ||||||
|  |                 } | ||||||
|  |                 Err(sftp_err) => { | ||||||
|  |                     return Err(SftpWormFileError::SftpError(sftp_err)) | ||||||
|  |                         .map_err(|e| io::Error::new(ErrorKind::Other, e))?; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Perform the move.
 | ||||||
|  |         fs.rename(root_dir.join(&temp_path), root_dir.join(worm_path.as_str())) | ||||||
|  |             .await | ||||||
|  |             .map_err(|e| io::Error::new(ErrorKind::Other, e))?; | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[tokio::test] | ||||||
|  | async fn test_lol() { | ||||||
|  |     let swf = SftpWormFilesystem::new("scone@sallie", "").await.unwrap(); | ||||||
|  |     let _ = swf.is_dir(WormPath::new("maddy").unwrap()).await; | ||||||
|  | 
 | ||||||
|  |     match swf.is_dir(WormPath::new("maddyss").unwrap()).await { | ||||||
|  |         Ok(x) => eprintln!("{x:?}"), | ||||||
|  |         Err(SftpWormFileError::SftpError(openssh_sftp_client::Error::SftpError( | ||||||
|  |             openssh_sftp_client::error::SftpErrorKind::NoSuchFile, | ||||||
|  |             _, | ||||||
|  |         ))) => { | ||||||
|  |             eprintln!("NSF"); | ||||||
|  |         } | ||||||
|  |         Err(other) => { | ||||||
|  |             eprintln!("other {other:?}"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let x = swf.list(WormPath::new("maddy").unwrap()).await.unwrap(); | ||||||
|  |     eprintln!("{x:?}"); | ||||||
|  | 
 | ||||||
|  |     // if let Err(e) = swf.sftp.close().await {
 | ||||||
|  |     //     eprintln!("sftp {e:?}");
 | ||||||
|  |     // }
 | ||||||
|  |     //
 | ||||||
|  |     // if let Err(e) = swf.ssh.close().await {
 | ||||||
|  |     //     eprintln!("sftp {e:?}");
 | ||||||
|  |     // }
 | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user