github.com/containerd/nerdctl@v1.7.7/pkg/platformutil/binfmt.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package platformutil 18 19 import ( 20 "fmt" 21 "os" 22 "runtime" 23 24 "github.com/containerd/platforms" 25 ) 26 27 func qemuArchFromOCIArch(ociArch string) (string, error) { 28 switch ociArch { 29 case "amd64": 30 return "x86_64", nil 31 case "arm64": 32 return "aarch64", nil 33 case "386": 34 return "i386", nil 35 case "arm", "s390x", "ppc64le", "riscv64", "mips64": 36 return ociArch, nil 37 case "mips64le": 38 return "mips64el", nil // NOT typo 39 } 40 return "", fmt.Errorf("unknown OCI architecture string: %q", ociArch) 41 } 42 43 func canExecProbably(s string) (bool, error) { 44 if s == "" { 45 return true, nil 46 } 47 p, err := platforms.Parse(s) 48 if err != nil { 49 return false, err 50 } 51 if platforms.Default().Match(p) { 52 return true, nil 53 } 54 if runtime.GOOS == "linux" { 55 qemuArch, err := qemuArchFromOCIArch(p.Architecture) 56 if err != nil { 57 return false, err 58 } 59 candidates := []string{ 60 "/proc/sys/fs/binfmt_misc/qemu-" + qemuArch, 61 "/proc/sys/fs/binfmt_misc/buildkit-qemu-" + qemuArch, 62 } 63 // Rosetta 2 for Linux on ARM Mac 64 // https://developer.apple.com/documentation/virtualization/running_intel_binaries_in_linux_vms_with_rosetta 65 if runtime.GOARCH == "arm64" && p.Architecture == "amd64" { 66 candidates = append(candidates, "/proc/sys/fs/binfmt_misc/rosetta") 67 } 68 for _, cand := range candidates { 69 if _, err := os.Stat(cand); err == nil { 70 return true, nil 71 } 72 } 73 } 74 return false, nil 75 } 76 77 func CanExecProbably(ss ...string) (bool, error) { 78 for _, s := range ss { 79 ok, err := canExecProbably(s) 80 if err != nil { 81 return false, err 82 } 83 if !ok { 84 return false, nil 85 } 86 } 87 return true, nil 88 }