keydb: map missing home dir to NotFound, not keydb-parse error

default_path returned Error::KeydbParse (E8004, rendered as 'failed to
parse the keydb file') when HOME/USERPROFILE was unset. That misreports
an environment failure — a process with no home directory, typically a
stripped container or CI config — as a corrupt keydb file the code never
read. Map it to an IoError(NotFound) in the I/O category instead, so no
display path blames the keydb. Add a regression test.
This commit is contained in:
Matthew Jackson
2026-06-23 04:05:41 -07:00
parent 662594ff40
commit f68a66c4be
+32 -2
View File
@@ -54,6 +54,18 @@ fn read_capped_to_string<R: Read>(reader: R) -> Result<String> {
/// `freemkv-keysources::keydb_search_paths`; this function is the single
/// *write* default used by `save`/`update`, kept in lock-step with that crate's
/// `default_keydb_path` for the same OS.
/// Build the error returned when no home directory can be determined
/// (`HOME`/`USERPROFILE` unset). This is an *environment* failure — the
/// process has no home dir, which typically signals a stripped container
/// or CI configuration — not a corrupt or unparseable keydb file. Map it
/// to a `NotFound` I/O error so display/remediation paths never claim a
/// keydb parse failure for a file that was never consulted.
fn no_home_dir() -> Error {
Error::IoError {
source: std::io::Error::from(std::io::ErrorKind::NotFound),
}
}
pub fn default_path() -> Result<PathBuf> {
#[cfg(windows)]
{
@@ -62,7 +74,7 @@ pub fn default_path() -> Result<PathBuf> {
return Ok(PathBuf::from(appdata).join("freemkv").join("keydb.cfg"));
}
}
let profile = std::env::var("USERPROFILE").map_err(|_| Error::KeydbParse)?;
let profile = std::env::var("USERPROFILE").map_err(|_| no_home_dir())?;
Ok(PathBuf::from(profile)
.join(".config")
.join("freemkv")
@@ -72,7 +84,7 @@ pub fn default_path() -> Result<PathBuf> {
{
let home = std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE"))
.map_err(|_| Error::KeydbParse)?;
.map_err(|_| no_home_dir())?;
Ok(PathBuf::from(home)
.join(".config")
.join("freemkv")
@@ -410,6 +422,24 @@ mod tests {
d
}
// Regression: a missing home directory (HOME/USERPROFILE unset) is an
// *environment* failure, not a corrupt keydb. It must NOT surface as
// E8004 (KeydbParse → "failed to parse the keydb file"), which would
// blame a file that was never consulted. It maps to a NotFound I/O
// error in the 5xxx (I/O) category instead.
#[test]
fn no_home_dir_is_io_not_found_not_keydb_parse() {
let e = no_home_dir();
match e {
Error::IoError { source } => {
assert_eq!(source.kind(), std::io::ErrorKind::NotFound);
}
other => panic!("expected IoError(NotFound), got {other:?}"),
}
// And explicitly: it is not the keydb-parse code.
assert_ne!(no_home_dir().code(), Error::KeydbParse.code());
}
#[test]
fn write_atomic_replaces_existing_and_leaves_no_temp() {
let dir = scratch("atomic");