github.com/shiroyuki/docker@v1.9.0/pkg/parsers/kernel/kernel.go (about)

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