| package kernel |
| |
| import ( |
| "bytes" |
| "errors" |
| "fmt" |
| ) |
| |
| type KernelVersionInfo struct { |
| Kernel int |
| Major int |
| Minor int |
| Flavor string |
| } |
| |
| func (k *KernelVersionInfo) String() string { |
| return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor) |
| } |
| |
| // Compare two KernelVersionInfo struct. |
| // Returns -1 if a < b, 0 if a == b, 1 it a > b |
| func CompareKernelVersion(a, b *KernelVersionInfo) int { |
| if a.Kernel < b.Kernel { |
| return -1 |
| } else if a.Kernel > b.Kernel { |
| return 1 |
| } |
| |
| if a.Major < b.Major { |
| return -1 |
| } else if a.Major > b.Major { |
| return 1 |
| } |
| |
| if a.Minor < b.Minor { |
| return -1 |
| } else if a.Minor > b.Minor { |
| return 1 |
| } |
| |
| return 0 |
| } |
| |
| func GetKernelVersion() (*KernelVersionInfo, error) { |
| var ( |
| err error |
| ) |
| |
| uts, err := uname() |
| if err != nil { |
| return nil, err |
| } |
| |
| release := make([]byte, len(uts.Release)) |
| |
| i := 0 |
| for _, c := range uts.Release { |
| release[i] = byte(c) |
| i++ |
| } |
| |
| // Remove the \x00 from the release for Atoi to parse correctly |
| release = release[:bytes.IndexByte(release, 0)] |
| |
| return ParseRelease(string(release)) |
| } |
| |
| func ParseRelease(release string) (*KernelVersionInfo, error) { |
| var ( |
| kernel, major, minor, parsed int |
| flavor, partial string |
| ) |
| |
| // Ignore error from Sscanf to allow an empty flavor. Instead, just |
| // make sure we got all the version numbers. |
| parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial) |
| if parsed < 2 { |
| return nil, errors.New("Can't parse kernel version " + release) |
| } |
| |
| // sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64 |
| parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor) |
| if parsed < 1 { |
| flavor = partial |
| } |
| |
| return &KernelVersionInfo{ |
| Kernel: kernel, |
| Major: major, |
| Minor: minor, |
| Flavor: flavor, |
| }, nil |
| } |