package rosa import ( "fmt" "io" "net/http" "os" "runtime" "time" "hakurei.app/container/fhs" "hakurei.app/internal/pkg" ) // busyboxBin is a busybox binary distribution installed under bin/busybox. type busyboxBin struct { // Underlying busybox binary. bin pkg.FileArtifact } // Kind returns the hardcoded [pkg.Kind] value. func (a busyboxBin) Kind() pkg.Kind { return kindBusyboxBin } // Params is a noop. func (a busyboxBin) Params(*pkg.IContext) {} // IsExclusive returns false: Cure performs a trivial filesystem write. func (busyboxBin) IsExclusive() bool { return false } // Dependencies returns the underlying busybox [pkg.File]. func (a busyboxBin) Dependencies() []pkg.Artifact { return []pkg.Artifact{a.bin} } // String returns the reporting name of the underlying file prefixed with expand. func (a busyboxBin) String() string { return "expand-" + a.bin.(fmt.Stringer).String() } // Cure installs the underlying busybox [pkg.File] to bin/busybox. func (a busyboxBin) Cure(t *pkg.TContext) (err error) { var r io.ReadCloser if r, err = t.Open(a.bin); err != nil { return } defer func() { closeErr := r.Close() if err == nil { err = closeErr } }() binDir := t.GetWorkDir().Append("bin") if err = os.MkdirAll(binDir.String(), 0700); err != nil { return } var w *os.File if w, err = os.OpenFile( binDir.Append("busybox").String(), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0500, ); err != nil { return } defer func() { closeErr := w.Close() if err == nil { err = closeErr } }() _, err = io.Copy(w, r) return } // newBusyboxBin returns a [pkg.Artifact] containing a busybox installation from // the https://busybox.net/downloads/binaries/ binary release. func newBusyboxBin() pkg.Artifact { var version, url, checksum string switch runtime.GOARCH { case "amd64": version = "1.35.0" url = "https://busybox.net/downloads/binaries/" + version + "-" + linuxArch() + "-linux-musl/busybox" checksum = "L7OBIsPu9enNHn7FqpBT1kOg_mCLNmetSeNMA3i4Y60Z5jTgnlX3qX3zcQtLx5AB" case "arm64": version = "1.31.0" url = "https://busybox.net/downloads/binaries/" + version + "-defconfig-multiarch-musl/busybox-armv8l" checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg" default: panic("unsupported target " + runtime.GOARCH) } return pkg.NewExec( "busybox-bin-"+version, nil, pkg.ExecTimeoutMax, false, fhs.AbsRoot, []string{ "PATH=/system/bin", }, AbsSystem.Append("bin", "busybox"), []string{"hush", "-c", "" + "busybox mkdir -p /work/system/bin/ && " + "busybox cp /system/bin/busybox /work/system/bin/ && " + "busybox --install -s /work/system/bin/"}, pkg.Path(AbsSystem, true, busyboxBin{pkg.NewHTTPGet( &http.Client{Transport: &http.Transport{ // busybox website is really slow to respond TLSHandshakeTimeout: 2 * time.Minute, }}, url, mustDecode(checksum), )}), ) }