mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-26 05:51:18 +02:00
fix(download): fsync staged downloads before the promote rename
The staged-write-then-rename protocol was atomic against process kills but not against power loss: f2fs/ext4 can persist the rename before the data, leaving a zero-length or truncated file under the final name. Sync the staged file before promoting and fsync the directory after.
This commit is contained in:
@@ -333,6 +333,14 @@ func (r *extensionRuntime) fileDownload(call goja.FunctionCall) goja.Value {
|
||||
}
|
||||
}
|
||||
|
||||
// Sync before the promote rename so a power loss right after the rename
|
||||
// cannot leave a truncated file under the final name.
|
||||
if err := out.Sync(); err != nil {
|
||||
return r.vm.ToValue(map[string]any{
|
||||
"success": false,
|
||||
"error": fmt.Sprintf("failed to sync file: %v", err),
|
||||
})
|
||||
}
|
||||
if err := out.Close(); err != nil {
|
||||
return r.vm.ToValue(map[string]any{
|
||||
"success": false,
|
||||
@@ -346,6 +354,7 @@ func (r *extensionRuntime) fileDownload(call goja.FunctionCall) goja.Value {
|
||||
})
|
||||
}
|
||||
promoted = true
|
||||
syncDir(filepath.Dir(fullPath))
|
||||
|
||||
GoLog("[Extension:%s] Downloaded %d bytes to %s\n", r.extensionID, written, fullPath)
|
||||
|
||||
@@ -590,6 +599,14 @@ func (r *extensionRuntime) fileDownloadChunked(client *http.Client, urlStr, full
|
||||
}
|
||||
}
|
||||
|
||||
// Sync before the promote rename so a power loss right after the rename
|
||||
// cannot leave a truncated file under the final name.
|
||||
if err := out.Sync(); err != nil {
|
||||
return r.vm.ToValue(map[string]any{
|
||||
"success": false,
|
||||
"error": fmt.Sprintf("failed to sync file: %v", err),
|
||||
})
|
||||
}
|
||||
if err := out.Close(); err != nil {
|
||||
return r.vm.ToValue(map[string]any{
|
||||
"success": false,
|
||||
@@ -603,6 +620,7 @@ func (r *extensionRuntime) fileDownloadChunked(client *http.Client, urlStr, full
|
||||
})
|
||||
}
|
||||
promoted = true
|
||||
syncDir(filepath.Dir(fullPath))
|
||||
|
||||
GoLog("[Extension:%s] Chunked download complete: %d bytes to %s\n", r.extensionID, totalWritten, fullPath)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user