use anyhow::{anyhow, Context, Result};
use std::path::PathBuf;
#[derive(Clone, Debug)]
pub struct TunnelStateDir {
path: PathBuf,
name: String,
}
impl TunnelStateDir {
pub fn for_service(service_name: &str) -> Result<Self> {
let path = base_dir()?.join(service_name);
std::fs::create_dir_all(&path)
.with_context(|| format!("creating state dir {}", path.display()))?;
Ok(Self {
path,
name: service_name.to_string(),
})
}
pub fn open(service_name: &str) -> Result<Self> {
let path = base_dir()?.join(service_name);
if !path.is_dir() {
return Err(anyhow!(
"no state for service '{service_name}' at {} — was the tunnel ever brought up?",
path.display()
));
}
Ok(Self {
path,
name: service_name.to_string(),
})
}
pub fn ip_marker(&self) -> PathBuf {
self.path.join("ip")
}
pub fn known_hosts(&self) -> PathBuf {
self.path.join("known_hosts")
}
pub fn client_key(&self) -> PathBuf {
self.path.join("client_id_ed25519")
}
pub fn wg_conf(&self) -> PathBuf {
self.path.join(format!("{}.conf", self.name))
}
}
pub fn remove_state_for_service(service_name: &str) -> Result<()> {
let path = base_dir()?.join(service_name);
if path.is_dir() {
std::fs::remove_dir_all(&path).with_context(|| format!("removing {}", path.display()))?;
}
Ok(())
}
fn base_dir() -> Result<PathBuf> {
Ok(home::home_dir()
.ok_or_else(|| anyhow!("could not find home directory"))?
.join(".config")
.join("innisfree"))
}