@@ -12,17 +12,10 @@ import (
1212
1313 "github.com/BurntSushi/toml"
1414
15+ "github.com/mozilla-ai/mcpd/v2/internal/files"
1516 "github.com/mozilla-ai/mcpd/v2/internal/perms"
1617)
1718
18- const (
19- // EnvVarXDGConfigHome is the XDG Base Directory env var name for config files.
20- EnvVarXDGConfigHome = "XDG_CONFIG_HOME"
21-
22- // EnvVarXDGCacheHome is the XDG Base Directory env var name for cache file.
23- EnvVarXDGCacheHome = "XDG_CACHE_HOME"
24- )
25-
2619// DefaultLoader loads execution context configurations.
2720type DefaultLoader struct {}
2821
@@ -126,13 +119,13 @@ func (c *ExecutionContextConfig) List() []ServerExecutionContext {
126119// SaveConfig saves the execution context configuration to a file with secure permissions.
127120// Used for runtime execution contexts that may contain sensitive data.
128121func (c * ExecutionContextConfig ) SaveConfig () error {
129- return c .saveConfig (EnsureAtLeastSecureDir , perms .SecureFile )
122+ return c .saveConfig (files . EnsureAtLeastSecureDir , perms .SecureFile )
130123}
131124
132125// SaveExportedConfig saves the execution context configuration to a file with regular permissions.
133126// Used for exported configurations that are sanitized and suitable for sharing.
134127func (c * ExecutionContextConfig ) SaveExportedConfig () error {
135- return c .saveConfig (EnsureAtLeastRegularDir , perms .RegularFile )
128+ return c .saveConfig (files . EnsureAtLeastRegularDir , perms .RegularFile )
136129}
137130
138131// Upsert updates the execution context for the given server name.
@@ -216,27 +209,6 @@ func (s *ServerExecutionContext) IsEmpty() bool {
216209 return len (s .Args ) == 0 && len (s .Env ) == 0 && len (s .Volumes ) == 0
217210}
218211
219- // AppDirName returns the name of the application directory for use in user-specific operations where data is being written.
220- func AppDirName () string {
221- return "mcpd"
222- }
223-
224- // EnsureAtLeastRegularDir creates a directory with standard permissions if it doesn't exist,
225- // and verifies that it has at least the required regular permissions if it already exists.
226- // It does not attempt to repair ownership or permissions: if they are wrong, it returns an error.
227- // Used for cache directories, data directories, and documentation.
228- func EnsureAtLeastRegularDir (path string ) error {
229- return ensureAtLeastDir (path , perms .RegularDir )
230- }
231-
232- // EnsureAtLeastSecureDir creates a directory with secure permissions if it doesn't exist,
233- // and verifies that it has at least the required secure permissions if it already exists.
234- // It does not attempt to repair ownership or permissions: if they are wrong,
235- // it returns an error.
236- func EnsureAtLeastSecureDir (path string ) error {
237- return ensureAtLeastDir (path , perms .SecureDir )
238- }
239-
240212// NewExecutionContextConfig returns a newly initialized ExecutionContextConfig.
241213func NewExecutionContextConfig (path string ) * ExecutionContextConfig {
242214 return & ExecutionContextConfig {
@@ -245,46 +217,6 @@ func NewExecutionContextConfig(path string) *ExecutionContextConfig {
245217 }
246218}
247219
248- // UserSpecificCacheDir returns the directory that should be used to store any user-specific cache files.
249- // It adheres to the XDG Base Directory Specification, respecting the XDG_CACHE_HOME environment variable.
250- // When XDG_CACHE_HOME is not set, it defaults to ~/.cache/mcpd/
251- // See: https://specifications.freedesktop.org/basedir-spec/latest/
252- func UserSpecificCacheDir () (string , error ) {
253- return userSpecificDir (EnvVarXDGCacheHome , ".cache" )
254- }
255-
256- // UserSpecificConfigDir returns the directory that should be used to store any user-specific configuration.
257- // It adheres to the XDG Base Directory Specification, respecting the XDG_CONFIG_HOME environment variable.
258- // When XDG_CONFIG_HOME is not set, it defaults to ~/.config/mcpd/
259- // See: https://specifications.freedesktop.org/basedir-spec/latest/
260- func UserSpecificConfigDir () (string , error ) {
261- return userSpecificDir (EnvVarXDGConfigHome , ".config" )
262- }
263-
264- // ensureAtLeastDir creates a directory with the specified permissions if it doesn't exist,
265- // and verifies that it has at least the required permissions if it already exists.
266- // It does not attempt to repair ownership or permissions: if they are wrong, it returns an error.
267- func ensureAtLeastDir (path string , perm os.FileMode ) error {
268- if err := os .MkdirAll (path , perm ); err != nil {
269- return fmt .Errorf ("could not ensure directory exists for '%s': %w" , path , err )
270- }
271-
272- info , err := os .Stat (path )
273- if err != nil {
274- return fmt .Errorf ("could not stat directory '%s': %w" , path , err )
275- }
276-
277- if ! isPermissionAcceptable (info .Mode ().Perm (), perm ) {
278- return fmt .Errorf (
279- "incorrect permissions for directory '%s' (%#o, want %#o or more restrictive)" ,
280- path , info .Mode ().Perm (),
281- perm ,
282- )
283- }
284-
285- return nil
286- }
287-
288220// equalSlices compares two string slices for equality, ignoring order.
289221func equalSlices (a []string , b []string ) bool {
290222 if len (a ) != len (b ) {
@@ -300,14 +232,6 @@ func equalSlices(a []string, b []string) bool {
300232 return slices .Equal (sortedA , sortedB )
301233}
302234
303- // isPermissionAcceptable checks if the actual permissions are acceptable for the required permissions.
304- // It returns true if the actual permissions are equal to or more restrictive than required.
305- // "More restrictive" means: no permission bit set in actual that isn't also set in required.
306- func isPermissionAcceptable (actual , required os.FileMode ) bool {
307- // Check that actual doesn't grant any permissions that required doesn't grant
308- return (actual & ^ required ) == 0
309- }
310-
311235// loadExecutionContextConfig loads a runtime execution context file from disk and expands environment variables.
312236//
313237// The function parses the TOML file at the specified path and automatically expands all ${VAR} references
@@ -396,31 +320,3 @@ func (c *ExecutionContextConfig) saveConfig(ensureDirFunc func(string) error, fi
396320
397321 return nil
398322}
399-
400- // userSpecificDir returns a user-specific directory following XDG Base Directory Specification.
401- // It respects the given environment variable, falling back to homeDir/dir/AppDirName() if not set.
402- // The envVar must have XDG_ prefix to follow the specification.
403- func userSpecificDir (envVar string , dir string ) (string , error ) {
404- envVar = strings .TrimSpace (envVar )
405- // Validate that the environment variable follows XDG naming convention.
406- if ! strings .HasPrefix (envVar , "XDG_" ) {
407- return "" , fmt .Errorf (
408- "environment variable '%s' does not follow XDG Base Directory Specification" ,
409- envVar ,
410- )
411- }
412-
413- // If the relevant environment variable is present and configured, then use it.
414- if ch , ok := os .LookupEnv (envVar ); ok && strings .TrimSpace (ch ) != "" {
415- home := strings .TrimSpace (ch )
416- return filepath .Join (home , AppDirName ()), nil
417- }
418-
419- // Attempt to locate the home directory for the current user and return the path that follows the spec.
420- homeDir , err := os .UserHomeDir ()
421- if err != nil {
422- return "" , fmt .Errorf ("failed to get user home directory: %w" , err )
423- }
424-
425- return filepath .Join (homeDir , dir , AppDirName ()), nil
426- }
0 commit comments