fix(cloud-files): Existierende normale Dateien vor Placeholder-Erstellung loeschen

Wenn der Client vorher aktiv war und dann deaktiviert wurde (oder
hart beendet), wandelt CfUnregisterSyncRoot alle Platzhalter in
normale Dateien um. Beim erneuten Aktivieren versuchte
populate_placeholders einen neuen Platzhalter anzulegen, was aber
mit ERROR_FILE_EXISTS scheiterte - der Fehler wurde zudem nur per
eprintln geloggt und verschluckt.

Ergebnis: die Datei blieb eine ganz normale Datei (kein Platzhalter,
kein Wolken-Icon). Spaeter fragt CfDehydratePlaceholder dann mit
HRESULT 0x80070178 "Die Datei ist keine Clouddatei", und "Speicher
freigeben" funktioniert nicht.

Jetzt prueft populate_placeholders vor jedem Create, ob die Datei
schon existiert und KEIN Platzhalter ist. Wenn ja: loeschen,
dann neu als Platzhalter anlegen. Erfolge und Fehler gehen beide
ins .minicloud-cloudfiles.log, damit man das Ergebnis prueft.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker 2026-04-23 22:56:58 +02:00
parent 3c340f9653
commit 78615d8897
1 changed files with 24 additions and 5 deletions

View File

@ -432,18 +432,37 @@ pub fn populate_placeholders(
std::fs::create_dir_all(&p).ok(); std::fs::create_dir_all(&p).ok();
} }
// Dann Dateien als Platzhalter // Dann Dateien als Platzhalter. Existierende "normale" Dateien
// (z.B. nach vorherigem CfUnregisterSyncRoot) vorher loeschen,
// weil CfCreatePlaceholders sonst mit ERROR_FILE_EXISTS scheitert
// und die Datei nie zum Platzhalter wird -> spaeter koennte man
// sie nicht mehr dehydrieren (0x80070178 "keine Clouddatei").
for e in entries.iter().filter(|e| !e.is_folder) { for e in entries.iter().filter(|e| !e.is_folder) {
let rel = rel_path(e, &by_id); let rel = rel_path(e, &by_id);
let full = mount_point.join(&rel);
let parent = rel let parent = rel
.parent() .parent()
.map(|p| mount_point.join(p)) .map(|p| mount_point.join(p))
.unwrap_or_else(|| mount_point.clone()); .unwrap_or_else(|| mount_point.clone());
let identity = e.id.to_string(); let identity = e.id.to_string();
if let Err(err) =
create_placeholder(&parent, &e.name, e.size, &e.modified_at, identity.as_bytes()) if full.exists() && !is_cfapi_placeholder(&full) {
{ log_msg(mount_point, &format!(
eprintln!("placeholder {}: {}", e.name, err); "deleting non-placeholder {} to recreate",
full.display()
));
if let Err(err) = std::fs::remove_file(&full) {
log_err(mount_point, &format!(
"remove {} failed: {err}", full.display()
));
}
}
match create_placeholder(&parent, &e.name, e.size, &e.modified_at, identity.as_bytes()) {
Ok(()) => log_msg(mount_point, &format!("placeholder created: {}", full.display())),
Err(err) => log_err(mount_point, &format!(
"placeholder {} FAILED: {err}", full.display()
)),
} }
} }
Ok(()) Ok(())