package daemon import ( "errors" "fmt" "io/fs" "os" "path/filepath" "slices" "strings" "sync" ) func getDefaultHTTPSocketDirPath() string { path, err := firstExistingDir( "/tmp", // TODO it's possible the daemon process can't actually write to these "/run", "/var/run", "/dev/shm", ) if err != nil { panic(fmt.Sprintf("Failed to find directory for HTTP socket: %v", err)) } return path } // HTTPSocketPath returns the path to the daemon's HTTP socket which is used for // RPC and other functionality. var HTTPSocketPath = sync.OnceValue(func() string { return envOr( "ISLE_DAEMON_HTTP_SOCKET_PATH", func() string { return filepath.Join( getDefaultHTTPSocketDirPath(), "isle-daemon.sock", ) }, ) }) //////////////////////////////////////////////////////////////////////////////// // Jigs func envOr(name string, fallback func() string) string { if v := os.Getenv(name); v != "" { return v } return fallback() } func firstExistingDir(paths ...string) (string, error) { var errs []error for _, path := range paths { stat, err := os.Stat(path) switch { case errors.Is(err, fs.ErrExist): continue case err != nil: errs = append( errs, fmt.Errorf("checking if path %q exists: %w", path, err), ) case !stat.IsDir(): errs = append( errs, fmt.Errorf("path %q exists but is not a directory", path), ) default: return path, nil } } err := fmt.Errorf( "no directory found at any of the following paths: %s", strings.Join(paths, ", "), ) if len(errs) > 0 { err = errors.Join(slices.Insert(errs, 0, err)...) } return "", err }