@cryptotaxi247 / netdata-1 / commits / 539f59e41

fix(go.d): correct Windows install paths (#21451)

Ilya Mashchenko committed Dec 11, 2025 at 19:13 UTC 539f59e41562bfc5bc25fe304c6fd6f6ae79fb6a
2 files changed +107 -2
src/go/cmd/godplugin/main.go
+1 -1
@@ -60,7 +60,7 @@ func main() {
60 DumpSummary: opts.DumpSummary,
61 })
62
63 - a.Debugf("plugin: name=%s, %s", a.Name, buildinfo.Info())
63 + a.Infof("plugin: name=%s, %s", a.Name, buildinfo.Info())
64 if u, err := user.Current(); err == nil {
65 a.Debugf("current user: name=%s, uid=%s", u.Username, u.Uid)
66 }
src/go/pkg/buildinfo/buildinfo.go
+106 -1
@@ -2,7 +2,14 @@
2
3 package buildinfo
4
5 -import "fmt"
5 +import (
6 + "fmt"
7 + "path/filepath"
8 + "runtime"
9 + "strings"
10 +
11 + "github.com/netdata/netdata/go/plugins/pkg/executable"
12 +)
13
14 // The following variables are set at build time using linker flags.
15
@@ -32,3 +39,101 @@ func Info() string {
39 NetdataBinDir,
40 )
41 }
42 +
43 +func init() {
44 + if runtime.GOOS != "windows" {
45 + return
46 + }
47 +
48 + execDir := executable.Directory
49 + if execDir == "" || PluginsDir == "" {
50 + return
51 + }
52 +
53 + // ----------------------------------------------------------------------------
54 + // 1. Detect install prefix on Windows
55 + //
56 + // We assume that on Windows the *running binary* lives inside PluginsDir.
57 + //
58 + // Example:
59 + // execDir = "C:/Program Files/Netdata/usr/libexec/netdata/plugins.d"
60 + // PluginsDir = "/usr/libexec/netdata/plugins.d"
61 + //
62 + // By normalizing both paths to forward-slash format, we can test:
63 + //
64 + // strings.HasSuffix(execDir, PluginsDir) → true
65 + //
66 + // From that, we strip the suffix and recover the actual installation prefix:
67 + //
68 + // prefix = "C:/Program Files/Netdata"
69 + //
70 + // If execDir does *not* end with PluginsDir, we simply do nothing — this keeps
71 + // development/testing environments safe where binaries are run outside the
72 + // expected layout.
73 + // ----------------------------------------------------------------------------
74 + normalized := filepath.ToSlash(execDir)
75 + suffix := filepath.ToSlash(PluginsDir)
76 +
77 + if !strings.HasSuffix(normalized, suffix) {
78 + return
79 + }
80 +
81 + // Extract the prefix by removing the suffix.
82 + //
83 + // Example:
84 + // normalized = "C:/Program Files/Netdata/usr/libexec/netdata/plugins.d"
85 + // suffix = "/usr/libexec/netdata/plugins.d"
86 + //
87 + // → prefix = "C:/Program Files/Netdata"
88 + prefix := strings.TrimSuffix(normalized, suffix)
89 + prefix = strings.TrimSuffix(prefix, "/")
90 +
91 + installPrefix := filepath.FromSlash(prefix)
92 +
93 + // ----------------------------------------------------------------------------
94 + // 2. Rewrite all buildinfo paths as:
95 + // <installPrefix> + <original buildinfo path as relative suffix>
96 + //
97 + // Example:
98 + // NetdataBinDir build-time: "/usr/sbin"
99 + // After rewrite:
100 + // "C:\Program Files\Netdata\usr\sbin"
101 + //
102 + // Notes:
103 + // • We must remove the *leading slash* from the build-time path, otherwise
104 + // filepath.Join would treat it as absolute and ignore the prefix.
105 + //
106 + // Example of what we avoid:
107 + // filepath.Join("C:\\Program Files\\Netdata", "/usr/sbin") →
108 + // "\usr\sbin" (WRONG — prefix lost!)
109 + //
110 + // • Paths that were empty at build time should remain empty.
111 + // ----------------------------------------------------------------------------
112 + rebuild := func(p string) string {
113 + if p == "" {
114 + return ""
115 + }
116 +
117 + // Convert to slash form and trim the leading '/' so it becomes relative.
118 + //
119 + // Example:
120 + // p = "/usr/sbin"
121 + // → s = "usr/sbin"
122 + //
123 + s := filepath.ToSlash(p)
124 + s = strings.TrimPrefix(s, "/")
125 +
126 + // Now prefix + relative suffix works reliably on Windows.
127 + //
128 + // Example:
129 + // installPrefix = "C:\\Program Files\\Netdata"
130 + // s = "usr/sbin"
131 + // → result = "C:\\Program Files\\Netdata\\usr\\sbin"
132 + return filepath.Join(installPrefix, s)
133 + }
134 +
135 + UserConfigDir = rebuild(UserConfigDir)
136 + StockConfigDir = rebuild(StockConfigDir)
137 + PluginsDir = rebuild(PluginsDir)
138 + NetdataBinDir = rebuild(NetdataBinDir)
139 +}