From bc324dd4b780feac6a3b428eb535510ed12a1bda Mon Sep 17 00:00:00 2001 From: DragonSlayer_14 Date: Tue, 15 Sep 2026 23:06:03 +0200 Subject: [PATCH] Fix: drive remove/add - kein blockierender Unmount, kein stiller Fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `drive remove` brach bei einem Unmount-Fehler (z. B. fehlende Rechte, weil das Paar in einem anderen Kontext gemountet wurde) komplett ab, bevor das Paar aus der Konfiguration entfernt wurde - der Nutzer kam dann nicht mehr an sein eigenes `drive remove` heran. Der Unmount läuft jetzt best-effort (wie das bereits bestehende cleanup_credentials), ein Fehler wird geloggt statt zu blockieren. `drive add` fiel bei einem fehlgeschlagenen Konfigurations-Laden (z. B. korrupte Datei - eine fehlende Datei liefert bereits Standardwerte) still auf GlobalSettings::default() zurück. Das hätte nicht nur einen abweichenden mount_base_dir ignoriert, sondern auch das nachfolgende add_pair() (das intern selbst neu lädt) auf denselben kaputten Zustand treffen lassen - mit dem Risiko, dass alle bestehenden Paare durch die eine neue Konfiguration ersetzt werden. Ein Ladefehler bricht jetzt früh mit einer klaren Fehlermeldung ab. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LjyzpGWECyKSBWz5DtkTGz --- src/cli/drive.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/cli/drive.rs b/src/cli/drive.rs index 5a28d7f..35a08af 100644 --- a/src/cli/drive.rs +++ b/src/cli/drive.rs @@ -127,6 +127,17 @@ async fn remove(id: &str) -> anyhow::Result<()> { let cfg = config::pairs::load()?; let pair = config::pairs::find_pair(&cfg, id)?; + // Best-effort wie `cleanup_credentials` weiter unten: ein Unmount-Fehler (z. B. weil das + // Paar von einem anderen Nutzer/Kontext gemountet wurde und wir keine Berechtigung haben) + // darf das Entfernen aus der Konfiguration nicht blockieren - sonst käme der Nutzer nicht + // mehr an sein eigenes `drive remove` heran, ohne vorher erst als root/mit den richtigen + // Rechten manuell auszuhängen. + if let Err(e) = smart_mount::reconcile::unmount_pair(&pair, &cfg.settings).await { + logger_ctdra::warn( + "drive", + &format!("could not unmount drive pair '{id}' before removal: {e}"), + ); + } config::pairs::remove_pair(id)?; let creds = CredentialStore::open().await?; creds.delete(id, None).await?; @@ -173,9 +184,15 @@ async fn add(args: DriveArgs) -> anyhow::Result<()> { )?; let id = uuid::Uuid::new_v4().to_string(); - let settings = config::pairs::load() - .map(|c| c.settings) - .unwrap_or_default(); + // Bewusst KEIN `unwrap_or_default()`: ein Ladefehler bedeutet eine kaputte/korrupte + // Konfigurationsdatei (eine fehlende Datei liefert bereits Standardwerte, siehe + // `config_ctdra::load`), nicht "noch keine Konfiguration vorhanden". Stillschweigend mit + // `GlobalSettings::default()` weiterzumachen würde nicht nur einen ggf. abweichenden + // `mount_base_dir` ignorieren, sondern - schwerwiegender - auch das nachfolgende + // `add_pair()` (das intern selbst frisch lädt) auf denselben kaputten Zustand treffen + // lassen, was dort ALLE bestehenden Paare durch die eine neue Konfiguration ersetzen + // würde. Besser früh mit einem klaren Fehler abbrechen. + let settings = config::pairs::load()?.settings; let mount_point = settings.mount_base_dir.join(&id); let pair = DrivePair {