From 496dd44c34086843f635088c9b614acb855d8b4c Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 17 Apr 2026 16:02:01 +0200 Subject: [PATCH 1/3] upki: inline user dir helper functions --- upki/src/lib.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/upki/src/lib.rs b/upki/src/lib.rs index 315381fc..2bdf5676 100644 --- a/upki/src/lib.rs +++ b/upki/src/lib.rs @@ -51,7 +51,7 @@ impl Config { /// Return a sensible default configuration. pub fn try_user_default() -> Result { Ok(Self { - cache_dir: user_cache_dir()?, + cache_dir: project_dirs()?.cache_dir().to_owned(), revocation: RevocationConfig::default(), }) } @@ -84,7 +84,11 @@ impl ConfigPath { pub fn new(specified: Option) -> Result { match specified { Some(f) => Ok(Self::Specified(f)), - None => user_config_file().map(ConfigPath::Default), + None => Ok(Self::Default( + project_dirs()? + .config_dir() + .join(CONFIG_FILE), + )), } } } @@ -156,16 +160,6 @@ impl fmt::Display for Error { } } -fn user_config_file() -> Result { - Ok(project_dirs()? - .config_dir() - .join(CONFIG_FILE)) -} - -fn user_cache_dir() -> Result { - Ok(project_dirs()?.cache_dir().to_owned()) -} - fn project_dirs() -> Result { ProjectDirs::from("dev", "rustls", PREFIX).ok_or(Error::NoValidHomeDirectory) } From 7e7c945c6eaa6ef7968a8c63d18b72bd80fc97d3 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 17 Apr 2026 16:44:40 +0200 Subject: [PATCH 2/3] upki: introduce new PathKind enum --- upki/src/lib.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/upki/src/lib.rs b/upki/src/lib.rs index 2bdf5676..55f22d03 100644 --- a/upki/src/lib.rs +++ b/upki/src/lib.rs @@ -51,7 +51,7 @@ impl Config { /// Return a sensible default configuration. pub fn try_user_default() -> Result { Ok(Self { - cache_dir: project_dirs()?.cache_dir().to_owned(), + cache_dir: PathKind::User.cache_dir()?, revocation: RevocationConfig::default(), }) } @@ -85,8 +85,8 @@ impl ConfigPath { match specified { Some(f) => Ok(Self::Specified(f)), None => Ok(Self::Default( - project_dirs()? - .config_dir() + PathKind::User + .config_dir()? .join(CONFIG_FILE), )), } @@ -102,6 +102,27 @@ impl AsRef for ConfigPath { } } +/// What kind of path is being determined. +#[derive(Clone, Copy, Debug)] +pub enum PathKind { + /// User-relative configuration and data. + User, +} + +impl PathKind { + fn config_dir(self) -> Result { + Ok(match self { + Self::User => project_dirs()?.config_dir().to_owned(), + }) + } + + fn cache_dir(self) -> Result { + Ok(match self { + Self::User => project_dirs()?.cache_dir().to_owned(), + }) + } +} + /// Errors for the upki library API. #[non_exhaustive] #[derive(Debug)] From 87411847412ed5f3543717b02d075cb59846095b Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Fri, 17 Apr 2026 16:47:18 +0200 Subject: [PATCH 3/3] upki: take PathKind for Config construction --- revoke-test/benches/bench.rs | 9 +++++---- rustls-upki/src/lib.rs | 6 +++--- upki-cli/src/bin/upki.rs | 8 ++++---- upki-ffi/src/lib.rs | 4 ++-- upki/src/lib.rs | 22 +++++++++------------- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/revoke-test/benches/bench.rs b/revoke-test/benches/bench.rs index b36c7e3d..76f8aff8 100644 --- a/revoke-test/benches/bench.rs +++ b/revoke-test/benches/bench.rs @@ -11,12 +11,12 @@ use criterion::{Criterion, criterion_group, criterion_main}; use revoke_test::RevocationTestSites; use rustls_pki_types::CertificateDer; use upki::revocation::{Index, Manifest, RevocationCheckInput, RevocationStatus}; -use upki::{Config, ConfigPath}; +use upki::{Config, ConfigPath, PathKind}; fn revocation(c: &mut Criterion) { c.bench_function("load-config", |b| { b.iter(|| { - Config::from_file_or_user_default(&ConfigPath::Specified(PathBuf::from( + Config::from_file_or_default(&ConfigPath::Specified(PathBuf::from( "benches/data/config.toml", ))) .unwrap() @@ -24,7 +24,7 @@ fn revocation(c: &mut Criterion) { }); c.bench_function("load-manifest", |b| { - let config = Config::from_file_or_user_default(&ConfigPath::Specified(PathBuf::from( + let config = Config::from_file_or_default(&ConfigPath::Specified(PathBuf::from( "benches/data/config.toml", ))) .unwrap(); @@ -43,7 +43,8 @@ fn revocation(c: &mut Criterion) { }); c.bench_function("revocation-check", |b| { - let config = Config::from_file_or_user_default(&ConfigPath::new(None).unwrap()).unwrap(); + let config = + Config::from_file_or_default(&ConfigPath::new(None, PathKind::User).unwrap()).unwrap(); let revoked_certs = certificates_for_test_site(BENCHMARK_CASE); b.iter(|| { diff --git a/rustls-upki/src/lib.rs b/rustls-upki/src/lib.rs index 2c01f4c0..6513e400 100644 --- a/rustls-upki/src/lib.rs +++ b/rustls-upki/src/lib.rs @@ -17,7 +17,7 @@ use upki::revocation::{ CertSerial, CtTimestamp, Index, IssuerSpkiHash, Manifest, RevocationCheckInput, RevocationStatus, }; -use upki::{self, Config, ConfigPath}; +use upki::{self, Config, ConfigPath, PathKind}; use webpki::{EndEntityCert, ExtendedKeyUsage, InvalidNameContext, VerifiedPath}; /// A [`ServerCertVerifier`] that uses upki to check revocation status of server certificates. @@ -64,8 +64,8 @@ impl ServerVerifier { }) .expect("no cipher suites supported with SHA256"); - let config = ConfigPath::new(config_path) - .and_then(|path| Config::from_file_or_user_default(&path)) + let config = ConfigPath::new(config_path, PathKind::User) + .and_then(|path| Config::from_file_or_default(&path)) .map_err(|report| rustls::Error::General(report.to_string()))?; // Pre-roll storage to check it works, and bring (eg. permanent configuration) errors diff --git a/upki-cli/src/bin/upki.rs b/upki-cli/src/bin/upki.rs index 4eb6b30f..ca4d6a40 100644 --- a/upki-cli/src/bin/upki.rs +++ b/upki-cli/src/bin/upki.rs @@ -9,7 +9,7 @@ use eyre::{Context, Report}; use rustls_pki_types::CertificateDer; use rustls_pki_types::pem::PemObject; use upki::revocation::{Index, Manifest, RevocationCheckInput, fetch}; -use upki::{Config, ConfigPath}; +use upki::{Config, ConfigPath, PathKind}; #[tokio::main(flavor = "current_thread")] async fn main() -> Result { @@ -22,15 +22,15 @@ async fn main() -> Result { .init(); } - let config_path = - ConfigPath::new(args.config_file).wrap_err("cannot find configuration path")?; + let config_path = ConfigPath::new(args.config_file, PathKind::User) + .wrap_err("cannot find configuration path")?; if let Command::ShowConfigPath = args.command { println!("{}", config_path.as_ref().display()); return Ok(ExitCode::SUCCESS); } - let config = Config::from_file_or_user_default(&config_path)?; + let config = Config::from_file_or_default(&config_path)?; Ok(match args.command { Command::Fetch { dry_run } => fetch(dry_run, &config).await?, diff --git a/upki-ffi/src/lib.rs b/upki-ffi/src/lib.rs index 54ff4472..fdb275a0 100644 --- a/upki-ffi/src/lib.rs +++ b/upki-ffi/src/lib.rs @@ -9,7 +9,7 @@ use std::slice; use rustls_pki_types::CertificateDer; use upki::revocation::{self, Index, RevocationCheckInput, RevocationStatus}; -use upki::{Config, Error}; +use upki::{Config, Error, PathKind}; /// Check the revocation status of a certificate. /// @@ -119,7 +119,7 @@ pub unsafe extern "C" fn upki_config_new_user(out: *mut *mut upki_config) -> upk return upki_result::UPKI_ERR_NULL_POINTER; } - match Config::try_user_default() { + match Config::try_default(PathKind::User) { Ok(config) => { unsafe { *out = Box::into_raw(Box::new(upki_config(config))) }; upki_result::UPKI_OK diff --git a/upki/src/lib.rs b/upki/src/lib.rs index 55f22d03..bfb7a132 100644 --- a/upki/src/lib.rs +++ b/upki/src/lib.rs @@ -27,10 +27,10 @@ impl Config { /// Load the configuration data from a file at `path`. /// /// If no file exists at `path`, a default configuration is returned. - pub fn from_file_or_user_default(path: &ConfigPath) -> Result { + pub fn from_file_or_default(path: &ConfigPath) -> Result { match path { - ConfigPath::Default(path) if path.exists() => Self::from_file(path), - ConfigPath::Default(_) => Self::try_user_default(), + ConfigPath::Default(path, _) if path.exists() => Self::from_file(path), + ConfigPath::Default(_, kind) => Self::try_default(*kind), ConfigPath::Specified(path) => Self::from_file(path), } } @@ -49,9 +49,9 @@ impl Config { } /// Return a sensible default configuration. - pub fn try_user_default() -> Result { + pub fn try_default(kind: PathKind) -> Result { Ok(Self { - cache_dir: PathKind::User.cache_dir()?, + cache_dir: kind.cache_dir()?, revocation: RevocationConfig::default(), }) } @@ -66,7 +66,7 @@ pub enum ConfigPath { /// The path was directly specified by a user. Specified(PathBuf), /// The path was determined automatically. - Default(PathBuf), + Default(PathBuf, PathKind), } impl ConfigPath { @@ -81,14 +81,10 @@ impl ConfigPath { /// /// This function fails for platform-specific reasons, typically if `$HOME` is not /// set, or another XDG environment variable is malformed. - pub fn new(specified: Option) -> Result { + pub fn new(specified: Option, kind: PathKind) -> Result { match specified { Some(f) => Ok(Self::Specified(f)), - None => Ok(Self::Default( - PathKind::User - .config_dir()? - .join(CONFIG_FILE), - )), + None => Ok(Self::Default(kind.config_dir()?.join(CONFIG_FILE), kind)), } } } @@ -97,7 +93,7 @@ impl AsRef for ConfigPath { fn as_ref(&self) -> &Path { match self { Self::Specified(path) => path.as_ref(), - Self::Default(path) => path.as_ref(), + Self::Default(path, _) => path.as_ref(), } } }