Papierkorb unter Rust: Crate, Netzlaufwerke, Kosten #21

Closed
opened 2026-08-28 09:22:43 +00:00 by RDietermann · 1 comment
Owner

Part of #16

Question

Wie löscht eine Rust-Desktop-App unter Windows eine Datei so, dass sie im Papierkorb landet — und was kostet das?

Entschieden ist: Gelöscht wird in den Papierkorb des Betriebssystems, nicht in einen eigenen. Offen ist das Wie.

Konkret zu klären:

  • Welche Crate ist der Standardweg (trash?), wird sie gepflegt, welche Version? Wie viele zusätzliche Pakete zieht sie in den Abhängigkeitsgraph — und lässt sich das über Features begrenzen, wie es bei rfd nötig war?
  • Was passiert auf einem Netzlaufwerk oder einem USB-Stick? Dort gibt es je nach Dateisystem und Konfiguration keinen Papierkorb. Fällt der Aufruf auf endgültiges Löschen zurück, oder schlägt er fehl?
  • Wie erfährt das Programm, welcher der beiden Fälle eingetreten ist? Der Nutzer muss wissen, ob seine Datei wiederherstellbar ist.
  • Funktioniert der Aufruf blockierend oder asynchron, und wie lange dauert er bei großen Dateien?
  • Wie sieht es unter macOS und Linux aus, falls billig zu beantworten?

Zielgröße: eine benennbare Crate mit Version, ein Aufruf-Snippet, und eine klare Aussage zum Netzlaufwerk-Fall.

Part of #16 ## Question Wie löscht eine Rust-Desktop-App unter Windows eine Datei so, dass sie im Papierkorb landet — und was kostet das? Entschieden ist: Gelöscht wird in den Papierkorb des Betriebssystems, nicht in einen eigenen. Offen ist das Wie. Konkret zu klären: - Welche Crate ist der Standardweg (`trash`?), wird sie gepflegt, welche Version? Wie viele zusätzliche Pakete zieht sie in den Abhängigkeitsgraph — und lässt sich das über Features begrenzen, wie es bei `rfd` nötig war? - Was passiert auf einem **Netzlaufwerk** oder einem **USB-Stick**? Dort gibt es je nach Dateisystem und Konfiguration keinen Papierkorb. Fällt der Aufruf auf endgültiges Löschen zurück, oder schlägt er fehl? - Wie erfährt das Programm, welcher der beiden Fälle eingetreten ist? Der Nutzer muss wissen, ob seine Datei wiederherstellbar ist. - Funktioniert der Aufruf blockierend oder asynchron, und wie lange dauert er bei großen Dateien? - Wie sieht es unter macOS und Linux aus, falls billig zu beantworten? Zielgröße: eine benennbare Crate mit Version, ein Aufruf-Snippet, und eine klare Aussage zum Netzlaufwerk-Fall.
RDietermann added the wayfinder:research label 2026-08-28 09:22:43 +00:00
RDietermann added a new dependency 2026-08-28 09:24:10 +00:00
RDietermann self-assigned this 2026-08-28 09:25:37 +00:00
Author
Owner

Papierkorb unter Rust: Ergebnis

Crate: trash, aktuell 5.2.6 (2026-05-03), gepflegt aus https://github.com/Byron/trash-rs, MIT, rust-version 1.85.

trash::delete(&pfad)?;
trash::delete_all(&pfade)?;

Kosten: +6 Pakete, und die kriegt man nicht weg

Ein Gegenstueck zum rfd/Wayland-Fall gibt es hier nicht. Die vier coinit_*-Features von trash haben leere Dependency-Listen, und das einzige wirksame Feature (chrono) ist nur unter cfg(unix) deklariert — --no-default-features spart unter Windows exakt null.

Variante Windows Linux
default +6 (419 -> 425) +4
--no-default-features +6 +2

Fuenf der sechs sind eine zweite Kopie der windows-Crate-Familie: trash haengt auf windows 0.56.0, im Lock steht ueber dioxus/wry bereits 0.61.3 — semver-inkompatibel, wird nicht dedupliziert. Auf Linux ist es harmlos (reines Rust, kein GTK/dbus), auf macOS praktisch gratis.

Netzlaufwerke — die wichtigste Frage, und die Antwort ist unangenehm

Nicht erschlossen, sondern gegen ein echtes SMB-Share gemessen. Es sind zwei getrennte Probleme:

1. trash 5.2.6 funktioniert auf Netzlaufwerken gar nicht.

trash::delete -> Err(Os { code: -2147024894,
    "windows error: Das System kann die angegebene Datei nicht finden. (0x80070002)" })
Datei existiert noch? true

Ursache ist ein Pfad-Bug, kein Papierkorb-Thema: trash kanonisiert via std::fs::canonicalize und schneidet dann stumpf \\?\ ab. Aus \\?\UNC\server\share wird UNC\server\share — Unsinn. Betrifft gemappte Laufwerksbuchstaben und UNC-Pfade gleichermassen. Das ist der seit 2022 offene Bug trash-rs#55. Immerhin: es geht nichts verloren, die Datei bleibt liegen.

2. Waere der Bug behoben, waere es gefaehrlich. IFileOperation direkt, gleiche Flags, unverbogener Pfad:

Netzlaufwerk Z:  PerformOperations -> Ok(())   GetAnyOperationsAborted -> false
                 Datei existiert noch? false   Papierkorb-Treffer: 0   <- WEG, endgueltig

Windows loescht auf Netzlaufwerken still und endgueltig und meldet denselben Erfolg wie beim Recyceln. FOF_WANTNUKEWARNING loest dabei keinen Dialog aus (trash setzt zusaetzlich FOF_SILENT|FOF_NOERRORUI).

=> Ja, die App braucht eine Rueckfrage vor dem Loeschen. Auf Ok(()) zu vertrauen reicht nicht.

Wie erfaehrt das Programm, was passiert ist?

Ueber trash gar nicht — keine Error-Variante druckt das aus, im kritischen Fall kommt Ok(()).

Zuverlaessig geht es nur ueber IFileOperationProgressSink, gemessen:

PreDeleteItem dwFlags PostDeleteItem psiNewlyCreated
lokal C: 0x282 (enthaelt TSF_DELETE_RECYCLE_IF_POSSIBLE) Some -> $Recycle.Bin\...\$R1V9IFD.md
Netz Z: 0x202 (Bit fehlt) NULL

Microsoft dokumentiert das woertlich: "If the item was fully deleted, this value is NULL." Windows sagt sogar schon vor dem Loeschen (in PreDeleteItem) per Flag-Bit, ob es recyceln wird. hrDelete taugt nicht — in beiden Faellen identisch 0x00270008.

Haken: trash uebergibt den Sink hart als None (pfo.DeleteItem(&shi, None)). Ueber die Crate-API kommt man nicht heran.

Blockierend, und schnell

Synchron, kein Thread-Spawn. Die Dateigroesse ist egal — 512 MiB lokal in 26,7 ms (Rename im selben Volume). Was kostet, ist der erste Aufruf im Prozess: 740 ms COM-Init. Netzlaufwerk ~0,3-0,4 s. Gehoert nicht in den UI-Thread, sonst unkritisch.

macOS / Linux

macOS: Finder (AppleScript, Default) oder NsFileManager (trashItemAtURL, schneller, aber ohne "Put Back"). Deps stehen schon im Lock. Linux: FreeDesktop-Spec v1.0, legt Trash-Ordner selbst an, faellt bei Cross-Device auf copy+delete zurueck — ein stilles endgueltiges Loeschen ist dort im Code nicht angelegt.

Nicht belastbar beantwortet

USB-Sticks. Die beiden Wechseldatentraeger im Testrechner sind leere Kartenleser. Vermutung (ausdruecklich ungeprueft): lokale Wechselmedien bekommen sehr wohl einen $RECYCLE.BIN, der kritische Fall ist das Netzlaufwerk. Vor der Implementierung mit einem echten Stick nachmessen. Ebenfalls ungeprueft: der pro Volume abschaltbare Papierkorb auf lokalem NTFS — eine Pruefung, die nur den Laufwerkstyp anschaut, greift zu kurz.


Ausfuehrliche Fassung mit allen Rohausgaben, Quellcode-Zitaten und Quellen-URLs: docs/research/papierkorb.md, Branch research/papierkorb (nicht gepusht). Cargo.toml/Cargo.lock sind unveraendert.

## Papierkorb unter Rust: Ergebnis **Crate:** `trash`, aktuell **5.2.6** (2026-05-03), gepflegt aus <https://github.com/Byron/trash-rs>, MIT, rust-version 1.85. ```rust trash::delete(&pfad)?; trash::delete_all(&pfade)?; ``` ### Kosten: +6 Pakete, und die kriegt man nicht weg Ein Gegenstueck zum `rfd`/Wayland-Fall gibt es hier **nicht**. Die vier `coinit_*`-Features von `trash` haben leere Dependency-Listen, und das einzige wirksame Feature (`chrono`) ist nur unter `cfg(unix)` deklariert — `--no-default-features` spart unter Windows **exakt null**. | Variante | Windows | Linux | |---|---|---| | default | **+6** (419 -> 425) | +4 | | `--no-default-features` | **+6** | +2 | Fuenf der sechs sind eine **zweite Kopie der windows-Crate-Familie**: `trash` haengt auf `windows 0.56.0`, im Lock steht ueber dioxus/wry bereits `0.61.3` — semver-inkompatibel, wird nicht dedupliziert. Auf Linux ist es harmlos (reines Rust, kein GTK/dbus), auf macOS praktisch gratis. ### Netzlaufwerke — die wichtigste Frage, und die Antwort ist unangenehm Nicht erschlossen, sondern **gegen ein echtes SMB-Share gemessen**. Es sind **zwei getrennte Probleme**: **1. `trash 5.2.6` funktioniert auf Netzlaufwerken gar nicht.** ``` trash::delete -> Err(Os { code: -2147024894, "windows error: Das System kann die angegebene Datei nicht finden. (0x80070002)" }) Datei existiert noch? true ``` Ursache ist ein Pfad-Bug, kein Papierkorb-Thema: `trash` kanonisiert via `std::fs::canonicalize` und schneidet dann stumpf `\\?\` ab. Aus `\\?\UNC\server\share` wird `UNC\server\share` — Unsinn. Betrifft gemappte Laufwerksbuchstaben und UNC-Pfade gleichermassen. Das ist der seit 2022 offene Bug trash-rs#55. Immerhin: **es geht nichts verloren**, die Datei bleibt liegen. **2. Waere der Bug behoben, waere es gefaehrlich.** `IFileOperation` direkt, gleiche Flags, unverbogener Pfad: ``` Netzlaufwerk Z: PerformOperations -> Ok(()) GetAnyOperationsAborted -> false Datei existiert noch? false Papierkorb-Treffer: 0 <- WEG, endgueltig ``` **Windows loescht auf Netzlaufwerken still und endgueltig und meldet denselben Erfolg wie beim Recyceln.** `FOF_WANTNUKEWARNING` loest dabei **keinen** Dialog aus (`trash` setzt zusaetzlich `FOF_SILENT|FOF_NOERRORUI`). **=> Ja, die App braucht eine Rueckfrage vor dem Loeschen.** Auf `Ok(())` zu vertrauen reicht nicht. ### Wie erfaehrt das Programm, was passiert ist? Ueber `trash` **gar nicht** — keine Error-Variante druckt das aus, im kritischen Fall kommt `Ok(())`. Zuverlaessig geht es nur ueber `IFileOperationProgressSink`, gemessen: | | `PreDeleteItem` dwFlags | `PostDeleteItem` psiNewlyCreated | |---|---|---| | lokal C: | `0x282` (enthaelt `TSF_DELETE_RECYCLE_IF_POSSIBLE`) | `Some` -> `$Recycle.Bin\...\$R1V9IFD.md` | | Netz Z: | `0x202` (Bit fehlt) | **NULL** | Microsoft dokumentiert das woertlich: *"If the item was fully deleted, this value is NULL."* Windows sagt sogar schon **vor** dem Loeschen (in `PreDeleteItem`) per Flag-Bit, ob es recyceln wird. `hrDelete` taugt nicht — in beiden Faellen identisch `0x00270008`. **Haken:** `trash` uebergibt den Sink hart als `None` (`pfo.DeleteItem(&shi, None)`). Ueber die Crate-API kommt man nicht heran. ### Blockierend, und schnell Synchron, kein Thread-Spawn. **Die Dateigroesse ist egal** — 512 MiB lokal in **26,7 ms** (Rename im selben Volume). Was kostet, ist der erste Aufruf im Prozess: **740 ms** COM-Init. Netzlaufwerk ~0,3-0,4 s. Gehoert nicht in den UI-Thread, sonst unkritisch. ### macOS / Linux macOS: `Finder` (AppleScript, Default) oder `NsFileManager` (`trashItemAtURL`, schneller, aber ohne "Put Back"). Deps stehen schon im Lock. Linux: FreeDesktop-Spec v1.0, legt Trash-Ordner selbst an, faellt bei Cross-Device auf copy+delete zurueck — ein stilles endgueltiges Loeschen ist dort im Code nicht angelegt. ### Nicht belastbar beantwortet **USB-Sticks.** Die beiden Wechseldatentraeger im Testrechner sind leere Kartenleser. Vermutung (ausdruecklich ungeprueft): lokale Wechselmedien bekommen sehr wohl einen `$RECYCLE.BIN`, der kritische Fall ist das Netzlaufwerk. **Vor der Implementierung mit einem echten Stick nachmessen.** Ebenfalls ungeprueft: der pro Volume abschaltbare Papierkorb auf lokalem NTFS — eine Pruefung, die nur den Laufwerkstyp anschaut, greift zu kurz. --- Ausfuehrliche Fassung mit allen Rohausgaben, Quellcode-Zitaten und Quellen-URLs: `docs/research/papierkorb.md`, Branch **`research/papierkorb`** (nicht gepusht). `Cargo.toml`/`Cargo.lock` sind unveraendert.
Sign in to join this conversation.