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,8 +1,8 @@
|
||||
use std::path::PathBuf;
|
||||
use anyhow::{Result, anyhow};
|
||||
use log::{info, debug, warn};
|
||||
use crate::vfs::{VfsBackend, VfsFile, VfsError};
|
||||
use crate::vfs::open_flags::OpenFlags;
|
||||
use crate::vfs::{VfsBackend, VfsFile};
|
||||
use anyhow::{anyhow, Result};
|
||||
use log::{debug, info, warn};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// MPLEX_BASE from rsync io.h
|
||||
const MPLEX_BASE: u32 = 7;
|
||||
@@ -18,7 +18,9 @@ pub(crate) enum RsyncState {
|
||||
WaitVersion,
|
||||
ReadFileList,
|
||||
/// Sum head (4 × write_int = 16 bytes) + checksum seed (4 bytes) = 20 bytes
|
||||
ReadSumHead { need: usize },
|
||||
ReadSumHead {
|
||||
need: usize,
|
||||
},
|
||||
SendSumCount,
|
||||
/// Raw file data from MSG_DATA packets
|
||||
ReadFileData,
|
||||
@@ -51,9 +53,16 @@ impl RsyncHandler {
|
||||
let mut dest = String::new();
|
||||
|
||||
for p in &parts[1..] {
|
||||
if *p == "--server" { is_server = true; continue; }
|
||||
if *p == "--sender" || p.starts_with('-') { continue; }
|
||||
if *p == "." { continue; }
|
||||
if *p == "--server" {
|
||||
is_server = true;
|
||||
continue;
|
||||
}
|
||||
if *p == "--sender" || p.starts_with('-') {
|
||||
continue;
|
||||
}
|
||||
if *p == "." {
|
||||
continue;
|
||||
}
|
||||
dest = p.to_string();
|
||||
}
|
||||
|
||||
@@ -107,8 +116,10 @@ impl RsyncHandler {
|
||||
break;
|
||||
}
|
||||
let header = u32::from_le_bytes([
|
||||
self.raw_input[0], self.raw_input[1],
|
||||
self.raw_input[2], self.raw_input[3],
|
||||
self.raw_input[0],
|
||||
self.raw_input[1],
|
||||
self.raw_input[2],
|
||||
self.raw_input[3],
|
||||
]);
|
||||
let raw_tag = ((header >> 24) & 0xFF) as u8;
|
||||
let tag = raw_tag.wrapping_sub(MPLEX_BASE as u8);
|
||||
@@ -182,12 +193,17 @@ impl RsyncHandler {
|
||||
RsyncState::WaitVersion => {
|
||||
if self.rsync_input.len() >= 4 {
|
||||
let version = u32::from_le_bytes([
|
||||
self.rsync_input[0], self.rsync_input[1],
|
||||
self.rsync_input[2], self.rsync_input[3],
|
||||
self.rsync_input[0],
|
||||
self.rsync_input[1],
|
||||
self.rsync_input[2],
|
||||
self.rsync_input[3],
|
||||
]);
|
||||
self.rsync_input.drain(..4);
|
||||
self.protocol_version = std::cmp::min(self.protocol_version, version);
|
||||
info!("rsync: negotiated protocol version {}", self.protocol_version);
|
||||
info!(
|
||||
"rsync: negotiated protocol version {}",
|
||||
self.protocol_version
|
||||
);
|
||||
self.multiplex = self.protocol_version >= 30;
|
||||
self.transition(RsyncState::ReadFileList);
|
||||
} else {
|
||||
@@ -197,7 +213,9 @@ impl RsyncHandler {
|
||||
|
||||
RsyncState::ReadFileList => {
|
||||
loop {
|
||||
if self.rsync_input.is_empty() { break; }
|
||||
if self.rsync_input.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
let flags = self.rsync_input[0];
|
||||
if flags == 0 {
|
||||
@@ -215,17 +233,25 @@ impl RsyncHandler {
|
||||
let mut pos = 1;
|
||||
|
||||
let _more_flags = if flags & 0x80 != 0 {
|
||||
if self.rsync_input.len() <= pos { break; }
|
||||
if self.rsync_input.len() <= pos {
|
||||
break;
|
||||
}
|
||||
let ef = self.rsync_input[pos];
|
||||
pos += 1;
|
||||
ef
|
||||
} else { 0 };
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let has_name = !(flags & 0x02 != 0 && self.current_file > 0);
|
||||
|
||||
if has_name {
|
||||
if let Some(nul_pos) = self.rsync_input[pos..].iter().position(|&b| b == 0) {
|
||||
let name = String::from_utf8_lossy(&self.rsync_input[pos..pos + nul_pos]).to_string();
|
||||
if let Some(nul_pos) =
|
||||
self.rsync_input[pos..].iter().position(|&b| b == 0)
|
||||
{
|
||||
let name =
|
||||
String::from_utf8_lossy(&self.rsync_input[pos..pos + nul_pos])
|
||||
.to_string();
|
||||
pos += nul_pos + 1;
|
||||
self.file_entries.push(name.clone());
|
||||
debug!("rsync: file entry: {}", name);
|
||||
@@ -269,24 +295,34 @@ impl RsyncHandler {
|
||||
RsyncState::ReadSumHead { need } => {
|
||||
if self.rsync_input.len() >= need {
|
||||
let sum_count = i32::from_le_bytes([
|
||||
self.rsync_input[0], self.rsync_input[1],
|
||||
self.rsync_input[2], self.rsync_input[3],
|
||||
self.rsync_input[0],
|
||||
self.rsync_input[1],
|
||||
self.rsync_input[2],
|
||||
self.rsync_input[3],
|
||||
]);
|
||||
let _sum_blength = i32::from_le_bytes([
|
||||
self.rsync_input[4], self.rsync_input[5],
|
||||
self.rsync_input[6], self.rsync_input[7],
|
||||
self.rsync_input[4],
|
||||
self.rsync_input[5],
|
||||
self.rsync_input[6],
|
||||
self.rsync_input[7],
|
||||
]);
|
||||
let _sum_s2length = i32::from_le_bytes([
|
||||
self.rsync_input[8], self.rsync_input[9],
|
||||
self.rsync_input[10], self.rsync_input[11],
|
||||
self.rsync_input[8],
|
||||
self.rsync_input[9],
|
||||
self.rsync_input[10],
|
||||
self.rsync_input[11],
|
||||
]);
|
||||
let _sum_remainder = i32::from_le_bytes([
|
||||
self.rsync_input[12], self.rsync_input[13],
|
||||
self.rsync_input[14], self.rsync_input[15],
|
||||
self.rsync_input[12],
|
||||
self.rsync_input[13],
|
||||
self.rsync_input[14],
|
||||
self.rsync_input[15],
|
||||
]);
|
||||
let checksum_seed = i32::from_le_bytes([
|
||||
self.rsync_input[16], self.rsync_input[17],
|
||||
self.rsync_input[18], self.rsync_input[19],
|
||||
self.rsync_input[16],
|
||||
self.rsync_input[17],
|
||||
self.rsync_input[18],
|
||||
self.rsync_input[19],
|
||||
]);
|
||||
self.rsync_input.drain(..20);
|
||||
|
||||
@@ -308,7 +344,9 @@ impl RsyncHandler {
|
||||
|
||||
RsyncState::ReadFileData => {
|
||||
let done_marker = b"RSYNCDONE";
|
||||
if let Some(pos) = self.rsync_input.windows(done_marker.len())
|
||||
if let Some(pos) = self
|
||||
.rsync_input
|
||||
.windows(done_marker.len())
|
||||
.position(|w| w == done_marker)
|
||||
{
|
||||
if pos > 0 {
|
||||
@@ -323,8 +361,11 @@ impl RsyncHandler {
|
||||
warn!("rsync flush error: {}", e);
|
||||
}
|
||||
}
|
||||
info!("rsync: file {} complete ({} bytes written to {})",
|
||||
self.file_entries.get(self.current_file).unwrap_or(&"?".to_string()),
|
||||
info!(
|
||||
"rsync: file {} complete ({} bytes written to {})",
|
||||
self.file_entries
|
||||
.get(self.current_file)
|
||||
.unwrap_or(&"?".to_string()),
|
||||
self.total_written,
|
||||
self.dest_path.display(),
|
||||
);
|
||||
@@ -332,8 +373,11 @@ impl RsyncHandler {
|
||||
self.current_file += 1;
|
||||
if self.current_file >= self.file_entries.len() {
|
||||
self.transition(RsyncState::Done);
|
||||
info!("rsync ALL DONE: {} bytes written to {}",
|
||||
self.total_written, self.dest_path.display());
|
||||
info!(
|
||||
"rsync ALL DONE: {} bytes written to {}",
|
||||
self.total_written,
|
||||
self.dest_path.display()
|
||||
);
|
||||
} else {
|
||||
self.transition(RsyncState::ReadSumHead { need: 20 });
|
||||
}
|
||||
@@ -360,7 +404,9 @@ impl RsyncHandler {
|
||||
self.vfs.create_dir_all(parent, 0o755).ok();
|
||||
}
|
||||
let flags = OpenFlags::new().write().create().truncate();
|
||||
let file = self.vfs.open_file(&self.dest_path, &flags)
|
||||
let file = self
|
||||
.vfs
|
||||
.open_file(&self.dest_path, &flags)
|
||||
.map_err(|e| anyhow!("open error: {}", e))?;
|
||||
self.output_file = Some(file);
|
||||
info!("rsync: opened {} for writing", self.dest_path.display());
|
||||
@@ -379,31 +425,43 @@ impl RsyncHandler {
|
||||
|
||||
/// Read rsync varint (LSB-first 7-bit groups, 0xFF prefix for negative)
|
||||
fn read_varint(buf: &[u8]) -> Option<(i32, usize)> {
|
||||
if buf.is_empty() { return None; }
|
||||
if buf.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut pos = 0;
|
||||
let mut b = buf[pos];
|
||||
pos += 1;
|
||||
|
||||
let neg = if b == 0xFF {
|
||||
if pos >= buf.len() { return None; }
|
||||
if pos >= buf.len() {
|
||||
return None;
|
||||
}
|
||||
b = buf[pos];
|
||||
pos += 1;
|
||||
true
|
||||
} else { false };
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let mut x = (b & 0x7F) as i32;
|
||||
let mut shift = 7;
|
||||
|
||||
while b & 0x80 != 0 {
|
||||
if pos >= buf.len() { return None; }
|
||||
if pos >= buf.len() {
|
||||
return None;
|
||||
}
|
||||
b = buf[pos];
|
||||
pos += 1;
|
||||
x |= ((b & 0x7F) as i32) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
|
||||
if neg { Some((-x, pos)) } else { Some((x, pos)) }
|
||||
if neg {
|
||||
Some((-x, pos))
|
||||
} else {
|
||||
Some((x, pos))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -419,8 +477,9 @@ mod tests {
|
||||
fn test_parse_command() {
|
||||
let h = RsyncHandler::parse_rsync_command(
|
||||
"rsync --server -g -l -o -p -D -r -t -v --dirs . /tmp/upload.bin",
|
||||
make_vfs()
|
||||
).unwrap();
|
||||
make_vfs(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(h.dest_path, PathBuf::from("/tmp/upload.bin"));
|
||||
}
|
||||
|
||||
@@ -428,14 +487,16 @@ mod tests {
|
||||
fn test_parse_command_sender() {
|
||||
let h = RsyncHandler::parse_rsync_command(
|
||||
"rsync --server --sender -vlogDtprz . /home/user/file.txt",
|
||||
make_vfs()
|
||||
).unwrap();
|
||||
make_vfs(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(h.dest_path, PathBuf::from("/home/user/file.txt"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version_exchange() {
|
||||
let mut h = RsyncHandler::parse_rsync_command("rsync --server . /tmp/test.bin", make_vfs()).unwrap();
|
||||
let mut h = RsyncHandler::parse_rsync_command("rsync --server . /tmp/test.bin", make_vfs())
|
||||
.unwrap();
|
||||
let output = h.drain_output();
|
||||
assert_eq!(output, b"\x1e\x00\x00\x00");
|
||||
assert_eq!(h.state, RsyncState::WaitVersion);
|
||||
@@ -447,7 +508,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_version_negotiate_down() {
|
||||
let mut h = RsyncHandler::parse_rsync_command("rsync --server . /tmp/test.bin", make_vfs()).unwrap();
|
||||
let mut h = RsyncHandler::parse_rsync_command("rsync --server . /tmp/test.bin", make_vfs())
|
||||
.unwrap();
|
||||
let _ = h.drain_output();
|
||||
h.feed(b"\x1d\x00\x00\x00").unwrap();
|
||||
assert_eq!(h.protocol_version, 29);
|
||||
@@ -464,26 +526,33 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_file_list_multiplex() {
|
||||
let mut h = RsyncHandler::parse_rsync_command("rsync --server . /tmp/rsync_test.bin", make_vfs()).unwrap();
|
||||
let mut h =
|
||||
RsyncHandler::parse_rsync_command("rsync --server . /tmp/rsync_test.bin", make_vfs())
|
||||
.unwrap();
|
||||
let _ = h.drain_output();
|
||||
h.feed(b"\x1e\x00\x00\x00").unwrap();
|
||||
assert!(h.multiplex);
|
||||
|
||||
let mut flist = Vec::new();
|
||||
// File list: flags=1 (has name), then name with NUL terminator
|
||||
flist.push(1); // flags: has name
|
||||
flist.push(1); // flags: has name
|
||||
flist.extend_from_slice(b"test.txt");
|
||||
flist.push(0); // name terminator
|
||||
flist.push(0); // name terminator
|
||||
|
||||
fn write_varint(buf: &mut Vec<u8>, val: i32) {
|
||||
if val == 0 { buf.push(0); return; }
|
||||
if val == 0 {
|
||||
buf.push(0);
|
||||
return;
|
||||
}
|
||||
if val < 0 {
|
||||
buf.push(0xFF);
|
||||
let mut v = (-val) as u32;
|
||||
while v > 0 {
|
||||
let mut byte = (v & 0x7F) as u8;
|
||||
v >>= 7;
|
||||
if v > 0 { byte |= 0x80; }
|
||||
if v > 0 {
|
||||
byte |= 0x80;
|
||||
}
|
||||
buf.push(byte);
|
||||
}
|
||||
} else {
|
||||
@@ -491,7 +560,9 @@ mod tests {
|
||||
while v > 0 {
|
||||
let mut byte = (v & 0x7F) as u8;
|
||||
v >>= 7;
|
||||
if v > 0 { byte |= 0x80; }
|
||||
if v > 0 {
|
||||
byte |= 0x80;
|
||||
}
|
||||
buf.push(byte);
|
||||
}
|
||||
}
|
||||
@@ -502,7 +573,7 @@ mod tests {
|
||||
write_varint(&mut flist, 1700000000);
|
||||
write_varint(&mut flist, 100);
|
||||
write_varint(&mut flist, 0);
|
||||
flist.push(0); // file list end marker
|
||||
flist.push(0); // file list end marker
|
||||
|
||||
let mut sum_head = Vec::new();
|
||||
sum_head.extend_from_slice(&0i32.to_le_bytes());
|
||||
@@ -527,22 +598,51 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_file_data_multiplex() {
|
||||
let mut h = RsyncHandler::parse_rsync_command("rsync --server . /tmp/rsync_test.bin", make_vfs()).unwrap();
|
||||
let mut h =
|
||||
RsyncHandler::parse_rsync_command("rsync --server . /tmp/rsync_test.bin", make_vfs())
|
||||
.unwrap();
|
||||
let _ = h.drain_output();
|
||||
h.feed(b"\x1e\x00\x00\x00").unwrap();
|
||||
|
||||
let mut flist = Vec::new();
|
||||
flist.push(1); // flags: has name
|
||||
flist.push(1); // flags: has name
|
||||
flist.extend_from_slice(b"test.bin");
|
||||
flist.push(0);
|
||||
fn wv(buf: &mut Vec<u8>, val: i32) {
|
||||
if val == 0 { buf.push(0); return; }
|
||||
if val < 0 { buf.push(0xFF); let mut v = (-val) as u32; while v > 0 { let mut byte = (v & 0x7F) as u8; v >>= 7; if v > 0 { byte |= 0x80; } buf.push(byte); } }
|
||||
else { let mut v = val as u32; while v > 0 { let mut byte = (v & 0x7F) as u8; v >>= 7; if v > 0 { byte |= 0x80; } buf.push(byte); } }
|
||||
if val == 0 {
|
||||
buf.push(0);
|
||||
return;
|
||||
}
|
||||
if val < 0 {
|
||||
buf.push(0xFF);
|
||||
let mut v = (-val) as u32;
|
||||
while v > 0 {
|
||||
let mut byte = (v & 0x7F) as u8;
|
||||
v >>= 7;
|
||||
if v > 0 {
|
||||
byte |= 0x80;
|
||||
}
|
||||
buf.push(byte);
|
||||
}
|
||||
} else {
|
||||
let mut v = val as u32;
|
||||
while v > 0 {
|
||||
let mut byte = (v & 0x7F) as u8;
|
||||
v >>= 7;
|
||||
if v > 0 {
|
||||
byte |= 0x80;
|
||||
}
|
||||
buf.push(byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
wv(&mut flist, 33188); wv(&mut flist, 501); wv(&mut flist, 20);
|
||||
wv(&mut flist, 1700000000); wv(&mut flist, 100); wv(&mut flist, 0);
|
||||
flist.push(0); // file list end
|
||||
wv(&mut flist, 33188);
|
||||
wv(&mut flist, 501);
|
||||
wv(&mut flist, 20);
|
||||
wv(&mut flist, 1700000000);
|
||||
wv(&mut flist, 100);
|
||||
wv(&mut flist, 0);
|
||||
flist.push(0); // file list end
|
||||
h.feed(&build_multiplex(&flist)).unwrap();
|
||||
|
||||
let mut sh = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user