gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

version.go (3199B)


      1 package internal
      2 
      3 import (
      4 	"fmt"
      5 	"sync"
      6 
      7 	"github.com/cilium/ebpf/internal/unix"
      8 )
      9 
     10 const (
     11 	// Version constant used in ELF binaries indicating that the loader needs to
     12 	// substitute the eBPF program's version with the value of the kernel's
     13 	// KERNEL_VERSION compile-time macro. Used for compatibility with BCC, gobpf
     14 	// and RedSift.
     15 	MagicKernelVersion = 0xFFFFFFFE
     16 )
     17 
     18 var (
     19 	kernelVersion = struct {
     20 		once    sync.Once
     21 		version Version
     22 		err     error
     23 	}{}
     24 )
     25 
     26 // A Version in the form Major.Minor.Patch.
     27 type Version [3]uint16
     28 
     29 // NewVersion creates a version from a string like "Major.Minor.Patch".
     30 //
     31 // Patch is optional.
     32 func NewVersion(ver string) (Version, error) {
     33 	var major, minor, patch uint16
     34 	n, _ := fmt.Sscanf(ver, "%d.%d.%d", &major, &minor, &patch)
     35 	if n < 2 {
     36 		return Version{}, fmt.Errorf("invalid version: %s", ver)
     37 	}
     38 	return Version{major, minor, patch}, nil
     39 }
     40 
     41 // NewVersionFromCode creates a version from a LINUX_VERSION_CODE.
     42 func NewVersionFromCode(code uint32) Version {
     43 	return Version{
     44 		uint16(uint8(code >> 16)),
     45 		uint16(uint8(code >> 8)),
     46 		uint16(uint8(code)),
     47 	}
     48 }
     49 
     50 func (v Version) String() string {
     51 	if v[2] == 0 {
     52 		return fmt.Sprintf("v%d.%d", v[0], v[1])
     53 	}
     54 	return fmt.Sprintf("v%d.%d.%d", v[0], v[1], v[2])
     55 }
     56 
     57 // Less returns true if the version is less than another version.
     58 func (v Version) Less(other Version) bool {
     59 	for i, a := range v {
     60 		if a == other[i] {
     61 			continue
     62 		}
     63 		return a < other[i]
     64 	}
     65 	return false
     66 }
     67 
     68 // Unspecified returns true if the version is all zero.
     69 func (v Version) Unspecified() bool {
     70 	return v[0] == 0 && v[1] == 0 && v[2] == 0
     71 }
     72 
     73 // Kernel implements the kernel's KERNEL_VERSION macro from linux/version.h.
     74 // It represents the kernel version and patch level as a single value.
     75 func (v Version) Kernel() uint32 {
     76 
     77 	// Kernels 4.4 and 4.9 have their SUBLEVEL clamped to 255 to avoid
     78 	// overflowing into PATCHLEVEL.
     79 	// See kernel commit 9b82f13e7ef3 ("kbuild: clamp SUBLEVEL to 255").
     80 	s := v[2]
     81 	if s > 255 {
     82 		s = 255
     83 	}
     84 
     85 	// Truncate members to uint8 to prevent them from spilling over into
     86 	// each other when overflowing 8 bits.
     87 	return uint32(uint8(v[0]))<<16 | uint32(uint8(v[1]))<<8 | uint32(uint8(s))
     88 }
     89 
     90 // KernelVersion returns the version of the currently running kernel.
     91 func KernelVersion() (Version, error) {
     92 	kernelVersion.once.Do(func() {
     93 		kernelVersion.version, kernelVersion.err = detectKernelVersion()
     94 	})
     95 
     96 	if kernelVersion.err != nil {
     97 		return Version{}, kernelVersion.err
     98 	}
     99 	return kernelVersion.version, nil
    100 }
    101 
    102 // detectKernelVersion returns the version of the running kernel.
    103 func detectKernelVersion() (Version, error) {
    104 	vc, err := vdsoVersion()
    105 	if err != nil {
    106 		return Version{}, err
    107 	}
    108 	return NewVersionFromCode(vc), nil
    109 }
    110 
    111 // KernelRelease returns the release string of the running kernel.
    112 // Its format depends on the Linux distribution and corresponds to directory
    113 // names in /lib/modules by convention. Some examples are 5.15.17-1-lts and
    114 // 4.19.0-16-amd64.
    115 func KernelRelease() (string, error) {
    116 	var uname unix.Utsname
    117 	if err := unix.Uname(&uname); err != nil {
    118 		return "", fmt.Errorf("uname failed: %w", err)
    119 	}
    120 
    121 	return unix.ByteSliceToString(uname.Release[:]), nil
    122 }