github.com/pawelgaczynski/giouring@v0.0.0-20230826085535-69588b89acb9/kernel.go (about)

     1  // MIT License
     2  //
     3  // Copyright (c) 2023 Paweł Gaczyński
     4  //
     5  // Permission is hereby granted, free of charge, to any person obtaining a
     6  // copy of this software and associated documentation files (the
     7  // "Software"), to deal in the Software without restriction, including
     8  // without limitation the rights to use, copy, modify, merge, publish,
     9  // distribute, sublicense, and/or sell copies of the Software, and to
    10  // permit persons to whom the Software is furnished to do so, subject to
    11  // the following conditions:
    12  //
    13  // The above copyright notice and this permission notice shall be included
    14  // in all copies or substantial portions of the Software.
    15  //
    16  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    17  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    18  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    19  // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    20  // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    21  // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    22  // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    23  
    24  package giouring
    25  
    26  import (
    27  	"fmt"
    28  
    29  	"golang.org/x/sys/unix"
    30  )
    31  
    32  type KernelVersion struct {
    33  	Kernel int
    34  	Major  int
    35  	Minor  int
    36  	Flavor string
    37  }
    38  
    39  const (
    40  	firstNumberOfParts  = 2
    41  	secondNumberOfParts = 1
    42  )
    43  
    44  func parseKernelVersion(kernelVersionStr string) (*KernelVersion, error) {
    45  	var (
    46  		kernel, major, minor, parsed int
    47  		flavor, partial              string
    48  	)
    49  
    50  	parsed, _ = fmt.Sscanf(kernelVersionStr, "%d.%d%s", &kernel, &major, &partial)
    51  	if parsed < firstNumberOfParts {
    52  		return nil, fmt.Errorf("cannot parse kernel version: %s", kernelVersionStr)
    53  	}
    54  
    55  	parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor)
    56  	if parsed < secondNumberOfParts {
    57  		flavor = partial
    58  	}
    59  
    60  	return &KernelVersion{
    61  		Kernel: kernel,
    62  		Major:  major,
    63  		Minor:  minor,
    64  		Flavor: flavor,
    65  	}, nil
    66  }
    67  
    68  func GetKernelVersion() (*KernelVersion, error) {
    69  	uts := &unix.Utsname{}
    70  
    71  	if err := unix.Uname(uts); err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	return parseKernelVersion(unix.ByteSliceToString(uts.Release[:]))
    76  }
    77  
    78  func CompareKernelVersion(a, b KernelVersion) int {
    79  	if a.Kernel > b.Kernel {
    80  		return 1
    81  	} else if a.Kernel < b.Kernel {
    82  		return -1
    83  	}
    84  
    85  	if a.Major > b.Major {
    86  		return 1
    87  	} else if a.Major < b.Major {
    88  		return -1
    89  	}
    90  
    91  	if a.Minor > b.Minor {
    92  		return 1
    93  	} else if a.Minor < b.Minor {
    94  		return -1
    95  	}
    96  
    97  	return 0
    98  }
    99  
   100  func CheckKernelVersion(k, major, minor int) (bool, error) {
   101  	var (
   102  		v   *KernelVersion
   103  		err error
   104  	)
   105  	if v, err = GetKernelVersion(); err != nil {
   106  		return false, err
   107  	}
   108  	if CompareKernelVersion(*v, KernelVersion{Kernel: k, Major: major, Minor: minor}) < 0 {
   109  		return false, nil
   110  	}
   111  
   112  	return true, nil
   113  }