// Package paths handles the resolution of configuration and runtime directories, // providing a consistent way to locate profile and PID tracking files. // // Profile Storage: // Profiles are stored as standard .conf files in ~/.config/wg-wrap/profiles/. // // PID Tracking: // To manage namespace lifecycles and shared sessions, wg-wrap tracks active processes // using PID files located in the runtime base directory: // /run/user/$UID/wg-wrap/profiles//pids/ package paths import ( "fmt" "os" "path/filepath" ) // PathManager handles the resolution of configuration and runtime directories. // By using a struct, we can instantiate different managers for parallel tests. type PathManager struct { // ConfigDirOverride allows overriding the default config directory (usually XDG_CONFIG_HOME/wg-wrap/profiles). ConfigDirOverride string // RuntimeBaseOverride allows overriding the default runtime directory (usually XDG_RUNTIME_DIR). RuntimeBaseOverride string } // NewPathManager creates a PathManager with the given overrides. func NewPathManager(configOverride, runtimeOverride string) *PathManager { return &PathManager{ ConfigDirOverride: configOverride, RuntimeBaseOverride: runtimeOverride, } } // ConfigDir returns the persistent storage path for .conf files. func (pm *PathManager) ConfigDir() string { if pm.ConfigDirOverride != "" { return pm.ConfigDirOverride } configHome := os.Getenv("XDG_CONFIG_HOME") if configHome == "" { home, err := os.UserHomeDir() if err != nil { return "/etc/wg-wrap/profiles" // Fallback } configHome = filepath.Join(home, ".config") } return filepath.Join(configHome, "wg-wrap", "profiles") } // RuntimeBaseDir returns the base ephemeral path. func (pm *PathManager) RuntimeBaseDir() string { if pm.RuntimeBaseOverride != "" { return pm.RuntimeBaseOverride } if envDir := os.Getenv("WG_WRAP_HOST_RUNTIME_BASE_DIR"); envDir != "" { return envDir } if envDir := os.Getenv("XDG_RUNTIME_DIR"); envDir != "" { return envDir } uid := os.Getuid() return fmt.Sprintf("/run/user/%d", uid) } // ProfileNamespacePath returns the specific path for a pinned namespace. func (pm *PathManager) ProfileNamespacePath(profile string) string { return filepath.Join(pm.RuntimeBaseDir(), "profiles", profile+".ns") } // ProfilePidsDir returns the path for PID tracking. func (pm *PathManager) ProfilePidsDir(profile string) string { return filepath.Join(pm.RuntimeBaseDir(), "profiles", profile, "pids") }