-
Notifications
You must be signed in to change notification settings - Fork 601
/
Copy patharch.go
154 lines (133 loc) · 4.32 KB
/
arch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2014-2015 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package arch
import (
"log"
"runtime"
"syscall"
"github.com/snapcore/snapd/release"
)
// ArchitectureType is the type for a supported snappy architecture
type ArchitectureType string
// arch is global to allow tools like ubuntu-device-flash to
// change the architecture. This is important to e.g. install
// armhf snaps onto a armhf image that is generated on an amd64
// machine
var arch = ArchitectureType(ubuntuArchFromGoArch(runtime.GOARCH))
// SetArchitecture allows overriding the auto detected Architecture
func SetArchitecture(newArch ArchitectureType) {
arch = newArch
}
// FIXME: rename all Ubuntu*Architecture() to SnapdArchitecture()
// (or DpkgArchitecture)
// UbuntuArchitecture returns the debian equivalent architecture for the
// currently running architecture.
//
// If the architecture does not map any debian architecture, the
// GOARCH is returned.
func UbuntuArchitecture() string {
return string(arch)
}
// ubuntuArchFromGoArch maps a go architecture string to the coresponding
// Ubuntu architecture string.
//
// E.g. the go "386" architecture string maps to the ubuntu "i386"
// architecture.
func ubuntuArchFromGoArch(goarch string) string {
goArchMapping := map[string]string{
// go ubuntu
"386": "i386",
"amd64": "amd64",
"arm": "armhf",
"arm64": "arm64",
"ppc64le": "ppc64el",
"s390x": "s390x",
"ppc": "powerpc",
// available in debian and other distros
"ppc64": "ppc64",
}
// If we are running on an ARM platform we need to have a
// closer look if we are on armhf or armel. If we're not
// on a armv6 platform we can continue to use the Go
// arch mapping. The Go arch sadly doesn't map this out
// for us so we have to fallback to uname here.
if goarch == "arm" {
machineName := release.Machine()
if machineName == "armv6l" {
return "armel"
}
}
ubuntuArch := goArchMapping[goarch]
if ubuntuArch == "" {
log.Panicf("unknown goarch %q", goarch)
}
return ubuntuArch
}
// UbuntuKernelArchitecture return the debian equivalent architecture
// for the current running kernel. This is usually the same as the
// UbuntuArchitecture - however there maybe cases that you run e.g.
// a snapd:i386 on an amd64 kernel.
func UbuntuKernelArchitecture() string {
var utsname syscall.Utsname
if err := syscall.Uname(&utsname); err != nil {
log.Panicf("cannot get kernel architecture: %v", err)
}
// syscall.Utsname{} is using [65]int8 for all char[] inside it,
// this makes converting it so awkward. The alternative would be
// to use a unsafe.Pointer() to cast it to a [65]byte slice.
// see https://github.com/golang/go/issues/20753
kernelArch := make([]byte, 0, len(utsname.Machine))
for _, c := range utsname.Machine {
if c == 0 {
break
}
kernelArch = append(kernelArch, byte(c))
}
return ubuntuArchFromKernelArch(string(kernelArch))
}
// ubuntuArchFromkernelArch maps the kernel architecture as reported
// via uname() to the dpkg architecture
func ubuntuArchFromKernelArch(utsMachine string) string {
kernelArchMapping := map[string]string{
// kernel ubuntu
"i686": "i386",
"x86_64": "amd64",
"armv7l": "armhf",
"aarch64": "arm64",
"ppc64le": "ppc64el",
"s390x": "s390x",
"ppc": "powerpc",
// available in debian and other distros
"ppc64": "ppc64",
}
ubuntuArch := kernelArchMapping[utsMachine]
if ubuntuArch == "" {
log.Panicf("unknown kernel arch %q", utsMachine)
}
return ubuntuArch
}
// IsSupportedArchitecture returns true if the system architecture is in the
// list of architectures.
func IsSupportedArchitecture(architectures []string) bool {
for _, a := range architectures {
if a == "all" || a == string(arch) {
return true
}
}
return false
}