pub struct AppPaths { /* private fields */ }Expand description
The four directories the daemon owns.
Resolved once and passed down, rather than recomputed at each use. Two resolutions in one process must agree, and the cheapest way to guarantee that is to only resolve once.
Implementations§
Source§impl AppPaths
impl AppPaths
Sourcepub fn from_directories(
config: impl Into<PathBuf>,
state: impl Into<PathBuf>,
runtime: impl Into<PathBuf>,
logs: impl Into<PathBuf>,
) -> Self
pub fn from_directories( config: impl Into<PathBuf>, state: impl Into<PathBuf>, runtime: impl Into<PathBuf>, logs: impl Into<PathBuf>, ) -> Self
Rebuilds a previously resolved four-directory layout.
Service registrations use this to carry the installing operator’s
application-data directories across the account boundary to the daemon.
It is deliberately distinct from Self::rooted_at: these paths are
already the four leaves, and forcing them under a new root would point
the service at a second SQLite database.
Sourcepub fn discover() -> Result<Self, PathsError>
pub fn discover() -> Result<Self, PathsError>
Resolves the platform-standard locations for this account.
§Errors
PathsError::NoHomeDirectory when the operating system reports no
home directory, which is the only way this can fail: nothing is touched
on disk here. Use AppPaths::create_all for that.
Sourcepub fn rooted_at(root: impl AsRef<Path>) -> Self
pub fn rooted_at(root: impl AsRef<Path>) -> Self
Places all four directories under one root, using the names
05-infrastructure.md gives them.
This is how a test gets a disposable layout and how a service that was
installed against an explicitly configured root reproduces it. It is
deliberately not what AppPaths::discover falls back to: a relative
root passed here stays relative, and that is the caller’s decision to
make rather than a default anything acquires by accident.
Sourcepub fn config_dir(&self) -> &Path
pub fn config_dir(&self) -> &Path
Non-secret TOML configuration and the SQLite database.
Sourcepub fn state_dir(&self) -> &Path
pub fn state_dir(&self) -> &Path
The agent lock, the attempt journal, and the retained runner package cache.
Sourcepub fn runtime_dir(&self) -> &Path
pub fn runtime_dir(&self) -> &Path
Per-attempt disposable runner workspaces.
Sourcepub fn all(&self) -> [(&'static str, &Path); 4]
pub fn all(&self) -> [(&'static str, &Path); 4]
The four directories, paired with the name each is known by. Ordered
as 05-infrastructure.md lists them.
Sourcepub fn create_all(&self) -> Result<(), PathsError>
pub fn create_all(&self) -> Result<(), PathsError>
Creates every directory that does not already exist.
Idempotent, and restrictive where the platform expresses that through
mode bits: on Unix each leaf is created at 0700, so a runner
workspace, an attempt journal, and a diagnostics file are not readable
by other local accounts. Intermediate directories — ~/.local,
~/.config — are left alone, because they are shared with every other
application and are not this program’s to tighten.
The mode is passed to mkdir(2) rather than applied with a following
chmod, for the same reason crate::process::RestrictiveHandoff
passes it to open(2): the two-step version leaves a window in which
state/ and runtime/ exist at the umask default — typically 0755 —
and those are the directories holding the attempt journal and the runner
workspaces. A directory that was already there is still tightened,
which is what keeps this idempotent and what upgrades a tree created by
an earlier version.
On Windows the per-account AppData tree already denies other
non-administrative users, and the one file whose exposure actually
matters gets an explicit DACL of its own rather than relying on that:
see crate::process::RestrictiveHandoff.
§Errors
PathsError::Create, naming which of the four failed and why.