fix(sync): S-03 — symlink detection and cycle protection
This commit is contained in:
+12
@@ -1481,6 +1481,12 @@ fn handle_sync(
|
||||
" • Bereits aktuell: {} Dateien (übersprungen)",
|
||||
stats.files_skipped
|
||||
);
|
||||
if stats.files_skipped_symlinks > 0 {
|
||||
println!(
|
||||
" • Symlinks: {} übersprungen",
|
||||
stats.files_skipped_symlinks
|
||||
);
|
||||
}
|
||||
if delete {
|
||||
println!(
|
||||
" • Zu löschen: {} Dateien/Ordner",
|
||||
@@ -1508,6 +1514,12 @@ fn handle_sync(
|
||||
" • Übersprungen: {} Dateien (bereits aktuell)",
|
||||
stats.files_skipped
|
||||
);
|
||||
if stats.files_skipped_symlinks > 0 {
|
||||
println!(
|
||||
" • Symlinks: {} übersprungen",
|
||||
stats.files_skipped_symlinks
|
||||
);
|
||||
}
|
||||
if delete {
|
||||
println!(
|
||||
" • Gelöscht: {} verwaiste Dateien/Ordner",
|
||||
|
||||
+39
-2
@@ -105,6 +105,7 @@ pub struct SyncStats {
|
||||
pub files_scanned: usize,
|
||||
pub files_transferred: usize,
|
||||
pub files_skipped: usize,
|
||||
pub files_skipped_symlinks: usize,
|
||||
pub files_deleted: usize,
|
||||
pub bytes_transferred: u64,
|
||||
pub elapsed: Duration,
|
||||
@@ -485,6 +486,21 @@ fn sync_push(
|
||||
target_str
|
||||
};
|
||||
|
||||
let sym_meta = fs::symlink_metadata(local_source)?;
|
||||
if sym_meta.file_type().is_symlink() {
|
||||
stats.files_scanned += 1;
|
||||
stats.files_skipped += 1;
|
||||
stats.files_skipped_symlinks += 1;
|
||||
if !options.quiet {
|
||||
println!(
|
||||
" {} Symlink übersprungen: {}",
|
||||
ui::yellow("[!]"),
|
||||
source_str
|
||||
);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if local_source.is_file() {
|
||||
let file_name = local_source
|
||||
.file_name()
|
||||
@@ -615,6 +631,22 @@ fn collect_and_push_dir(
|
||||
continue;
|
||||
}
|
||||
|
||||
// S-03: Symlinks standardmäßig überspringen (Schutz vor Zyklen und Rekursion)
|
||||
let sym_meta = match fs::symlink_metadata(&path) {
|
||||
Ok(m) => m,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
if sym_meta.file_type().is_symlink() {
|
||||
stats.files_scanned += 1;
|
||||
stats.files_skipped += 1;
|
||||
stats.files_skipped_symlinks += 1;
|
||||
if !options.quiet {
|
||||
println!(" {} Symlink übersprungen: {}", ui::yellow("[!]"), rel_path);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
local_relative_paths.insert(rel_path.clone());
|
||||
|
||||
if path.is_dir() {
|
||||
@@ -1071,9 +1103,14 @@ fn delete_orphans_on_host(
|
||||
}
|
||||
}
|
||||
|
||||
let is_symlink = match fs::symlink_metadata(&path) {
|
||||
Ok(m) => m.file_type().is_symlink(),
|
||||
Err(_) => false,
|
||||
};
|
||||
|
||||
if !vault_relative_paths.contains(&rel_path) {
|
||||
stats.files_deleted += 1;
|
||||
if path.is_dir() {
|
||||
if path.is_dir() && !is_symlink {
|
||||
if dry_run {
|
||||
if !quiet {
|
||||
println!(
|
||||
@@ -1104,7 +1141,7 @@ fn delete_orphans_on_host(
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if path.is_dir() {
|
||||
} else if path.is_dir() && !is_symlink {
|
||||
delete_orphans_on_host(
|
||||
base_dir,
|
||||
&path,
|
||||
|
||||
Reference in New Issue
Block a user