github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/arch/arch.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2014-2015 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package arch
    21  
    22  import (
    23  	"log"
    24  	"runtime"
    25  
    26  	"github.com/snapcore/snapd/osutil"
    27  )
    28  
    29  // ArchitectureType is the type for a supported snappy architecture
    30  type ArchitectureType string
    31  
    32  // arch is global to allow tools like ubuntu-device-flash to
    33  // change the architecture. This is important to e.g. install
    34  // armhf snaps onto a armhf image that is generated on an amd64
    35  // machine
    36  var arch = ArchitectureType(dpkgArchFromGoArch(runtime.GOARCH))
    37  
    38  // SetArchitecture allows overriding the auto detected Architecture
    39  func SetArchitecture(newArch ArchitectureType) {
    40  	arch = newArch
    41  }
    42  
    43  // DpkgArchitecture returns the debian equivalent architecture for the
    44  // currently running architecture.
    45  //
    46  // If the architecture does not map any debian architecture, the
    47  // GOARCH is returned.
    48  func DpkgArchitecture() string {
    49  	return string(arch)
    50  }
    51  
    52  // dpkgArchFromGoArch maps a go architecture string to the coresponding
    53  // Debian equivalent architecture string.
    54  //
    55  // E.g. the go "386" architecture string maps to the ubuntu "i386"
    56  // architecture.
    57  func dpkgArchFromGoArch(goarch string) string {
    58  	goArchMapping := map[string]string{
    59  		// go      dpkg
    60  		"386":     "i386",
    61  		"amd64":   "amd64",
    62  		"arm":     "armhf",
    63  		"arm64":   "arm64",
    64  		"ppc":     "powerpc",
    65  		"ppc64":   "ppc64", // available in debian and other distros
    66  		"ppc64le": "ppc64el",
    67  		"riscv64": "riscv64",
    68  		"s390x":   "s390x",
    69  	}
    70  
    71  	// If we are running on an ARM platform we need to have a
    72  	// closer look if we are on armhf or armel. If we're not
    73  	// on a armv6 platform we can continue to use the Go
    74  	// arch mapping. The Go arch sadly doesn't map this out
    75  	// for us so we have to fallback to uname here.
    76  	if goarch == "arm" {
    77  		if osutil.MachineName() == "armv6l" {
    78  			return "armel"
    79  		}
    80  	}
    81  
    82  	dpkgArch := goArchMapping[goarch]
    83  	if dpkgArch == "" {
    84  		log.Panicf("unknown goarch %q", goarch)
    85  	}
    86  
    87  	return dpkgArch
    88  }
    89  
    90  // DpkgKernelArchitecture returns the debian equivalent architecture
    91  // for the current running kernel. This is usually the same as the
    92  // DpkgArchitecture - however there maybe cases that you run e.g.
    93  // a snapd:i386 on an amd64 kernel.
    94  func DpkgKernelArchitecture() string {
    95  	return dpkgArchFromKernelArch(osutil.MachineName())
    96  }
    97  
    98  // dpkgArchFromkernelArch maps the kernel architecture as reported
    99  // via uname() to the dpkg architecture
   100  func dpkgArchFromKernelArch(utsMachine string) string {
   101  	kernelArchMapping := map[string]string{
   102  		// kernel  dpkg
   103  		"aarch64": "arm64",
   104  		"armv7l":  "armhf",
   105  		"armv8l":  "arm64",
   106  		"i686":    "i386",
   107  		"ppc":     "powerpc",
   108  		"ppc64":   "ppc64", // available in debian and other distros
   109  		"ppc64le": "ppc64el",
   110  		"riscv64": "riscv64",
   111  		"s390x":   "s390x",
   112  		"x86_64":  "amd64",
   113  	}
   114  
   115  	dpkgArch := kernelArchMapping[utsMachine]
   116  	if dpkgArch == "" {
   117  		log.Panicf("unknown kernel arch %q", utsMachine)
   118  	}
   119  
   120  	return dpkgArch
   121  }
   122  
   123  // IsSupportedArchitecture returns true if the system architecture is in the
   124  // list of architectures.
   125  func IsSupportedArchitecture(architectures []string) bool {
   126  	for _, a := range architectures {
   127  		if a == "all" || a == string(arch) {
   128  			return true
   129  		}
   130  	}
   131  
   132  	return false
   133  }