Fix code quality: trailing whitespace, unused imports, clippy warnings
- Fix trailing whitespace in kex.rs and s3.rs - Add missing KexProposal import in kex_complete.rs - Auto-fix clippy warnings across all crates - All 153 tests pass
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
// SCP协议实现(Phase 8)
|
||||
// 参考OpenSSH scp.c源码
|
||||
|
||||
use crate::vfs::{VfsBackend, VfsFile, VfsError, VfsStat};
|
||||
use crate::vfs::open_flags::OpenFlags;
|
||||
use anyhow::{Result, anyhow};
|
||||
use log::{info, warn, debug};
|
||||
use crate::vfs::{VfsBackend, VfsFile, VfsStat};
|
||||
use anyhow::{anyhow, Result};
|
||||
use log::{debug, info, warn};
|
||||
use std::io::{BufRead, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::io::{Read, Write, BufRead};
|
||||
use std::time::SystemTime;
|
||||
|
||||
/// SCP Handler(参考OpenSSH scp.c)
|
||||
pub struct ScpHandler {
|
||||
@@ -38,13 +37,13 @@ impl ScpHandler {
|
||||
/// 解析SCP命令(参考OpenSSH scp.c: parse_command())
|
||||
pub fn parse_scp_command(command: &str, vfs: Box<dyn VfsBackend>) -> Result<Self> {
|
||||
let parts: Vec<&str> = command.split_whitespace().collect();
|
||||
|
||||
|
||||
if parts.len() < 2 || parts[0] != "scp" {
|
||||
return Err(anyhow!("Invalid SCP command: {}", command));
|
||||
}
|
||||
|
||||
let mut handler = ScpHandler::new(PathBuf::from("/tmp"), vfs);
|
||||
|
||||
|
||||
for part in &parts[1..] {
|
||||
match part {
|
||||
&"-f" => handler.mode = ScpMode::Source,
|
||||
@@ -71,10 +70,15 @@ impl ScpHandler {
|
||||
|
||||
/// SCP Source Mode(scp -f,发送文件)
|
||||
fn handle_source_mode(&self, channel: &mut dyn ReadWrite) -> Result<()> {
|
||||
info!("SCP source mode: sending files from {}", self.root_dir.display());
|
||||
info!(
|
||||
"SCP source mode: sending files from {}",
|
||||
self.root_dir.display()
|
||||
);
|
||||
|
||||
let full_path = self.resolve_path(&self.root_dir.to_string_lossy())?;
|
||||
let stat = self.vfs.stat(&full_path)
|
||||
let stat = self
|
||||
.vfs
|
||||
.stat(&full_path)
|
||||
.map_err(|e| anyhow!("stat error: {}", e))?;
|
||||
|
||||
if stat.is_dir {
|
||||
@@ -91,16 +95,19 @@ impl ScpHandler {
|
||||
|
||||
/// SCP Destination Mode(scp -t,接收文件)
|
||||
fn handle_destination_mode(&mut self, channel: &mut dyn ReadWrite) -> Result<()> {
|
||||
info!("SCP destination mode: receiving files to {}", self.root_dir.display());
|
||||
info!(
|
||||
"SCP destination mode: receiving files to {}",
|
||||
self.root_dir.display()
|
||||
);
|
||||
|
||||
channel.write_all(&[0])?;
|
||||
channel.flush()?;
|
||||
|
||||
|
||||
let mut buffer = String::new();
|
||||
|
||||
|
||||
loop {
|
||||
buffer.clear();
|
||||
|
||||
|
||||
let mut reader = std::io::BufReader::new(&mut *channel);
|
||||
match reader.read_line(&mut buffer)? {
|
||||
0 => break,
|
||||
@@ -130,7 +137,9 @@ impl ScpHandler {
|
||||
|
||||
/// 发送文件(参考OpenSSH scp.c: source())
|
||||
fn send_file(&self, channel: &mut dyn ReadWrite, path: &Path) -> Result<()> {
|
||||
let stat = self.vfs.stat(path)
|
||||
let stat = self
|
||||
.vfs
|
||||
.stat(path)
|
||||
.map_err(|e| anyhow!("stat error: {}", e))?;
|
||||
let size = stat.size;
|
||||
let filename = path.file_name().unwrap().to_string_lossy();
|
||||
@@ -146,13 +155,16 @@ impl ScpHandler {
|
||||
}
|
||||
|
||||
let flags = OpenFlags::new().read();
|
||||
let mut file = self.vfs.open_file(path, &flags)
|
||||
let mut file = self
|
||||
.vfs
|
||||
.open_file(path, &flags)
|
||||
.map_err(|e| anyhow!("open error: {}", e))?;
|
||||
|
||||
let mut buffer = vec![0u8; 8192];
|
||||
|
||||
loop {
|
||||
let n = file.read(&mut buffer)
|
||||
let n = file
|
||||
.read(&mut buffer)
|
||||
.map_err(|e| anyhow!("read error: {}", e))?;
|
||||
if n == 0 {
|
||||
break;
|
||||
@@ -188,7 +200,9 @@ impl ScpHandler {
|
||||
return Err(anyhow!("SCP directory command rejected"));
|
||||
}
|
||||
|
||||
let entries = self.vfs.read_dir(path)
|
||||
let entries = self
|
||||
.vfs
|
||||
.read_dir(path)
|
||||
.map_err(|e| anyhow!("read_dir error: {}", e))?;
|
||||
|
||||
for entry in &entries {
|
||||
@@ -218,7 +232,7 @@ impl ScpHandler {
|
||||
/// 处理文件命令(C0644 size filename)
|
||||
fn handle_file_command(&self, channel: &mut dyn ReadWrite, command: &str) -> Result<()> {
|
||||
let parts: Vec<&str> = command.split_whitespace().collect();
|
||||
|
||||
|
||||
if parts.len() != 3 {
|
||||
return self.send_error(channel, "Invalid file command format");
|
||||
}
|
||||
@@ -227,7 +241,10 @@ impl ScpHandler {
|
||||
let size: u64 = parts[1].parse()?;
|
||||
let filename = parts[2];
|
||||
|
||||
debug!("SCP receive file: mode={}, size={}, name={}", mode_str, size, filename);
|
||||
debug!(
|
||||
"SCP receive file: mode={}, size={}, name={}",
|
||||
mode_str, size, filename
|
||||
);
|
||||
|
||||
if size > 1024 * 1024 * 1024 {
|
||||
return self.send_error(channel, "File too large (max 1GB)");
|
||||
@@ -236,7 +253,9 @@ impl ScpHandler {
|
||||
let full_path = self.resolve_path(filename)?;
|
||||
|
||||
let flags = OpenFlags::new().write().create().truncate();
|
||||
let mut file = self.vfs.open_file(&full_path, &flags)
|
||||
let mut file = self
|
||||
.vfs
|
||||
.open_file(&full_path, &flags)
|
||||
.map_err(|e| anyhow!("open error: {}", e))?;
|
||||
|
||||
channel.write_all(&[0])?;
|
||||
@@ -263,7 +282,8 @@ impl ScpHandler {
|
||||
if mode_int != 0 {
|
||||
let mut set_stat = VfsStat::new();
|
||||
set_stat.mode = mode_int;
|
||||
self.vfs.set_stat(&full_path, &set_stat)
|
||||
self.vfs
|
||||
.set_stat(&full_path, &set_stat)
|
||||
.map_err(|e| anyhow!("set_stat error: {}", e))?;
|
||||
}
|
||||
|
||||
@@ -280,7 +300,7 @@ impl ScpHandler {
|
||||
/// 处理目录命令(D0755 0 dirname)
|
||||
fn handle_directory_command(&self, channel: &mut dyn ReadWrite, command: &str) -> Result<()> {
|
||||
let parts: Vec<&str> = command.split_whitespace().collect();
|
||||
|
||||
|
||||
if parts.len() != 3 {
|
||||
return self.send_error(channel, "Invalid directory command format");
|
||||
}
|
||||
@@ -297,7 +317,8 @@ impl ScpHandler {
|
||||
let full_path = self.resolve_path(dirname)?;
|
||||
|
||||
let mode_int: u32 = mode_str.parse()?;
|
||||
self.vfs.create_dir_all(&full_path, mode_int)
|
||||
self.vfs
|
||||
.create_dir_all(&full_path, mode_int)
|
||||
.map_err(|e| anyhow!("create_dir_all error: {}", e))?;
|
||||
|
||||
channel.write_all(&[0])?;
|
||||
@@ -326,7 +347,7 @@ impl ScpHandler {
|
||||
}
|
||||
|
||||
let parts: Vec<&str> = command.split_whitespace().collect();
|
||||
|
||||
|
||||
if parts.len() != 3 {
|
||||
return self.send_error(channel, "Invalid time command format");
|
||||
}
|
||||
@@ -353,11 +374,15 @@ impl ScpHandler {
|
||||
/// 路径解析(安全性检查)
|
||||
fn resolve_path(&self, path: &str) -> Result<PathBuf> {
|
||||
let full_path = self.root_dir.join(path);
|
||||
|
||||
let canonical_path = self.vfs.real_path(&full_path)
|
||||
|
||||
let canonical_path = self
|
||||
.vfs
|
||||
.real_path(&full_path)
|
||||
.map_err(|e| anyhow!("Path resolution error: {}", e))?;
|
||||
|
||||
let root_canonical = self.vfs.real_path(&self.root_dir)
|
||||
let root_canonical = self
|
||||
.vfs
|
||||
.real_path(&self.root_dir)
|
||||
.map_err(|e| anyhow!("Root path resolution error: {}", e))?;
|
||||
|
||||
if !canonical_path.starts_with(&root_canonical) {
|
||||
@@ -383,20 +408,23 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_scp_command_parse() {
|
||||
let handler = ScpHandler::parse_scp_command("scp -t /tmp", Box::new(LocalFs::new())).unwrap();
|
||||
let handler =
|
||||
ScpHandler::parse_scp_command("scp -t /tmp", Box::new(LocalFs::new())).unwrap();
|
||||
assert_eq!(handler.mode, ScpMode::Destination);
|
||||
assert_eq!(handler.root_dir, PathBuf::from("/tmp"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scp_recursive_parse() {
|
||||
let handler = ScpHandler::parse_scp_command("scp -r -t /tmp", Box::new(LocalFs::new())).unwrap();
|
||||
let handler =
|
||||
ScpHandler::parse_scp_command("scp -r -t /tmp", Box::new(LocalFs::new())).unwrap();
|
||||
assert!(handler.recursive);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scp_source_parse() {
|
||||
let handler = ScpHandler::parse_scp_command("scp -f /tmp", Box::new(LocalFs::new())).unwrap();
|
||||
let handler =
|
||||
ScpHandler::parse_scp_command("scp -f /tmp", Box::new(LocalFs::new())).unwrap();
|
||||
assert_eq!(handler.mode, ScpMode::Source);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user