@@ -7,7 +7,9 @@ import (
@@ -17,6 +19,23 @@ import (
17 httpswagger "github.com/swaggo/http-swagger/v2"
19 httpswagger "github.com/swaggo/http-swagger/v2"
22+// maxUnixSocketPathLen is the maximum length of a Unix domain socket
23+// path. The macOS sun_path field is 104 bytes; Linux allows 108. We
24+// use 104 so the resulting path is portable across both platforms.
25+const maxUnixSocketPathLen = 104
27+// socketDir returns the directory used for the Crush Unix socket.
28+// It prefers $XDG_RUNTIME_DIR when set (systemd's per-user runtime
29+// directory on Linux), and otherwise falls back to [os.TempDir],
30+// which resolves to the per-user private $TMPDIR on macOS and to
32+func socketDir() string {
33+ if dir := os.Getenv("XDG_RUNTIME_DIR"); dir != "" {
20// ErrServerClosed is returned when the server is closed.
39// ErrServerClosed is returned when the server is closed.
21var ErrServerClosed = http.ErrServerClosed
40var ErrServerClosed = http.ErrServerClosed
@@ -44,6 +63,14 @@ func ParseHostURL(host string) (*url.URL, error) {
46// DefaultHost returns the default server host.
65// DefaultHost returns the default server host.
67+// On Windows the address is a named pipe under \\.\pipe\. On Unix
68+// platforms the socket lives in the per-user runtime directory
69+// returned by [socketDir] and is named crush-<uid>.sock, falling
70+// back to crush.sock when the current uid cannot be determined. If
71+// the composed path would exceed [maxUnixSocketPathLen] bytes (the
72+// macOS sun_path limit), we fall back to /tmp/crush-<uid>.sock so
73+// the socket remains bindable.
47func DefaultHost() string {
74func DefaultHost() string {
48 sock := "crush.sock"
75 sock := "crush.sock"
49 usr, err := user.Current()
76 usr, err := user.Current()
@@ -53,7 +80,11 @@ func DefaultHost() string {
53 if runtime.GOOS == "windows" {
80 if runtime.GOOS == "windows" {
54 return fmt.Sprintf("npipe:////./pipe/%s", sock)
81 return fmt.Sprintf("npipe:////./pipe/%s", sock)
83+ path := filepath.Join(socketDir(), sock)
84+ if len(path) > maxUnixSocketPathLen {
85+ path = filepath.Join("/tmp", sock)
56− return fmt.Sprintf("unix:///tmp/%s", sock)
87+ return "unix://" + path
59// Server represents a Crush server bound to a specific address.
90// Server represents a Crush server bound to a specific address.