use std::path::{Path, PathBuf};
use std::sync::OnceLock;
static TEMP_ROOT: OnceLock<PathBuf> = OnceLock::new();
static LEGACY_TEMP_DIR: OnceLock<PathBuf> = OnceLock::new();
#[must_use]
pub(crate) fn temp_root() -> Option<&'static Path> {
TEMP_ROOT.get().map(PathBuf::as_path)
}
#[must_use]
pub(crate) fn legacy_temp_dir() -> Option<&'static Path> {
LEGACY_TEMP_DIR.get().map(PathBuf::as_path)
}
#[cfg(unix)]
pub fn init_temp_root() -> anyhow::Result<()> {
let legacy = std::env::temp_dir();
let uid = unsafe { libc::geteuid() };
let root = PathBuf::from("/tmp/mahbot");
match std::fs::create_dir(&root) {
Ok(()) => {
std::fs::set_permissions(&root, std::os::unix::fs::PermissionsExt::from_mode(0o700))
.map_err(|e| {
anyhow::anyhow!("temp root {}: chmod 0700 failed: {e}", root.display())
})?;
}
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {
use std::os::unix::fs::MetadataExt;
let meta = std::fs::symlink_metadata(&root)
.map_err(|e| anyhow::anyhow!("temp root {}: stat failed: {e}", root.display()))?;
if !meta.is_dir() {
anyhow::bail!(
"temp root {} exists and is not a directory — refusing to use it",
root.display()
);
}
if meta.uid() != uid {
anyhow::bail!(
"temp root {} is owned by uid {} (expected {uid}) — refusing a squatted path",
root.display(),
meta.uid()
);
}
let mode = meta.mode() & 0o777;
if mode & 0o077 != 0 {
std::fs::set_permissions(&root, std::os::unix::fs::PermissionsExt::from_mode(0o700))
.map_err(|e| {
anyhow::anyhow!(
"temp root {} has group/other permissions (mode {mode:o}) and re-chmod 0700 failed: {e}",
root.display()
)
})?;
tracing::warn!(
root = %root.display(),
mode = format_args!("{mode:o}"),
"Temp root had loose permissions — re-chmod 0700 (self-heal, path owned by self)"
);
}
}
Err(e) => anyhow::bail!("temp root {}: create failed: {e}", root.display()),
}
let _ = TEMP_ROOT.set(root.clone());
let _ = LEGACY_TEMP_DIR.set(legacy);
unsafe { std::env::set_var("TMPDIR", &root) };
tracing::info!(root = %root.display(), "Pinned daemon temp root");
Ok(())
}
#[cfg(not(unix))]
pub fn init_temp_root() -> anyhow::Result<()> {
Ok(())
}
#[must_use]
pub(crate) fn shell_tmpdir() -> String {
temp_root().map_or_else(|| "/tmp".to_string(), |p| p.to_string_lossy().into_owned())
}
#[must_use]
pub(crate) fn bare_mktemp_landing_root() -> PathBuf {
#[cfg(target_os = "macos")]
{
if let Some(legacy) = legacy_temp_dir() {
return legacy.to_path_buf();
}
}
std::env::temp_dir()
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(unix)]
#[test]
fn legacy_capture_and_pin_are_consistent() {
assert!(temp_root().is_none());
assert!(legacy_temp_dir().is_none());
assert_eq!(shell_tmpdir(), "/tmp");
}
}