feat: Schreibrechte-Prüfung vor Umbenennung

- is_safe_rename() prüft jetzt Schreibrechte im Parent-Verzeichnis
- Prüfung für Quell- und Ziel-Verzeichnis
- Unix-spezifisch: Nutzt PermissionsExt für mode-Check
- Bessere Fehlermeldungen bei fehlenden Schreibrechten
- Verhindert sinnlose Rename-Versuche, die ohnehin fehlschlagen würden

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-02-10 10:26:24 +01:00
commit 60a56ec021

View file

@ -208,6 +208,7 @@ pub fn is_excluded(entry: &DirEntry, patterns: &[Pattern]) -> bool {
/// Überprüft, ob eine Umbenennungsoperation sicher ist
pub fn is_safe_rename(src: &Path, dst: &Path, force: bool) -> bool {
// Prüfen ob Ziel bereits existiert
if src.exists() && dst.exists() && !force {
warn!(
"Ziel existiert bereits und --force nicht gesetzt: {}",
@ -216,8 +217,69 @@ pub fn is_safe_rename(src: &Path, dst: &Path, force: bool) -> bool {
return false;
}
// Prüfen auf zusätzliche Sicherheitsrisiken
// z.B. Systemdateien, schreibgeschützte Verzeichnisse, etc.
// Prüfen ob Quell-Datei überhaupt existiert
if !src.exists() {
warn!("Quell-Datei existiert nicht: {}", src.display());
return false;
}
// Prüfen ob Parent-Verzeichnis der Quelle schreibbar ist
if let Some(parent) = src.parent() {
match std::fs::metadata(parent) {
Ok(metadata) => {
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let permissions = metadata.permissions();
if permissions.mode() & 0o200 == 0 {
warn!(
"Keine Schreibrechte im Verzeichnis: {}",
parent.display()
);
return false;
}
}
}
Err(e) => {
warn!(
"Kann Metadaten des Verzeichnisses nicht lesen {}: {}",
parent.display(),
e
);
return false;
}
}
}
// Prüfen ob Parent-Verzeichnis des Ziels schreibbar ist (falls unterschiedlich)
if let Some(dst_parent) = dst.parent() {
if src.parent() != Some(dst_parent) {
match std::fs::metadata(dst_parent) {
Ok(metadata) => {
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let permissions = metadata.permissions();
if permissions.mode() & 0o200 == 0 {
warn!(
"Keine Schreibrechte im Ziel-Verzeichnis: {}",
dst_parent.display()
);
return false;
}
}
}
Err(e) => {
warn!(
"Kann Metadaten des Ziel-Verzeichnisses nicht lesen {}: {}",
dst_parent.display(),
e
);
return false;
}
}
}
}
true
}