mirror of
https://github.com/clearlinux/clr-installer.git
synced 2026-09-02 19:51:30 +00:00
Now check for which service is handling wired network interfaces. Needed by the TUI which still handles static IP configurations for wired connections. TODO: Once NetworkManager is the new OS default, we can explore configuring wireless interfaces via the TUI as well. TODO: Consider change the other systemctl calls to use new dbus. Dropping coverage requirement for this build Signed-off-by: Mark D Horn <mark.d.horn@intel.com>
296 lines
6.9 KiB
Go
296 lines
6.9 KiB
Go
// Copyright © 2018 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/user"
|
|
"path"
|
|
"path/filepath"
|
|
"regexp"
|
|
"runtime"
|
|
"strings"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"github.com/digitalocean/go-smbios/smbios"
|
|
|
|
"github.com/clearlinux/clr-installer/errors"
|
|
)
|
|
|
|
// ClearVersion is running version of the OS
|
|
var ClearVersion string
|
|
|
|
// ParseOSClearVersion parses the current version of the Clear Linux OS
|
|
func ParseOSClearVersion() error {
|
|
var versionBuf []byte
|
|
var err error
|
|
|
|
// in order to avoid issues raised by format bumps between installers image
|
|
// version and the latest released we assume the installers host version
|
|
// in other words we use the same version swupd is based on
|
|
if versionBuf, err = ioutil.ReadFile("/usr/lib/os-release"); err != nil {
|
|
return errors.Errorf("Read version file /usr/lib/os-release: %v", err)
|
|
}
|
|
versionExp := regexp.MustCompile(`VERSION_ID=([0-9][0-9]*)`)
|
|
match := versionExp.FindSubmatch(versionBuf)
|
|
|
|
if len(match) < 2 {
|
|
return errors.Errorf("Version not found in /usr/lib/os-release")
|
|
}
|
|
|
|
ClearVersion = string(match[1])
|
|
|
|
return nil
|
|
}
|
|
|
|
// MkdirAll similar to go's standard os.MkdirAll() this function creates a directory
|
|
// named path, along with any necessary parents but also checks if path exists and
|
|
// takes no action if that's true.
|
|
func MkdirAll(path string, perm os.FileMode) error {
|
|
if _, err := os.Stat(path); err == nil {
|
|
return nil
|
|
}
|
|
|
|
if err := os.MkdirAll(path, perm); err != nil {
|
|
return errors.Errorf("mkdir %s: %v", path, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CopyAllFiles copy all of the files in a directory recursively
|
|
func CopyAllFiles(srcDir string, destDir string) error {
|
|
err := filepath.Walk(srcDir,
|
|
func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return errors.Errorf("Failure accessing a path %q: %v\n", path, err)
|
|
}
|
|
target := filepath.Join(destDir, path)
|
|
if info.IsDir() {
|
|
// Create the matching target directory
|
|
if err := MkdirAll(target, info.Mode()); err != nil {
|
|
return errors.Errorf("Failed to mkdir %q", target)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
if err := CopyFile(path, target); err != nil {
|
|
return errors.Errorf("Failed to copy file %q", target)
|
|
}
|
|
|
|
// Ensure all contents is owned correctly
|
|
sys := info.Sys()
|
|
stat, ok := sys.(*syscall.Stat_t)
|
|
if ok {
|
|
if err := os.Chown(target, int(stat.Uid), int(stat.Gid)); err != nil {
|
|
return errors.Errorf("Failed to change ownership of %q to UID:%d, GID:%d",
|
|
target, stat.Uid, stat.Gid)
|
|
}
|
|
} else {
|
|
return errors.Errorf("Could not stat file %q", path)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to copy files")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CopyFile copies src file to dest
|
|
func CopyFile(src string, dest string) error {
|
|
destDir := filepath.Dir(dest)
|
|
|
|
srcInfo, err := os.Stat(src)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return errors.Errorf("no such file: %s", src)
|
|
}
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
if _, err = os.Stat(destDir); err != nil {
|
|
if os.IsNotExist(err) {
|
|
return errors.Errorf("no such dest directory: %s", destDir)
|
|
}
|
|
return errors.Wrap(err)
|
|
}
|
|
|
|
data, err := ioutil.ReadFile(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = ioutil.WriteFile(dest, data, srcInfo.Mode()&os.ModePerm); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// FileExists returns true if the file or directory exists
|
|
// else it returns false and the associated error
|
|
func FileExists(filePath string) (bool, error) {
|
|
_, err := os.Stat(filePath)
|
|
if err == nil {
|
|
return true, nil
|
|
}
|
|
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
|
|
return true, err
|
|
}
|
|
|
|
// VerifyRootUser returns an error if we're not running as root
|
|
func VerifyRootUser() string {
|
|
// ProgName is the short name of this executable
|
|
progName := path.Base(os.Args[0])
|
|
|
|
user, err := user.Current()
|
|
if err != nil {
|
|
return fmt.Sprintf("%s MUST run as 'root' user to install! (user=%s)",
|
|
progName, "UNKNOWN")
|
|
}
|
|
|
|
if user.Uid != "0" {
|
|
return fmt.Sprintf("%s MUST run as 'root' user to install! (user=%s)",
|
|
progName, user.Uid)
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// IsClearLinux checks if the current OS is Clear by looking for Swupd
|
|
// Mostly used in Go Testing
|
|
func IsClearLinux() bool {
|
|
is := false
|
|
|
|
if runtime.GOOS == "linux" {
|
|
clearFile := "/usr/bin/swupd"
|
|
if _, err := os.Stat(clearFile); !os.IsNotExist(err) {
|
|
is = true
|
|
}
|
|
}
|
|
|
|
return is
|
|
}
|
|
|
|
// IsRoot checks if the current User is root (UID 0)
|
|
// Mostly used in Go Testing
|
|
func IsRoot() bool {
|
|
is := false
|
|
|
|
user, err := user.Current()
|
|
if err == nil {
|
|
if user.Uid == "0" {
|
|
is = true
|
|
}
|
|
}
|
|
|
|
return is
|
|
}
|
|
|
|
// StringSliceContains returns true if sl contains str, returns false otherwise
|
|
func StringSliceContains(sl []string, str string) bool {
|
|
for _, curr := range sl {
|
|
if curr == str {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IntSliceContains returns true if is contains value, returns false otherwise
|
|
func IntSliceContains(is []int, value int) bool {
|
|
for _, curr := range is {
|
|
if curr == value {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsCheckCoverage returns true if CHECK_COVERAGE variable is set
|
|
func IsCheckCoverage() bool {
|
|
return os.Getenv("CHECK_COVERAGE") != ""
|
|
}
|
|
|
|
// IsStdoutTTY returns true if the stdout is attached to a tty
|
|
func IsStdoutTTY() bool {
|
|
var termios syscall.Termios
|
|
|
|
fd := os.Stdout.Fd()
|
|
ptr := uintptr(unsafe.Pointer(&termios))
|
|
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, syscall.TCGETS, ptr, 0, 0, 0)
|
|
|
|
return err == 0
|
|
}
|
|
|
|
// ExpandVariables iterates over vars map and replace all the ocorrences of ${var} or
|
|
// $var in the str string
|
|
func ExpandVariables(vars map[string]string, str string) string {
|
|
// iterate over available variables
|
|
for k, v := range vars {
|
|
// tries to replace both ${var} and $var forms
|
|
for _, rep := range []string{fmt.Sprintf("$%s", k), fmt.Sprintf("${%s}", k)} {
|
|
if strings.Contains(str, rep) {
|
|
return strings.Replace(str, rep, v, -1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// if no variables are expanded return the original string
|
|
return str
|
|
}
|
|
|
|
// IsVirtualBox returns true if the running system is executed
|
|
// from within VirtualBox
|
|
// Attempt to parse the System Management BIOS (SMBIOS) and
|
|
// Desktop Management Interface (DMI) to determine if we are
|
|
// executing inside a VirtualBox. Ignoring error conditions and
|
|
// assuming we are not VirtualBox.
|
|
func IsVirtualBox() bool {
|
|
virtualBox := false
|
|
|
|
// Find SMBIOS data in operating system-specific location.
|
|
rc, _, err := smbios.Stream()
|
|
if err != nil {
|
|
return virtualBox
|
|
}
|
|
|
|
// Be sure to close the stream!
|
|
defer func() { _ = rc.Close() }()
|
|
|
|
// Decode SMBIOS structures from the stream.
|
|
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.1.1.pdf
|
|
d := smbios.NewDecoder(rc)
|
|
ss, err := d.Decode()
|
|
if err != nil {
|
|
return virtualBox
|
|
}
|
|
|
|
for _, s := range ss {
|
|
// 7.2 System Information (Type 1)
|
|
if s.Header.Type == 1 {
|
|
for _, str := range s.Strings {
|
|
if strings.Contains(strings.ToLower(str), "virtualbox") {
|
|
virtualBox = true
|
|
return virtualBox
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return virtualBox
|
|
}
|