Enhance CLI output: UTF-8 console codepage, VT colors, clean status cards
This commit is contained in:
+41
-31
@@ -10,10 +10,11 @@ use hyper::service::service_fn;
|
||||
use hyper_util::rt::TokioIo;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::sync::watch;
|
||||
use tracing::{debug, error, info, warn};
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::crypto::{derive_kek, unwrap_dek};
|
||||
use crate::storage::Database;
|
||||
use crate::ui;
|
||||
use crate::vfs::SanctumFs;
|
||||
|
||||
/// Hilfsfunktion zur Formatierung des Laufwerksbuchstabens (z. B. 'S' -> "S:")
|
||||
@@ -24,7 +25,6 @@ pub fn format_drive(drive_letter: char) -> String {
|
||||
/// Trennt ein Windows-Netzlaufwerk via `net use <DRIVE>: /delete /y`.
|
||||
pub fn unmount_drive(drive_letter: char) -> Result<()> {
|
||||
let drive_str = format_drive(drive_letter);
|
||||
info!("Trennen des Netzlaufwerks {} ...", drive_str);
|
||||
|
||||
let output = Command::new("net")
|
||||
.args(["use", &drive_str, "/delete", "/y"])
|
||||
@@ -42,14 +42,12 @@ pub fn unmount_drive(drive_letter: char) -> Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
info!("Laufwerk {} erfolgreich getrennt.", drive_str);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Bindet ein Windows-Netzlaufwerk via `net use <DRIVE>: http://127.0.0.1:<PORT>/ /persistent:no` ein.
|
||||
fn run_net_use_mount(drive_str: &str, port: u16) -> Result<()> {
|
||||
let url = format!("http://127.0.0.1:{}/", port);
|
||||
info!("Verbinde Netzlaufwerk {} mit {} ...", drive_str, url);
|
||||
|
||||
let output = Command::new("net")
|
||||
.args(["use", drive_str, &url, "/persistent:no"])
|
||||
@@ -67,7 +65,6 @@ fn run_net_use_mount(drive_str: &str, port: u16) -> Result<()> {
|
||||
);
|
||||
}
|
||||
|
||||
info!("Laufwerk {} erfolgreich eingebunden!", drive_str);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -87,23 +84,20 @@ pub async fn mount_container(
|
||||
);
|
||||
}
|
||||
|
||||
info!(
|
||||
"Öffne Container '{}' ...",
|
||||
container_path.display()
|
||||
);
|
||||
println!();
|
||||
ui::step(1, 4, "📦", "Öffne Container & verifiziere Header...");
|
||||
let db = Database::open(container_path)
|
||||
.context("Konnte Container-Datenbank nicht öffnen")?;
|
||||
|
||||
info!("Lese Header und verifiziere Magic Bytes ...");
|
||||
let meta = db
|
||||
.read_meta()
|
||||
.context("Konnte Container-Header nicht lesen")?;
|
||||
|
||||
info!("Leite KEK via Argon2id ab ...");
|
||||
ui::step(2, 4, "🔑", "Leite KEK via Argon2id ab...");
|
||||
let kek = derive_kek(password, &meta.kdf_salt, &meta.kdf_params)
|
||||
.context("Schlüsselableitung fehlgeschlagen")?;
|
||||
|
||||
info!("Entschlüssele DEK via AES-256-GCM ...");
|
||||
ui::step(3, 4, "🔓", "Entschlüssele DEK via AES-256-GCM...");
|
||||
let dek = unwrap_dek(
|
||||
&kek,
|
||||
&meta.wrapped_dek,
|
||||
@@ -124,10 +118,6 @@ pub async fn mount_container(
|
||||
let listener = match TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], port_to_try))).await {
|
||||
Ok(l) => l,
|
||||
Err(_) if requested_port.is_none() => {
|
||||
info!(
|
||||
"Standard-Port {} belegt, wähle dynamischen freien Port ...",
|
||||
port_to_try
|
||||
);
|
||||
TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 0)))
|
||||
.await
|
||||
.context("Konnte keinen lokalen TCP-Port binden")?
|
||||
@@ -139,7 +129,16 @@ pub async fn mount_container(
|
||||
|
||||
let bound_addr = listener.local_addr()?;
|
||||
let bound_port = bound_addr.port();
|
||||
info!("WebDAV-Server lauscht auf http://{}", bound_addr);
|
||||
|
||||
ui::step(
|
||||
4,
|
||||
4,
|
||||
"🌐",
|
||||
&format!(
|
||||
"Starte WebDAV (Port {}) & binde Netzlaufwerk {} ein...",
|
||||
bound_port, drive_str
|
||||
),
|
||||
);
|
||||
|
||||
let (shutdown_tx, mut shutdown_rx) = watch::channel(false);
|
||||
|
||||
@@ -175,7 +174,7 @@ pub async fn mount_container(
|
||||
});
|
||||
}
|
||||
_ = shutdown_rx.changed() => {
|
||||
info!("WebDAV-Server-Task empfängt Shutdown-Signal.");
|
||||
debug!("WebDAV-Server-Task empfängt Shutdown-Signal.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -190,13 +189,15 @@ pub async fn mount_container(
|
||||
}
|
||||
|
||||
println!();
|
||||
println!("============================================================");
|
||||
println!(" Sanctum Container erfolgreich gemountet!");
|
||||
println!(" Pfad: {}", container_path.display());
|
||||
println!(" Laufwerk: {}", drive_str);
|
||||
println!(" WebDAV URL: http://127.0.0.1:{}/", bound_port);
|
||||
println!(" Drücke [Ctrl+C] zum sauberen Trennen und Schließen.");
|
||||
println!("============================================================");
|
||||
println!("┌─────────────────────────────────────────────────────────────┐");
|
||||
println!("│ ✔ Sanctum Container erfolgreich gemountet │");
|
||||
println!("└─────────────────────────────────────────────────────────────┘");
|
||||
println!();
|
||||
println!(" • Container: {}", container_path.display());
|
||||
println!(" • Netzlaufwerk: {} (im Windows Explorer bereit)", ui::cyan(&drive_str));
|
||||
println!(" • WebDAV-URL: http://127.0.0.1:{}/", bound_port);
|
||||
println!();
|
||||
println!(" [{}] Drücke [Ctrl+C] zum sicheren Trennen und Schließen.", ui::yellow("Tipp"));
|
||||
println!();
|
||||
|
||||
// Warten auf Strg+C
|
||||
@@ -205,12 +206,15 @@ pub async fn mount_container(
|
||||
.context("Fehler beim Registrieren des Ctrl+C Signalhandlers")?;
|
||||
|
||||
println!();
|
||||
info!("Beendigungssignal (Ctrl+C) erhalten.");
|
||||
info!("Trennen des Windows-Netzlaufwerks {} ...", drive_str);
|
||||
println!(" {} Beendigungssignal (Ctrl+C) empfangen.", ui::yellow("[!]"));
|
||||
print!(" {} Trenne Windows-Netzlaufwerk {} ... ", ui::dim("[-]"), drive_str);
|
||||
let _ = std::io::Write::flush(&mut std::io::stdout());
|
||||
|
||||
// Automatisches Unmount
|
||||
if let Err(e) = unmount_drive(drive_letter) {
|
||||
warn!("Warnung beim automatischen Unmount: {e}");
|
||||
println!("{}", ui::yellow(&format!("Warnung ({e})")));
|
||||
} else {
|
||||
println!("{}", ui::green("OK"));
|
||||
}
|
||||
|
||||
// HTTP Server beenden
|
||||
@@ -218,11 +222,17 @@ pub async fn mount_container(
|
||||
let _ = server_handle.await;
|
||||
|
||||
// SQLite WAL Checkpoint erzwingen
|
||||
info!("Führe SQLite WAL-Checkpoint aus (PRAGMA wal_checkpoint(TRUNCATE)) ...");
|
||||
print!(" {} Führe SQLite WAL-Checkpoint aus ... ", ui::dim("[-]"));
|
||||
let _ = std::io::Write::flush(&mut std::io::stdout());
|
||||
if let Err(e) = db.checkpoint() {
|
||||
error!("Fehler beim WAL-Checkpoint: {e}");
|
||||
println!("{}", ui::red(&format!("Fehler ({e})")));
|
||||
} else {
|
||||
println!("{}", ui::green("OK"));
|
||||
}
|
||||
|
||||
info!("Sanctum Container wurde sicher und vollständig geschlossen.");
|
||||
println!();
|
||||
println!("{} Sanctum Container wurde sicher und vollständig geschlossen.", ui::green("✔"));
|
||||
println!();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user