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:
Warren
2026-06-19 05:21:38 +08:00
parent 4b37e524cf
commit d94cb2df4c
135 changed files with 7256 additions and 4321 deletions

View File

@@ -1,15 +1,21 @@
use super::util;
use super::open_flags::OpenFlags;
use super::util;
use super::{VfsBackend, VfsDirEntry, VfsError, VfsFile, VfsStat};
use std::fs::{self, File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::{Path, PathBuf};
/// 本地文件系统实现(直接包装 std::fs不做路径解析
/// 路径解析由上层SftpHandler负责
pub struct LocalFs;
impl Default for LocalFs {
fn default() -> Self {
Self::new()
}
}
impl LocalFs {
pub fn new() -> Self {
Self
@@ -26,7 +32,9 @@ impl VfsFile for LocalFile {
}
fn write(&mut self, buf: &[u8]) -> Result<usize, VfsError> {
self.file.write(buf).map_err(|e| VfsError::Io(e.to_string()))
self.file
.write(buf)
.map_err(|e| VfsError::Io(e.to_string()))
}
fn seek(&mut self, pos: SeekFrom) -> Result<u64, VfsError> {
@@ -38,12 +46,17 @@ impl VfsFile for LocalFile {
}
fn stat(&mut self) -> Result<VfsStat, VfsError> {
let meta = self.file.metadata().map_err(|e| VfsError::Io(e.to_string()))?;
let meta = self
.file
.metadata()
.map_err(|e| VfsError::Io(e.to_string()))?;
Ok(util::stat_from_metadata(&meta, false))
}
fn set_len(&mut self, size: u64) -> Result<(), VfsError> {
self.file.set_len(size).map_err(|e| VfsError::Io(e.to_string()))
self.file
.set_len(size)
.map_err(|e| VfsError::Io(e.to_string()))
}
}
@@ -86,8 +99,7 @@ impl VfsBackend for LocalFs {
if flags.create && !flags.exclusive {
if let Ok(meta) = file.metadata() {
if flags.mode != 0 && meta.permissions().mode() != flags.mode {
fs::set_permissions(path, std::fs::Permissions::from_mode(flags.mode))
.ok();
fs::set_permissions(path, std::fs::Permissions::from_mode(flags.mode)).ok();
}
}
}
@@ -157,10 +169,12 @@ impl VfsBackend for LocalFs {
stat.atime.duration_since(std::time::UNIX_EPOCH).ok(),
stat.mtime.duration_since(std::time::UNIX_EPOCH).ok(),
) {
filetime::set_file_times(path,
filetime::set_file_times(
path,
filetime::FileTime::from_unix_time(atime.as_secs() as i64, 0),
filetime::FileTime::from_unix_time(mtime.as_secs() as i64, 0),
).map_err(|e| util::map_io_error(path, e))?;
)
.map_err(|e| util::map_io_error(path, e))?;
}
Ok(())
@@ -174,8 +188,7 @@ impl VfsBackend for LocalFs {
fn create_symlink(&self, target: &Path, link: &Path) -> Result<(), VfsError> {
#[cfg(unix)]
{
std::os::unix::fs::symlink(target, link)
.map_err(|e| util::map_io_error(link, e))?;
std::os::unix::fs::symlink(target, link).map_err(|e| util::map_io_error(link, e))?;
}
#[cfg(not(unix))]
@@ -188,7 +201,9 @@ impl VfsBackend for LocalFs {
}
fn real_path(&self, path: &Path) -> Result<PathBuf, VfsError> {
let canonical = path.canonicalize().map_err(|e| util::map_io_error(path, e))?;
let canonical = path
.canonicalize()
.map_err(|e| util::map_io_error(path, e))?;
Ok(canonical)
}
@@ -204,7 +219,9 @@ impl VfsBackend for LocalFs {
#[cfg(not(unix))]
{
return Err(VfsError::Unsupported("hard_link not supported on non-Unix systems".to_string()));
return Err(VfsError::Unsupported(
"hard_link not supported on non-Unix systems".to_string(),
));
}
Ok(())

View File

@@ -1,5 +1,5 @@
pub mod open_flags;
pub mod local_fs;
pub mod open_flags;
pub mod s3_fs;
pub mod util;
@@ -120,7 +120,11 @@ pub trait VfsBackend: Send {
fn read_dir(&self, path: &Path) -> Result<Vec<VfsDirEntry>, VfsError>;
/// 打开文件(读/写)
fn open_file(&self, path: &Path, flags: &open_flags::OpenFlags) -> Result<Box<dyn VfsFile>, VfsError>;
fn open_file(
&self,
path: &Path,
flags: &open_flags::OpenFlags,
) -> Result<Box<dyn VfsFile>, VfsError>;
/// 获取文件/目录元数据
fn stat(&self, path: &Path) -> Result<VfsStat, VfsError>;

View File

@@ -56,7 +56,10 @@ impl S3Vfs {
let credentials = Credentials::new(access_key, secret_key);
Ok(Self { bucket, credentials })
Ok(Self {
bucket,
credentials,
})
}
fn path_to_key(path: &Path) -> String {
@@ -118,7 +121,10 @@ impl S3Vfs {
.map_err(|e| VfsError::Io(format!("S3 PUT failed: {}", e)))?;
if resp.status() != 200 {
return Err(VfsError::Io(format!("PutObject returned {}", resp.status())));
return Err(VfsError::Io(format!(
"PutObject returned {}",
resp.status()
)));
}
Ok(())
}
@@ -149,15 +155,15 @@ impl S3Vfs {
.map_err(|e| VfsError::Io(format!("S3 CopyObject failed: {}", e)))?;
if resp.status() != 200 {
return Err(VfsError::Io(format!("CopyObject returned {}", resp.status())));
return Err(VfsError::Io(format!(
"CopyObject returned {}",
resp.status()
)));
}
Ok(())
}
fn list_objects(
&self,
prefix: &str,
) -> Result<actions::ListObjectsV2Response, VfsError> {
fn list_objects(&self, prefix: &str) -> Result<actions::ListObjectsV2Response, VfsError> {
let mut action = actions::ListObjectsV2::new(&self.bucket, Some(&self.credentials));
if !prefix.is_empty() {
action.with_prefix(prefix);
@@ -181,9 +187,8 @@ impl S3Vfs {
.read_to_string(&mut body)
.map_err(|e| VfsError::Io(format!("Failed to read S3 list response: {}", e)))?;
actions::ListObjectsV2::parse_response(&body).map_err(|e| {
VfsError::Io(format!("Failed to parse S3 list response XML: {}", e))
})
actions::ListObjectsV2::parse_response(&body)
.map_err(|e| VfsError::Io(format!("Failed to parse S3 list response XML: {}", e)))
}
}
@@ -409,7 +414,9 @@ impl VfsBackend for S3Vfs {
impl VfsFile for S3VfsFile {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, VfsError> {
let to_read = buf.len().min((self.size.saturating_sub(self.position)) as usize);
let to_read = buf
.len()
.min((self.size.saturating_sub(self.position)) as usize);
if to_read == 0 {
return Ok(0);
}
@@ -443,7 +450,7 @@ impl VfsFile for S3VfsFile {
self.position = sz.saturating_add(offset as u64);
} else {
let abs = offset.unsigned_abs();
self.position = if abs <= sz { sz - abs } else { 0 };
self.position = sz.saturating_sub(abs);
}
}
std::io::SeekFrom::Current(offset) => {
@@ -451,11 +458,7 @@ impl VfsFile for S3VfsFile {
self.position = self.position.saturating_add(offset as u64);
} else {
let abs = offset.unsigned_abs();
self.position = if abs <= self.position {
self.position - abs
} else {
0
};
self.position = self.position.saturating_sub(abs);
}
}
}
@@ -549,7 +552,10 @@ impl S3VfsLike {
.map_err(|e| VfsError::Io(format!("S3 PUT failed: {}", e)))?;
if resp.status() != 200 {
return Err(VfsError::Io(format!("PutObject returned {}", resp.status())));
return Err(VfsError::Io(format!(
"PutObject returned {}",
resp.status()
)));
}
Ok(())
}
@@ -612,10 +618,7 @@ mod tests {
#[test]
fn test_path_to_key() {
assert_eq!(
S3Vfs::path_to_key(Path::new("/foo/bar.txt")),
"foo/bar.txt"
);
assert_eq!(S3Vfs::path_to_key(Path::new("/foo/bar.txt")), "foo/bar.txt");
assert_eq!(S3Vfs::path_to_key(Path::new("/")), "");
assert_eq!(
S3Vfs::path_to_key(Path::new("relative/path")),

View File

@@ -7,7 +7,9 @@ use std::path::Path;
pub fn map_io_error(path: &Path, e: std::io::Error) -> VfsError {
match e.kind() {
std::io::ErrorKind::NotFound => VfsError::NotFound(path.display().to_string()),
std::io::ErrorKind::PermissionDenied => VfsError::PermissionDenied(path.display().to_string()),
std::io::ErrorKind::PermissionDenied => {
VfsError::PermissionDenied(path.display().to_string())
}
std::io::ErrorKind::AlreadyExists => VfsError::AlreadyExists(path.display().to_string()),
std::io::ErrorKind::DirectoryNotEmpty => VfsError::NotEmpty(path.display().to_string()),
std::io::ErrorKind::NotADirectory => VfsError::NotADirectory(path.display().to_string()),
@@ -65,13 +67,7 @@ pub fn build_long_name(stat: &VfsStat, name: &str) -> String {
format!(
"{}{} {} {} {} {} {} {}",
file_type, perms,
link_count,
stat.uid,
stat.gid,
size,
mtime,
name
file_type, perms, link_count, stat.uid, stat.gid, size, mtime, name
)
}