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,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(())
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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")),
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user