fix(data): align android_keystore temp extension with cleanup glob (M-21)
The keystore atomic write used path.with_extension("tmp") producing
auth_tokens.tmp, while cleanup_orphaned_tmp_files only matched *.json.tmp.
A crash after the write but before the rename left an orphaned file
invisible to cleanup.
Fix: use path.with_extension("bin.tmp") to produce auth_tokens.bin.tmp,
and broaden the cleanup glob from ends_with(".json.tmp") to
ends_with(".tmp") so both JSON and binary temp files are caught.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -295,9 +295,9 @@ fn read_file_bytes() -> Result<Vec<u8>, TokenError> {
|
|||||||
fn write_file_bytes(data: &[u8]) -> Result<(), TokenError> {
|
fn write_file_bytes(data: &[u8]) -> Result<(), TokenError> {
|
||||||
let path = token_file_path()
|
let path = token_file_path()
|
||||||
.ok_or_else(|| TokenError::KeychainUnavailable("no data dir".into()))?;
|
.ok_or_else(|| TokenError::KeychainUnavailable("no data dir".into()))?;
|
||||||
let tmp = path.with_extension("tmp");
|
let tmp = path.with_extension("bin.tmp");
|
||||||
std::fs::write(&tmp, data)
|
std::fs::write(&tmp, data)
|
||||||
.map_err(|e| TokenError::Keyring(format!("write auth_tokens.tmp: {e}")))?;
|
.map_err(|e| TokenError::Keyring(format!("write auth_tokens.bin.tmp: {e}")))?;
|
||||||
std::fs::rename(&tmp, &path)
|
std::fs::rename(&tmp, &path)
|
||||||
.map_err(|e| TokenError::Keyring(format!("rename auth_tokens: {e}")))
|
.map_err(|e| TokenError::Keyring(format!("rename auth_tokens: {e}")))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ pub fn delete_game_state_at(path: &Path) -> io::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove any leftover `*.json.tmp` files in the app data directory.
|
/// Remove any leftover `*.tmp` files in the app data directory.
|
||||||
///
|
///
|
||||||
/// These can be left behind if the process crashes between the write and rename
|
/// These can be left behind if the process crashes between the write and rename
|
||||||
/// in an atomic save. Safe to call on startup; missing or unreadable entries
|
/// in an atomic save. Safe to call on startup; missing or unreadable entries
|
||||||
@@ -266,7 +266,7 @@ pub fn time_attack_session_with_now(remaining_secs: f32, wins: u32) -> TimeAttac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inner helper: delete `*.json.tmp` entries inside `dir`.
|
/// Inner helper: delete `*.tmp` entries inside `dir`.
|
||||||
///
|
///
|
||||||
/// Per-file errors (already deleted, permission denied) are silently ignored.
|
/// Per-file errors (already deleted, permission denied) are silently ignored.
|
||||||
fn cleanup_tmp_files_in(dir: &Path) {
|
fn cleanup_tmp_files_in(dir: &Path) {
|
||||||
@@ -276,7 +276,7 @@ fn cleanup_tmp_files_in(dir: &Path) {
|
|||||||
if path
|
if path
|
||||||
.file_name()
|
.file_name()
|
||||||
.and_then(|n| n.to_str())
|
.and_then(|n| n.to_str())
|
||||||
.is_some_and(|n| n.ends_with(".json.tmp"))
|
.is_some_and(|n| n.ends_with(".tmp"))
|
||||||
{
|
{
|
||||||
let _ = fs::remove_file(&path);
|
let _ = fs::remove_file(&path);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user