kernel.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // +build !windows
  2. // Package kernel provides helper function to get, parse and compare kernel
  3. // versions for different platforms.
  4. package kernel
  5. import (
  6. "bytes"
  7. "errors"
  8. "fmt"
  9. )
  10. // VersionInfo holds information about the kernel.
  11. type VersionInfo struct {
  12. Kernel int // Version of the kernel (e.g. 4.1.2-generic -> 4)
  13. Major int // Major part of the kernel version (e.g. 4.1.2-generic -> 1)
  14. Minor int // Minor part of the kernel version (e.g. 4.1.2-generic -> 2)
  15. Flavor string // Flavor of the kernel version (e.g. 4.1.2-generic -> generic)
  16. }
  17. func (k *VersionInfo) String() string {
  18. return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor)
  19. }
  20. // CompareKernelVersion compares two kernel.VersionInfo structs.
  21. // Returns -1 if a < b, 0 if a == b, 1 it a > b
  22. func CompareKernelVersion(a, b VersionInfo) int {
  23. if a.Kernel < b.Kernel {
  24. return -1
  25. } else if a.Kernel > b.Kernel {
  26. return 1
  27. }
  28. if a.Major < b.Major {
  29. return -1
  30. } else if a.Major > b.Major {
  31. return 1
  32. }
  33. if a.Minor < b.Minor {
  34. return -1
  35. } else if a.Minor > b.Minor {
  36. return 1
  37. }
  38. return 0
  39. }
  40. // GetKernelVersion gets the current kernel version.
  41. func GetKernelVersion() (*VersionInfo, error) {
  42. var (
  43. err error
  44. )
  45. uts, err := uname()
  46. if err != nil {
  47. return nil, err
  48. }
  49. release := make([]byte, len(uts.Release))
  50. i := 0
  51. for _, c := range uts.Release {
  52. release[i] = byte(c)
  53. i++
  54. }
  55. // Remove the \x00 from the release for Atoi to parse correctly
  56. release = release[:bytes.IndexByte(release, 0)]
  57. return ParseRelease(string(release))
  58. }
  59. // ParseRelease parses a string and creates a VersionInfo based on it.
  60. func ParseRelease(release string) (*VersionInfo, error) {
  61. var (
  62. kernel, major, minor, parsed int
  63. flavor, partial string
  64. )
  65. // Ignore error from Sscanf to allow an empty flavor. Instead, just
  66. // make sure we got all the version numbers.
  67. parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial)
  68. if parsed < 2 {
  69. return nil, errors.New("Can't parse kernel version " + release)
  70. }
  71. // sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64
  72. parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor)
  73. if parsed < 1 {
  74. flavor = partial
  75. }
  76. return &VersionInfo{
  77. Kernel: kernel,
  78. Major: major,
  79. Minor: minor,
  80. Flavor: flavor,
  81. }, nil
  82. }