Dos daemons compartiendo el mismo config.toml corren sobre el mismo agentId/agentHash/streamSecret y corrompen el estado de sync del otro. flock advisory en <configDir>/unarr.lock al arrancar: el 2º start se niega con mensaje claro. El kernel suelta el lock al morir el proceso (incluido SIGKILL) → sin problema de lock obsoleto. Scope = config dir, no máquina: un UNARR_CONFIG_DIR distinto (p.ej. el agente dev) tiene su propio lock y corre en paralelo. No bloquea una 2ª instalación con config separada — solo el cross-talk de config compartida.
67 lines
1.9 KiB
Go
67 lines
1.9 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
const appName = "unarr"
|
|
|
|
// Dir returns the configuration directory following XDG conventions.
|
|
// - Linux: ~/.config/unarr
|
|
// - macOS: ~/Library/Application Support/unarr
|
|
// - Windows: %APPDATA%/unarr
|
|
//
|
|
// Overridable via UNARR_CONFIG_DIR env var.
|
|
func Dir() string {
|
|
if d := os.Getenv("UNARR_CONFIG_DIR"); d != "" {
|
|
return d
|
|
}
|
|
switch runtime.GOOS {
|
|
case "darwin":
|
|
home, _ := os.UserHomeDir()
|
|
return filepath.Join(home, "Library", "Application Support", appName)
|
|
case "windows":
|
|
return filepath.Join(os.Getenv("APPDATA"), appName)
|
|
default: // linux, freebsd, etc.
|
|
if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" {
|
|
return filepath.Join(xdg, appName)
|
|
}
|
|
home, _ := os.UserHomeDir()
|
|
return filepath.Join(home, ".config", appName)
|
|
}
|
|
}
|
|
|
|
// FilePath returns the full path to the config file.
|
|
func FilePath() string {
|
|
return filepath.Join(Dir(), "config.toml")
|
|
}
|
|
|
|
// LockPath returns the daemon single-instance lock file, alongside config.toml.
|
|
// Scoped to the config dir so a separate UNARR_CONFIG_DIR (e.g. a dev agent)
|
|
// gets its own lock and can run concurrently; two daemons sharing one config
|
|
// dir cannot — that's the case that causes cross-talk (same agentId/hash/secret
|
|
// racing each other).
|
|
func LockPath() string {
|
|
return filepath.Join(Dir(), "unarr.lock")
|
|
}
|
|
|
|
// DataDir returns the data directory for logs, cache, etc.
|
|
// - Linux: ~/.local/share/unarr
|
|
// - macOS: ~/Library/Application Support/unarr
|
|
// - Windows: %LOCALAPPDATA%/unarr
|
|
func DataDir() string {
|
|
switch runtime.GOOS {
|
|
case "darwin":
|
|
return Dir() // macOS uses same dir for config and data
|
|
case "windows":
|
|
return filepath.Join(os.Getenv("LOCALAPPDATA"), appName)
|
|
default:
|
|
if xdg := os.Getenv("XDG_DATA_HOME"); xdg != "" {
|
|
return filepath.Join(xdg, appName)
|
|
}
|
|
home, _ := os.UserHomeDir()
|
|
return filepath.Join(home, ".local", "share", appName)
|
|
}
|
|
}
|