ports/sysutils/beats8/files/patch-go-sysinfo
Oleksii Samorukov a26ef11678 sysutils/beats8: upgrade to 8.14.3
- fix beats by integrating patch from the https://github.com/elastic/go-sysinfo/pull/126
- upgrade to the latest version

ChangeLog: https://www.elastic.co/guide/en/beats/libbeat/current/release-notes.html
Approved by: otis (elastic)
PR: 272701
2024-07-21 14:16:24 +02:00

1327 lines
37 KiB
Text

diff -urN vendor.orig/github.com/elastic/go-sysinfo/internal/cgo/disabled.go vendor/github.com/elastic/go-sysinfo/internal/cgo/disabled.go
--- vendor.orig/github.com/elastic/go-sysinfo/internal/cgo/disabled.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/internal/cgo/disabled.go 2024-07-13 20:28:36.060882000 +0200
@@ -0,0 +1,23 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build !cgo
+
+package cgo
+
+// Enabled is true if cgo was enabled at compile-time.
+const Enabled = false
diff -urN vendor.orig/github.com/elastic/go-sysinfo/internal/cgo/enabled.go vendor/github.com/elastic/go-sysinfo/internal/cgo/enabled.go
--- vendor.orig/github.com/elastic/go-sysinfo/internal/cgo/enabled.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/internal/cgo/enabled.go 2024-07-13 20:28:36.060953000 +0200
@@ -0,0 +1,23 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build cgo
+
+package cgo
+
+// Enabled is true if cgo was enabled at compile-time.
+const Enabled = true
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/defs_freebsd.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/defs_freebsd.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/defs_freebsd.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/defs_freebsd.go 2024-07-13 20:28:36.065106000 +0200
@@ -0,0 +1,33 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build ignore
+// +build ignore
+
+package freebsd
+
+/*
+#include <sys/types.h>
+#include <sys/vmmeter.h>
+#include <sys/time.h>
+#include <kvm.h>
+*/
+import "C"
+
+type kvmSwap C.struct_kvm_swap
+
+type clockInfo C.struct_clockinfo
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/doc.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/doc.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/doc.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/doc.go 2024-07-13 20:28:36.065203000 +0200
@@ -0,0 +1,22 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Package freebsd implements the HostProvider and ProcessProvider interfaces
+// for providing information about FreeBSD.
+package freebsd
+
+//go:generate sh -c "go tool cgo -godefs defs_freebsd.go > ztypes_freebsd.go"
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo.go 2024-07-13 20:28:36.065317000 +0200
@@ -0,0 +1,238 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build freebsd && cgo
+
+package freebsd
+
+import (
+ "context"
+ "errors"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/prometheus/procfs"
+
+ "github.com/elastic/go-sysinfo/internal/registry"
+ "github.com/elastic/go-sysinfo/providers/shared"
+ "github.com/elastic/go-sysinfo/types"
+)
+
+func init() {
+ registry.Register(newFreeBSDSystem())
+}
+
+type freebsdSystem struct{}
+
+func newFreeBSDSystem() freebsdSystem {
+ return freebsdSystem{}
+}
+
+func (s freebsdSystem) Host() (types.Host, error) {
+ return newHost()
+}
+
+type host struct {
+ procFS procFS
+ info types.HostInfo
+}
+
+func (h *host) Info() types.HostInfo {
+ return h.info
+}
+
+func (h *host) CPUTime() (types.CPUTimes, error) {
+ cpu := types.CPUTimes{}
+ r := &reader{}
+ r.cpuTime(&cpu)
+ return cpu, r.Err()
+}
+
+func (h *host) Memory() (*types.HostMemoryInfo, error) {
+ m := &types.HostMemoryInfo{}
+ r := &reader{}
+ r.memInfo(m)
+ return m, r.Err()
+}
+
+func (h *host) FQDNWithContext(ctx context.Context) (string, error) {
+ return shared.FQDNWithContext(ctx)
+}
+
+func (h *host) FQDN() (string, error) {
+ return h.FQDNWithContext(context.Background())
+}
+
+func newHost() (*host, error) {
+ h := &host{}
+ r := &reader{}
+ r.architecture(h)
+ r.bootTime(h)
+ r.hostname(h)
+ r.network(h)
+ r.kernelVersion(h)
+ r.os(h)
+ r.time(h)
+ r.uniqueID(h)
+ return h, r.Err()
+}
+
+type reader struct {
+ errs []error
+}
+
+func (r *reader) addErr(err error) bool {
+ if err != nil {
+ if !errors.Is(err, types.ErrNotImplemented) {
+ r.errs = append(r.errs, err)
+ }
+ return true
+ }
+ return false
+}
+
+func (r *reader) Err() error {
+ return errors.Join(r.errs...)
+}
+
+func (r *reader) cpuTime(cpu *types.CPUTimes) {
+ times, err := cpuStateTimes()
+ if r.addErr(err) {
+ return
+ }
+ *cpu = *times
+}
+
+func (r *reader) memInfo(m *types.HostMemoryInfo) {
+ // Memory counter calculations:
+ // total = physical memory
+ // used = active + wired
+ // free = free
+ // available = buffers + inactive + cache + free
+
+ pageSize, err := pageSizeBytes()
+ if r.addErr(err) {
+ return
+ }
+
+ m.Total = totalPhysicalMem(r)
+ activePages := activePageCount(r)
+
+ m.Metrics = make(map[string]uint64, 6)
+ m.Metrics["active_bytes"] = activePages * pageSize
+
+ wirePages := wirePageCount(r)
+ m.Metrics["wired_bytes"] = wirePages * pageSize
+
+ inactivePages := inactivePageCount(r)
+ m.Metrics["inactive_bytes"] = inactivePages * pageSize
+
+ cachePages := cachePageCount(r)
+ m.Metrics["cache_bytes"] = cachePages * pageSize
+
+ freePages := freePageCount(r)
+ m.Metrics["free_bytes"] = freePages * pageSize
+
+ buffers := buffersUsedBytes(r)
+ m.Metrics["buffer_bytes"] = buffers
+
+ m.Used = (activePages + wirePages) * pageSize
+ m.Free = freePages * pageSize
+ m.Available = (inactivePages+cachePages+freePages)*pageSize + buffers
+
+ // Virtual (swap) Memory
+ swap, err := kvmGetSwapInfo()
+ if r.addErr(err) {
+ return
+ }
+
+ m.VirtualTotal = uint64(swap.Total) * pageSize
+ m.VirtualUsed = uint64(swap.Used) * pageSize
+ m.VirtualFree = m.VirtualTotal - m.VirtualUsed
+}
+
+func (r *reader) architecture(h *host) {
+ v, err := architecture()
+ if r.addErr(err) {
+ return
+ }
+ h.info.Architecture = v
+}
+
+func (r *reader) bootTime(h *host) {
+ v, err := bootTime()
+ if r.addErr(err) {
+ return
+ }
+ h.info.BootTime = v
+}
+
+func (r *reader) hostname(h *host) {
+ v, err := os.Hostname()
+ if r.addErr(err) {
+ return
+ }
+ h.info.Hostname = v
+}
+
+func (r *reader) network(h *host) {
+ ips, macs, err := shared.Network()
+ if r.addErr(err) {
+ return
+ }
+ h.info.IPs = ips
+ h.info.MACs = macs
+}
+
+func (r *reader) kernelVersion(h *host) {
+ v, err := kernelVersion()
+ if r.addErr(err) {
+ return
+ }
+ h.info.KernelVersion = v
+}
+
+func (r *reader) os(h *host) {
+ v, err := operatingSystem()
+ if r.addErr(err) {
+ return
+ }
+ h.info.OS = v
+}
+
+func (r *reader) time(h *host) {
+ h.info.Timezone, h.info.TimezoneOffsetSec = time.Now().Zone()
+}
+
+func (r *reader) uniqueID(h *host) {
+ v, err := machineID()
+ if r.addErr(err) {
+ return
+ }
+ h.info.UniqueID = v
+}
+
+type procFS struct {
+ procfs.FS
+ mountPoint string
+}
+
+func (fs *procFS) path(p ...string) string {
+ elem := append([]string{fs.mountPoint}, p...)
+ return filepath.Join(elem...)
+}
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo_test.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo_test.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo_test.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/host_freebsd_cgo_test.go 2024-07-13 20:28:36.065385000 +0200
@@ -0,0 +1,53 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build freebsd && cgo
+
+package freebsd
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/elastic/go-sysinfo/internal/registry"
+)
+
+var _ registry.HostProvider = freebsdSystem{}
+
+func TestHost(t *testing.T) {
+ host, err := newFreeBSDSystem().Host()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Run("Info", func(t *testing.T) {
+ info := host.Info()
+
+ data, _ := json.MarshalIndent(info, "", " ")
+ t.Log(string(data))
+ })
+
+ t.Run("Memory", func(t *testing.T) {
+ mem, err := host.Memory()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ data, _ := json.MarshalIndent(mem, "", " ")
+ t.Log(string(data))
+ })
+}
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/kvm_freebsd_cgo.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/kvm_freebsd_cgo.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/kvm_freebsd_cgo.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/kvm_freebsd_cgo.go 2024-07-13 20:28:36.065498000 +0200
@@ -0,0 +1,58 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build freebsd && cgo
+
+package freebsd
+
+/*
+#cgo LDFLAGS: -lkvm
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <paths.h>
+#include <kvm.h>
+#include <stdlib.h>
+*/
+import "C"
+
+import (
+ "fmt"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+// kvmGetSwapInfo returns swap summary statistics for the system. It accesses
+// the kernel virtual memory (kvm) images by using libkvm.
+func kvmGetSwapInfo() (*kvmSwap, error) {
+ // Obtain a KVM file descriptor.
+ var errstr *C.char
+ kd := C.kvm_open(nil, nil, nil, unix.O_RDONLY, errstr)
+ if errstr != nil {
+ return nil, fmt.Errorf("failed calling kvm_open: %s", C.GoString(errstr))
+ }
+ defer C.kvm_close(kd)
+
+ var swap kvmSwap
+ if n, err := C.kvm_getswapinfo(kd, (*C.struct_kvm_swap)(unsafe.Pointer(&swap)), 1, 0); n != 0 {
+ return nil, fmt.Errorf("failed to get kvm_getswapinfo: %w", err)
+ }
+
+ return &swap, nil
+}
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/process_freebsd_cgo.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/process_freebsd_cgo.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/process_freebsd_cgo.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/process_freebsd_cgo.go 2024-07-13 20:28:36.065578000 +0200
@@ -0,0 +1,386 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build freebsd && cgo
+
+package freebsd
+
+import "C"
+
+/*
+#cgo LDFLAGS: -lprocstat
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/user.h>
+
+#include <libprocstat.h>
+#include <string.h>
+
+struct kinfo_proc getProcInfoAt(struct kinfo_proc *procs, unsigned int index) {
+ return procs[index];
+}
+
+unsigned int countArrayItems(char **items) {
+ unsigned int i = 0;
+ for (i = 0; items[i] != NULL; ++i);
+ return i;
+}
+
+char * itemAtIndex(char **items, unsigned int index) {
+ return items[index];
+}
+
+unsigned int countFileStats(struct filestat_list *head) {
+ unsigned int count = 0;
+ struct filestat *fst;
+ STAILQ_FOREACH(fst, head, next) {
+ ++count;
+ }
+
+ return count;
+}
+
+void copyFileStats(struct filestat_list *head, struct filestat *out, unsigned int size) {
+ unsigned int index = 0;
+ struct filestat *fst;
+ if (size == 0) {
+ return;
+ }
+ STAILQ_FOREACH(fst, head, next) {
+ memcpy(out, fst, sizeof(*fst));
+ ++out;
+ --size;
+ }
+}
+*/
+import "C"
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/elastic/go-sysinfo/types"
+)
+
+func getProcInfo(op, arg int) ([]process, error) {
+ procstat, err := C.procstat_open_sysctl()
+ if procstat == nil {
+ return nil, fmt.Errorf("failed to open procstat sysctl: %w", err)
+ }
+ defer C.procstat_close(procstat)
+
+ var count C.uint = 0
+ kprocs, err := C.procstat_getprocs(procstat, C.int(op), C.int(arg), &count)
+ if kprocs == nil {
+ return nil, fmt.Errorf("getprocs failed: %w", err)
+ }
+ defer C.procstat_freeprocs(procstat, kprocs)
+
+ procs := make([]process, count)
+ var index C.uint
+ for index = 0; index < count; index++ {
+ proc := C.getProcInfoAt(kprocs, index)
+ procs[index].kinfo = proc
+ procs[index].pid = int(proc.ki_pid)
+ }
+
+ return procs, nil
+}
+
+func copyArray(from **C.char) []string {
+ if from == nil {
+ return nil
+ }
+
+ count := C.countArrayItems(from)
+ out := make([]string, count)
+
+ for index := C.uint(0); index < count; index++ {
+ out[index] = C.GoString(C.itemAtIndex(from, index))
+ }
+
+ return out
+}
+
+func makeMap(from []string) map[string]string {
+ out := make(map[string]string, len(from))
+
+ for _, env := range from {
+ parts := strings.Split(env, "=")
+ if len(parts) > 1 {
+ out[parts[0]] = parts[1]
+ }
+ }
+
+ return out
+}
+
+func getProcEnv(p *process) (map[string]string, error) {
+ procstat, err := C.procstat_open_sysctl()
+
+ if procstat == nil {
+ return nil, fmt.Errorf("failed to open procstat sysctl: %w", err)
+ }
+ defer C.procstat_close(procstat)
+
+ env, err := C.procstat_getenvv(procstat, &p.kinfo, 0)
+ defer C.procstat_freeenvv(procstat)
+
+ return makeMap(copyArray(env)), err
+}
+
+func getProcArgs(p *process) ([]string, error) {
+ procstat, err := C.procstat_open_sysctl()
+
+ if procstat == nil {
+ return nil, fmt.Errorf("failed to open procstat sysctl: %w", err)
+ }
+ defer C.procstat_close(procstat)
+
+ args, err := C.procstat_getargv(procstat, &p.kinfo, 0)
+ defer C.procstat_freeargv(procstat)
+
+ return copyArray(args), err
+}
+
+func getProcPathname(p *process) (string, error) {
+ procstat, err := C.procstat_open_sysctl()
+
+ if procstat == nil {
+ return "", fmt.Errorf("failed to open procstat sysctl: %w", err)
+ }
+ defer C.procstat_close(procstat)
+
+ const maxlen = uint(1024)
+ out := make([]C.char, maxlen)
+ if res, err := C.procstat_getpathname(procstat, &p.kinfo, &out[0], C.ulong(maxlen)); res != 0 {
+ return "", err
+ }
+ return C.GoString(&out[0]), nil
+}
+
+func getFileStats(fileStats *C.struct_filestat_list) []C.struct_filestat {
+ count := C.countFileStats(fileStats)
+
+ if count < 1 {
+ return nil
+ }
+
+ out := make([]C.struct_filestat, count)
+
+ C.copyFileStats(fileStats, &out[0], count)
+ return out
+}
+
+func getProcCWD(p *process) (string, error) {
+ procstat, err := C.procstat_open_sysctl()
+
+ if procstat == nil {
+ return "", fmt.Errorf("failed to open procstat sysctl: %w", err)
+ }
+ defer C.procstat_close(procstat)
+
+ fs, err := C.procstat_getfiles(procstat, &p.kinfo, 0)
+ if fs == nil {
+ return "", fmt.Errorf("failed to get files: %w", err)
+ }
+
+ defer C.procstat_freefiles(procstat, fs)
+
+ files := getFileStats(fs)
+ for _, f := range files {
+ if f.fs_uflags == C.PS_FST_UFLAG_CDIR {
+ return C.GoString(f.fs_path), nil
+ }
+ }
+
+ return "", nil
+}
+
+type process struct {
+ pid int
+ kinfo C.struct_kinfo_proc
+}
+
+func timevalToDuration(tm C.struct_timeval) time.Duration {
+ return time.Duration(tm.tv_sec)*time.Second +
+ time.Duration(tm.tv_usec)*time.Microsecond
+}
+
+func (p *process) CPUTime() (types.CPUTimes, error) {
+ procs, err := getProcInfo(C.KERN_PROC_PID, p.PID())
+ if err != nil {
+ return types.CPUTimes{}, err
+ }
+ p.kinfo = procs[0].kinfo
+
+ return types.CPUTimes{
+ User: timevalToDuration(p.kinfo.ki_rusage.ru_utime),
+ System: timevalToDuration(p.kinfo.ki_rusage.ru_stime),
+ }, nil
+}
+
+func (p *process) Info() (types.ProcessInfo, error) {
+ procs, err := getProcInfo(C.KERN_PROC_PID, p.PID())
+ if err != nil {
+ return types.ProcessInfo{}, err
+ }
+ p.kinfo = procs[0].kinfo
+
+ cwd, err := getProcCWD(p)
+ if err != nil {
+ return types.ProcessInfo{}, err
+ }
+
+ args, err := getProcArgs(p)
+ if err != nil {
+ return types.ProcessInfo{}, err
+ }
+
+ exe, _ := getProcPathname(p)
+
+ return types.ProcessInfo{
+ Name: C.GoString(&p.kinfo.ki_comm[0]),
+ PID: int(p.kinfo.ki_pid),
+ PPID: int(p.kinfo.ki_ppid),
+ CWD: cwd,
+ Exe: exe,
+ Args: args,
+ StartTime: time.Unix(int64(p.kinfo.ki_start.tv_sec), int64(p.kinfo.ki_start.tv_usec)*1000),
+ }, nil
+}
+
+func (p *process) Memory() (types.MemoryInfo, error) {
+ pageSize, err := pageSizeBytes()
+ if err != nil {
+ return types.MemoryInfo{}, err
+ }
+
+ procs, err := getProcInfo(C.KERN_PROC_PID, p.PID())
+ if err != nil {
+ return types.MemoryInfo{}, err
+ }
+ p.kinfo = procs[0].kinfo
+
+ return types.MemoryInfo{
+ Resident: uint64(p.kinfo.ki_rssize) * pageSize,
+ Virtual: uint64(p.kinfo.ki_size),
+ }, nil
+}
+
+func (p *process) User() (types.UserInfo, error) {
+ procs, err := getProcInfo(C.KERN_PROC_PID, p.PID())
+ if err != nil {
+ return types.UserInfo{}, err
+ }
+
+ p.kinfo = procs[0].kinfo
+
+ return types.UserInfo{
+ UID: strconv.FormatUint(uint64(p.kinfo.ki_ruid), 10),
+ EUID: strconv.FormatUint(uint64(p.kinfo.ki_uid), 10),
+ SUID: strconv.FormatUint(uint64(p.kinfo.ki_svuid), 10),
+ GID: strconv.FormatUint(uint64(p.kinfo.ki_rgid), 10),
+ EGID: strconv.FormatUint(uint64(p.kinfo.ki_groups[0]), 10),
+ SGID: strconv.FormatUint(uint64(p.kinfo.ki_svgid), 10),
+ }, nil
+}
+
+func (p *process) PID() int {
+ return p.pid
+}
+
+func (p *process) OpenHandles() ([]string, error) {
+ procstat := C.procstat_open_sysctl()
+ if procstat == nil {
+ return nil, errors.New("failed to open procstat sysctl")
+ }
+ defer C.procstat_close(procstat)
+
+ fs := C.procstat_getfiles(procstat, &p.kinfo, 0)
+ defer C.procstat_freefiles(procstat, fs)
+
+ files := getFileStats(fs)
+ names := make([]string, 0, len(files))
+
+ for _, file := range files {
+ if file.fs_type == 1 {
+ if path := C.GoString(file.fs_path); path != "" {
+ names = append(names, path)
+ }
+ }
+ }
+
+ return names, nil
+}
+
+func (p *process) OpenHandleCount() (int, error) {
+ procstat := C.procstat_open_sysctl()
+ if procstat == nil {
+ return 0, errors.New("failed to open procstat sysctl")
+ }
+ defer C.procstat_close(procstat)
+
+ fs := C.procstat_getfiles(procstat, &p.kinfo, 0)
+ defer C.procstat_freefiles(procstat, fs)
+ return int(C.countFileStats(fs)), nil
+}
+
+func (p *process) Environment() (map[string]string, error) {
+ return getProcEnv(p)
+}
+
+func (s freebsdSystem) Processes() ([]types.Process, error) {
+ procs, err := getProcInfo(C.KERN_PROC_PROC, 0)
+ out := make([]types.Process, 0, len(procs))
+
+ for _, proc := range procs {
+ out = append(out, &process{
+ pid: proc.pid,
+ kinfo: proc.kinfo,
+ })
+ }
+
+ return out, err
+}
+
+func (s freebsdSystem) Process(pid int) (types.Process, error) {
+ return &process{pid: pid}, nil
+}
+
+func (s freebsdSystem) Self() (types.Process, error) {
+ return s.Process(os.Getpid())
+}
+
+func (p *process) Parent() (types.Process, error) {
+ info, err := p.Info()
+ if err != nil {
+ return nil, err
+ }
+
+ proc := process{pid: info.PPID}
+
+ return &proc, nil
+}
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd.go 2024-07-13 20:28:36.065700000 +0200
@@ -0,0 +1,248 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build freebsd
+
+package freebsd
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+ "unsafe"
+
+ "github.com/elastic/go-sysinfo/types"
+
+ "golang.org/x/sys/unix"
+)
+
+var tickDuration = sync.OnceValues(func() (time.Duration, error) {
+ const mib = "kern.clockrate"
+
+ c, err := unix.SysctlClockinfo(mib)
+ if err != nil {
+ return 0, fmt.Errorf("failed to get %s: %w", mib, err)
+ }
+ return time.Duration(c.Tick) * time.Microsecond, nil
+})
+
+var pageSizeBytes = sync.OnceValues(func() (uint64, error) {
+ const mib = "vm.stats.vm.v_page_size"
+
+ v, err := unix.SysctlUint32(mib)
+ if err != nil {
+ return 0, fmt.Errorf("failed to get %s: %w", mib, err)
+ }
+
+ return uint64(v), nil
+})
+
+func activePageCount(r *reader) uint64 {
+ const mib = "vm.stats.vm.v_active_count"
+
+ v, err := unix.SysctlUint32(mib)
+ if r.addErr(err) {
+ return 0
+ }
+ return uint64(v)
+}
+
+func architecture() (string, error) {
+ const mib = "hw.machine"
+
+ arch, err := unix.Sysctl(mib)
+ if err != nil {
+ return "", fmt.Errorf("failed to get architecture: %w", err)
+ }
+
+ return arch, nil
+}
+
+func bootTime() (time.Time, error) {
+ const mib = "kern.boottime"
+
+ tv, err := unix.SysctlTimeval(mib)
+ if err != nil {
+ return time.Time{}, fmt.Errorf("failed to get host uptime: %w", err)
+ }
+
+ bootTime := time.Unix(tv.Sec, tv.Usec*int64(time.Microsecond))
+ return bootTime, nil
+}
+
+// buffersUsedBytes returns the number memory bytes used as disk cache.
+func buffersUsedBytes(r *reader) uint64 {
+ const mib = "vfs.bufspace"
+
+ v, err := unix.SysctlUint64(mib)
+ if r.addErr(err) {
+ return 0
+ }
+
+ return v
+}
+
+func cachePageCount(r *reader) uint64 {
+ const mib = "vm.stats.vm.v_cache_count"
+
+ v, err := unix.SysctlUint32(mib)
+ if r.addErr(err) {
+ return 0
+ }
+
+ return uint64(v)
+}
+
+const sizeOfUint64 = int(unsafe.Sizeof(uint64(0)))
+
+// cpuStateTimes uses sysctl kern.cp_time to get the amount of time spent in
+// different CPU states.
+func cpuStateTimes() (*types.CPUTimes, error) {
+ tickDuration, err := tickDuration()
+ if err != nil {
+ return nil, err
+ }
+
+ const mib = "kern.cp_time"
+ buf, err := unix.SysctlRaw(mib)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get %s: %w", mib, err)
+ }
+
+ var clockTicks [unix.CPUSTATES]uint64
+ if len(buf) < len(clockTicks)*sizeOfUint64 {
+ return nil, fmt.Errorf("kern.cp_time data is too short (got %d bytes)", len(buf))
+ }
+ for i := range clockTicks {
+ val := *(*uint64)(unsafe.Pointer(&buf[sizeOfUint64*i]))
+ clockTicks[i] = val
+ }
+
+ return &types.CPUTimes{
+ User: time.Duration(clockTicks[unix.CP_USER]) * tickDuration,
+ System: time.Duration(clockTicks[unix.CP_SYS]) * tickDuration,
+ Idle: time.Duration(clockTicks[unix.CP_IDLE]) * tickDuration,
+ IRQ: time.Duration(clockTicks[unix.CP_INTR]) * tickDuration,
+ Nice: time.Duration(clockTicks[unix.CP_NICE]) * tickDuration,
+ }, nil
+}
+
+func freePageCount(r *reader) uint64 {
+ const mib = "vm.stats.vm.v_free_count"
+
+ v, err := unix.SysctlUint32(mib)
+ if r.addErr(err) {
+ return 0
+ }
+
+ return uint64(v)
+}
+
+func inactivePageCount(r *reader) uint64 {
+ const mib = "vm.stats.vm.v_inactive_count"
+
+ v, err := unix.SysctlUint32(mib)
+ if r.addErr(err) {
+ return 0
+ }
+
+ return uint64(v)
+}
+
+func kernelVersion() (string, error) {
+ const mib = "kern.osrelease"
+
+ version, err := unix.Sysctl(mib)
+ if err != nil {
+ return "", fmt.Errorf("failed to get kernel version: %w", err)
+ }
+
+ return version, nil
+}
+
+func machineID() (string, error) {
+ const mib = "kern.hostuuid"
+
+ uuid, err := unix.Sysctl(mib)
+ if err != nil {
+ return "", fmt.Errorf("failed to get machine id: %w", err)
+ }
+
+ return uuid, nil
+}
+
+func operatingSystem() (*types.OSInfo, error) {
+ info := &types.OSInfo{
+ Type: "freebsd",
+ Family: "freebsd",
+ Platform: "freebsd",
+ }
+
+ osType, err := unix.Sysctl("kern.ostype")
+ if err != nil {
+ return info, err
+ }
+ info.Name = osType
+
+ // Example: 13.0-RELEASE-p11
+ osRelease, err := unix.Sysctl("kern.osrelease")
+ if err != nil {
+ return info, err
+ }
+ info.Version = osRelease
+
+ releaseParts := strings.Split(osRelease, "-")
+
+ majorMinor := strings.Split(releaseParts[0], ".")
+ if len(majorMinor) > 0 {
+ info.Major, _ = strconv.Atoi(majorMinor[0])
+ }
+ if len(majorMinor) > 1 {
+ info.Minor, _ = strconv.Atoi(majorMinor[1])
+ }
+
+ if len(releaseParts) > 1 {
+ info.Build = releaseParts[1]
+ }
+ if len(releaseParts) > 2 {
+ info.Patch, _ = strconv.Atoi(strings.TrimPrefix(releaseParts[2], "p"))
+ }
+
+ return info, nil
+}
+
+func totalPhysicalMem(r *reader) uint64 {
+ const mib = "hw.physmem"
+
+ v, err := unix.SysctlUint64(mib)
+ if r.addErr(err) {
+ return 0
+ }
+ return v
+}
+
+func wirePageCount(r *reader) uint64 {
+ const mib = "vm.stats.vm.v_wire_count"
+
+ v, err := unix.SysctlUint32(mib)
+ if r.addErr(err) {
+ return 0
+ }
+ return uint64(v)
+}
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd_test.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd_test.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd_test.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/sysctl_freebsd_test.go 2024-07-13 20:28:36.065808000 +0200
@@ -0,0 +1,137 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build freebsd
+
+package freebsd
+
+import (
+ "encoding/json"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "os/exec"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestArchitecture(t *testing.T) {
+ arch, err := architecture()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ assert.NotEmpty(t, arch)
+ assert.Regexp(t, `(amd64|i386|powerpc|arm(64)?|riscv|mips|sparc64|pc98)`, arch)
+}
+
+func TestBootTime(t *testing.T) {
+ bootTime, err := bootTime()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ bootDiff := time.Since(bootTime)
+ // t.Logf("bootTime in seconds: %#v", int64(bootDiff.Seconds()))
+
+ cmd := exec.Command("/usr/bin/uptime", "--libxo=json")
+ upcmd, err := cmd.Output()
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Logf(string(upcmd))
+
+ type UptimeOutput struct {
+ UptimeInformation struct {
+ Uptime int64 `json:"uptime"`
+ } `json:"uptime-information"`
+ }
+
+ var upInfo UptimeOutput
+ err = json.Unmarshal(upcmd, &upInfo)
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ upsec := upInfo.UptimeInformation.Uptime
+ uptime := time.Duration(upsec * int64(time.Second))
+ // t.Logf("uptime in seconds: %#v", int64(uptime.Seconds()))
+
+ assert.InDelta(t, uptime, bootDiff, float64(5*time.Second))
+}
+
+func TestCPUStateTimes(t *testing.T) {
+ times, err := cpuStateTimes()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ require.NotNil(t, times)
+ assert.NotZero(t, *times)
+}
+
+func TestKernelVersion(t *testing.T) {
+ kernel, err := kernelVersion()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Retrieve currently running kernel version
+ cmd := exec.Command("/bin/freebsd-version", "-r")
+ fbsdout, err := cmd.Output()
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ fbsdver := strings.TrimSuffix(string(fbsdout), "\n")
+
+ assert.NotEmpty(t, kernel)
+ assert.EqualValues(t, kernel, fbsdver)
+}
+
+func TestMachineID(t *testing.T) {
+ machineID, err := machineID()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ assert.NotEmpty(t, machineID)
+ assert.Regexp(t, "^[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}$", machineID)
+}
+
+func TestOperatingSystem(t *testing.T) {
+ t.Run("freebsd", func(t *testing.T) {
+ os, err := operatingSystem()
+ if err != nil {
+ t.Fatal(err)
+ }
+ assert.Equal(t, "freebsd", os.Type)
+ assert.Equal(t, "freebsd", os.Family)
+ assert.Equal(t, "freebsd", os.Platform)
+ assert.Equal(t, "FreeBSD", os.Name)
+ assert.Regexp(t, `\d{1,2}\.\d{1,2}-(RELEASE|STABLE|CURRENT|RC[0-9]|ALPHA(\d{0,2})|BETA(\d{0,2}))(-p\d)?`, os.Version)
+ assert.Regexp(t, `\d{1,2}`, os.Major)
+ assert.Regexp(t, `\d{1,2}`, os.Minor)
+ assert.Regexp(t, `\d{1,2}`, os.Patch)
+ assert.Regexp(t, `(RELEASE|STABLE|CURRENT|RC[0-9]|ALPHA([0-9]{0,2})|BETA([0-9]{0,2}))`, os.Build)
+ t.Logf("%#v", os)
+ })
+}
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/ztypes_freebsd.go vendor/github.com/elastic/go-sysinfo/providers/freebsd/ztypes_freebsd.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/freebsd/ztypes_freebsd.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/github.com/elastic/go-sysinfo/providers/freebsd/ztypes_freebsd.go 2024-07-13 20:28:36.065887000 +0200
@@ -0,0 +1,39 @@
+// Licensed to Elasticsearch B.V. under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Elasticsearch B.V. licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+// Code generated by cmd/cgo -godefs; and then patched up to fix
+// an alignment issue
+// cgo -godefs defs_freebsd.go
+
+package freebsd
+
+type kvmSwap struct {
+ Devname [32]int8
+ Used uint32
+ Total uint32
+ Flags int32
+ Reserved1 uint32
+ Reserved2 uint32
+}
+
+type clockInfo struct {
+ Hz int32
+ Tick int32
+ Spare int32
+ Stathz int32
+ Profhz int32
+}
diff -urN vendor.orig/github.com/elastic/go-sysinfo/providers/shared/fqdn.go vendor/github.com/elastic/go-sysinfo/providers/shared/fqdn.go
--- vendor.orig/github.com/elastic/go-sysinfo/providers/shared/fqdn.go 2024-07-13 21:34:29.109657000 +0200
+++ vendor/github.com/elastic/go-sysinfo/providers/shared/fqdn.go 2024-07-13 20:28:36.077420000 +0200
@@ -15,7 +15,7 @@
// specific language governing permissions and limitations
// under the License.
-//go:build linux || darwin || aix
+//go:build linux || darwin || aix || freebsd
package shared
diff -urN vendor.orig/github.com/elastic/go-sysinfo/system.go vendor/github.com/elastic/go-sysinfo/system.go
--- vendor.orig/github.com/elastic/go-sysinfo/system.go 2024-07-13 21:34:29.110051000 +0200
+++ vendor/github.com/elastic/go-sysinfo/system.go 2024-07-13 20:28:36.079545000 +0200
@@ -26,6 +26,7 @@
// Register host and process providers.
_ "github.com/elastic/go-sysinfo/providers/aix"
_ "github.com/elastic/go-sysinfo/providers/darwin"
+ _ "github.com/elastic/go-sysinfo/providers/freebsd"
_ "github.com/elastic/go-sysinfo/providers/linux"
_ "github.com/elastic/go-sysinfo/providers/windows"
)