mediamtx/internal/rpicamera/embeddedexe.go

85 lines
1.3 KiB
Go

//go:build rpicamera
// +build rpicamera
package rpicamera
import (
"fmt"
"os"
"os/exec"
"runtime"
"strconv"
"time"
)
const (
tempPathPrefix = "/dev/shm/rtspss-embeddedexe-"
)
func getKernelArch() (string, error) {
cmd := exec.Command("uname", "-m")
byts, err := cmd.Output()
if err != nil {
return "", err
}
return string(byts[:len(byts)-1]), nil
}
// 32-bit embedded executables can't run on 64-bit.
func checkArch() error {
if runtime.GOARCH != "arm" {
return nil
}
arch, err := getKernelArch()
if err != nil {
return err
}
if arch == "aarch64" {
return fmt.Errorf("OS is 64-bit, you need the arm64 server version")
}
return nil
}
type embeddedExe struct {
cmd *exec.Cmd
}
func newEmbeddedExe(content []byte, env []string) (*embeddedExe, error) {
err := checkArch()
if err != nil {
return nil, err
}
tempPath := tempPathPrefix + strconv.FormatInt(time.Now().UnixNano(), 10)
err = os.WriteFile(tempPath, content, 0o755)
if err != nil {
return nil, err
}
cmd := exec.Command(tempPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = env
err = cmd.Start()
os.Remove(tempPath)
if err != nil {
return nil, err
}
return &embeddedExe{
cmd: cmd,
}, nil
}
func (e *embeddedExe) close() {
e.cmd.Process.Kill()
e.cmd.Wait()
}