github.com/containerd/nerdctl/v2@v2.0.0-beta.5.0.20240520001846-b5758f54fa28/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 case "loong64": 40 return "loongarch64", nil // NOT typo 41 } 42 return "", fmt.Errorf("unknown OCI architecture string: %q", ociArch) 43 } 44 45 func canExecProbably(s string) (bool, error) { 46 if s == "" { 47 return true, nil 48 } 49 p, err := platforms.Parse(s) 50 if err != nil { 51 return false, err 52 } 53 if platforms.Default().Match(p) { 54 return true, nil 55 } 56 if runtime.GOOS == "linux" { 57 qemuArch, err := qemuArchFromOCIArch(p.Architecture) 58 if err != nil { 59 return false, err 60 } 61 candidates := []string{ 62 "/proc/sys/fs/binfmt_misc/qemu-" + qemuArch, 63 "/proc/sys/fs/binfmt_misc/buildkit-qemu-" + qemuArch, 64 } 65 // Rosetta 2 for Linux on ARM Mac 66 // https://developer.apple.com/documentation/virtualization/running_intel_binaries_in_linux_vms_with_rosetta 67 if runtime.GOARCH == "arm64" && p.Architecture == "amd64" { 68 candidates = append(candidates, "/proc/sys/fs/binfmt_misc/rosetta") 69 } 70 for _, cand := range candidates { 71 if _, err := os.Stat(cand); err == nil { 72 return true, nil 73 } 74 } 75 } 76 return false, nil 77 } 78 79 func CanExecProbably(ss ...string) (bool, error) { 80 for _, s := range ss { 81 ok, err := canExecProbably(s) 82 if err != nil { 83 return false, err 84 } 85 if !ok { 86 return false, nil 87 } 88 } 89 return true, nil 90 }