All checks were successful
Test / Create distribution (push) Successful in 1m5s
Test / Sandbox (push) Successful in 2m49s
Test / ShareFS (push) Successful in 3m40s
Test / Hakurei (push) Successful in 3m48s
Test / Sandbox (race detector) (push) Successful in 5m23s
Test / Hakurei (race detector) (push) Successful in 6m30s
Test / Flake checks (push) Successful in 1m23s
Signed-off-by: Ophestra <cat@gensokyo.uk>
150 lines
2.8 KiB
Go
150 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
|
|
"hakurei.app/check"
|
|
"hakurei.app/container"
|
|
"hakurei.app/internal/pkg"
|
|
"hakurei.app/internal/rosa"
|
|
"hakurei.app/message"
|
|
)
|
|
|
|
// cache refers to an instance of [pkg.Cache] that might be open.
|
|
type cache struct {
|
|
ctx context.Context
|
|
msg message.Msg
|
|
|
|
// Should generally not be used directly.
|
|
c *pkg.Cache
|
|
|
|
cures, jobs int
|
|
hostAbstract, idle bool
|
|
verboseInit bool
|
|
arch string
|
|
|
|
base string
|
|
}
|
|
|
|
// open opens the underlying [pkg.Cache].
|
|
func (cache *cache) open() (err error) {
|
|
if cache.c != nil {
|
|
return os.ErrInvalid
|
|
}
|
|
|
|
var base *check.Absolute
|
|
if cache.base, err = filepath.Abs(cache.base); err != nil {
|
|
return
|
|
} else if base, err = check.NewAbs(cache.base); err != nil {
|
|
return
|
|
}
|
|
|
|
var flags int
|
|
if cache.idle {
|
|
flags |= pkg.CSchedIdle
|
|
}
|
|
if cache.hostAbstract {
|
|
flags |= pkg.CHostAbstract
|
|
}
|
|
if !cache.verboseInit {
|
|
flags |= pkg.CSuppressInit
|
|
}
|
|
|
|
done := make(chan struct{})
|
|
defer close(done)
|
|
go func() {
|
|
select {
|
|
case <-cache.ctx.Done():
|
|
if testing.Testing() {
|
|
return
|
|
}
|
|
os.Exit(2)
|
|
|
|
case <-done:
|
|
return
|
|
}
|
|
}()
|
|
|
|
cache.msg.Verbosef("opening cache at %s", base)
|
|
cache.c, err = pkg.Open(
|
|
cache.ctx,
|
|
cache.msg,
|
|
flags,
|
|
cache.cures,
|
|
cache.jobs,
|
|
base,
|
|
)
|
|
if err != nil {
|
|
return
|
|
}
|
|
done <- struct{}{}
|
|
|
|
if cache.arch != "" && cache.arch != runtime.GOARCH {
|
|
var (
|
|
name string
|
|
offset byte
|
|
magic string
|
|
mask string
|
|
)
|
|
switch cache.arch {
|
|
case "riscv64":
|
|
name = "riscv64"
|
|
offset = 0
|
|
magic = "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00"
|
|
mask = "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"
|
|
|
|
case "arm64":
|
|
name = "aarch64"
|
|
offset = 0
|
|
magic = "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00"
|
|
mask = "\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"
|
|
|
|
default:
|
|
cache.c.Close()
|
|
err = pkg.UnsupportedArchError(cache.arch)
|
|
return
|
|
}
|
|
|
|
var pathname *check.Absolute
|
|
pathname, _, err = cache.c.Cure(rosa.Std.Load(rosa.QEMU))
|
|
if err != nil {
|
|
cache.c.Close()
|
|
return
|
|
}
|
|
|
|
pkg.RegisterArch(cache.arch, container.BinfmtEntry{
|
|
Offset: offset,
|
|
Magic: magic,
|
|
Mask: mask,
|
|
Interpreter: pathname.Append(
|
|
"system/bin",
|
|
"qemu-"+name,
|
|
),
|
|
})
|
|
rosa.DropCaches(cache.arch, rosa.Flags())
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Close closes the underlying [pkg.Cache] if it is open.
|
|
func (cache *cache) Close() {
|
|
if cache.c != nil {
|
|
cache.c.Close()
|
|
}
|
|
}
|
|
|
|
// Do calls f on the underlying cache and returns its error value.
|
|
func (cache *cache) Do(f func(cache *pkg.Cache) error) error {
|
|
if cache.c == nil {
|
|
if err := cache.open(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return f(cache.c)
|
|
}
|