9c9576b5b9
ci / test (macos-latest) (push) Has been cancelled
ci / test (ubuntu-latest) (push) Has been cancelled
ci / lint (push) Has been cancelled
ci / govulncheck (push) Has been cancelled
ci / tidy (push) Has been cancelled
ci / webview (push) Has been cancelled
ci / windows-gui (push) Has been cancelled
release / check (push) Has been cancelled
release / release (push) Has been cancelled
Docs / build (push) Has been cancelled
Docs / deploy-pages (push) Has been cancelled
Docs / deploy-cloudflare (push) Has been cancelled
58 lines
1.8 KiB
Go
58 lines
1.8 KiB
Go
package pack
|
|
|
|
import "os"
|
|
|
|
// Executable-format magic numbers, enough to tell the three desktop targets
|
|
// apart by their first bytes. We only need the family (windows, darwin, linux),
|
|
// not the architecture, so the smallest distinguishing prefix is plenty.
|
|
var (
|
|
magicELF = []byte{0x7f, 'E', 'L', 'F'} // Linux, FreeBSD, and other ELF systems
|
|
magicPE = []byte{'M', 'Z'} // Windows PE/COFF (DOS stub header)
|
|
machOLE64 = []byte{0xcf, 0xfa, 0xed, 0xfe} // Mach-O 64-bit, little-endian (amd64, arm64)
|
|
machOLE32 = []byte{0xce, 0xfa, 0xed, 0xfe} // Mach-O 32-bit, little-endian
|
|
machOBE64 = []byte{0xfe, 0xed, 0xfa, 0xcf} // Mach-O 64-bit, big-endian
|
|
machOBE32 = []byte{0xfe, 0xed, 0xfa, 0xce} // Mach-O 32-bit, big-endian
|
|
machOFat = []byte{0xca, 0xfe, 0xba, 0xbe} // Mach-O universal (fat) binary
|
|
)
|
|
|
|
// SniffOS reads the first bytes of an executable and returns the GOOS family it
|
|
// was built for: "windows", "darwin", "linux", or "" when the bytes match none
|
|
// of them. It is how pack decides whether a cross-built viewer needs a .exe
|
|
// suffix and which run hint to print, without trusting the base's file name.
|
|
func SniffOS(path string) string {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
defer func() { _ = f.Close() }()
|
|
|
|
head := make([]byte, 4)
|
|
if _, err := f.ReadAt(head, 0); err != nil {
|
|
return ""
|
|
}
|
|
switch {
|
|
case hasPrefix(head, magicPE):
|
|
return "windows"
|
|
case hasPrefix(head, magicELF):
|
|
return "linux"
|
|
case hasPrefix(head, machOLE64), hasPrefix(head, machOLE32),
|
|
hasPrefix(head, machOBE64), hasPrefix(head, machOBE32),
|
|
hasPrefix(head, machOFat):
|
|
return "darwin"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func hasPrefix(b, prefix []byte) bool {
|
|
if len(b) < len(prefix) {
|
|
return false
|
|
}
|
|
for i := range prefix {
|
|
if b[i] != prefix[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|