Compare commits
12 Commits
staging
...
90df5c13fb
| Author | SHA1 | Date | |
|---|---|---|---|
|
90df5c13fb
|
|||
|
3b5b903f0e
|
|||
|
443db2d03d
|
|||
|
f2d883ee8c
|
|||
|
536e3c97ea
|
|||
|
6a59d7df86
|
|||
|
e198a98daa
|
|||
|
4f0841e1eb
|
|||
|
90804b5653
|
|||
|
98b37cedf3
|
|||
|
f57d7fda33
|
|||
|
fce0375aef
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -13,6 +13,3 @@
|
||||
|
||||
# cmd/dist default destination
|
||||
/dist
|
||||
|
||||
# local packages
|
||||
/internal/rosa/package/local
|
||||
|
||||
1
cmd/dist/VERSION
vendored
1
cmd/dist/VERSION
vendored
@@ -1 +0,0 @@
|
||||
v0.4.3
|
||||
7
cmd/dist/main.go
vendored
7
cmd/dist/main.go
vendored
@@ -18,13 +18,8 @@ import (
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:generate sh -c "git describe --tags > VERSION"
|
||||
//go:embed VERSION
|
||||
var version string
|
||||
|
||||
// getenv looks up an environment variable, and returns fallback if it is unset.
|
||||
func getenv(key, fallback string) string {
|
||||
if v, ok := os.LookupEnv(key); ok {
|
||||
@@ -52,7 +47,7 @@ func main() {
|
||||
|
||||
verbose := os.Getenv("VERBOSE") != ""
|
||||
runTests := os.Getenv("HAKUREI_DIST_MAKE") == ""
|
||||
version = getenv("HAKUREI_VERSION", strings.TrimSpace(version))
|
||||
version := getenv("HAKUREI_VERSION", "untagged")
|
||||
prefix := getenv("PREFIX", "/usr")
|
||||
destdir := getenv("DESTDIR", "dist")
|
||||
|
||||
|
||||
@@ -5,91 +5,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"slices"
|
||||
"strings"
|
||||
. "syscall"
|
||||
|
||||
"hakurei.app/internal/kobject"
|
||||
"hakurei.app/internal/report"
|
||||
"hakurei.app/internal/uevent"
|
||||
"hakurei.app/message"
|
||||
)
|
||||
|
||||
var r report.Reporter
|
||||
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("earlyinit: ")
|
||||
r.SetOutput(log.Default())
|
||||
|
||||
// this handles SIGQUIT to provide useful debugging information without
|
||||
// terminating, and prevents the runtime from throwing on the must family
|
||||
// of early error reporting functions, DO NOT REMOVE
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, SIGQUIT)
|
||||
go func() {
|
||||
for {
|
||||
<-c
|
||||
if p := pprof.Lookup("goroutine"); p == nil {
|
||||
log.Println("initial built-in goroutine profile does not exist")
|
||||
} else if err := p.WriteTo(os.Stderr, 2); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// fatal calls [log.Println] with v and blocks forever. Must be called from
|
||||
// main. Must not be used after error reporting is set up.
|
||||
func fatal(v ...any) {
|
||||
log.Println(v...)
|
||||
log.Println("unable to continue, please reboot and resolve the problem manually")
|
||||
select {}
|
||||
}
|
||||
|
||||
// must calls fatal with err if it is non-nil.
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
select {}
|
||||
}
|
||||
}
|
||||
|
||||
// mustSyscall is like must, but with an additional action name.
|
||||
func mustSyscall(action string, err error) {
|
||||
if err != nil {
|
||||
fatal("cannot "+action+":", err)
|
||||
select {}
|
||||
}
|
||||
}
|
||||
|
||||
// must1 is like must, but with an additional passed through value.
|
||||
func must1[T any](v T, err error) T {
|
||||
must(err)
|
||||
return v
|
||||
}
|
||||
|
||||
const (
|
||||
// optionSystem specifies devpath of the system device.
|
||||
optionSystem = "system"
|
||||
|
||||
// flagVerbose increases output verbosity.
|
||||
flagVerbose = "verbose"
|
||||
// flagStrict sets [report.DStrict] on r.
|
||||
flagStrict = "strict"
|
||||
// flagNoRecover sets [report.DNoRecover] on r.
|
||||
flagNoRecover = "no_recover"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.LockOSThread()
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("earlyinit: ")
|
||||
|
||||
var (
|
||||
option map[string]string
|
||||
@@ -107,44 +33,15 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var flag uint64
|
||||
if slices.Contains(flags, flagStrict) {
|
||||
flag |= report.DStrict
|
||||
}
|
||||
if slices.Contains(flags, flagNoRecover) {
|
||||
flag |= report.DNoRecover
|
||||
}
|
||||
log.Printf("reporting flags %x", flag)
|
||||
r.SetFlags(flag)
|
||||
}
|
||||
|
||||
msg := message.New(log.Default())
|
||||
msg.SwapVerbose(slices.Contains(flags, flagVerbose))
|
||||
|
||||
mustSyscall("mount devtmpfs", Mount(
|
||||
if err := Mount(
|
||||
"devtmpfs",
|
||||
"/dev/",
|
||||
"devtmpfs",
|
||||
MS_NOSUID|MS_NOEXEC,
|
||||
"",
|
||||
))
|
||||
must(os.Mkdir("/dev/pts/", 0))
|
||||
mustSyscall("mount devpts", Mount(
|
||||
"devpts",
|
||||
"/dev/pts/",
|
||||
"devpts",
|
||||
MS_NOSUID|MS_NOEXEC,
|
||||
"mode=620,ptmxmode=666",
|
||||
))
|
||||
must(os.Mkdir("/dev/shm/", 0))
|
||||
mustSyscall("mount shm", Mount(
|
||||
"shm",
|
||||
"/dev/shm/",
|
||||
"tmpfs",
|
||||
MS_NOSUID|MS_NODEV,
|
||||
"",
|
||||
))
|
||||
); err != nil {
|
||||
log.Fatalf("cannot mount devtmpfs: %v", err)
|
||||
}
|
||||
|
||||
// The kernel might be unable to set up the console. When that happens,
|
||||
// printk is called with "Warning: unable to open an initial console."
|
||||
@@ -201,49 +98,6 @@ func main() {
|
||||
"",
|
||||
))
|
||||
|
||||
conn := must1(uevent.Dial(-128 * 1024 * 1024))
|
||||
events := make(chan *uevent.Message, 1<<10)
|
||||
var uuid uevent.UUID
|
||||
must1(rand.Read(uuid[:]))
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
go consume(ctx, msg, &r, conn, uuid, events)
|
||||
s := kobject.New(uuid, func(o *kobject.Object, env map[string]string) {
|
||||
p := make([]string, 0, len(env))
|
||||
for k, v := range env {
|
||||
p = append(p, k+"="+v)
|
||||
}
|
||||
slices.Sort(p)
|
||||
log.Printf("change %s: %s", o.DevPath, strings.Join(p, ", "))
|
||||
}, func(err error) {
|
||||
severity := report.Inconsistent
|
||||
if e, ok := err.(kobject.EventError); ok && e.Kind == kobject.EBadTarget {
|
||||
severity = report.Trivial
|
||||
}
|
||||
r.Dispatch(
|
||||
severity,
|
||||
"processed inconsistent uevent",
|
||||
err,
|
||||
)
|
||||
})
|
||||
go func() {
|
||||
s.Consume(ctx, events)
|
||||
|
||||
log.Println("closing NETLINK_KOBJECT_UEVENT socket")
|
||||
cancel()
|
||||
if err := conn.Close(); err != nil {
|
||||
log.Fatal(err) // not reached
|
||||
}
|
||||
}()
|
||||
|
||||
must(os.Mkdir("/system", 0))
|
||||
if devpath := option[optionSystem]; devpath == "" {
|
||||
fatal("system must be nonempty")
|
||||
} else {
|
||||
log.Printf("waiting for devpath pattern %q", devpath)
|
||||
mustMountSystem(ctx, s, devpath)
|
||||
}
|
||||
|
||||
// after top level has been set up
|
||||
mustSyscall("remount root", Mount(
|
||||
"",
|
||||
@@ -259,6 +113,19 @@ func main() {
|
||||
[]byte("/system/lib/firmware"),
|
||||
0,
|
||||
))
|
||||
go dispatchModprobe(ctx, s)
|
||||
|
||||
}
|
||||
|
||||
// mustSyscall calls [log.Fatalln] if err is non-nil.
|
||||
func mustSyscall(action string, err error) {
|
||||
if err != nil {
|
||||
log.Fatalln("cannot "+action+":", err)
|
||||
}
|
||||
}
|
||||
|
||||
// must calls [log.Fatal] with err if it is non-nil.
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/kobject"
|
||||
"hakurei.app/internal/report"
|
||||
"hakurei.app/internal/uevent"
|
||||
)
|
||||
|
||||
// ModprobeError describes an unsuccessful modprobe invocation.
|
||||
type ModprobeError struct {
|
||||
ModAlias string `json:"modalias"`
|
||||
Stdout string `json:"stdout"`
|
||||
Stderr string `json:"stderr"`
|
||||
ExitCode int `json:"exit_code"`
|
||||
}
|
||||
|
||||
var _ report.RepresentableError = ModprobeError{}
|
||||
|
||||
func (ModprobeError) Representable() {}
|
||||
func (e ModprobeError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"modprobe exit status %d: %s",
|
||||
e.ExitCode, strings.TrimSpace(e.Stderr),
|
||||
)
|
||||
}
|
||||
|
||||
// dispatchModprobe invokes modprobe for [uevent.KOBJ_ADD] events raising new
|
||||
// MODALIAS strings.
|
||||
func dispatchModprobe(
|
||||
ctx context.Context,
|
||||
s *kobject.State,
|
||||
) {
|
||||
aliases := make(chan string, 1<<8)
|
||||
go func() {
|
||||
defer close(aliases)
|
||||
s.Range(ctx, func(o *kobject.Object, act uevent.KobjectAction) bool {
|
||||
if act == uevent.KOBJ_ADD && o.Driver == "" && o.ModAlias != "" {
|
||||
aliases <- o.ModAlias
|
||||
}
|
||||
return true
|
||||
})
|
||||
}()
|
||||
|
||||
for alias := range aliases {
|
||||
stdout, err := exec.Command("/system/sbin/modprobe", alias).Output()
|
||||
if err == nil {
|
||||
if len(stdout) > 0 {
|
||||
log.Println(string(stdout))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
var exitError *exec.ExitError
|
||||
if !errors.As(err, &exitError) || exitError == nil {
|
||||
r.Dispatch(report.Degraded, "invoke modprobe", err)
|
||||
continue
|
||||
}
|
||||
|
||||
r.Dispatch(report.Trivial, "load device driver", ModprobeError{
|
||||
ModAlias: alias,
|
||||
Stdout: string(stdout),
|
||||
Stderr: string(exitError.Stderr),
|
||||
ExitCode: exitError.ExitCode(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/fhs"
|
||||
"hakurei.app/internal/kobject"
|
||||
"hakurei.app/internal/uevent"
|
||||
)
|
||||
|
||||
// mustMountSystem waits for and mounts a system device matching pattern.
|
||||
func mustMountSystem(
|
||||
ctx context.Context,
|
||||
s *kobject.State,
|
||||
pattern string,
|
||||
) {
|
||||
c, stop := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer stop()
|
||||
|
||||
for {
|
||||
var matchErr error
|
||||
var systemPath *check.Absolute
|
||||
s.Range(c, func(o *kobject.Object, act uevent.KobjectAction) bool {
|
||||
if (act != uevent.KOBJ_ADD && act != uevent.KOBJ_CHANGE) ||
|
||||
o.Subsystem != "block" ||
|
||||
o.Env["DEVTYPE"] != "disk" {
|
||||
return true
|
||||
}
|
||||
|
||||
if ok, err := filepath.Match(pattern, o.DevPath); err != nil {
|
||||
matchErr = err
|
||||
return false
|
||||
} else if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
name, ok := o.Env["DEVNAME"]
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
systemPath = fhs.AbsDev.Append(name)
|
||||
return false
|
||||
})
|
||||
if c.Err() != nil {
|
||||
fatal("devpath", strconv.Quote(pattern), "never appeared")
|
||||
}
|
||||
if matchErr != nil {
|
||||
fatal("cannot match system devpath:", matchErr)
|
||||
}
|
||||
err := syscall.Mount(
|
||||
systemPath.String(),
|
||||
"/system/",
|
||||
"squashfs",
|
||||
0,
|
||||
"threads=multi",
|
||||
)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
fatal("cannot mount system:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"hakurei.app/fhs"
|
||||
"hakurei.app/internal/report"
|
||||
"hakurei.app/internal/uevent"
|
||||
"hakurei.app/message"
|
||||
)
|
||||
|
||||
// newRejectColdboot returns a function to be called on every subsequent pending
|
||||
// coldboot, and returns whether coldboot should proceed. Rejection is sticky.
|
||||
func newRejectColdboot() func() bool {
|
||||
// one coldboot per five minutes, two consecutive coldboot
|
||||
const (
|
||||
coldbootInterval = 5 * time.Minute
|
||||
coldbootBurst = 2
|
||||
)
|
||||
|
||||
done := make(chan struct{})
|
||||
s := make(chan struct{}, coldbootBurst)
|
||||
s <- struct{}{} // for early fault before reporting is ready
|
||||
go func() {
|
||||
t := time.NewTicker(coldbootInterval)
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
|
||||
case <-t.C:
|
||||
select {
|
||||
case s <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return func() bool {
|
||||
select {
|
||||
case <-s:
|
||||
return true
|
||||
|
||||
case <-done:
|
||||
return false
|
||||
|
||||
default:
|
||||
close(done)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// consume continuously consumes events from conn with retries.
|
||||
func consume(
|
||||
ctx context.Context,
|
||||
msg message.Msg,
|
||||
r *report.Reporter,
|
||||
conn *uevent.Conn,
|
||||
uuid uevent.UUID,
|
||||
events chan<- *uevent.Message,
|
||||
) {
|
||||
defer close(events)
|
||||
|
||||
nextColdboot := newRejectColdboot()
|
||||
coldboot := true
|
||||
retry:
|
||||
if dispatchErr := conn.Consume(ctx, fhs.Sys, &uuid, events, coldboot, func(path string) {
|
||||
msg.Verbose("coldboot visited", path)
|
||||
}, func(err error) bool {
|
||||
if _, ok := err.(uevent.NeedsColdboot); ok && !nextColdboot() {
|
||||
r.Dispatch(
|
||||
report.Degraded,
|
||||
"rejecting coldboot loop",
|
||||
err,
|
||||
)
|
||||
return false
|
||||
}
|
||||
r.Dispatch(
|
||||
report.Inconsistent,
|
||||
"consumed invalid message",
|
||||
err,
|
||||
)
|
||||
return true
|
||||
}, nil); dispatchErr != nil {
|
||||
if _, ok := dispatchErr.(uevent.Recoverable); !ok {
|
||||
r.Dispatch(
|
||||
report.Fatal,
|
||||
"discontinuing uevent processing due to nonrecoverable error",
|
||||
dispatchErr,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if _, ok := dispatchErr.(uevent.NeedsColdboot); ok {
|
||||
// coldboot loop rejected by handler
|
||||
coldboot = false
|
||||
}
|
||||
|
||||
goto retry
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"testing/synctest"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRejectColdboot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
nextColdboot := newRejectColdboot()
|
||||
want := func(want bool) {
|
||||
if got := nextColdboot(); got != want {
|
||||
t.Fatalf("nextColdboot: %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
synctest.Wait()
|
||||
want(true)
|
||||
time.Sleep(time.Hour)
|
||||
synctest.Wait()
|
||||
want(true)
|
||||
want(true)
|
||||
time.Sleep(5 * time.Minute)
|
||||
synctest.Wait()
|
||||
want(true)
|
||||
want(false)
|
||||
time.Sleep(time.Hour)
|
||||
synctest.Wait()
|
||||
want(false)
|
||||
want(false)
|
||||
})
|
||||
}
|
||||
@@ -39,13 +39,14 @@ func commandInfo(
|
||||
t := rosa.Native().Std()
|
||||
for i, name := range args {
|
||||
handle := rosa.ArtifactH(unique.Make(name))
|
||||
if meta, a := t.Load(handle); meta == nil {
|
||||
if meta := rosa.Native().Get(handle); meta == nil {
|
||||
return fmt.Errorf("unknown artifact %q", name)
|
||||
} else {
|
||||
var suffix string
|
||||
|
||||
if meta.Version != rosa.Unversioned {
|
||||
suffix += "-" + meta.Version
|
||||
a, version := t.MustLoad(handle)
|
||||
if version != rosa.Unversioned {
|
||||
suffix += "-" + version
|
||||
}
|
||||
mustPrintln("name : " + name + suffix)
|
||||
|
||||
@@ -57,10 +58,9 @@ func commandInfo(
|
||||
if len(meta.Dependencies) > 0 {
|
||||
mustPrint("depends on :")
|
||||
for _, d := range meta.Dependencies {
|
||||
_meta, _ := rosa.Native().Std().MustLoad(d)
|
||||
s := _meta.Name
|
||||
if _meta.Version != rosa.Unversioned {
|
||||
s += "-" + _meta.Version
|
||||
s := rosa.Native().MustGet(d).Name
|
||||
if _, _version := t.Load(d); _version != rosa.Unversioned {
|
||||
s += "-" + _version
|
||||
}
|
||||
mustPrint(" " + s)
|
||||
}
|
||||
|
||||
@@ -22,12 +22,12 @@ func TestInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_t := rosa.Native().Std()
|
||||
qemuMeta, _ := _t.Load(rosa.H("qemu"))
|
||||
glibMeta, _ := _t.Load(rosa.H("glib"))
|
||||
zlibMeta, zlib := _t.Load(rosa.H("zlib"))
|
||||
zstdMeta, _ := _t.Load(rosa.H("zstd"))
|
||||
hakureiMeta, _ := _t.Load(rosa.H("hakurei"))
|
||||
hakureiDistMeta, _ := _t.Load(rosa.H("hakurei-dist"))
|
||||
_, qemuVersion := _t.Load(rosa.QEMU)
|
||||
_, glibVersion := _t.Load(rosa.GLib)
|
||||
zlib, zlibVersion := _t.Load(rosa.Zlib)
|
||||
_, zstdVersion := _t.Load(rosa.Zstd)
|
||||
_, hakureiVersion := _t.Load(rosa.Hakurei)
|
||||
_, hakureiDistVersion := _t.Load(rosa.HakureiDist)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -38,24 +38,24 @@ func TestInfo(t *testing.T) {
|
||||
wantErr any
|
||||
}{
|
||||
{"qemu", []string{"qemu"}, nil, "", `
|
||||
name : qemu-` + qemuMeta.Version + `
|
||||
name : qemu-` + qemuVersion + `
|
||||
description : a generic and open source machine emulator and virtualizer
|
||||
website : https://www.qemu.org
|
||||
depends on : glib-` + glibMeta.Version + ` zstd-` + zstdMeta.Version + `
|
||||
depends on : glib-` + glibVersion + ` zstd-` + zstdVersion + `
|
||||
`, nil},
|
||||
|
||||
{"multi", []string{"hakurei", "hakurei-dist"}, nil, "", `
|
||||
name : hakurei-` + hakureiMeta.Version + `
|
||||
name : hakurei-` + hakureiVersion + `
|
||||
description : low-level userspace tooling for Rosa OS
|
||||
website : https://hakurei.app
|
||||
|
||||
name : hakurei-dist-` + hakureiDistMeta.Version + `
|
||||
name : hakurei-dist-` + hakureiDistVersion + `
|
||||
description : low-level userspace tooling for Rosa OS (distribution tarball)
|
||||
website : https://hakurei.app
|
||||
`, nil},
|
||||
|
||||
{"nonexistent", []string{"zlib", "\x00"}, nil, "", `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
name : zlib-` + zlibVersion + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
|
||||
@@ -65,12 +65,12 @@ website : https://zlib.net
|
||||
"zstd": "internal/pkg (amd64) on satori\n",
|
||||
"hakurei": "internal/pkg (amd64) on satori\n\n",
|
||||
}, "", `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
name : zlib-` + zlibVersion + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
status : not yet cured
|
||||
|
||||
name : zstd-` + zstdMeta.Version + `
|
||||
name : zstd-` + zstdVersion + `
|
||||
description : a fast compression algorithm
|
||||
website : https://facebook.github.io/zstd
|
||||
status : internal/pkg (amd64) on satori
|
||||
@@ -79,7 +79,7 @@ status : internal/pkg (amd64) on satori
|
||||
{"status cache perm", []string{"zlib"}, map[string]string{
|
||||
"zlib": "\x00",
|
||||
}, "", `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
name : zlib-` + zlibVersion + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
`, func(cm *cache) error {
|
||||
@@ -91,7 +91,7 @@ website : https://zlib.net
|
||||
}},
|
||||
|
||||
{"status report", []string{"zlib"}, nil, strings.Repeat("\x00", len(pkg.Checksum{})+8), `
|
||||
name : zlib-` + zlibMeta.Version + `
|
||||
name : zlib-` + zlibVersion + `
|
||||
description : lossless data-compression library
|
||||
website : https://zlib.net
|
||||
status : not in report
|
||||
@@ -140,7 +140,7 @@ status : not in report
|
||||
|
||||
if tc.status != nil {
|
||||
for name, status := range tc.status {
|
||||
_, a := _t.Load(rosa.ArtifactH(unique.Make(name)))
|
||||
a, _ := _t.Load(rosa.ArtifactH(unique.Make(name)))
|
||||
if a == nil {
|
||||
t.Fatalf("invalid name %q", name)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ var (
|
||||
// handleInfo writes constant system information.
|
||||
func handleInfo(w http.ResponseWriter, _ *http.Request) {
|
||||
infoPayloadOnce.Do(func() {
|
||||
infoPayload.Count = len(rosa.Native().Collect())
|
||||
infoPayload.Count = int(rosa.Native().Count())
|
||||
infoPayload.HakureiVersion = info.Version()
|
||||
})
|
||||
// TODO(mae): cache entire response if no additional fields are planned
|
||||
|
||||
@@ -31,7 +31,7 @@ func TestAPIInfo(t *testing.T) {
|
||||
checkPayload(t, resp, struct {
|
||||
Count int `json:"count"`
|
||||
HakureiVersion string `json:"hakurei_version"`
|
||||
}{len(rosa.Native().Collect()), info.Version()})
|
||||
}{rosa.Native().Count(), info.Version()})
|
||||
}
|
||||
|
||||
func TestAPIGet(t *testing.T) {
|
||||
@@ -92,12 +92,11 @@ func TestAPIGet(t *testing.T) {
|
||||
)
|
||||
})
|
||||
|
||||
count := len(rosa.Native().Collect())
|
||||
t.Run("index", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
checkValidate(
|
||||
t, "limit=1&sort=0&index", 0, count-1,
|
||||
"index must be an integer between 0 and "+strconv.Itoa(count-1),
|
||||
t, "limit=1&sort=0&index", 0, rosa.Native().Count()-1,
|
||||
"index must be an integer between 0 and "+strconv.Itoa(rosa.Native().Count()-1),
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@ type packageIndex struct {
|
||||
// metadata holds [rosa.Metadata] extended with additional information.
|
||||
type metadata struct {
|
||||
handle rosa.ArtifactH
|
||||
*rosa.Metadata
|
||||
*rosa.Artifact
|
||||
|
||||
// Copied from [rosa.Metadata], [rosa.Unversioned] is equivalent to the zero
|
||||
// value. Otherwise, the zero value is invalid.
|
||||
// Populated via [rosa.Toolchain.Version], [rosa.Unversioned] is equivalent
|
||||
// to the zero value. Otherwise, the zero value is invalid.
|
||||
Version string `json:"version,omitempty"`
|
||||
// Output data size, available if present in report.
|
||||
Size int64 `json:"size,omitempty"`
|
||||
@@ -61,12 +61,12 @@ func (index *packageIndex) populate(report *rosa.Report) (err error) {
|
||||
index.names = make(map[string]*metadata)
|
||||
ir := pkg.NewIR()
|
||||
for i, handle := range handles {
|
||||
meta, a := rosa.Native().Std().MustLoad(handle)
|
||||
a, version := rosa.Native().Std().MustLoad(handle)
|
||||
m := metadata{
|
||||
handle: handle,
|
||||
|
||||
Metadata: meta,
|
||||
Version: meta.Version,
|
||||
Artifact: rosa.Native().MustGet(handle),
|
||||
Version: version,
|
||||
}
|
||||
if m.Version == "" {
|
||||
return errors.New("invalid version from " + m.Name)
|
||||
|
||||
2
cmd/mbf/internal/pkgserver/ui/all_tests.ts
Normal file
2
cmd/mbf/internal/pkgserver/ui/all_tests.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// Import all test files to register their test suites.
|
||||
import "./index_test.js";
|
||||
@@ -5,11 +5,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="icon" href="https://hakurei.app/favicon.ico"/>
|
||||
<title>Rosa OS Packages</title>
|
||||
<title>Hakurei PkgServer</title>
|
||||
<script src="index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Rosa OS Packages</h1>
|
||||
<h1>Hakurei PkgServer</h1>
|
||||
<div class="top-controls" id="top-controls-regular">
|
||||
<p>Showing entries <span id="entry-counter"></span>.</p>
|
||||
<span id="search-bar">
|
||||
|
||||
2
cmd/mbf/internal/pkgserver/ui/index_test.ts
Normal file
2
cmd/mbf/internal/pkgserver/ui/index_test.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import { suite, test } from "./jstest/jstest.js";
|
||||
import "./index.js";
|
||||
48
cmd/mbf/internal/pkgserver/ui/jstest/cli.ts
Normal file
48
cmd/mbf/internal/pkgserver/ui/jstest/cli.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Many editors have terminal emulators built in, so running tests with NodeJS
|
||||
// provides faster iteration, especially for those acclimated to test-driven
|
||||
// development.
|
||||
|
||||
import "../all_tests.js";
|
||||
import { StreamReporter, GLOBAL_REGISTRAR } from "./jstest.js";
|
||||
|
||||
// TypeScript doesn't like process and Deno as their type definitions aren't
|
||||
// installed, but doesn't seem to complain if they're accessed through
|
||||
// globalThis.
|
||||
const process: any = (globalThis as any).process;
|
||||
const Deno: any = (globalThis as any).Deno;
|
||||
|
||||
function getArgs(): string[] {
|
||||
if (process) {
|
||||
const [runtime, program, ...args] = process.argv;
|
||||
return args;
|
||||
}
|
||||
if (Deno) return Deno.args;
|
||||
return [];
|
||||
}
|
||||
|
||||
function exit(code?: number): never {
|
||||
if (Deno) Deno.exit(code);
|
||||
if (process) process.exit(code);
|
||||
throw `exited with code ${code ?? 0}`;
|
||||
}
|
||||
|
||||
const args = getArgs();
|
||||
let verbose = false;
|
||||
if (args.length > 1) {
|
||||
console.error("Too many arguments");
|
||||
exit(1);
|
||||
}
|
||||
if (args.length === 1) {
|
||||
if (args[0] === "-v" || args[0] === "--verbose" || args[0] === "-verbose") {
|
||||
verbose = true;
|
||||
} else if (args[0] !== "--") {
|
||||
console.error(`Unknown argument '${args[0]}'`);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
let reporter = new StreamReporter({ writeln: console.log }, verbose);
|
||||
GLOBAL_REGISTRAR.run(reporter);
|
||||
exit(reporter.succeeded() ? 0 : 1);
|
||||
13
cmd/mbf/internal/pkgserver/ui/jstest/failure-closed.svg
Normal file
13
cmd/mbf/internal/pkgserver/ui/jstest/failure-closed.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
|
||||
<!-- This triangle should match success-closed.svg, fill and stroke color notwithstanding. -->
|
||||
<polygon points="0,0 100,50 0,100" fill="red" stroke="red" stroke-width="15" stroke-linejoin="round"/>
|
||||
<!--
|
||||
! y-coordinates go before x-coordinates here to highlight the difference
|
||||
! (or, lack thereof) between these numbers and the ones in failure-open.svg;
|
||||
! try a textual diff. Make sure to keep the numbers in sync!
|
||||
-->
|
||||
<line y1="30" x1="10" y2="70" x2="50" stroke="white" stroke-width="16"/>
|
||||
<line y1="30" x1="50" y2="70" x2="10" stroke="white" stroke-width="16"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 788 B |
35
cmd/mbf/internal/pkgserver/ui/jstest/failure-open.svg
Normal file
35
cmd/mbf/internal/pkgserver/ui/jstest/failure-open.svg
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
! This view box is a bit weird: the strokes assume they're working in a view
|
||||
! box that spans from the (0,0) to (100,100), and indeed that is convenient
|
||||
! conceptualizing the strokes, but the stroke itself has a considerable width
|
||||
! that gets clipped by restrictive view box dimensions. Hence, the view is
|
||||
! shifted from (0,0)–(100,100) to (-20,-20)–(120,120), to make room for the
|
||||
! clipped stroke, while leaving behind an illusion of working in a view box
|
||||
! spanning from (0,0) to (100,100).
|
||||
!
|
||||
! However, the resulting SVG is too close to the summary text, and CSS
|
||||
! properties to add padding do not seem to work with `content:` (likely because
|
||||
! they're anonymous replaced elements); thus, the width of the view is
|
||||
! increased considerably to provide padding in the SVG itself, while leaving
|
||||
! the strokes oblivious.
|
||||
!
|
||||
! It gets worse: the summary text isn't vertically aligned with the icon! As
|
||||
! a flexbox cannot be used in a summary to align the marker with the text, the
|
||||
! simplest and most effective solution is to reduce the height of the view box
|
||||
! from 140 to 130, thereby removing some of the bottom padding present.
|
||||
!
|
||||
! All six SVGs use the same view box (and indeed, they refer to this comment)
|
||||
! so that they all appear to be the same size and position relative to each
|
||||
! other on the DOM—indeed, the view box dimensions, alongside the width,
|
||||
! directly control their placement on the DOM.
|
||||
!
|
||||
! TL;DR: CSS is janky, overflow is weird, and SVG is awesome!
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
|
||||
<!-- This triangle should match success-open.svg, fill and stroke color notwithstanding. -->
|
||||
<polygon points="0,0 100,0 50,100" fill="red" stroke="red" stroke-width="15" stroke-linejoin="round"/>
|
||||
<!-- See the comment in failure-closed.svg before modifying this. -->
|
||||
<line x1="30" y1="10" x2="70" y2="50" stroke="white" stroke-width="16"/>
|
||||
<line x1="30" y1="50" x2="70" y2="10" stroke="white" stroke-width="16"/>
|
||||
</svg>
|
||||
@@ -0,0 +1,3 @@
|
||||
import "../all_tests.js";
|
||||
import { GoTestReporter, GLOBAL_REGISTRAR } from "./jstest.js";
|
||||
GLOBAL_REGISTRAR.run(new GoTestReporter());
|
||||
39
cmd/mbf/internal/pkgserver/ui/jstest/index.html
Normal file
39
cmd/mbf/internal/pkgserver/ui/jstest/index.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="./style.css">
|
||||
<title>PkgServer Tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
I hate JavaScript as much as you, but this page runs tests written in
|
||||
JavaScript to test the functionality of code written in JavaScript, so it
|
||||
wouldn't make sense for it to work without JavaScript. <strong>Please turn
|
||||
JavaScript on!</strong>
|
||||
</noscript>
|
||||
|
||||
<h1>PkgServer Tests</h1>
|
||||
|
||||
<main>
|
||||
<p id="counters">
|
||||
<span id="success-counter">0</span> succeeded, <span id="failure-counter">0</span>
|
||||
failed<span id="skip-counter-text" hidden>, <span id="skip-counter">0</span> skipped</span>.
|
||||
</p>
|
||||
|
||||
<p hidden id="success-description">Successful test</p>
|
||||
<p hidden id="failure-description">Failed test</p>
|
||||
<p hidden id="skip-description">Partially or fully skipped test</p>
|
||||
|
||||
<div id="root">
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import "../all_tests.js";
|
||||
import { DOMReporter, GLOBAL_REGISTRAR } from "./jstest.js";
|
||||
GLOBAL_REGISTRAR.run(new DOMReporter());
|
||||
</script>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
478
cmd/mbf/internal/pkgserver/ui/jstest/jstest.ts
Normal file
478
cmd/mbf/internal/pkgserver/ui/jstest/jstest.ts
Normal file
@@ -0,0 +1,478 @@
|
||||
// =============================================================================
|
||||
// DSL
|
||||
|
||||
type TestTree = TestGroup | Test;
|
||||
type TestGroup = { name: string; children: TestTree[] };
|
||||
type Test = { name: string; test: (t: TestController) => void };
|
||||
|
||||
// A registrar provides a central location to register test suites.
|
||||
export class TestRegistrar {
|
||||
// Note that, while this is equivalent to a new tree node sans a name, the
|
||||
// lack of a name provides the illusion of multiple “top-level” suites,
|
||||
// while still allowing reporters to pick their favorite name—say, “JS
|
||||
// tests”—were they to need to label all suites together.
|
||||
#suites: TestGroup[];
|
||||
|
||||
constructor() {
|
||||
this.#suites = [];
|
||||
}
|
||||
|
||||
suite(name: string, children: TestTree[]) {
|
||||
checkDuplicates(name, children);
|
||||
this.#suites.push({ name, children });
|
||||
}
|
||||
|
||||
run(reporter: Reporter) {
|
||||
reporter.register(this.#suites);
|
||||
for (const suite of this.#suites) {
|
||||
for (const c of suite.children) runTests(reporter, [suite.name], c);
|
||||
}
|
||||
reporter.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
export let GLOBAL_REGISTRAR = new TestRegistrar();
|
||||
|
||||
// Register a suite in the global registrar.
|
||||
export function suite(name: string, children: TestTree[]) {
|
||||
GLOBAL_REGISTRAR.suite(name, children);
|
||||
}
|
||||
|
||||
export function group(name: string, children: TestTree[]): TestTree {
|
||||
checkDuplicates(name, children);
|
||||
return { name, children };
|
||||
}
|
||||
export const context = group;
|
||||
export const describe = group;
|
||||
|
||||
export function test(name: string, test: (t: TestController) => void): TestTree {
|
||||
return { name, test };
|
||||
}
|
||||
|
||||
// While this function could certainly refine the type to a map instead of
|
||||
// simply checking for duplicates and discarding that knowledge, these test
|
||||
// trees are primarily for flooding—that is, iteration—for which an array is
|
||||
// better suited.
|
||||
function checkDuplicates(parent: string, names: { name: string }[]) {
|
||||
let seen = new Set<string>();
|
||||
for (const { name } of names) {
|
||||
if (seen.has(name)) {
|
||||
throw new RangeError(`duplicate name '${name}' in '${parent}'`);
|
||||
}
|
||||
seen.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
export type TestState = "success" | "failure" | "skip";
|
||||
|
||||
class AbortSentinel {}
|
||||
|
||||
export class TestController {
|
||||
#state: TestState;
|
||||
logs: string[];
|
||||
|
||||
constructor() {
|
||||
this.#state = "success";
|
||||
this.logs = [];
|
||||
}
|
||||
|
||||
getState(): TestState {
|
||||
return this.#state;
|
||||
}
|
||||
|
||||
fail() {
|
||||
this.#state = "failure";
|
||||
}
|
||||
|
||||
failed(): boolean {
|
||||
return this.#state === "failure";
|
||||
}
|
||||
|
||||
failNow(): never {
|
||||
this.fail();
|
||||
throw new AbortSentinel();
|
||||
}
|
||||
|
||||
log(message: string) {
|
||||
this.logs.push(message);
|
||||
}
|
||||
|
||||
error(message: string) {
|
||||
this.log(message);
|
||||
this.fail();
|
||||
}
|
||||
|
||||
fatal(message: string): never {
|
||||
this.log(message);
|
||||
this.failNow();
|
||||
}
|
||||
|
||||
skip(message?: string): never {
|
||||
if (message != null) this.log(message);
|
||||
if (this.#state !== "failure") this.#state = "skip";
|
||||
throw new AbortSentinel();
|
||||
}
|
||||
|
||||
skipped(): boolean {
|
||||
return this.#state === "skip";
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Execution
|
||||
|
||||
export interface TestResult {
|
||||
state: TestState;
|
||||
logs: string[];
|
||||
}
|
||||
|
||||
function runTests(reporter: Reporter, parents: string[], node: TestTree) {
|
||||
const path = [...parents, node.name];
|
||||
if ("children" in node) {
|
||||
for (const c of node.children) runTests(reporter, path, c);
|
||||
return;
|
||||
}
|
||||
let controller = new TestController();
|
||||
try {
|
||||
node.test(controller);
|
||||
} catch (e) {
|
||||
if (!(e instanceof AbortSentinel)) {
|
||||
controller.error(extractExceptionString(e));
|
||||
}
|
||||
}
|
||||
reporter.update(path, { state: controller.getState(), logs: controller.logs });
|
||||
}
|
||||
|
||||
function extractExceptionString(e: any): string {
|
||||
// String() instead of .toString() as null and undefined don't have
|
||||
// properties.
|
||||
const s = String(e);
|
||||
if (!(e instanceof Error && e.stack)) return s;
|
||||
// v8 (Chromium, NodeJS) includes the error message, while Firefox and
|
||||
// WebKit do not.
|
||||
if (e.stack.startsWith(s)) return e.stack;
|
||||
return `${s}\n${e.stack}`;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Reporting
|
||||
|
||||
export interface Reporter {
|
||||
// A notable feature—or flaw, to some—of the DSL is that the tree of tests
|
||||
// is statically known, which might greatly aid in implementing a reporter.
|
||||
register(suites: TestGroup[]): void;
|
||||
// While we could simply call a function with a tree representing all
|
||||
// results, which would indeed greatly simplify implementation of reporters,
|
||||
// simply registering a path and allowing the reporter to—either implicitly
|
||||
// or explicitly—construct a tree themselves allows for results to be
|
||||
// *incrementally reported*, instead of a great deal of silence until all
|
||||
// tests finish.
|
||||
update(path: string[], result: TestResult): void;
|
||||
// With just update(), the reporter never knows when all tests have
|
||||
// completed. The simplest possible use for this is to notify the user, but
|
||||
// its intent is actually more tailored to the StreamReporter scenario:
|
||||
// while destructively updated report rendering (as with a tree of DOM nodes
|
||||
// which are mutated) always displays the results in a structured manner
|
||||
// matching that of the tests, “rerendering” or otherwise destructively
|
||||
// updating the rendered output might be infeasible in some paradigms, such
|
||||
// as command-line applications—all existing implementations of such
|
||||
// rendering both mess up the scrollback position and necessarily crop out
|
||||
// some of the data at the bottom (since the top of the tree is forced to be
|
||||
// at the top of the screen, as one cannot unscroll portably). Explicitly
|
||||
// signaling to the reporter that no more results will be received permits
|
||||
// it to simply display live test progress linearly, while building up
|
||||
// a tree and displaying it once it's known the tree is complete.
|
||||
finalize(): void;
|
||||
}
|
||||
|
||||
// A reporter that diligently reports absolutely nothing. This is essentially
|
||||
// a way to “undo” the incremental reporting update() provides, getting back the
|
||||
// underlying result tree; this makes it extremely convenient in some cases like
|
||||
// testing ourself.
|
||||
export class NoOpReporter implements Reporter {
|
||||
suites: TestGroup[];
|
||||
results: ({ path: string[] } & TestResult)[];
|
||||
finalized: boolean;
|
||||
|
||||
constructor() {
|
||||
this.suites = [];
|
||||
this.results = [];
|
||||
this.finalized = false;
|
||||
}
|
||||
|
||||
register(suites: TestGroup[]) {
|
||||
this.suites = suites;
|
||||
}
|
||||
|
||||
update(path: string[], result: TestResult) {
|
||||
this.results.push({ path, ...result });
|
||||
}
|
||||
|
||||
finalize() {
|
||||
this.finalized = true;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Stream {
|
||||
writeln(s: string): void;
|
||||
}
|
||||
|
||||
const SEP = " ❯ ";
|
||||
|
||||
// A simple reporter that outputs to some stream; suitable for CLIs.
|
||||
export class StreamReporter implements Reporter {
|
||||
stream: Stream;
|
||||
verbose: boolean;
|
||||
#successes: ({ path: string[] } & TestResult)[];
|
||||
#failures: ({ path: string[] } & TestResult)[];
|
||||
#skips: ({ path: string[] } & TestResult)[];
|
||||
|
||||
constructor(stream: Stream, verbose: boolean = false) {
|
||||
this.stream = stream;
|
||||
this.verbose = verbose;
|
||||
this.#successes = [];
|
||||
this.#failures = [];
|
||||
this.#skips = [];
|
||||
}
|
||||
|
||||
succeeded(): boolean {
|
||||
return this.#successes.length > 0 && this.#failures.length === 0;
|
||||
}
|
||||
|
||||
// We don't need the structure for reporting.
|
||||
register(suites: TestGroup[]) {}
|
||||
|
||||
update(path: string[], result: TestResult) {
|
||||
if (path.length === 0) throw new RangeError("path is empty");
|
||||
const pathStr = path.join(SEP);
|
||||
switch (result.state) {
|
||||
case "success":
|
||||
this.#successes.push({ path, ...result });
|
||||
// NOTE: emojis are used instead of colored Unicode symbols as
|
||||
// coloring isn't possible through all streams and detecting if
|
||||
// colors should be used is very difficult¹. Furthermore, ensuring
|
||||
// reasonable contrast is retained on every possible theme is
|
||||
// difficult, with reverse video often being the only way (which
|
||||
// also has questionable support across terminal emulators), and the
|
||||
// Unicode characters might be too small to be immediately
|
||||
// noticeable—consider ✓ and ⚠ and ✗. Emojis have an upper hand in
|
||||
// that they're more common than obscure Unicode characters—which
|
||||
// also means you're likely to have an emoji font but not a font for
|
||||
// some weird symbols—and that they're double-width. Finally,
|
||||
// Unicode characters are often very different across fonts; some
|
||||
// fonts make ⚠ filled in, while others have just an outline for the
|
||||
// triangle (which is much harder to comprehend), and the various
|
||||
// crosses like all of x ⨯ × ✕ ✖ ✗ 🗙 🞨 🞩 🞪 🞫 🞬 🞭 🞮 look different
|
||||
// across different fonts, which makes using them for some specific
|
||||
// purpose difficult. Emojis don't have this problem because emoji
|
||||
// vendors try to make them look similar to each other.
|
||||
//
|
||||
// ¹This necessitates checking if the stream is a TTY, checking if
|
||||
// $TERM is `dumb` when connected to a TTY, checking
|
||||
// https://no-color.org, https://bixense.com/clicolors, and
|
||||
// https://force-color.org, checking if setting the
|
||||
// ENABLE_VIRTUAL_TERMINAL_PROCESSING bit on the TTY works when on
|
||||
// on Windows, and doing something similar for Cygwin.
|
||||
if (this.verbose) this.stream.writeln(`✅️ ${pathStr}`);
|
||||
break;
|
||||
case "failure":
|
||||
this.#failures.push({ path, ...result });
|
||||
this.stream.writeln(`⚠️ ${pathStr}`);
|
||||
break;
|
||||
case "skip":
|
||||
this.#skips.push({ path, ...result });
|
||||
this.stream.writeln(`⏭️ ${pathStr}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
finalize() {
|
||||
if (this.verbose) this.#displaySection("successes", this.#successes, true);
|
||||
this.#displaySection("failures", this.#failures);
|
||||
this.#displaySection("skips", this.#skips);
|
||||
this.stream.writeln("");
|
||||
this.stream.writeln(
|
||||
`${this.#successes.length} succeeded, ${this.#failures.length} failed` +
|
||||
(this.#skips.length ? `, ${this.#skips.length} skipped` : ""),
|
||||
);
|
||||
}
|
||||
|
||||
#displaySection(name: string, data: ({ path: string[] } & TestResult)[], ignoreEmpty: boolean = false) {
|
||||
if (!data.length) return;
|
||||
|
||||
// Transform [{ path: ["a", "b", "c"] }, { path: ["a", "b", "d"] }] into
|
||||
// { "a ❯ b": ["c", "d"] }. NOTE: intermediate nodes are collapsed as
|
||||
// excessive nesting is difficult to convey clearly in a text-only
|
||||
// environment.
|
||||
let pathMap = new Map<string, ({ name: string } & TestResult)[]>();
|
||||
for (const t of data) {
|
||||
if (t.path.length === 0) throw new RangeError("path is empty");
|
||||
const key = t.path.slice(0, -1).join(SEP);
|
||||
if (!pathMap.has(key)) pathMap.set(key, []);
|
||||
pathMap.get(key)!.push({ name: t.path.at(-1)!, ...t });
|
||||
}
|
||||
|
||||
this.stream.writeln("");
|
||||
this.stream.writeln(name.toUpperCase());
|
||||
this.stream.writeln("=".repeat(name.length));
|
||||
|
||||
for (let [path, tests] of pathMap) {
|
||||
if (ignoreEmpty) tests = tests.filter((t) => t.logs.length);
|
||||
if (tests.length === 0) continue;
|
||||
if (tests.length === 1) {
|
||||
this.#writeOutput(tests[0], path ? `${path}${SEP}` : "", false);
|
||||
} else {
|
||||
this.stream.writeln(path);
|
||||
for (const t of tests) this.#writeOutput(t, " - ", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#writeOutput(test: { name: string } & TestResult, prefix: string, nested: boolean) {
|
||||
let output = "";
|
||||
if (test.logs.length) {
|
||||
// Individual logs might span multiple lines, so join them together
|
||||
// then split it again.
|
||||
const logStr = test.logs.join("\n");
|
||||
const lines = logStr.split("\n");
|
||||
if (lines.length <= 1) {
|
||||
output = `: ${logStr}`;
|
||||
} else {
|
||||
const padding = nested ? " " : " ";
|
||||
output = ":\n" + lines.map((line) => padding + line).join("\n");
|
||||
}
|
||||
}
|
||||
this.stream.writeln(`${prefix}${test.name}${output}`);
|
||||
}
|
||||
}
|
||||
|
||||
function assertGetElementById(id: string): HTMLElement {
|
||||
let elem = document.getElementById(id);
|
||||
if (elem == null) throw new ReferenceError(`element with ID '${id}' missing from DOM`);
|
||||
return elem;
|
||||
}
|
||||
|
||||
// A reporter that directly translates a tree of results into a tree of
|
||||
// collapsible elements in the DOM.
|
||||
export class DOMReporter implements Reporter {
|
||||
// It is very difficult to implement this using the statically known tree,
|
||||
// because Map doesn't handle array keys properly (to store the path), and
|
||||
// it's unknown of there's any way to implement it without writing one's own
|
||||
// data types. Oh well; using the DOM as a data structure might seem hacky
|
||||
// but it does have its benefits, apart from encouraging a tagless final.
|
||||
register(suites: TestGroup[]) {}
|
||||
|
||||
update(path: string[], result: TestResult) {
|
||||
if (path.length === 0) throw new RangeError("path is empty");
|
||||
if (result.state === "skip") {
|
||||
assertGetElementById("skip-counter-text").hidden = false;
|
||||
}
|
||||
const counter = assertGetElementById(`${result.state}-counter`);
|
||||
counter.innerText = (Number(counter.innerText) + 1).toString();
|
||||
|
||||
let parent = assertGetElementById("root");
|
||||
for (const node of path) {
|
||||
let child: HTMLDetailsElement | null = null;
|
||||
let summary: HTMLElement | null = null;
|
||||
let d: Element;
|
||||
outer: for (d of parent.children) {
|
||||
if (!(d instanceof HTMLDetailsElement)) continue;
|
||||
for (const s of d.children) {
|
||||
if (!(s instanceof HTMLElement)) continue;
|
||||
if (!(s.tagName === "SUMMARY" && s.innerText === node)) continue;
|
||||
child = d;
|
||||
summary = s;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
if (!child) {
|
||||
child = document.createElement("details");
|
||||
child.className = "test-node";
|
||||
child.ariaRoleDescription = "test";
|
||||
summary = document.createElement("summary");
|
||||
summary.appendChild(document.createTextNode(node));
|
||||
summary.ariaRoleDescription = "test name";
|
||||
child.appendChild(summary);
|
||||
parent.appendChild(child);
|
||||
}
|
||||
if (!summary) throw new Error("unreachable as assigned above");
|
||||
|
||||
switch (result.state) {
|
||||
case "failure":
|
||||
// Only expand failures, to minimize successes and skips.
|
||||
child.open = true;
|
||||
child.classList.add("failure");
|
||||
child.classList.remove("skip");
|
||||
child.classList.remove("success");
|
||||
// The summary marker does not appear in the AOM, so setting its
|
||||
// alt text is fruitless; label the summary itself instead.
|
||||
summary.setAttribute("aria-labelledby", "failure-description");
|
||||
break;
|
||||
case "skip":
|
||||
if (child.classList.contains("failure")) break;
|
||||
child.classList.add("skip");
|
||||
child.classList.remove("success");
|
||||
summary.setAttribute("aria-labelledby", "skip-description");
|
||||
break;
|
||||
case "success":
|
||||
if (child.classList.contains("failure") || child.classList.contains("skip")) break;
|
||||
child.classList.add("success");
|
||||
summary.setAttribute("aria-labelledby", "success-description");
|
||||
break;
|
||||
}
|
||||
|
||||
parent = child;
|
||||
}
|
||||
|
||||
const p = document.createElement("p");
|
||||
p.classList.add("test-desc");
|
||||
if (result.logs.length) {
|
||||
const pre = document.createElement("pre");
|
||||
pre.appendChild(document.createTextNode(result.logs.join("\n")));
|
||||
p.appendChild(pre);
|
||||
} else {
|
||||
p.classList.add("italic");
|
||||
p.appendChild(document.createTextNode("No output."));
|
||||
}
|
||||
parent.appendChild(p);
|
||||
}
|
||||
|
||||
finalize() {}
|
||||
}
|
||||
|
||||
interface GoNode {
|
||||
name: string;
|
||||
subtests?: GoNode[];
|
||||
}
|
||||
|
||||
// Used to display results via `go test`, via some glue code from the Go side.
|
||||
// TODO(ophestra): said glue code has to be written.
|
||||
export class GoTestReporter implements Reporter {
|
||||
register(suites: TestGroup[]) {
|
||||
console.log(JSON.stringify(suites.map(GoTestReporter.serialize)));
|
||||
}
|
||||
|
||||
// Convert a test tree into the one expected by the Go code.
|
||||
static serialize(node: TestTree): GoNode {
|
||||
return {
|
||||
name: node.name,
|
||||
subtests: "children" in node ? node.children.map(GoTestReporter.serialize) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
update(path: string[], result: TestResult) {
|
||||
let state: number;
|
||||
switch (result.state) {
|
||||
case "success": state = 0; break;
|
||||
case "failure": state = 1; break;
|
||||
case "skip": state = 2; break;
|
||||
}
|
||||
console.log(JSON.stringify({ path, state, logs: result.logs }));
|
||||
}
|
||||
|
||||
// Unnecessary but convenient on the Go side, so that it doesn't have to
|
||||
// infer this via process exit.
|
||||
finalize() {
|
||||
console.log("null");
|
||||
}
|
||||
}
|
||||
21
cmd/mbf/internal/pkgserver/ui/jstest/skip-closed.svg
Normal file
21
cmd/mbf/internal/pkgserver/ui/jstest/skip-closed.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
|
||||
<!-- This triangle should match success-closed.svg, fill and stroke color notwithstanding. -->
|
||||
<polygon points="0,0 100,50 0,100" fill="blue" stroke="blue" stroke-width="15" stroke-linejoin="round"/>
|
||||
<!--
|
||||
! This path is extremely similar to the one in skip-open.svg; before
|
||||
! making minor modifications, diff the two to understand how they should
|
||||
! remain in sync.
|
||||
-->
|
||||
<path
|
||||
d="M 50,50
|
||||
A 23,23 270,1,1 30,30
|
||||
l -10,20
|
||||
m 10,-20
|
||||
l -20,-10"
|
||||
fill="none"
|
||||
stroke="white"
|
||||
stroke-width="12"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 812 B |
21
cmd/mbf/internal/pkgserver/ui/jstest/skip-open.svg
Normal file
21
cmd/mbf/internal/pkgserver/ui/jstest/skip-open.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
|
||||
<!-- This triangle should match success-open.svg, fill and stroke color notwithstanding. -->
|
||||
<polygon points="0,0 100,0 50,100" fill="blue" stroke="blue" stroke-width="15" stroke-linejoin="round"/>
|
||||
<!--
|
||||
! This path is extremely similar to the one in skip-closed.svg; before
|
||||
! making minor modifications, diff the two to understand how they should
|
||||
! remain in sync.
|
||||
-->
|
||||
<path
|
||||
d="M 50,50
|
||||
A 23,23 270,1,1 70,30
|
||||
l 10,-20
|
||||
m -10,20
|
||||
l -20,-10"
|
||||
fill="none"
|
||||
stroke="white"
|
||||
stroke-width="12"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 812 B |
87
cmd/mbf/internal/pkgserver/ui/jstest/style.css
Normal file
87
cmd/mbf/internal/pkgserver/ui/jstest/style.css
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* When updating the theme colors, also update them in success-closed.svg and
|
||||
* success-open.svg!
|
||||
*/
|
||||
|
||||
:root {
|
||||
--bg: #d3d3d3;
|
||||
--fg: black;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg: #2c2c2c;
|
||||
--fg: ghostwhite;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
background-color: var(--bg);
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
h1, p, summary, noscript {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
noscript {
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
.root {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
details.test-node {
|
||||
margin-left: 1rem;
|
||||
padding: 0.2rem 0.5rem;
|
||||
border-left: 2px dashed var(--fg);
|
||||
> summary {
|
||||
cursor: pointer;
|
||||
}
|
||||
&.success > summary::marker {
|
||||
/*
|
||||
* WebKit only supports color and font-size properties in ::marker [1], and
|
||||
* its ::-webkit-details-marker only supports hiding the marker entirely
|
||||
* [2], contrary to mdn's example [3]; thus, set a color as a fallback:
|
||||
* while it may not be accessible for colorblind individuals, it's better
|
||||
* than no indication of a test's state for anyone, as that there's no other
|
||||
* way to include an indication in the marker on WebKit.
|
||||
*
|
||||
* [1]: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/::marker#browser_compatibility
|
||||
* [2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/summary#default_style
|
||||
* [3]: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/summary#changing_the_summarys_icon
|
||||
*/
|
||||
color: var(--fg);
|
||||
content: url("./success-closed.svg") / "success";
|
||||
}
|
||||
&.success[open] > summary::marker {
|
||||
content: url("./success-open.svg") / "success";
|
||||
}
|
||||
&.failure > summary::marker {
|
||||
color: red;
|
||||
content: url("./failure-closed.svg") / "failure";
|
||||
}
|
||||
&.failure[open] > summary::marker {
|
||||
content: url("./failure-open.svg") / "failure";
|
||||
}
|
||||
&.skip > summary::marker {
|
||||
color: blue;
|
||||
content: url("./skip-closed.svg") / "skip";
|
||||
}
|
||||
&.skip[open] > summary::marker {
|
||||
content: url("./skip-open.svg") / "skip";
|
||||
}
|
||||
}
|
||||
|
||||
p.test-desc {
|
||||
margin: 0 0 0 1rem;
|
||||
padding: 2px 0;
|
||||
> pre {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
16
cmd/mbf/internal/pkgserver/ui/jstest/success-closed.svg
Normal file
16
cmd/mbf/internal/pkgserver/ui/jstest/success-closed.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
|
||||
<style>
|
||||
.adaptive-stroke {
|
||||
stroke: black;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.adaptive-stroke {
|
||||
stroke: ghostwhite;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!-- When updating this triangle, also update the other five SVGs. -->
|
||||
<polygon points="0,0 100,50 0,100" fill="none" class="adaptive-stroke" stroke-width="15" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 572 B |
16
cmd/mbf/internal/pkgserver/ui/jstest/success-open.svg
Normal file
16
cmd/mbf/internal/pkgserver/ui/jstest/success-open.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- See failure-open.svg for an explanation of the view box dimensions. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" viewBox="-20,-20 160 130">
|
||||
<style>
|
||||
.adaptive-stroke {
|
||||
stroke: black;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.adaptive-stroke {
|
||||
stroke: ghostwhite;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!-- When updating this triangle, also update the other five SVGs. -->
|
||||
<polygon points="0,0 100,0 50,100" fill="none" class="adaptive-stroke" stroke-width="15" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 572 B |
13
cmd/mbf/internal/pkgserver/ui/test_ui.go
Normal file
13
cmd/mbf/internal/pkgserver/ui/test_ui.go
Normal file
@@ -0,0 +1,13 @@
|
||||
//go:build frontend && frontend_test
|
||||
|
||||
package ui
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:generate tsc -p tsconfig.test.json
|
||||
//go:generate cp index.html style.css favicon.ico static
|
||||
//go:generate cp jstest/index.html jstest/style.css static/jstest
|
||||
//go:generate sh -c "cp jstest/*.svg static/jstest"
|
||||
//go:embed static
|
||||
var _static embed.FS
|
||||
var static = staticFS(_static)
|
||||
@@ -1,8 +1,11 @@
|
||||
// This file defines the common options for all TypeScript here. This shouldn't
|
||||
// be directly used as the project file in builds; see tsconfig.*.json instead,
|
||||
// which inherit from this file and essentially define specific build targets.
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2024",
|
||||
"strict": true,
|
||||
"alwaysStrict": true,
|
||||
"outDir": "static"
|
||||
}
|
||||
}
|
||||
"outDir": "static",
|
||||
},
|
||||
}
|
||||
|
||||
5
cmd/mbf/internal/pkgserver/ui/tsconfig.test.json
Normal file
5
cmd/mbf/internal/pkgserver/ui/tsconfig.test.json
Normal file
@@ -0,0 +1,5 @@
|
||||
// Project file for building pkgserver alongside its tests. test_ui.go uses this
|
||||
// as its project file.
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
}
|
||||
6
cmd/mbf/internal/pkgserver/ui/tsconfig.ui.json
Normal file
6
cmd/mbf/internal/pkgserver/ui/tsconfig.ui.json
Normal file
@@ -0,0 +1,6 @@
|
||||
// Project file for building just the pkgserver UI, with none of the testing
|
||||
// stuff attached. ui_full.go uses this as its project file.
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["jstest", "all_tests.ts", "*_test.ts"],
|
||||
}
|
||||
@@ -1,7 +1,19 @@
|
||||
// Package ui holds the static web UI.
|
||||
package ui
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// staticFS is an internal helper to wrap around go:embed's filesystem.
|
||||
func staticFS(static fs.FS) fs.FS {
|
||||
if f, err := fs.Sub(static, "static"); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return f
|
||||
}
|
||||
}
|
||||
|
||||
// Register arranges for mux to serve the embedded frontend.
|
||||
func Register(mux *http.ServeMux) {
|
||||
|
||||
@@ -1,21 +1,11 @@
|
||||
//go:build frontend
|
||||
//go:build frontend && !frontend_test
|
||||
|
||||
package ui
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
)
|
||||
import "embed"
|
||||
|
||||
//go:generate tsc
|
||||
//go:generate tsc -p tsconfig.ui.json
|
||||
//go:generate cp index.html style.css static
|
||||
//go:embed static
|
||||
var _static embed.FS
|
||||
|
||||
var static = func() fs.FS {
|
||||
if f, err := fs.Sub(_static, "static"); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
return f
|
||||
}
|
||||
}()
|
||||
var static = staticFS(_static)
|
||||
|
||||
118
cmd/mbf/main.go
118
cmd/mbf/main.go
@@ -58,20 +58,6 @@ func main() {
|
||||
log.Fatal("this program must not run as root")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch r.(type) {
|
||||
case rosa.LoadError, pkg.IRStringError:
|
||||
log.Fatal(r)
|
||||
default:
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(),
|
||||
syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||
defer stop()
|
||||
@@ -85,22 +71,12 @@ func main() {
|
||||
flagArch string
|
||||
flagCheck bool
|
||||
flagLTO bool
|
||||
flagPT bool
|
||||
|
||||
flagSourcePath string
|
||||
flagCrossOverride int
|
||||
|
||||
addr net.UnixAddr
|
||||
)
|
||||
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) error {
|
||||
if !rosa.Native().HasStageEarly() {
|
||||
return pkg.UnsupportedArchError(runtime.GOARCH)
|
||||
}
|
||||
|
||||
if flagPT {
|
||||
log.Println("parsed in", rosa.ParseTime())
|
||||
}
|
||||
|
||||
msg.SwapVerbose(!flagQuiet)
|
||||
cm.ctx, cm.msg = ctx, msg
|
||||
cm.base = os.ExpandEnv(cm.base)
|
||||
@@ -124,7 +100,7 @@ func main() {
|
||||
rosa.Native().DropCaches("", flags)
|
||||
cross := flagArch != "" && flagArch != runtime.GOARCH
|
||||
if flagQEMU || cross {
|
||||
_, cm.qemu = rosa.Native().Std().MustLoad(rosa.H("qemu"))
|
||||
cm.qemu, _ = rosa.Native().Std().Load(rosa.QEMU)
|
||||
}
|
||||
|
||||
if cross {
|
||||
@@ -133,17 +109,11 @@ func main() {
|
||||
}
|
||||
|
||||
rosa.Native().DropCaches(flagArch, flags)
|
||||
if !rosa.Native().HasStageEarly() {
|
||||
if !rosa.HasStage0() {
|
||||
return pkg.UnsupportedArchError(flagArch)
|
||||
}
|
||||
}
|
||||
|
||||
if flagSourcePath != "" {
|
||||
if err := rosa.Native().SetSource(os.DirFS(flagSourcePath)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}).Flag(
|
||||
&flagQuiet,
|
||||
@@ -200,14 +170,6 @@ func main() {
|
||||
&addr.Name,
|
||||
"socket", command.StringFlag("$MBF_DAEMON_SOCKET"),
|
||||
"Pathname of socket to bind to",
|
||||
).Flag(
|
||||
&flagPT,
|
||||
"parse-time", command.BoolFlag(false),
|
||||
"Print duration of the initial azalea parse",
|
||||
).Flag(
|
||||
&flagSourcePath,
|
||||
"source", command.StringFlag(""),
|
||||
"Override hakurei source tree",
|
||||
)
|
||||
|
||||
c.NewCommand(
|
||||
@@ -360,10 +322,7 @@ func main() {
|
||||
)
|
||||
|
||||
{
|
||||
var (
|
||||
flagJobs int
|
||||
flagNoBlock bool
|
||||
)
|
||||
var flagJobs int
|
||||
c.NewCommand("updates", command.UsageInternal, func([]string) error {
|
||||
var (
|
||||
errsMu sync.Mutex
|
||||
@@ -377,16 +336,11 @@ func main() {
|
||||
for range max(flagJobs, 1) {
|
||||
wg.Go(func() {
|
||||
for p := range w {
|
||||
meta, _ := rosa.Native().Std().MustLoad(p)
|
||||
meta := rosa.Native().MustGet(p)
|
||||
if meta.ID == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if !flagNoBlock && meta.Blocked != "" {
|
||||
msg.Verbosef("%s is blocked: %s", meta.Name, meta.Blocked)
|
||||
continue
|
||||
}
|
||||
|
||||
v, err := meta.GetVersions(ctx)
|
||||
if err != nil {
|
||||
errsMu.Lock()
|
||||
@@ -395,9 +349,13 @@ func main() {
|
||||
continue
|
||||
}
|
||||
|
||||
if latest := meta.GetLatest(v); meta.Version != latest {
|
||||
_, version := rosa.Native().Std().Load(p)
|
||||
if current, latest :=
|
||||
version,
|
||||
meta.GetLatest(v); current != latest {
|
||||
|
||||
n.Add(1)
|
||||
log.Printf("%s %s < %s", meta.Name, meta.Version, latest)
|
||||
log.Printf("%s %s < %s", meta.Name, current, latest)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -407,7 +365,7 @@ func main() {
|
||||
}
|
||||
|
||||
done:
|
||||
for _, p := range rosa.Native().CollectAll() {
|
||||
for _, p := range rosa.Native().Collect() {
|
||||
select {
|
||||
case w <- p:
|
||||
break
|
||||
@@ -427,23 +385,9 @@ func main() {
|
||||
&flagJobs,
|
||||
"j", command.IntFlag(32),
|
||||
"Maximum number of simultaneous connections",
|
||||
).Flag(
|
||||
&flagNoBlock,
|
||||
"ignore-block", command.BoolFlag(false),
|
||||
"Inhibit update blocking",
|
||||
)
|
||||
}
|
||||
|
||||
c.NewCommand("blocked", command.UsageInternal, func([]string) error {
|
||||
for _, p := range rosa.Native().CollectAll() {
|
||||
meta, _ := rosa.Native().Std().Load(p)
|
||||
if meta.Blocked != "" {
|
||||
fmt.Printf("%s: %s\n", meta.Name, meta.Blocked)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
c.NewCommand(
|
||||
"daemon",
|
||||
"Service artifact IR with Rosa OS extensions",
|
||||
@@ -461,6 +405,8 @@ func main() {
|
||||
var (
|
||||
flagGentoo string
|
||||
flagChecksum string
|
||||
|
||||
flagStage0 bool
|
||||
)
|
||||
c.NewCommand(
|
||||
"stage3",
|
||||
@@ -484,9 +430,8 @@ func main() {
|
||||
checksum [2]unique.Handle[pkg.Checksum]
|
||||
)
|
||||
|
||||
_llvm := rosa.H("llvm")
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
_, llvm := rosa.Native().New(s - 2).Load(_llvm)
|
||||
llvm, _ := rosa.Native().New(s - 2).Load(rosa.LLVM)
|
||||
pathname, _, err = cache.Cure(llvm)
|
||||
return
|
||||
}); err != nil {
|
||||
@@ -495,7 +440,7 @@ func main() {
|
||||
log.Println("stage1:", pathname)
|
||||
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
_, llvm := rosa.Native().New(s - 1).Load(_llvm)
|
||||
llvm, _ := rosa.Native().New(s - 1).Load(rosa.LLVM)
|
||||
pathname, checksum[0], err = cache.Cure(llvm)
|
||||
return
|
||||
}); err != nil {
|
||||
@@ -503,7 +448,7 @@ func main() {
|
||||
}
|
||||
log.Println("stage2:", pathname)
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
_, llvm := rosa.Native().New(s).Load(_llvm)
|
||||
llvm, _ := rosa.Native().New(s).Load(rosa.LLVM)
|
||||
pathname, checksum[1], err = cache.Cure(llvm)
|
||||
return
|
||||
}); err != nil {
|
||||
@@ -522,6 +467,18 @@ func main() {
|
||||
"("+pkg.Encode(checksum[0].Value())+")",
|
||||
)
|
||||
}
|
||||
|
||||
if flagStage0 {
|
||||
if err = cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
stage0, _ := rosa.Native().New(s).Load(rosa.Stage0)
|
||||
pathname, _, err = cache.Cure(stage0)
|
||||
return
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
log.Println(pathname)
|
||||
}
|
||||
|
||||
return
|
||||
},
|
||||
).Flag(
|
||||
@@ -532,6 +489,10 @@ func main() {
|
||||
&flagChecksum,
|
||||
"checksum", command.StringFlag(""),
|
||||
"Checksum of Gentoo stage3 tarball",
|
||||
).Flag(
|
||||
&flagStage0,
|
||||
"stage0", command.BoolFlag(false),
|
||||
"Create bootstrap stage0 tarball",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -563,7 +524,7 @@ func main() {
|
||||
t -= 1
|
||||
}
|
||||
|
||||
_, a := rosa.Native().New(t).Load(rosa.ArtifactH(unique.Make(args[0])))
|
||||
a, _ := rosa.Native().New(t).Load(rosa.ArtifactH(unique.Make(args[0])))
|
||||
if a == nil {
|
||||
return fmt.Errorf("unknown artifact %q", args[0])
|
||||
}
|
||||
@@ -776,22 +737,22 @@ func main() {
|
||||
"shell",
|
||||
"Interactive shell in the specified Rosa OS environment",
|
||||
func(args []string) error {
|
||||
handles := make([]rosa.ArtifactH, len(args), len(args)+3)
|
||||
handles := make([]rosa.ArtifactH, len(args)+3)
|
||||
for i, arg := range args {
|
||||
handles[i] = rosa.ArtifactH(unique.Make(arg))
|
||||
if meta, _ := rosa.Native().Std().Load(handles[i]); meta == nil {
|
||||
if rosa.Native().Get(handles[i]) == nil {
|
||||
return fmt.Errorf("unknown artifact %q", arg)
|
||||
}
|
||||
}
|
||||
|
||||
base := rosa.H("llvm")
|
||||
base := rosa.LLVM
|
||||
if !flagWithToolchain {
|
||||
base = rosa.H("musl")
|
||||
base = rosa.Musl
|
||||
}
|
||||
handles = append(handles,
|
||||
base,
|
||||
rosa.H("mksh"),
|
||||
rosa.H("toybox"),
|
||||
rosa.Mksh,
|
||||
rosa.Toybox,
|
||||
)
|
||||
|
||||
root := make(pkg.Collect, 0, 6+len(args))
|
||||
@@ -915,6 +876,7 @@ func main() {
|
||||
"with-toolchain", command.BoolFlag(false),
|
||||
"Include the stage2 LLVM toolchain",
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
c.Command(
|
||||
|
||||
@@ -36,8 +36,8 @@ func TestCureAll(t *testing.T) {
|
||||
})
|
||||
|
||||
for _, handle := range rosa.Native().Collect() {
|
||||
_, a := rosa.Native().Std().MustLoad(handle)
|
||||
t.Run(handle.String(), func(t *testing.T) {
|
||||
a, _ := rosa.Native().Std().MustLoad(handle)
|
||||
t.Run(rosa.Native().MustGet(handle).Name, func(t *testing.T) {
|
||||
_, err := cureRemote(t.Context(), &addr, a, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
GOCACHE="$(mktemp -d)" \
|
||||
PATH="${pkgs.pkgsStatic.musl.bin}/bin:$PATH" \
|
||||
DESTDIR="$out" \
|
||||
HAKUREI_VERSION="v${hakurei.version}" \
|
||||
./all.sh
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package kobject
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"maps"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
@@ -29,22 +28,6 @@ type Event struct {
|
||||
Subsystem string `json:"subsystem"`
|
||||
}
|
||||
|
||||
// Clone returns a copy of e.
|
||||
func (e *Event) Clone() Event {
|
||||
v := *e
|
||||
v.Env = maps.Clone(e.Env)
|
||||
return v
|
||||
}
|
||||
|
||||
// makeColdboot allocates a new [Object] from e in [StateColdboot].
|
||||
func (e *Event) makeColdboot() *Object {
|
||||
return &Object{
|
||||
State: StateColdboot,
|
||||
DevPath: e.DevPath,
|
||||
Subsystem: e.Subsystem,
|
||||
}
|
||||
}
|
||||
|
||||
// Populate populates e with the contents of a [uevent.Message].
|
||||
//
|
||||
// The ACTION and DEVPATH environment variables are ignored and assumed to be
|
||||
|
||||
@@ -1,491 +0,0 @@
|
||||
// Package kobject interprets uevent messages from a NETLINK_KOBJECT_UEVENT socket.
|
||||
package kobject
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"hakurei.app/internal/report"
|
||||
"hakurei.app/internal/uevent"
|
||||
)
|
||||
|
||||
const (
|
||||
// StateColdboot denotes an [Object] populated by a coldboot event. It is
|
||||
// eligible for all event actions.
|
||||
StateColdboot = iota
|
||||
// StateNew denotes an [Object] previously populated by a [uevent.KOBJ_ADD]
|
||||
// event, but has not yet been targeted by a [uevent.KOBJ_BIND] event, or
|
||||
// has been targeted by a [uevent.KOBJ_UNBIND] event.
|
||||
StateNew
|
||||
// StateBound denotes an [Object] that has been targeted by a
|
||||
// [uevent.KOBJ_BIND] and has not been targeted by a [uevent.KOBJ_UNBIND]
|
||||
// after that.
|
||||
StateBound
|
||||
)
|
||||
|
||||
// Object represents a kernel object.
|
||||
type Object struct {
|
||||
// Origin of the object.
|
||||
State int `json:"state,omitempty"`
|
||||
// Set by [uevent.KOBJ_OFFLINE] and [uevent.KOBJ_ONLINE].
|
||||
Offline bool `json:"offline,omitempty"`
|
||||
|
||||
// alloc_uevent_skb: devpath
|
||||
DevPath string `json:"devpath"`
|
||||
// registered per-driver (optional)
|
||||
ModAlias string `json:"modalias,omitempty"`
|
||||
// dev_driver_uevent: drv->name (optional)
|
||||
Driver string `json:"driver,omitempty"`
|
||||
|
||||
// SUBSYSTEM value set by the kernel.
|
||||
Subsystem string `json:"subsystem"`
|
||||
|
||||
// Uninterpreted environment variable pairs. An entry missing a separator
|
||||
// gains the value "\x00".
|
||||
Env map[string]string `json:"env"`
|
||||
}
|
||||
|
||||
// Clone returns the address of a copy of o.
|
||||
func (o *Object) Clone() *Object {
|
||||
v := *o
|
||||
v.Env = maps.Clone(o.Env)
|
||||
return &v
|
||||
}
|
||||
|
||||
// GoString returns compound literal for the underlying value.
|
||||
func (o *Object) GoString() string {
|
||||
return fmt.Sprintf("&%#v", *o)
|
||||
}
|
||||
|
||||
// merge merges uninterpreted environment variable pairs from an [Event].
|
||||
func (o *Object) merge(env map[string]string) {
|
||||
for k, v := range env {
|
||||
if v == "\x00" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch k {
|
||||
case "MODALIAS":
|
||||
o.ModAlias = v
|
||||
continue
|
||||
|
||||
case "DRIVER":
|
||||
o.Driver = v
|
||||
continue
|
||||
|
||||
default:
|
||||
if o.Env == nil {
|
||||
o.Env = make(map[string]string)
|
||||
}
|
||||
o.Env[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update updates o with pairs from env, optionally stripping visited pairs.
|
||||
func (o *Object) update(env map[string]string, strip bool) {
|
||||
for k := range o.Env {
|
||||
if v, ok := env[k]; ok {
|
||||
if strip {
|
||||
delete(env, k)
|
||||
}
|
||||
o.Env[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A pendingIterator is a callback currently iterating through objects targeted
|
||||
// by ongoing events.
|
||||
type pendingIterator struct {
|
||||
f func(o *Object, act uevent.KobjectAction) bool
|
||||
done chan<- struct{}
|
||||
}
|
||||
|
||||
// State processes a stream of [Event] populated from [uevent.Message] received
|
||||
// from a NETLINK_KOBJECT_UEVENT socket and presents an efficient representation
|
||||
// of kernel state.
|
||||
type State struct {
|
||||
// Next expected SEQNUM.
|
||||
seq uint64
|
||||
// DevPath to environment variables.
|
||||
uevent map[string]*Object
|
||||
// Synchronises access to uevent and its objects.
|
||||
ueventMu sync.RWMutex
|
||||
// Alive iterators.
|
||||
iter []*pendingIterator
|
||||
// Synchronises access to iter.
|
||||
iterMu sync.Mutex
|
||||
// UUID for synthetic [uevent.Coldboot] events.
|
||||
coldboot uevent.UUID
|
||||
// Called on [uevent.KOBJ_CHANGE] with stripped environment variables.
|
||||
handleChange func(o *Object, env map[string]string)
|
||||
// Reports errors populating [Event] from [uevent.Message]. A user-supplied
|
||||
// nil value is replaced with a noop.
|
||||
reportErr func(error)
|
||||
}
|
||||
|
||||
// New returns the address of a new [State].
|
||||
func New(
|
||||
coldboot uevent.UUID,
|
||||
handleChange func(o *Object, env map[string]string),
|
||||
reportErr func(error),
|
||||
) *State {
|
||||
return &State{
|
||||
uevent: make(map[string]*Object),
|
||||
coldboot: coldboot,
|
||||
handleChange: handleChange,
|
||||
reportErr: reportErr,
|
||||
}
|
||||
}
|
||||
|
||||
// deleteIter removes an iterator from s. Must be called after acquiring iterMu.
|
||||
func (s *State) deleteIter(p *pendingIterator) {
|
||||
s.iter = slices.DeleteFunc(s.iter, func(v *pendingIterator) bool {
|
||||
return p == v
|
||||
})
|
||||
}
|
||||
|
||||
// dispatchIter broadcasts an [Object] to all alive iterators.
|
||||
func (s *State) dispatchIter(o *Object, act uevent.KobjectAction) {
|
||||
s.iterMu.Lock()
|
||||
defer s.iterMu.Unlock()
|
||||
|
||||
for _, p := range s.iter {
|
||||
if !p.f(o, act) {
|
||||
s.deleteIter(p)
|
||||
close(p.done)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Range calls f on all current and upcoming [Object] values tracked by s until
|
||||
// f returns false or the context is cancelled. f must not retain o or modify
|
||||
// the value it points to.
|
||||
func (s *State) Range(
|
||||
ctx context.Context,
|
||||
f func(o *Object, act uevent.KobjectAction) bool,
|
||||
) {
|
||||
done := make(chan struct{})
|
||||
p := pendingIterator{f, done}
|
||||
|
||||
s.iterMu.Lock()
|
||||
s.ueventMu.RLock()
|
||||
for _, o := range s.uevent {
|
||||
if !f(o, uevent.KOBJ_ADD) {
|
||||
s.ueventMu.RUnlock()
|
||||
s.iterMu.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
s.ueventMu.RUnlock()
|
||||
s.iter = append(s.iter, &p)
|
||||
s.iterMu.Unlock()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
s.iterMu.Lock()
|
||||
s.deleteIter(&p)
|
||||
s.iterMu.Unlock()
|
||||
return
|
||||
|
||||
case <-done:
|
||||
// deregistered by dispatchIter
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// An EventError describes a malformed or inconsistent [Event].
|
||||
type EventError struct {
|
||||
Kind int `json:"fault"`
|
||||
E Event `json:"event"`
|
||||
O *Object `json:"object,omitempty"`
|
||||
}
|
||||
|
||||
var _ report.RepresentableError = EventError{}
|
||||
|
||||
func (EventError) Representable() {}
|
||||
|
||||
const (
|
||||
// EUnexpectedColdboot is reported for a coldboot event with action other
|
||||
// than the expected [uevent.KOBJ_ADD].
|
||||
EUnexpectedColdboot = iota
|
||||
// EDuplicateAdd is reported for a [uevent.KOBJ_ADD] event on a
|
||||
// still-existing entry that was not the result of a coldboot.
|
||||
EDuplicateAdd
|
||||
// EBadTarget is reported for an event on a nonexistent [Object]. This is
|
||||
// generally only possible before coldboot completes.
|
||||
EBadTarget
|
||||
// ERemoveState is reported for a [uevent.KOBJ_REMOVE] event targeting an
|
||||
// entry in a state other than [StateColdboot] and [StateNew].
|
||||
ERemoveState
|
||||
// EUnexpectedOffline is reported for a [uevent.KOBJ_OFFLINE] or
|
||||
// [uevent.KOBJ_ONLINE] event targeting an already offline or online object.
|
||||
EUnexpectedOffline
|
||||
// EBindState is reported for a [uevent.KOBJ_BIND] event targeting an entry
|
||||
// in a state other than [StateColdboot] and [StateNew].
|
||||
EBindState
|
||||
// EUnbindState is reported for a [uevent.KOBJ_UNBIND] event targeting an
|
||||
// entry in a state other than [StateBound].
|
||||
EUnbindState
|
||||
// EMalformedMove is reported for a [uevent.KOBJ_MOVE] event missing the
|
||||
// DEVPATH_OLD environment variable.
|
||||
EMalformedMove
|
||||
)
|
||||
|
||||
func (e EventError) Error() string {
|
||||
switch e.Kind {
|
||||
case EUnexpectedColdboot:
|
||||
return "unexpected " + e.E.Action.String() + " coldboot event"
|
||||
case EDuplicateAdd:
|
||||
return "duplicate add event on devpath " + strconv.Quote(e.E.DevPath)
|
||||
case EBadTarget:
|
||||
return "unexpected " + e.E.Action.String() + " event on devpath " +
|
||||
strconv.Quote(e.E.DevPath)
|
||||
case ERemoveState:
|
||||
if e.O == nil {
|
||||
return "invalid remove event error"
|
||||
}
|
||||
return "remove event targeting devpath " + strconv.Quote(e.E.DevPath) +
|
||||
" in state " + strconv.Itoa(e.O.State)
|
||||
case EUnexpectedOffline:
|
||||
if e.O == nil {
|
||||
return "invalid unexpected offline error"
|
||||
}
|
||||
if e.O.Offline {
|
||||
return "offline event targeting devpath " + strconv.Quote(e.E.DevPath)
|
||||
}
|
||||
return "online event targeting devpath " + strconv.Quote(e.E.DevPath)
|
||||
case EBindState:
|
||||
if e.O == nil {
|
||||
return "invalid bind state error"
|
||||
}
|
||||
return "bind event targeting devpath " + strconv.Quote(e.E.DevPath) +
|
||||
" in state " + strconv.Itoa(e.O.State)
|
||||
case EUnbindState:
|
||||
if e.O == nil {
|
||||
return "invalid unbind state error"
|
||||
}
|
||||
return "unbind event targeting devpath " + strconv.Quote(e.E.DevPath) +
|
||||
" in state " + strconv.Itoa(e.O.State)
|
||||
case EMalformedMove:
|
||||
return "move event targeting devpath " + strconv.Quote(e.E.DevPath) +
|
||||
" missing DEVPATH_OLD"
|
||||
|
||||
default:
|
||||
return "invalid event error kind " + strconv.Itoa(e.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
// NewError returns a new [EventError] for e and o.
|
||||
func (e *Event) NewError(kind int, o *Object) error {
|
||||
if o != nil {
|
||||
o = o.Clone()
|
||||
}
|
||||
return EventError{kind, e.Clone(), o}
|
||||
}
|
||||
|
||||
// processEvent merges an event into s.
|
||||
func (s *State) processEvent(e *Event) {
|
||||
s.ueventMu.Lock()
|
||||
defer s.ueventMu.Unlock()
|
||||
|
||||
coldboot := e.Synth != nil
|
||||
if e.Action != uevent.KOBJ_ADD && coldboot {
|
||||
s.reportErr(e.NewError(EUnexpectedColdboot, nil))
|
||||
return
|
||||
}
|
||||
|
||||
switch act := e.Action; act {
|
||||
case uevent.KOBJ_ADD:
|
||||
if e.Synth == nil {
|
||||
if o, ok := s.uevent[e.DevPath]; ok {
|
||||
s.reportErr(e.NewError(EDuplicateAdd, o))
|
||||
o.merge(e.Env)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
}
|
||||
}
|
||||
o := e.makeColdboot()
|
||||
if !coldboot {
|
||||
o.State = StateNew
|
||||
}
|
||||
o.merge(e.Env)
|
||||
s.uevent[e.DevPath] = o
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_REMOVE:
|
||||
if o, ok := s.uevent[e.DevPath]; !ok {
|
||||
s.reportErr(e.NewError(EBadTarget, nil))
|
||||
return
|
||||
} else if o.State != StateColdboot && o.State != StateNew {
|
||||
s.reportErr(e.NewError(ERemoveState, o))
|
||||
}
|
||||
delete(s.uevent, e.DevPath)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_CHANGE:
|
||||
o, ok := s.uevent[e.DevPath]
|
||||
if !ok {
|
||||
s.reportErr(e.NewError(EBadTarget, nil))
|
||||
// this suffers from the coldboot race window similar to KOBJ_MOVE,
|
||||
// however this action combines driver-specific and change-specific
|
||||
// environment variables and combines them with environment
|
||||
// variables meant to convey state of the kobject, and it is not
|
||||
// possible to reliably separate them, so this fallback avoids the
|
||||
// race at the cost of including some garbage in tracked state
|
||||
o = e.makeColdboot()
|
||||
o.merge(e.Env)
|
||||
s.uevent[e.DevPath] = o
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
}
|
||||
o.update(e.Env, true)
|
||||
if s.handleChange != nil {
|
||||
s.handleChange(o, e.Env)
|
||||
}
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_MOVE:
|
||||
var o *Object
|
||||
if old, ok := e.Env["DEVPATH_OLD"]; !ok {
|
||||
s.reportErr(e.NewError(EMalformedMove, nil))
|
||||
// not reached
|
||||
o = e.makeColdboot()
|
||||
} else if o, ok = s.uevent[old]; !ok {
|
||||
s.reportErr(e.NewError(EBadTarget, nil))
|
||||
// this generally happens during coldboot, dropping the event here
|
||||
// may cause inconsistent state if the coldboot event for this
|
||||
// object was generated before the bind event
|
||||
delete(e.Env, "DEVPATH_OLD")
|
||||
o = e.makeColdboot()
|
||||
} else {
|
||||
delete(s.uevent, old)
|
||||
delete(e.Env, "DEVPATH_OLD")
|
||||
}
|
||||
o.merge(e.Env)
|
||||
s.uevent[e.DevPath] = o
|
||||
o.DevPath = e.DevPath
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_ONLINE:
|
||||
o, ok := s.uevent[e.DevPath]
|
||||
if !ok {
|
||||
s.reportErr(e.NewError(EBadTarget, nil))
|
||||
// coldboot race window similar to an unexpected KOBJ_MOVE
|
||||
o = e.makeColdboot()
|
||||
s.uevent[e.DevPath] = o
|
||||
o.merge(e.Env)
|
||||
}
|
||||
if !o.Offline {
|
||||
s.reportErr(e.NewError(EUnexpectedOffline, o))
|
||||
}
|
||||
o.Offline = false
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_OFFLINE:
|
||||
o, ok := s.uevent[e.DevPath]
|
||||
if !ok {
|
||||
s.reportErr(e.NewError(EBadTarget, nil))
|
||||
// coldboot race window similar to an unexpected KOBJ_MOVE
|
||||
o = e.makeColdboot()
|
||||
s.uevent[e.DevPath] = o
|
||||
o.merge(e.Env)
|
||||
}
|
||||
if o.Offline {
|
||||
s.reportErr(e.NewError(EUnexpectedOffline, o))
|
||||
}
|
||||
o.Offline = true
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_BIND:
|
||||
o, ok := s.uevent[e.DevPath]
|
||||
if !ok {
|
||||
s.reportErr(e.NewError(EBadTarget, nil))
|
||||
// coldboot race window similar to an unexpected KOBJ_MOVE
|
||||
o = e.makeColdboot()
|
||||
s.uevent[e.DevPath] = o
|
||||
}
|
||||
if o.State != StateColdboot && o.State != StateNew {
|
||||
s.reportErr(e.NewError(EBindState, o))
|
||||
}
|
||||
o.State = StateBound
|
||||
o.merge(e.Env)
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
case uevent.KOBJ_UNBIND:
|
||||
o, ok := s.uevent[e.DevPath]
|
||||
if !ok {
|
||||
s.reportErr(e.NewError(EBadTarget, nil))
|
||||
// coldboot race window similar to an unexpected KOBJ_MOVE, but does
|
||||
// not result in inconsistent state if dropped
|
||||
return
|
||||
}
|
||||
if o.State != StateBound {
|
||||
s.reportErr(e.NewError(EUnbindState, o))
|
||||
}
|
||||
o.State = StateNew
|
||||
o.Driver = ""
|
||||
s.dispatchIter(o, act)
|
||||
return
|
||||
|
||||
default: // not reached
|
||||
s.reportErr(fmt.Errorf("invalid action %d", e.Action))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// BadSequenceError is reported for an unexpected SEQNUM.
|
||||
type BadSequenceError struct{ Got, Want uint64 }
|
||||
|
||||
func (e BadSequenceError) Error() string {
|
||||
return "SEQNUM=" + strconv.FormatUint(e.Got, 10) +
|
||||
", want " + strconv.FormatUint(e.Want, 10)
|
||||
}
|
||||
|
||||
// Consume receives uevent messages and updates s to reflect state of kernel.
|
||||
func (s *State) Consume(ctx context.Context, events <-chan *uevent.Message) {
|
||||
if s.uevent == nil {
|
||||
s.uevent = make(map[string]*Object)
|
||||
}
|
||||
if s.reportErr == nil {
|
||||
s.reportErr = func(error) {}
|
||||
}
|
||||
|
||||
var e Event
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
case m, ok := <-events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
e.Populate(s.reportErr, m)
|
||||
|
||||
// skip external synthetic event
|
||||
if e.Synth != nil && *e.Synth != s.coldboot {
|
||||
continue
|
||||
}
|
||||
|
||||
if s.seq == 0 {
|
||||
s.seq = e.Sequence
|
||||
}
|
||||
if s.seq != e.Sequence {
|
||||
s.reportErr(BadSequenceError{e.Sequence, s.seq})
|
||||
}
|
||||
s.seq++
|
||||
s.processEvent(&e)
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
266
internal/kobject/testdata/00-coldboot
vendored
266
internal/kobject/testdata/00-coldboot
vendored
@@ -1,266 +0,0 @@
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXPWRBN:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXPWRBN:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:LNXPWRBN:","SEQNUM=777"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXPWRBN:00/wakeup/wakeup7","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXPWRBN:00/wakeup/wakeup7","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=778"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0010:00/LNXCPU:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0010:00/LNXCPU:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:LNXCPU:","SEQNUM=779"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0010:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0010:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:ACPI0010:PNP0A05:","SEQNUM=780"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0103:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0103:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0103:","SEQNUM=781"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/PNP0A06:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/PNP0A06:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0A06:","SEQNUM=782"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/PNP0A06:01","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/PNP0A06:01","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0A06:","SEQNUM=783"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/PNP0A06:02","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/PNP0A06:02","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0A06:","SEQNUM=784"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/QEMU0002:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/QEMU0002:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:QEMU0002:","SEQNUM=785"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=786"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:00/wakeup/wakeup0","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:00/wakeup/wakeup0","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=787"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0303:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0303:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0303:","SEQNUM=788"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0400:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0400:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0400:","SEQNUM=789"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0501:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0501:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0501:","SEQNUM=790"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0700:00/device:02","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0700:00/device:02","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=791"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0700:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0700:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0700:","SEQNUM=792"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0B00:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0B00:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0B00:","SEQNUM=793"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0F13:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/PNP0F13:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0F13:","SEQNUM=794"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=795"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/wakeup/wakeup1","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:01/wakeup/wakeup1","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=796"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:03","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:03","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=797"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:03/wakeup/wakeup2","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:03/wakeup/wakeup2","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=798"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:04","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:04","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=799"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:04/wakeup/wakeup3","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:04/wakeup/wakeup3","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=800"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:05","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:05","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=801"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:05/wakeup/wakeup4","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:05/wakeup/wakeup4","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=802"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:06","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:06","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=803"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:06/wakeup/wakeup5","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:06/wakeup/wakeup5","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=804"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=805"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=806"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:09","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:09","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=807"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0a","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0a","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=808"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0b","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0b","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=809"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0c","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0c","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=810"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0d","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0d","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=811"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0e","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0e","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=812"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0f","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:0f","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=813"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:10","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:10","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=814"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:11","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:11","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=815"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:12","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:12","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=816"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:13","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:13","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=817"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:14","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:14","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=818"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:15","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:15","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=819"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:16","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:16","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=820"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:17","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:17","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=821"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:18","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:18","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=822"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:19","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:19","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=823"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1a","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1a","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=824"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1b","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1b","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=825"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1c","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1c","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=826"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1d","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1d","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=827"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1e","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1e","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=828"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1f","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:1f","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=829"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:20","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:20","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=830"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:21","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:21","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=831"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:22","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:22","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=832"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0A03:","SEQNUM=833"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/wakeup/wakeup6","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/wakeup/wakeup6","SUBSYSTEM=wakeup","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=834"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0C0F:","SEQNUM=835"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:01","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:01","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0C0F:","SEQNUM=836"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:02","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:02","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0C0F:","SEQNUM=837"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:03","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:03","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0C0F:","SEQNUM=838"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:04","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0F:04","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0C0F:","SEQNUM=839"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:LNXSYBUS:","SEQNUM=840"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:01","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:01","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:LNXSYBUS:","SEQNUM=841"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00","SUBSYSTEM=acpi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:LNXSYSTM:","SEQNUM=842"]}
|
||||
{"action":"add","devpath":"/devices/breakpoint","env":["ACTION=add","DEVPATH=/devices/breakpoint","SUBSYSTEM=event_source","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=843"]}
|
||||
{"action":"add","devpath":"/devices/cpu","env":["ACTION=add","DEVPATH=/devices/cpu","SUBSYSTEM=event_source","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=844"]}
|
||||
{"action":"add","devpath":"/devices/kprobe","env":["ACTION=add","DEVPATH=/devices/kprobe","SUBSYSTEM=event_source","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=845"]}
|
||||
{"action":"add","devpath":"/devices/msr","env":["ACTION=add","DEVPATH=/devices/msr","SUBSYSTEM=event_source","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=846"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:00.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:00.0","SUBSYSTEM=pci","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","PCI_CLASS=60000","PCI_ID=8086:1237","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:00.0","MODALIAS=pci:v00008086d00001237sv00001AF4sd00001100bc06sc00i00","SEQNUM=847"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.0","SUBSYSTEM=pci","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","PCI_CLASS=60100","PCI_ID=8086:7000","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:01.0","MODALIAS=pci:v00008086d00007000sv00001AF4sd00001100bc06sc01i00","SEQNUM=848"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata1/ata_port/ata1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata1/ata_port/ata1","SUBSYSTEM=ata_port","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=849"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata1/host0/scsi_host/host0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata1/host0/scsi_host/host0","SUBSYSTEM=scsi_host","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=850"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata1/host0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata1/host0","SUBSYSTEM=scsi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=scsi_host","SEQNUM=851"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata1/link1/ata_link/link1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata1/link1/ata_link/link1","SUBSYSTEM=ata_link","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=852"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata1/link1/dev1.0/ata_device/dev1.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata1/link1/dev1.0/ata_device/dev1.0","SUBSYSTEM=ata_device","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=853"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata1/link1/dev1.1/ata_device/dev1.1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata1/link1/dev1.1/ata_device/dev1.1","SUBSYSTEM=ata_device","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=854"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/ata_port/ata2","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/ata_port/ata2","SUBSYSTEM=ata_port","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=855"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/host1/scsi_host/host1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/host1/scsi_host/host1","SUBSYSTEM=scsi_host","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=856"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/bsg/1:0:0:0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/bsg/1:0:0:0","SUBSYSTEM=bsg","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=251","MINOR=0","DEVNAME=bsg/1:0:0:0","SEQNUM=857"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/scsi_device/1:0:0:0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0/scsi_device/1:0:0:0","SUBSYSTEM=scsi_device","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=858"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0/1:0:0:0","SUBSYSTEM=scsi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=scsi_device","MODALIAS=scsi:t-0x05","SEQNUM=859"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/host1/target1:0:0","SUBSYSTEM=scsi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=scsi_target","SEQNUM=860"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/host1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/host1","SUBSYSTEM=scsi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=scsi_host","SEQNUM=861"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/link2/ata_link/link2","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/link2/ata_link/link2","SUBSYSTEM=ata_link","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=862"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/link2/dev2.0/ata_device/dev2.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/link2/dev2.0/ata_device/dev2.0","SUBSYSTEM=ata_device","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=863"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1/ata2/link2/dev2.1/ata_device/dev2.1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1/ata2/link2/dev2.1/ata_device/dev2.1","SUBSYSTEM=ata_device","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=864"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.1","SUBSYSTEM=pci","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DRIVER=ata_piix","PCI_CLASS=10180","PCI_ID=8086:7010","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:01.1","MODALIAS=pci:v00008086d00007010sv00001AF4sd00001100bc01sc01i80","SEQNUM=865"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:01.3","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:01.3","SUBSYSTEM=pci","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","PCI_CLASS=68000","PCI_ID=8086:7113","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:01.3","MODALIAS=pci:v00008086d00007113sv00001AF4sd00001100bc06sc80i00","SEQNUM=866"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:02.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:02.0","SUBSYSTEM=pci","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","PCI_CLASS=20000","PCI_ID=8086:100E","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:02.0","MODALIAS=pci:v00008086d0000100Esv00001AF4sd00001100bc02sc00i00","SEQNUM=867"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:03.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:03.0","SUBSYSTEM=pci","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DRIVER=virtio-pci","PCI_CLASS=10000","PCI_ID=1AF4:1001","PCI_SUBSYS_ID=1AF4:0002","PCI_SLOT_NAME=0000:00:03.0","MODALIAS=pci:v00001AF4d00001001sv00001AF4sd00000002bc01sc00i00","SEQNUM=868"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:03.0/virtio0/block/vda","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda","SUBSYSTEM=block","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=254","MINOR=0","DEVNAME=vda","DEVTYPE=disk","DISKSEQ=1","SEQNUM=869"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:03.0/virtio0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:03.0/virtio0","SUBSYSTEM=virtio","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DRIVER=virtio_blk","MODALIAS=virtio:d00000002v00001AF4","SEQNUM=870"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/QEMU0002:00","env":["ACTION=add","DEVPATH=/devices/pci0000:00/QEMU0002:00","SUBSYSTEM=platform","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:QEMU0002:","SEQNUM=871"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/pci_bus/0000:00","env":["ACTION=add","DEVPATH=/devices/pci0000:00/pci_bus/0000:00","SUBSYSTEM=pci_bus","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=872"]}
|
||||
{"action":"add","devpath":"/devices/platform/PNP0103:00","env":["ACTION=add","DEVPATH=/devices/platform/PNP0103:00","SUBSYSTEM=platform","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=acpi:PNP0103:","SEQNUM=873"]}
|
||||
{"action":"add","devpath":"/devices/platform/pcspkr","env":["ACTION=add","DEVPATH=/devices/platform/pcspkr","SUBSYSTEM=platform","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=platform:pcspkr","SEQNUM=874"]}
|
||||
{"action":"add","devpath":"/devices/platform/reg-dummy/regulator/regulator.0","env":["ACTION=add","DEVPATH=/devices/platform/reg-dummy/regulator/regulator.0","SUBSYSTEM=regulator","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=875"]}
|
||||
{"action":"add","devpath":"/devices/platform/reg-dummy","env":["ACTION=add","DEVPATH=/devices/platform/reg-dummy","SUBSYSTEM=platform","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DRIVER=reg-dummy","MODALIAS=platform:reg-dummy","SEQNUM=876"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250/serial8250:0/serial8250:0.1/tty/ttyS1","env":["ACTION=add","DEVPATH=/devices/platform/serial8250/serial8250:0/serial8250:0.1/tty/ttyS1","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=65","DEVNAME=ttyS1","SEQNUM=877"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250/serial8250:0/serial8250:0.1","env":["ACTION=add","DEVPATH=/devices/platform/serial8250/serial8250:0/serial8250:0.1","SUBSYSTEM=serial-base","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=port","DRIVER=port","SEQNUM=878"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250/serial8250:0/serial8250:0.2/tty/ttyS2","env":["ACTION=add","DEVPATH=/devices/platform/serial8250/serial8250:0/serial8250:0.2/tty/ttyS2","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=66","DEVNAME=ttyS2","SEQNUM=879"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250/serial8250:0/serial8250:0.2","env":["ACTION=add","DEVPATH=/devices/platform/serial8250/serial8250:0/serial8250:0.2","SUBSYSTEM=serial-base","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=port","DRIVER=port","SEQNUM=880"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250/serial8250:0/serial8250:0.3/tty/ttyS3","env":["ACTION=add","DEVPATH=/devices/platform/serial8250/serial8250:0/serial8250:0.3/tty/ttyS3","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=67","DEVNAME=ttyS3","SEQNUM=881"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250/serial8250:0/serial8250:0.3","env":["ACTION=add","DEVPATH=/devices/platform/serial8250/serial8250:0/serial8250:0.3","SUBSYSTEM=serial-base","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=port","DRIVER=port","SEQNUM=882"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250/serial8250:0","env":["ACTION=add","DEVPATH=/devices/platform/serial8250/serial8250:0","SUBSYSTEM=serial-base","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=ctrl","DRIVER=ctrl","SEQNUM=883"]}
|
||||
{"action":"add","devpath":"/devices/platform/serial8250","env":["ACTION=add","DEVPATH=/devices/platform/serial8250","SUBSYSTEM=platform","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DRIVER=serial8250","MODALIAS=platform:serial8250","SEQNUM=884"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:00","env":["ACTION=add","DEVPATH=/devices/pnp0/00:00","SUBSYSTEM=pnp","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=885"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:01","env":["ACTION=add","DEVPATH=/devices/pnp0/00:01","SUBSYSTEM=pnp","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=886"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:02","env":["ACTION=add","DEVPATH=/devices/pnp0/00:02","SUBSYSTEM=pnp","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=887"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:03","env":["ACTION=add","DEVPATH=/devices/pnp0/00:03","SUBSYSTEM=pnp","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=888"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:04/00:04:0/00:04:0.0/tty/ttyS0","env":["ACTION=add","DEVPATH=/devices/pnp0/00:04/00:04:0/00:04:0.0/tty/ttyS0","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=64","DEVNAME=ttyS0","SEQNUM=889"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:04/00:04:0/00:04:0.0","env":["ACTION=add","DEVPATH=/devices/pnp0/00:04/00:04:0/00:04:0.0","SUBSYSTEM=serial-base","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=port","DRIVER=port","SEQNUM=890"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:04/00:04:0","env":["ACTION=add","DEVPATH=/devices/pnp0/00:04/00:04:0","SUBSYSTEM=serial-base","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DEVTYPE=ctrl","DRIVER=ctrl","SEQNUM=891"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:04","env":["ACTION=add","DEVPATH=/devices/pnp0/00:04","SUBSYSTEM=pnp","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DRIVER=serial","SEQNUM=892"]}
|
||||
{"action":"add","devpath":"/devices/pnp0/00:05","env":["ACTION=add","DEVPATH=/devices/pnp0/00:05","SUBSYSTEM=pnp","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=893"]}
|
||||
{"action":"add","devpath":"/devices/software","env":["ACTION=add","DEVPATH=/devices/software","SUBSYSTEM=event_source","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=894"]}
|
||||
{"action":"add","devpath":"/devices/system/clockevents/broadcast","env":["ACTION=add","DEVPATH=/devices/system/clockevents/broadcast","SUBSYSTEM=clockevents","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=895"]}
|
||||
{"action":"add","devpath":"/devices/system/clockevents/clockevent0","env":["ACTION=add","DEVPATH=/devices/system/clockevents/clockevent0","SUBSYSTEM=clockevents","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=896"]}
|
||||
{"action":"add","devpath":"/devices/system/clocksource/clocksource0","env":["ACTION=add","DEVPATH=/devices/system/clocksource/clocksource0","SUBSYSTEM=clocksource","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=897"]}
|
||||
{"action":"add","devpath":"/devices/system/container/PNP0A06:00","env":["ACTION=add","DEVPATH=/devices/system/container/PNP0A06:00","SUBSYSTEM=container","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=898"]}
|
||||
{"action":"add","devpath":"/devices/system/container/PNP0A06:01","env":["ACTION=add","DEVPATH=/devices/system/container/PNP0A06:01","SUBSYSTEM=container","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=899"]}
|
||||
{"action":"add","devpath":"/devices/system/container/PNP0A06:02","env":["ACTION=add","DEVPATH=/devices/system/container/PNP0A06:02","SUBSYSTEM=container","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=900"]}
|
||||
{"action":"add","devpath":"/devices/system/cpu/cpu0","env":["ACTION=add","DEVPATH=/devices/system/cpu/cpu0","SUBSYSTEM=cpu","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","DRIVER=processor","MODALIAS=cpu:type:x86,ven0002fam000Fmod006B:feature:,0000,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0017,0018,0019,001A,0020,0022,0023,0024,0025,0026,0027,0028,0029,002B,002C,002D,002E,002F,0030,0031,0034,0037,0038,003D,0064,006E,0070,0074,0075,0076,0079,007A,007F,0080,008D,0095,009F,00C0,00C8,00ED,00F3,010F,0115,0165,016C,0282\n","SEQNUM=901"]}
|
||||
{"action":"add","devpath":"/devices/system/machinecheck/machinecheck0","env":["ACTION=add","DEVPATH=/devices/system/machinecheck/machinecheck0","SUBSYSTEM=machinecheck","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=902"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory0","env":["ACTION=add","DEVPATH=/devices/system/memory/memory0","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=903"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory1","env":["ACTION=add","DEVPATH=/devices/system/memory/memory1","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=904"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory2","env":["ACTION=add","DEVPATH=/devices/system/memory/memory2","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=905"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory3","env":["ACTION=add","DEVPATH=/devices/system/memory/memory3","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=906"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory4","env":["ACTION=add","DEVPATH=/devices/system/memory/memory4","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=907"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory5","env":["ACTION=add","DEVPATH=/devices/system/memory/memory5","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=908"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory6","env":["ACTION=add","DEVPATH=/devices/system/memory/memory6","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=909"]}
|
||||
{"action":"add","devpath":"/devices/system/memory/memory7","env":["ACTION=add","DEVPATH=/devices/system/memory/memory7","SUBSYSTEM=memory","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=910"]}
|
||||
{"action":"add","devpath":"/devices/system/node/node0","env":["ACTION=add","DEVPATH=/devices/system/node/node0","SUBSYSTEM=node","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=911"]}
|
||||
{"action":"add","devpath":"/devices/tracepoint","env":["ACTION=add","DEVPATH=/devices/tracepoint","SUBSYSTEM=event_source","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=912"]}
|
||||
{"action":"add","devpath":"/devices/uprobe","env":["ACTION=add","DEVPATH=/devices/uprobe","SUBSYSTEM=event_source","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=913"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/254:0","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/254:0","SUBSYSTEM=bdi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=914"]}
|
||||
{"action":"add","devpath":"/devices/virtual/devlink/:ata2--scsi:1:0:0:0","env":["ACTION=add","DEVPATH=/devices/virtual/devlink/:ata2--scsi:1:0:0:0","SUBSYSTEM=devlink","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=915"]}
|
||||
{"action":"add","devpath":"/devices/virtual/dmi/id","env":["ACTION=add","DEVPATH=/devices/virtual/dmi/id","SUBSYSTEM=dmi","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MODALIAS=dmi:bvnSeaBIOS:bvrrel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org:bd04/01/2014:br0.0:svnQEMU:pnStandardPC(i440FX+PIIX,1996):pvrpc-i440fx-10.1:cvnQEMU:ct1:cvrpc-i440fx-10.1:sku:","SEQNUM=916"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/full","env":["ACTION=add","DEVPATH=/devices/virtual/mem/full","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=7","DEVNAME=full","DEVMODE=0666","SEQNUM=917"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/kmsg","env":["ACTION=add","DEVPATH=/devices/virtual/mem/kmsg","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=11","DEVNAME=kmsg","DEVMODE=0644","SEQNUM=918"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/mem","env":["ACTION=add","DEVPATH=/devices/virtual/mem/mem","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=1","DEVNAME=mem","SEQNUM=919"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/null","env":["ACTION=add","DEVPATH=/devices/virtual/mem/null","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=3","DEVNAME=null","DEVMODE=0666","SEQNUM=920"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/port","env":["ACTION=add","DEVPATH=/devices/virtual/mem/port","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=4","DEVNAME=port","SEQNUM=921"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/random","env":["ACTION=add","DEVPATH=/devices/virtual/mem/random","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=8","DEVNAME=random","DEVMODE=0666","SEQNUM=922"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/urandom","env":["ACTION=add","DEVPATH=/devices/virtual/mem/urandom","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=9","DEVNAME=urandom","DEVMODE=0666","SEQNUM=923"]}
|
||||
{"action":"add","devpath":"/devices/virtual/mem/zero","env":["ACTION=add","DEVPATH=/devices/virtual/mem/zero","SUBSYSTEM=mem","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=1","MINOR=5","DEVNAME=zero","DEVMODE=0666","SEQNUM=924"]}
|
||||
{"action":"add","devpath":"/devices/virtual/memory_tiering/memory_tier4","env":["ACTION=add","DEVPATH=/devices/virtual/memory_tiering/memory_tier4","SUBSYSTEM=memory_tiering","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=925"]}
|
||||
{"action":"add","devpath":"/devices/virtual/misc/cpu_dma_latency","env":["ACTION=add","DEVPATH=/devices/virtual/misc/cpu_dma_latency","SUBSYSTEM=misc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=10","MINOR=259","DEVNAME=cpu_dma_latency","SEQNUM=926"]}
|
||||
{"action":"add","devpath":"/devices/virtual/misc/hpet","env":["ACTION=add","DEVPATH=/devices/virtual/misc/hpet","SUBSYSTEM=misc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=10","MINOR=228","DEVNAME=hpet","SEQNUM=927"]}
|
||||
{"action":"add","devpath":"/devices/virtual/misc/snapshot","env":["ACTION=add","DEVPATH=/devices/virtual/misc/snapshot","SUBSYSTEM=misc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=10","MINOR=231","DEVNAME=snapshot","SEQNUM=928"]}
|
||||
{"action":"add","devpath":"/devices/virtual/misc/udmabuf","env":["ACTION=add","DEVPATH=/devices/virtual/misc/udmabuf","SUBSYSTEM=misc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=10","MINOR=258","DEVNAME=udmabuf","SEQNUM=929"]}
|
||||
{"action":"add","devpath":"/devices/virtual/misc/userfaultfd","env":["ACTION=add","DEVPATH=/devices/virtual/misc/userfaultfd","SUBSYSTEM=misc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=10","MINOR=257","DEVNAME=userfaultfd","SEQNUM=930"]}
|
||||
{"action":"add","devpath":"/devices/virtual/misc/vga_arbiter","env":["ACTION=add","DEVPATH=/devices/virtual/misc/vga_arbiter","SUBSYSTEM=misc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=10","MINOR=256","DEVNAME=vga_arbiter","SEQNUM=931"]}
|
||||
{"action":"add","devpath":"/devices/virtual/net/lo","env":["ACTION=add","DEVPATH=/devices/virtual/net/lo","SUBSYSTEM=net","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","INTERFACE=lo","IFINDEX=1","SEQNUM=932"]}
|
||||
{"action":"add","devpath":"/devices/virtual/thermal/cooling_device0","env":["ACTION=add","DEVPATH=/devices/virtual/thermal/cooling_device0","SUBSYSTEM=thermal","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=933"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/console","env":["ACTION=add","DEVPATH=/devices/virtual/tty/console","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=5","MINOR=1","DEVNAME=console","SEQNUM=934"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/ptmx","env":["ACTION=add","DEVPATH=/devices/virtual/tty/ptmx","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=5","MINOR=2","DEVNAME=ptmx","DEVMODE=0666","SEQNUM=935"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=5","MINOR=0","DEVNAME=tty","DEVMODE=0666","SEQNUM=936"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty0","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty0","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=0","DEVNAME=tty0","SEQNUM=937"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty1","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty1","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=1","DEVNAME=tty1","SEQNUM=938"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty10","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty10","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=10","DEVNAME=tty10","SEQNUM=939"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty11","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty11","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=11","DEVNAME=tty11","SEQNUM=940"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty12","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty12","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=12","DEVNAME=tty12","SEQNUM=941"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty13","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty13","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=13","DEVNAME=tty13","SEQNUM=942"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty14","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty14","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=14","DEVNAME=tty14","SEQNUM=943"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty15","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty15","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=15","DEVNAME=tty15","SEQNUM=944"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty16","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty16","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=16","DEVNAME=tty16","SEQNUM=945"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty17","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty17","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=17","DEVNAME=tty17","SEQNUM=946"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty18","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty18","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=18","DEVNAME=tty18","SEQNUM=947"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty19","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty19","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=19","DEVNAME=tty19","SEQNUM=948"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty2","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty2","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=2","DEVNAME=tty2","SEQNUM=949"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty20","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty20","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=20","DEVNAME=tty20","SEQNUM=950"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty21","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty21","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=21","DEVNAME=tty21","SEQNUM=951"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty22","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty22","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=22","DEVNAME=tty22","SEQNUM=952"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty23","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty23","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=23","DEVNAME=tty23","SEQNUM=953"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty24","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty24","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=24","DEVNAME=tty24","SEQNUM=954"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty25","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty25","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=25","DEVNAME=tty25","SEQNUM=955"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty26","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty26","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=26","DEVNAME=tty26","SEQNUM=956"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty27","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty27","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=27","DEVNAME=tty27","SEQNUM=957"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty28","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty28","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=28","DEVNAME=tty28","SEQNUM=958"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty29","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty29","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=29","DEVNAME=tty29","SEQNUM=959"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty3","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty3","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=3","DEVNAME=tty3","SEQNUM=960"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty30","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty30","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=30","DEVNAME=tty30","SEQNUM=961"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty31","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty31","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=31","DEVNAME=tty31","SEQNUM=962"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty32","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty32","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=32","DEVNAME=tty32","SEQNUM=963"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty33","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty33","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=33","DEVNAME=tty33","SEQNUM=964"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty34","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty34","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=34","DEVNAME=tty34","SEQNUM=965"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty35","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty35","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=35","DEVNAME=tty35","SEQNUM=966"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty36","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty36","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=36","DEVNAME=tty36","SEQNUM=967"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty37","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty37","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=37","DEVNAME=tty37","SEQNUM=968"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty38","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty38","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=38","DEVNAME=tty38","SEQNUM=969"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty39","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty39","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=39","DEVNAME=tty39","SEQNUM=970"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty4","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty4","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=4","DEVNAME=tty4","SEQNUM=971"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty40","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty40","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=40","DEVNAME=tty40","SEQNUM=972"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty41","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty41","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=41","DEVNAME=tty41","SEQNUM=973"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty42","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty42","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=42","DEVNAME=tty42","SEQNUM=974"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty43","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty43","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=43","DEVNAME=tty43","SEQNUM=975"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty44","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty44","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=44","DEVNAME=tty44","SEQNUM=976"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty45","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty45","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=45","DEVNAME=tty45","SEQNUM=977"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty46","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty46","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=46","DEVNAME=tty46","SEQNUM=978"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty47","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty47","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=47","DEVNAME=tty47","SEQNUM=979"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty48","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty48","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=48","DEVNAME=tty48","SEQNUM=980"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty49","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty49","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=49","DEVNAME=tty49","SEQNUM=981"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty5","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty5","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=5","DEVNAME=tty5","SEQNUM=982"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty50","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty50","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=50","DEVNAME=tty50","SEQNUM=983"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty51","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty51","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=51","DEVNAME=tty51","SEQNUM=984"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty52","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty52","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=52","DEVNAME=tty52","SEQNUM=985"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty53","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty53","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=53","DEVNAME=tty53","SEQNUM=986"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty54","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty54","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=54","DEVNAME=tty54","SEQNUM=987"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty55","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty55","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=55","DEVNAME=tty55","SEQNUM=988"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty56","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty56","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=56","DEVNAME=tty56","SEQNUM=989"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty57","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty57","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=57","DEVNAME=tty57","SEQNUM=990"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty58","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty58","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=58","DEVNAME=tty58","SEQNUM=991"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty59","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty59","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=59","DEVNAME=tty59","SEQNUM=992"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty6","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty6","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=6","DEVNAME=tty6","SEQNUM=993"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty60","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty60","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=60","DEVNAME=tty60","SEQNUM=994"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty61","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty61","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=61","DEVNAME=tty61","SEQNUM=995"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty62","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty62","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=62","DEVNAME=tty62","SEQNUM=996"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty63","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty63","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=63","DEVNAME=tty63","SEQNUM=997"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty7","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty7","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=7","DEVNAME=tty7","SEQNUM=998"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty8","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty8","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=8","DEVNAME=tty8","SEQNUM=999"]}
|
||||
{"action":"add","devpath":"/devices/virtual/tty/tty9","env":["ACTION=add","DEVPATH=/devices/virtual/tty/tty9","SUBSYSTEM=tty","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=4","MINOR=9","DEVNAME=tty9","SEQNUM=1000"]}
|
||||
{"action":"add","devpath":"/devices/virtual/vc/vcs","env":["ACTION=add","DEVPATH=/devices/virtual/vc/vcs","SUBSYSTEM=vc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=7","MINOR=0","DEVNAME=vcs","SEQNUM=1001"]}
|
||||
{"action":"add","devpath":"/devices/virtual/vc/vcs1","env":["ACTION=add","DEVPATH=/devices/virtual/vc/vcs1","SUBSYSTEM=vc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=7","MINOR=1","DEVNAME=vcs1","SEQNUM=1002"]}
|
||||
{"action":"add","devpath":"/devices/virtual/vc/vcsa","env":["ACTION=add","DEVPATH=/devices/virtual/vc/vcsa","SUBSYSTEM=vc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=7","MINOR=128","DEVNAME=vcsa","SEQNUM=1003"]}
|
||||
{"action":"add","devpath":"/devices/virtual/vc/vcsa1","env":["ACTION=add","DEVPATH=/devices/virtual/vc/vcsa1","SUBSYSTEM=vc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=7","MINOR=129","DEVNAME=vcsa1","SEQNUM=1004"]}
|
||||
{"action":"add","devpath":"/devices/virtual/vc/vcsu","env":["ACTION=add","DEVPATH=/devices/virtual/vc/vcsu","SUBSYSTEM=vc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=7","MINOR=64","DEVNAME=vcsu","SEQNUM=1005"]}
|
||||
{"action":"add","devpath":"/devices/virtual/vc/vcsu1","env":["ACTION=add","DEVPATH=/devices/virtual/vc/vcsu1","SUBSYSTEM=vc","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","MAJOR=7","MINOR=65","DEVNAME=vcsu1","SEQNUM=1006"]}
|
||||
{"action":"add","devpath":"/devices/virtual/vtconsole/vtcon0","env":["ACTION=add","DEVPATH=/devices/virtual/vtconsole/vtcon0","SUBSYSTEM=vtconsole","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1007"]}
|
||||
{"action":"add","devpath":"/devices/virtual/workqueue/nvme-auth-wq","env":["ACTION=add","DEVPATH=/devices/virtual/workqueue/nvme-auth-wq","SUBSYSTEM=workqueue","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1008"]}
|
||||
{"action":"add","devpath":"/devices/virtual/workqueue/nvme-delete-wq","env":["ACTION=add","DEVPATH=/devices/virtual/workqueue/nvme-delete-wq","SUBSYSTEM=workqueue","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1009"]}
|
||||
{"action":"add","devpath":"/devices/virtual/workqueue/nvme-reset-wq","env":["ACTION=add","DEVPATH=/devices/virtual/workqueue/nvme-reset-wq","SUBSYSTEM=workqueue","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1010"]}
|
||||
{"action":"add","devpath":"/devices/virtual/workqueue/nvme-wq","env":["ACTION=add","DEVPATH=/devices/virtual/workqueue/nvme-wq","SUBSYSTEM=workqueue","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1011"]}
|
||||
{"action":"add","devpath":"/devices/virtual/workqueue/scsi_tmf_0","env":["ACTION=add","DEVPATH=/devices/virtual/workqueue/scsi_tmf_0","SUBSYSTEM=workqueue","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1012"]}
|
||||
{"action":"add","devpath":"/devices/virtual/workqueue/scsi_tmf_1","env":["ACTION=add","DEVPATH=/devices/virtual/workqueue/scsi_tmf_1","SUBSYSTEM=workqueue","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1013"]}
|
||||
{"action":"add","devpath":"/devices/virtual/workqueue/writeback","env":["ACTION=add","DEVPATH=/devices/virtual/workqueue/writeback","SUBSYSTEM=workqueue","SYNTH_UUID=fe4d7c9d-b8c6-4a70-9ef1-3d8a58d18eed","SEQNUM=1014"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07/wakeup/wakeup8","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07/wakeup/wakeup8","SUBSYSTEM=wakeup","SEQNUM=1015"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:04.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:04.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:04.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1016"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:04.0/virtio1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:04.0/virtio1","SUBSYSTEM=virtio","MODALIAS=virtio:d00000019v00001AF4","SEQNUM=1017"]}
|
||||
{"action":"bind","devpath":"/devices/pci0000:00/0000:00:04.0","env":["ACTION=bind","DEVPATH=/devices/pci0000:00/0000:00:04.0","SUBSYSTEM=pci","DRIVER=virtio-pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:04.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1018"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","SUBSYSTEM=wakeup","SEQNUM=1019"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1020"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:05.0/virtio2","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:05.0/virtio2","SUBSYSTEM=virtio","MODALIAS=virtio:d00000019v00001AF4","SEQNUM=1021"]}
|
||||
{"action":"bind","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=bind","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","DRIVER=virtio-pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1022"]}
|
||||
{"action":"remove","devpath":"/devices/pci0000:00/0000:00:04.0/virtio1","env":["ACTION=remove","DEVPATH=/devices/pci0000:00/0000:00:04.0/virtio1","SUBSYSTEM=virtio","MODALIAS=virtio:d00000019v00001AF4","SEQNUM=1023"]}
|
||||
{"action":"unbind","devpath":"/devices/pci0000:00/0000:00:04.0","env":["ACTION=unbind","DEVPATH=/devices/pci0000:00/0000:00:04.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:04.0","SEQNUM=1024"]}
|
||||
{"action":"remove","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07/wakeup/wakeup8","env":["ACTION=remove","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07/wakeup/wakeup8","SUBSYSTEM=wakeup","SEQNUM=1025"]}
|
||||
{"action":"remove","devpath":"/devices/pci0000:00/0000:00:04.0","env":["ACTION=remove","DEVPATH=/devices/pci0000:00/0000:00:04.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:04.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1026"]}
|
||||
{"action":"remove","devpath":"/devices/pci0000:00/0000:00:05.0/virtio2","env":["ACTION=remove","DEVPATH=/devices/pci0000:00/0000:00:05.0/virtio2","SUBSYSTEM=virtio","MODALIAS=virtio:d00000019v00001AF4","SEQNUM=1027"]}
|
||||
{"action":"unbind","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=unbind","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","SEQNUM=1028"]}
|
||||
{"action":"remove","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","env":["ACTION=remove","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","SUBSYSTEM=wakeup","SEQNUM=1029"]}
|
||||
{"action":"remove","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=remove","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1030"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07/wakeup/wakeup8","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:07/wakeup/wakeup8","SUBSYSTEM=wakeup","SEQNUM=1031"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:04.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:04.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:04.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1032"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:04.0/virtio1","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:04.0/virtio1","SUBSYSTEM=virtio","MODALIAS=virtio:d00000019v00001AF4","SEQNUM=1033"]}
|
||||
{"action":"bind","devpath":"/devices/pci0000:00/0000:00:04.0","env":["ACTION=bind","DEVPATH=/devices/pci0000:00/0000:00:04.0","SUBSYSTEM=pci","DRIVER=virtio-pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:04.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1034"]}
|
||||
{"action":"add","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","env":["ACTION=add","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","SUBSYSTEM=wakeup","SEQNUM=1035"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1036"]}
|
||||
{"action":"add","devpath":"/devices/pci0000:00/0000:00:05.0/virtio2","env":["ACTION=add","DEVPATH=/devices/pci0000:00/0000:00:05.0/virtio2","SUBSYSTEM=virtio","MODALIAS=virtio:d00000019v00001AF4","SEQNUM=1037"]}
|
||||
{"action":"bind","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=bind","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","DRIVER=virtio-pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1038"]}
|
||||
{"action":"remove","devpath":"/devices/pci0000:00/0000:00:05.0/virtio2","env":["ACTION=remove","DEVPATH=/devices/pci0000:00/0000:00:05.0/virtio2","SUBSYSTEM=virtio","MODALIAS=virtio:d00000019v00001AF4","SEQNUM=1039"]}
|
||||
{"action":"unbind","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=unbind","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","SEQNUM=1040"]}
|
||||
{"action":"remove","devpath":"/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","env":["ACTION=remove","DEVPATH=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/device:08/wakeup/wakeup9","SUBSYSTEM=wakeup","SEQNUM=1041"]}
|
||||
{"action":"remove","devpath":"/devices/pci0000:00/0000:00:05.0","env":["ACTION=remove","DEVPATH=/devices/pci0000:00/0000:00:05.0","SUBSYSTEM=pci","PCI_CLASS=40100","PCI_ID=1AF4:1059","PCI_SUBSYS_ID=1AF4:1100","PCI_SLOT_NAME=0000:00:05.0","MODALIAS=pci:v00001AF4d00001059sv00001AF4sd00001100bc04sc01i00","SEQNUM=1042"]}
|
||||
1
internal/kobject/testdata/01-move
vendored
1
internal/kobject/testdata/01-move
vendored
@@ -1 +0,0 @@
|
||||
{"action":"move","devpath":"/devices/virtual/net/_lo","env":["ACTION=move","DEVPATH=/devices/virtual/net/_lo","SUBSYSTEM=net","DEVPATH_OLD=/devices/virtual/net/lo","INTERFACE=_lo","IFINDEX=1","SEQNUM=1043"]}
|
||||
8
internal/kobject/testdata/02-cpu
vendored
8
internal/kobject/testdata/02-cpu
vendored
@@ -1,8 +0,0 @@
|
||||
{"action":"remove","devpath":"/devices/system/machinecheck/machinecheck0","env":["ACTION=remove","DEVPATH=/devices/system/machinecheck/machinecheck0","SUBSYSTEM=machinecheck","SEQNUM=1044"]}
|
||||
{"action":"offline","devpath":"/devices/system/cpu/cpu0","env":["ACTION=offline","DEVPATH=/devices/system/cpu/cpu0","SUBSYSTEM=cpu","DRIVER=processor","MODALIAS=cpu:type:x86,ven0002fam000Fmod006B:feature:,0000,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0017,0018,0019,001A,001C,0020,0022,0023,0024,0025,0026,0027,0028,0029,002B,002C,002D,002E,002F,0030,0031,0034,0037,0038,003D,0064,006E,0070,0074,0075,0076,0079,007A,007F,0080,008D,0095,009F,00C0,00C1,00C8,00ED,00F3,010F,0115,0165,016C,0282\n","SEQNUM=1045"]}
|
||||
{"action":"add","devpath":"/devices/system/machinecheck/machinecheck0","env":["ACTION=add","DEVPATH=/devices/system/machinecheck/machinecheck0","SUBSYSTEM=machinecheck","SEQNUM=1046"]}
|
||||
{"action":"online","devpath":"/devices/system/cpu/cpu0","env":["ACTION=online","DEVPATH=/devices/system/cpu/cpu0","SUBSYSTEM=cpu","DRIVER=processor","MODALIAS=cpu:type:x86,ven0002fam000Fmod006B:feature:,0000,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0017,0018,0019,001A,001C,0020,0022,0023,0024,0025,0026,0027,0028,0029,002B,002C,002D,002E,002F,0030,0031,0034,0037,0038,003D,0064,006E,0070,0074,0075,0076,0079,007A,007F,0080,008D,0095,009F,00C0,00C1,00C8,00ED,00F3,010F,0115,0165,016C,0282\n","SEQNUM=1047"]}
|
||||
{"action":"remove","devpath":"/devices/system/machinecheck/machinecheck0","env":["ACTION=remove","DEVPATH=/devices/system/machinecheck/machinecheck0","SUBSYSTEM=machinecheck","SEQNUM=1048"]}
|
||||
{"action":"offline","devpath":"/devices/system/cpu/cpu0","env":["ACTION=offline","DEVPATH=/devices/system/cpu/cpu0","SUBSYSTEM=cpu","DRIVER=processor","MODALIAS=cpu:type:x86,ven0002fam000Fmod006B:feature:,0000,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0017,0018,0019,001A,001C,0020,0022,0023,0024,0025,0026,0027,0028,0029,002B,002C,002D,002E,002F,0030,0031,0034,0037,0038,003D,0064,006E,0070,0074,0075,0076,0079,007A,007F,0080,008D,0095,009F,00C0,00C1,00C8,00ED,00F3,010F,0115,0165,016C,0282\n","SEQNUM=1049"]}
|
||||
{"action":"add","devpath":"/devices/system/machinecheck/machinecheck0","env":["ACTION=add","DEVPATH=/devices/system/machinecheck/machinecheck0","SUBSYSTEM=machinecheck","SEQNUM=1050"]}
|
||||
{"action":"online","devpath":"/devices/system/cpu/cpu0","env":["ACTION=online","DEVPATH=/devices/system/cpu/cpu0","SUBSYSTEM=cpu","DRIVER=processor","MODALIAS=cpu:type:x86,ven0002fam000Fmod006B:feature:,0000,0002,0003,0004,0005,0006,0007,0008,0009,000B,000C,000D,000E,000F,0010,0011,0013,0017,0018,0019,001A,001C,0020,0022,0023,0024,0025,0026,0027,0028,0029,002B,002C,002D,002E,002F,0030,0031,0034,0037,0038,003D,0064,006E,0070,0074,0075,0076,0079,007A,007F,0080,008D,0095,009F,00C0,00C1,00C8,00ED,00F3,010F,0115,0165,016C,0282\n","SEQNUM=1051"]}
|
||||
19
internal/kobject/testdata/03-loop
vendored
19
internal/kobject/testdata/03-loop
vendored
@@ -1,19 +0,0 @@
|
||||
{"action":"add","devpath":"/devices/virtual/misc/loop-control","env":["ACTION=add","DEVPATH=/devices/virtual/misc/loop-control","SUBSYSTEM=misc","MAJOR=10","MINOR=237","DEVNAME=loop-control","SEQNUM=1052"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:0","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:0","SUBSYSTEM=bdi","SEQNUM=1053"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop0","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop0","SUBSYSTEM=block","MAJOR=7","MINOR=0","DEVNAME=loop0","DEVTYPE=disk","DISKSEQ=2","SEQNUM=1054"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:1","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:1","SUBSYSTEM=bdi","SEQNUM=1055"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop1","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop1","SUBSYSTEM=block","MAJOR=7","MINOR=1","DEVNAME=loop1","DEVTYPE=disk","DISKSEQ=3","SEQNUM=1056"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:2","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:2","SUBSYSTEM=bdi","SEQNUM=1057"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop2","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop2","SUBSYSTEM=block","MAJOR=7","MINOR=2","DEVNAME=loop2","DEVTYPE=disk","DISKSEQ=4","SEQNUM=1058"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:3","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:3","SUBSYSTEM=bdi","SEQNUM=1059"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop3","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop3","SUBSYSTEM=block","MAJOR=7","MINOR=3","DEVNAME=loop3","DEVTYPE=disk","DISKSEQ=5","SEQNUM=1060"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:4","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:4","SUBSYSTEM=bdi","SEQNUM=1061"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop4","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop4","SUBSYSTEM=block","MAJOR=7","MINOR=4","DEVNAME=loop4","DEVTYPE=disk","DISKSEQ=6","SEQNUM=1062"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:5","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:5","SUBSYSTEM=bdi","SEQNUM=1063"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop5","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop5","SUBSYSTEM=block","MAJOR=7","MINOR=5","DEVNAME=loop5","DEVTYPE=disk","DISKSEQ=7","SEQNUM=1064"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:6","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:6","SUBSYSTEM=bdi","SEQNUM=1065"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop6","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop6","SUBSYSTEM=block","MAJOR=7","MINOR=6","DEVNAME=loop6","DEVTYPE=disk","DISKSEQ=8","SEQNUM=1066"]}
|
||||
{"action":"add","devpath":"/devices/virtual/bdi/7:7","env":["ACTION=add","DEVPATH=/devices/virtual/bdi/7:7","SUBSYSTEM=bdi","SEQNUM=1067"]}
|
||||
{"action":"add","devpath":"/devices/virtual/block/loop7","env":["ACTION=add","DEVPATH=/devices/virtual/block/loop7","SUBSYSTEM=block","MAJOR=7","MINOR=7","DEVNAME=loop7","DEVTYPE=disk","DISKSEQ=9","SEQNUM=1068"]}
|
||||
{"action":"add","devpath":"/module/loop","env":["ACTION=add","DEVPATH=/module/loop","SUBSYSTEM=module","SEQNUM=1069"]}
|
||||
{"action":"change","devpath":"/devices/virtual/block/loop0","env":["ACTION=change","DEVPATH=/devices/virtual/block/loop0","SUBSYSTEM=block","MAJOR=7","MINOR=0","DEVNAME=loop0","DEVTYPE=disk","DISKSEQ=10","SEQNUM=1070"]}
|
||||
2
internal/kobject/testdata/04-loop-detach
vendored
2
internal/kobject/testdata/04-loop-detach
vendored
@@ -1,2 +0,0 @@
|
||||
{"action":"change","devpath":"/devices/virtual/block/loop0","env":["ACTION=change","DEVPATH=/devices/virtual/block/loop0","SUBSYSTEM=block","MAJOR=7","MINOR=0","DEVNAME=loop0","DEVTYPE=disk","DISKSEQ=10","SEQNUM=1071"]}
|
||||
{"action":"change","devpath":"/devices/virtual/block/loop0","env":["ACTION=change","DEVPATH=/devices/virtual/block/loop0","SUBSYSTEM=block","DISK_MEDIA_CHANGE=1","MAJOR=7","MINOR=0","DEVNAME=loop0","DEVTYPE=disk","DISKSEQ=10","SEQNUM=1072"]}
|
||||
18
internal/kobject/testdata/05-loop-remove
vendored
18
internal/kobject/testdata/05-loop-remove
vendored
@@ -1,18 +0,0 @@
|
||||
{"action":"remove","devpath":"/devices/virtual/misc/loop-control","env":["ACTION=remove","DEVPATH=/devices/virtual/misc/loop-control","SUBSYSTEM=misc","MAJOR=10","MINOR=237","DEVNAME=loop-control","SEQNUM=1073"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:0","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:0","SUBSYSTEM=bdi","SEQNUM=1074"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop0","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop0","SUBSYSTEM=block","MAJOR=7","MINOR=0","DEVNAME=loop0","DEVTYPE=disk","DISKSEQ=11","SEQNUM=1075"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:1","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:1","SUBSYSTEM=bdi","SEQNUM=1076"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop1","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop1","SUBSYSTEM=block","MAJOR=7","MINOR=1","DEVNAME=loop1","DEVTYPE=disk","DISKSEQ=3","SEQNUM=1077"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:2","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:2","SUBSYSTEM=bdi","SEQNUM=1078"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop2","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop2","SUBSYSTEM=block","MAJOR=7","MINOR=2","DEVNAME=loop2","DEVTYPE=disk","DISKSEQ=4","SEQNUM=1079"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:3","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:3","SUBSYSTEM=bdi","SEQNUM=1080"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop3","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop3","SUBSYSTEM=block","MAJOR=7","MINOR=3","DEVNAME=loop3","DEVTYPE=disk","DISKSEQ=5","SEQNUM=1081"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:4","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:4","SUBSYSTEM=bdi","SEQNUM=1082"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop4","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop4","SUBSYSTEM=block","MAJOR=7","MINOR=4","DEVNAME=loop4","DEVTYPE=disk","DISKSEQ=6","SEQNUM=1083"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:5","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:5","SUBSYSTEM=bdi","SEQNUM=1084"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop5","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop5","SUBSYSTEM=block","MAJOR=7","MINOR=5","DEVNAME=loop5","DEVTYPE=disk","DISKSEQ=7","SEQNUM=1085"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:6","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:6","SUBSYSTEM=bdi","SEQNUM=1086"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop6","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop6","SUBSYSTEM=block","MAJOR=7","MINOR=6","DEVNAME=loop6","DEVTYPE=disk","DISKSEQ=8","SEQNUM=1087"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/bdi/7:7","env":["ACTION=remove","DEVPATH=/devices/virtual/bdi/7:7","SUBSYSTEM=bdi","SEQNUM=1088"]}
|
||||
{"action":"remove","devpath":"/devices/virtual/block/loop7","env":["ACTION=remove","DEVPATH=/devices/virtual/block/loop7","SUBSYSTEM=block","MAJOR=7","MINOR=7","DEVNAME=loop7","DEVTYPE=disk","DISKSEQ=9","SEQNUM=1089"]}
|
||||
{"action":"remove","devpath":"/module/loop","env":["ACTION=remove","DEVPATH=/module/loop","SUBSYSTEM=module","SEQNUM=1090"]}
|
||||
@@ -183,10 +183,10 @@ func TestExec(t *testing.T) {
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/IY91PCtOpCYy21AaIK0c9f8-Z6fb2_2ewoHWkt4dxoLf0GOrWqS8yAGFLV84b1Dw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/QwS7SmiatdqryQYgESdGw7Yw2PcpNf0vNfpvUA0t92BTlKiUjfCrXyMW17G2X77X": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/" + expected.Offline: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/" + expected.OfflineS: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"substitute": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package expected
|
||||
|
||||
const (
|
||||
Offline = "q5ktDTq0miP-VvB2blxqXQeaRXCUWgP_KbC18KNtUDtyoaI_h5mHmGuPMArVEBDs"
|
||||
OfflineS = "IY91PCtOpCYy21AaIK0c9f8-Z6fb2_2ewoHWkt4dxoLf0GOrWqS8yAGFLV84b1Dw"
|
||||
OvlRoot = "NacZGXwuRkTvcHaG08a22ujJ8qCWN0RSoFlRSR5FSt0ZcBbJ28FRvkYsHEtX7G8i"
|
||||
Layers = "WBJDrATtX6rIE5yAu8ePX3WmDF0Tt9kFiue0m3cRnyRoVx1my8a67fh3CAW486oP"
|
||||
Net = "CmYtj2sNB3LHtqiDuck_Lz3MjLLIiwyP8N4NDitQ1Icvv__LVP9p8tm-sHeQaKKp"
|
||||
Promote = "TX3eCloaQFkV-SZIH6Jg6E5WKH--rcXY1P0jnZKmLFKWrNqnOzd4G9eIBh6i5ywN"
|
||||
Work = "OuNiLSC68pZhAOr1YQ4WbV1tzASA0nxLEBcK7lO7MqxDY_j8dmP_C612RTuF23Lu"
|
||||
Offline = "q5ktDTq0miP-VvB2blxqXQeaRXCUWgP_KbC18KNtUDtyoaI_h5mHmGuPMArVEBDs"
|
||||
OvlRoot = "NacZGXwuRkTvcHaG08a22ujJ8qCWN0RSoFlRSR5FSt0ZcBbJ28FRvkYsHEtX7G8i"
|
||||
Layers = "WBJDrATtX6rIE5yAu8ePX3WmDF0Tt9kFiue0m3cRnyRoVx1my8a67fh3CAW486oP"
|
||||
Net = "CmYtj2sNB3LHtqiDuck_Lz3MjLLIiwyP8N4NDitQ1Icvv__LVP9p8tm-sHeQaKKp"
|
||||
Promote = "TX3eCloaQFkV-SZIH6Jg6E5WKH--rcXY1P0jnZKmLFKWrNqnOzd4G9eIBh6i5ywN"
|
||||
Work = "OuNiLSC68pZhAOr1YQ4WbV1tzASA0nxLEBcK7lO7MqxDY_j8dmP_C612RTuF23Lu"
|
||||
)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package expected
|
||||
|
||||
const (
|
||||
Offline = "WapqyoPxbWSnq07dWHt71mHaJXq99pAjJfFlELlJljSiZMhTFqqlzU1_mN86shSj"
|
||||
OfflineS = "ibQZHcdXgNQ1OiMX1FrburBbGPVvKEHvPilbQCkm_0oV0BQCHomyyTbYNrFMGIwl"
|
||||
OvlRoot = "V9anFOiRvjGfAeBhLl14AL8TKdWZyD0WTPYe4fS9mOBw8iW5Lmarvt6TG6MV8uWm"
|
||||
Layers = "tKx7JNRoSBdK_7MdzI-nwTNV2wmiPzwYdcd17oLmXKL_iLmUzUiA79qTqdrTasrv"
|
||||
Net = "aXyDLzBCJ9XltXZIfetEVsEkrqHfcXuD5XE_FcUnYbN3emwL55N6P8LlHzNfGnM5"
|
||||
Promote = "3k4V16n96Lq04gjFSKmm4sFjyQ883FFBNXgTy9s_DjeTwxT3pg_iacEh8yMb_S4m"
|
||||
Work = "6Q49MhFWRE3Ne6MycwAotgl1GtoU5WCHqJNWG2byYZCY-zX-IxPrWiKk7bKkNzhE"
|
||||
Offline = "WapqyoPxbWSnq07dWHt71mHaJXq99pAjJfFlELlJljSiZMhTFqqlzU1_mN86shSj"
|
||||
OvlRoot = "V9anFOiRvjGfAeBhLl14AL8TKdWZyD0WTPYe4fS9mOBw8iW5Lmarvt6TG6MV8uWm"
|
||||
Layers = "tKx7JNRoSBdK_7MdzI-nwTNV2wmiPzwYdcd17oLmXKL_iLmUzUiA79qTqdrTasrv"
|
||||
Net = "aXyDLzBCJ9XltXZIfetEVsEkrqHfcXuD5XE_FcUnYbN3emwL55N6P8LlHzNfGnM5"
|
||||
Promote = "3k4V16n96Lq04gjFSKmm4sFjyQ883FFBNXgTy9s_DjeTwxT3pg_iacEh8yMb_S4m"
|
||||
Work = "6Q49MhFWRE3Ne6MycwAotgl1GtoU5WCHqJNWG2byYZCY-zX-IxPrWiKk7bKkNzhE"
|
||||
)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package expected
|
||||
|
||||
const (
|
||||
Offline = "Z6yXE5gOJScL3srmnVMWgCXccDiUNZ5snSrf6RkXuU1_U0rX_kGVwsfHUgNG_awd"
|
||||
OfflineS = "zN16xv6LKRJRipUJwupyxg2rZcvf-qpsMn_qCxUmgxlTSuNwYI70ZEb7dHW5k0gO"
|
||||
OvlRoot = "zYXJHFRLuxvUhuisZEXgGgVvdQd6piMfp5jmtT6jdVjvC2gICXquOq-UTwlrSD5I"
|
||||
Layers = "_F8EDazHbcLeT0sVSQXRN_kn9IjduqJcDYgzXpsT-hpKU4EBcZ0PISN2zchpqMbm"
|
||||
Net = "CA_FAaSIYJgapBEHV40doxpH23PdUEy_6s1TZc7wfSPN0XYqwGpMceXXDSabGveO"
|
||||
Promote = "_3LPrLp--4h9k4GsNNApu9hHtAafq-GUhfU6d4hJKBDKT3bz_szOsvkXxc5sK53d"
|
||||
Work = "FEgHeiCD_WT4wsfB-9kDH5n6cRWCEYtJmXdKZgmUUukAOoXumH_hLlosXREC-tqq"
|
||||
Offline = "Z6yXE5gOJScL3srmnVMWgCXccDiUNZ5snSrf6RkXuU1_U0rX_kGVwsfHUgNG_awd"
|
||||
OvlRoot = "zYXJHFRLuxvUhuisZEXgGgVvdQd6piMfp5jmtT6jdVjvC2gICXquOq-UTwlrSD5I"
|
||||
Layers = "_F8EDazHbcLeT0sVSQXRN_kn9IjduqJcDYgzXpsT-hpKU4EBcZ0PISN2zchpqMbm"
|
||||
Net = "CA_FAaSIYJgapBEHV40doxpH23PdUEy_6s1TZc7wfSPN0XYqwGpMceXXDSabGveO"
|
||||
Promote = "_3LPrLp--4h9k4GsNNApu9hHtAafq-GUhfU6d4hJKBDKT3bz_szOsvkXxc5sK53d"
|
||||
Work = "FEgHeiCD_WT4wsfB-9kDH5n6cRWCEYtJmXdKZgmUUukAOoXumH_hLlosXREC-tqq"
|
||||
)
|
||||
|
||||
@@ -155,7 +155,7 @@ type TContext struct {
|
||||
// Target [Artifact] encoded identifier.
|
||||
ids string
|
||||
// Pathname status was created at.
|
||||
statusPath, statusSPath *check.Absolute
|
||||
statusPath *check.Absolute
|
||||
// File statusHeader and logs are written to.
|
||||
status *os.File
|
||||
// Error value during prepareStatus.
|
||||
@@ -258,11 +258,6 @@ func (t *TContext) destroy(errP *error) {
|
||||
), 10),
|
||||
).String(),
|
||||
))
|
||||
if t.statusSPath != nil {
|
||||
t.cache.checksumMu.Lock()
|
||||
*errP = errors.Join(*errP, os.Remove(t.statusSPath.String()))
|
||||
t.cache.checksumMu.Unlock()
|
||||
}
|
||||
}
|
||||
t.status = nil
|
||||
}
|
||||
@@ -1928,9 +1923,6 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
}
|
||||
c.exitCure(a, curesExempt)
|
||||
if err != nil {
|
||||
if c.msg.IsVerbose() {
|
||||
c.msg.Verbosef("cure file %s: %v", reportName(f, id), err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1962,7 +1954,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
t := TContext{
|
||||
c.base.Append(dirWork, ids),
|
||||
c.base.Append(dirTemp, ids),
|
||||
ids, nil, nil, nil, nil,
|
||||
ids, nil, nil, nil,
|
||||
common{ctx, c},
|
||||
}
|
||||
switch ca := a.(type) {
|
||||
@@ -1974,9 +1966,6 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
err = ca.Cure(&t)
|
||||
c.exitCure(a, curesExempt)
|
||||
if err != nil {
|
||||
if c.msg.IsVerbose() {
|
||||
c.msg.Verbosef("cure trivial %s: %v", reportName(ca, id), err)
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
@@ -2054,25 +2043,16 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
}
|
||||
err = ca.Cure(&f)
|
||||
if err == nil && f.status != nil {
|
||||
statusS := c.base.Append(
|
||||
dirStatus,
|
||||
substitutes,
|
||||
)
|
||||
c.checksumMu.Lock()
|
||||
err = os.Link(c.base.Append(
|
||||
dirStatus,
|
||||
ids,
|
||||
).String(), statusS.String())
|
||||
c.checksumMu.Unlock()
|
||||
if err == nil {
|
||||
f.statusSPath = statusS
|
||||
}
|
||||
).String(), c.base.Append(
|
||||
dirStatus,
|
||||
substitutes,
|
||||
).String())
|
||||
}
|
||||
c.exitCure(a, curesExempt)
|
||||
if err != nil {
|
||||
if c.msg.IsVerbose() {
|
||||
c.msg.Verbosef("cure %s: %v", reportName(ca, id), err)
|
||||
}
|
||||
return
|
||||
}
|
||||
break
|
||||
@@ -2121,9 +2101,6 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
Got: gotChecksum,
|
||||
Want: checksum.Value(),
|
||||
}
|
||||
if c.msg.IsVerbose() {
|
||||
c.msg.Verbosef("validate %s: %v", reportName(a, id), err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
package report
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"hakurei.app/check"
|
||||
)
|
||||
|
||||
const (
|
||||
// Trivial denotes an error that may happen frequently under normal operation.
|
||||
Trivial = iota
|
||||
// Inconsistent denotes an error diagnosed due to inconsistent state.
|
||||
Inconsistent
|
||||
// Degraded denotes an error condition causing a degraded state.
|
||||
Degraded
|
||||
// Fatal denotes an unrecoverable error. This is generally followed by
|
||||
// notifying the user and suggesting immediate restart, or an automatic
|
||||
// restart of a nonessential daemon process.
|
||||
Fatal
|
||||
)
|
||||
|
||||
// A Reporter represents an error reporting object backed by user-facing display
|
||||
// and optional persistent storage. A Reporter can be used simultaneously from
|
||||
// multiple goroutines.
|
||||
type Reporter struct {
|
||||
// Backing logger, the zero value implies the return value of [log.Default].
|
||||
log atomic.Pointer[log.Logger]
|
||||
// Backing persistent storage.
|
||||
pathname atomic.Pointer[check.Absolute]
|
||||
// Reporting behaviour.
|
||||
flag atomic.Uint64
|
||||
|
||||
// Caller-supplied reporting functions.
|
||||
notify []func(e Error)
|
||||
// Synchronises access to notify.
|
||||
notifyMu sync.RWMutex
|
||||
|
||||
// Synchronises access to persistent storage.
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// SetOutput sets the backing [log.Logger].
|
||||
func (r *Reporter) SetOutput(l *log.Logger) { r.log.Store(l) }
|
||||
|
||||
// SetPathname sets the pathname to persistent storage.
|
||||
func (r *Reporter) SetPathname(a *check.Absolute) { r.pathname.Store(a) }
|
||||
|
||||
const (
|
||||
// DStrict causes all dispatches to end in a call to panic.
|
||||
DStrict = 1 << iota
|
||||
// DNoRecover disallows recovering from error write to persistent storage.
|
||||
DNoRecover
|
||||
// DBypassEarly allows persistent storage to be skipped before it is ready.
|
||||
DBypassEarly
|
||||
)
|
||||
|
||||
// SetFlags sets flags for r.
|
||||
func (r *Reporter) SetFlags(flag uint64) { r.flag.Store(flag) }
|
||||
|
||||
// An Error represents an error reported via [Reporter.Dispatch].
|
||||
type Error struct {
|
||||
// Nature of error.
|
||||
Severity int
|
||||
// User-facing reporting message.
|
||||
Message string
|
||||
// Underlying error.
|
||||
Err error
|
||||
}
|
||||
|
||||
// RepresentableError is implemented by errors friendly to JSON serialisation.
|
||||
type RepresentableError interface {
|
||||
error
|
||||
Representable()
|
||||
}
|
||||
|
||||
// MarshalJSON returns an incomplete JSON representation of e.
|
||||
func (e Error) MarshalJSON() (data []byte, err error) {
|
||||
v := struct {
|
||||
Severity any `json:"kind"`
|
||||
Message string `json:"message"`
|
||||
Err json.RawMessage `json:"error"`
|
||||
}{Message: e.Message}
|
||||
|
||||
switch e.Severity {
|
||||
case Trivial:
|
||||
v.Severity = "trivial"
|
||||
case Inconsistent:
|
||||
v.Severity = "inconsistent"
|
||||
case Degraded:
|
||||
v.Severity = "degradation"
|
||||
case Fatal:
|
||||
v.Severity = "fatal"
|
||||
default:
|
||||
v.Severity = e.Severity
|
||||
}
|
||||
|
||||
var re RepresentableError
|
||||
if errors.As(e.Err, &re) {
|
||||
v.Err, err = json.Marshal(re)
|
||||
} else {
|
||||
v.Err, err = json.Marshal(e.Err.Error())
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return json.Marshal(&v)
|
||||
}
|
||||
|
||||
// Error is generally only called during a [Reporter.Dispatch] call ending in
|
||||
// a panic or an otherwise unrecoverable condition.
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprintf("%s: %v", e.Message, e.Err)
|
||||
}
|
||||
|
||||
// Notify arranges for f to be called for all future dispatched errors.
|
||||
func (r *Reporter) Notify(f func(Error)) {
|
||||
r.notifyMu.Lock()
|
||||
r.notify = append(r.notify, f)
|
||||
r.notifyMu.Unlock()
|
||||
}
|
||||
|
||||
// getLog returns the address of the underlying [log.Logger], or the return
|
||||
// value of [log.Default].
|
||||
func (r *Reporter) getLog() *log.Logger {
|
||||
l := r.log.Load()
|
||||
if l == nil {
|
||||
l = log.Default()
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// dispatch implements Dispatch but returns the reporting error.
|
||||
func (r *Reporter) dispatch(severity int, message string, e error) (err error) {
|
||||
p := Error{severity, message, e}
|
||||
r.getLog().Println(message+":", e)
|
||||
|
||||
flag := r.flag.Load()
|
||||
defer func() {
|
||||
if flag&DNoRecover != 0 && err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if a := r.pathname.Load(); a != nil {
|
||||
var w *os.File
|
||||
r.mu.Lock()
|
||||
w, err = os.OpenFile(
|
||||
a.Append(strconv.FormatUint(uint64(time.Now().UnixNano()), 10)).String(),
|
||||
os.O_CREATE|os.O_EXCL|os.O_WRONLY,
|
||||
0400,
|
||||
)
|
||||
if err != nil {
|
||||
r.mu.Unlock()
|
||||
return
|
||||
}
|
||||
err = json.NewEncoder(w).Encode(p)
|
||||
if _err := w.Close(); err == nil {
|
||||
err = _err
|
||||
}
|
||||
r.mu.Unlock()
|
||||
} else if flag&DBypassEarly == 0 && severity != Trivial {
|
||||
panic(p)
|
||||
}
|
||||
|
||||
if flag&DStrict != 0 && severity != Trivial {
|
||||
panic(p)
|
||||
}
|
||||
|
||||
r.notifyMu.RLock()
|
||||
defer r.notifyMu.RUnlock()
|
||||
for _, f := range r.notify {
|
||||
f(p)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Dispatch reports an error and saves it to backing storage if available.
|
||||
func (r *Reporter) Dispatch(severity int, message string, e error) {
|
||||
if err := r.dispatch(severity, message, e); err != nil {
|
||||
r.getLog().Println(err)
|
||||
}
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
package report_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"slices"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/internal/kobject"
|
||||
"hakurei.app/internal/report"
|
||||
"hakurei.app/internal/stub"
|
||||
"hakurei.app/internal/uevent"
|
||||
)
|
||||
|
||||
type representableUE struct{ stub.UniqueError }
|
||||
|
||||
func (representableUE) Representable() {}
|
||||
|
||||
func TestDispatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
flag uint64
|
||||
errs []report.Error
|
||||
|
||||
persist bool
|
||||
wantFiles []string
|
||||
wantLog string
|
||||
wantPanic error
|
||||
}{
|
||||
{"default", 0, []report.Error{
|
||||
{
|
||||
Severity: report.Fatal,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
},
|
||||
{
|
||||
Severity: report.Inconsistent,
|
||||
Message: "processed inconsistent uevent",
|
||||
Err: (&kobject.Event{
|
||||
Action: uevent.KOBJ_ADD,
|
||||
DevPath: "\x00",
|
||||
Env: map[string]string{"V": "\xfd"},
|
||||
Sequence: 2,
|
||||
}).NewError(kobject.EDuplicateAdd, &kobject.Object{
|
||||
State: kobject.StateNew,
|
||||
DevPath: "\x00",
|
||||
Env: map[string]string{"V": "\xff"},
|
||||
}),
|
||||
},
|
||||
}, true, []string{`{"kind":"fatal","message":"rejecting coldboot loop","error":"unique error 51966 injected by the test suite"}
|
||||
`, `{"kind":"inconsistent","message":"processed inconsistent uevent","error":{"fault":1,"event":{"action":"add","devpath":"\u0000","env":{"V":"\ufffd"},"seqnum":2,"subsystem":""},"object":{"state":1,"devpath":"\u0000","subsystem":"","env":{"V":"\ufffd"}}}}
|
||||
`}, `dispatch: rejecting coldboot loop: unique error 51966 injected by the test suite
|
||||
dispatch: processed inconsistent uevent: duplicate add event on devpath "\x00"
|
||||
`, nil},
|
||||
|
||||
{"strict", report.DStrict, []report.Error{
|
||||
{
|
||||
Severity: report.Degraded,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
},
|
||||
}, true, []string{
|
||||
`{"kind":"degradation","message":"rejecting coldboot loop","error":"unique error 51966 injected by the test suite"}
|
||||
`,
|
||||
}, "dispatch: rejecting coldboot loop: unique error 51966 injected by the test suite\n", report.Error{
|
||||
Severity: report.Degraded,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
}},
|
||||
|
||||
{"strict no recover", report.DStrict | report.DNoRecover, []report.Error{
|
||||
{
|
||||
Severity: report.Inconsistent,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
},
|
||||
}, true, []string{
|
||||
`{"kind":"inconsistent","message":"rejecting coldboot loop","error":"unique error 51966 injected by the test suite"}
|
||||
`,
|
||||
}, "dispatch: rejecting coldboot loop: unique error 51966 injected by the test suite\n", report.Error{
|
||||
Severity: report.Inconsistent,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
}},
|
||||
|
||||
{"no recover", report.DNoRecover, []report.Error{
|
||||
{
|
||||
Severity: 0xbeef,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: representableUE{stub.UniqueError(0xcafe)},
|
||||
},
|
||||
}, true, []string{
|
||||
`{"kind":48879,"message":"rejecting coldboot loop","error":{"UniqueError":51966}}
|
||||
`,
|
||||
}, "dispatch: rejecting coldboot loop: unique error 51966 injected by the test suite\n", nil},
|
||||
|
||||
{"early", 0, []report.Error{
|
||||
{
|
||||
Severity: report.Fatal,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
},
|
||||
}, false, nil, "dispatch: rejecting coldboot loop: unique error 51966 injected by the test suite\n", report.Error{
|
||||
Severity: report.Fatal,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
}},
|
||||
|
||||
{"bypass early", report.DBypassEarly, []report.Error{
|
||||
{
|
||||
Severity: report.Fatal,
|
||||
Message: "rejecting coldboot loop",
|
||||
Err: stub.UniqueError(0xcafe),
|
||||
},
|
||||
}, false, nil, "dispatch: rejecting coldboot loop: unique error 51966 injected by the test suite\n", nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var r report.Reporter
|
||||
r.SetFlags(tc.flag)
|
||||
var buf bytes.Buffer
|
||||
l := log.New(&buf, "dispatch: ", 0)
|
||||
r.SetOutput(l)
|
||||
|
||||
a := check.MustAbs(t.TempDir())
|
||||
if tc.persist {
|
||||
r.SetPathname(a)
|
||||
}
|
||||
|
||||
var got []report.Error
|
||||
r.Notify(func(p report.Error) { got = append(got, p) })
|
||||
|
||||
var gotPanic any
|
||||
func() {
|
||||
defer func() { gotPanic = recover() }()
|
||||
for _, p := range tc.errs {
|
||||
r.Dispatch(p.Severity, p.Message, p.Err)
|
||||
}
|
||||
}()
|
||||
|
||||
if gotPanic == nil && !reflect.DeepEqual(got, tc.errs) {
|
||||
t.Errorf("Dispatch: %#v, want %#v", got, tc.errs)
|
||||
}
|
||||
if !reflect.DeepEqual(gotPanic, tc.wantPanic) {
|
||||
t.Errorf("Dispatch: panic = %v, want %v", gotPanic, tc.wantPanic)
|
||||
}
|
||||
if gotLog := buf.String(); gotLog != tc.wantLog {
|
||||
t.Errorf("Dispatch: log =\n%s\nwant\n%s", gotLog, tc.wantLog)
|
||||
}
|
||||
|
||||
if tc.persist {
|
||||
var names []string
|
||||
if dents, err := os.ReadDir(a.String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
names = make([]string, len(dents))
|
||||
for i, dent := range dents {
|
||||
names[i] = dent.Name()
|
||||
}
|
||||
slices.Sort(names)
|
||||
}
|
||||
|
||||
gotFiles := make([]string, len(names))
|
||||
for i, name := range names {
|
||||
if p, err := os.ReadFile(a.Append(name).String()); err != nil {
|
||||
t.Fatal(err)
|
||||
} else {
|
||||
gotFiles[i] = unsafe.String(unsafe.SliceData(p), len(p))
|
||||
}
|
||||
}
|
||||
|
||||
if !slices.Equal(gotFiles, tc.wantFiles) {
|
||||
t.Errorf("Dispatch: persist = %s, want %s", gotFiles, tc.wantFiles)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadPersist(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var r report.Reporter
|
||||
r.SetFlags(report.DNoRecover)
|
||||
r.SetPathname(check.MustAbs("/proc/nonexistent"))
|
||||
|
||||
var pathError *os.PathError
|
||||
func() {
|
||||
defer func() {
|
||||
if !errors.As(recover().(error), &pathError) {
|
||||
t.Fatal("invalid panic kind")
|
||||
}
|
||||
}()
|
||||
r.Dispatch(report.Fatal, "\x00", stub.UniqueError(0xbad))
|
||||
}()
|
||||
if !errors.Is(pathError.Err, os.ErrNotExist) {
|
||||
t.Fatalf("Dispatch: panic = %v", pathError)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
l := log.New(&buf, "persist: ", 0)
|
||||
r.SetOutput(l)
|
||||
r.SetFlags(0)
|
||||
r.Dispatch(report.Fatal, "\x00", stub.UniqueError(0xbad))
|
||||
}
|
||||
110
internal/rosa/acl.go
Normal file
110
internal/rosa/acl.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newAttr() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.5.2"
|
||||
checksum = "YWEphrz6vg1sUMmHHVr1CRo53pFXRhq_pjN-AlG8UgwZK1y6m7zuDhxqJhD0SV0l"
|
||||
)
|
||||
return t.NewPackage("attr", version, newTar(
|
||||
"https://download.savannah.nongnu.org/releases/attr/"+
|
||||
"attr-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"libgen-basename", `From 8a80d895dfd779373363c3a4b62ecce5a549efb2 Mon Sep 17 00:00:00 2001
|
||||
From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
|
||||
Date: Sat, 30 Mar 2024 10:17:10 +0100
|
||||
Subject: tools/attr.c: Add missing libgen.h include for basename(3)
|
||||
|
||||
Fixes compilation issue with musl and modern C99 compilers.
|
||||
|
||||
See: https://bugs.gentoo.org/926294
|
||||
---
|
||||
tools/attr.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/tools/attr.c b/tools/attr.c
|
||||
index f12e4af..6a3c1e9 100644
|
||||
--- a/tools/attr.c
|
||||
+++ b/tools/attr.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
+#include <libgen.h>
|
||||
|
||||
#include <attr/attributes.h>
|
||||
|
||||
--
|
||||
cgit v1.1`},
|
||||
|
||||
{"musl-errno", `diff --git a/test/attr.test b/test/attr.test
|
||||
index 6ce2f9b..e9bde92 100644
|
||||
--- a/test/attr.test
|
||||
+++ b/test/attr.test
|
||||
@@ -11,7 +11,7 @@ Try various valid and invalid names
|
||||
|
||||
$ touch f
|
||||
$ setfattr -n user -v value f
|
||||
- > setfattr: f: Operation not supported
|
||||
+ > setfattr: f: Not supported
|
||||
|
||||
$ setfattr -n user. -v value f
|
||||
> setfattr: f: Invalid argument
|
||||
`},
|
||||
},
|
||||
|
||||
ScriptEarly: `
|
||||
ln -s ../../system/bin/perl /usr/bin
|
||||
`,
|
||||
}, (*MakeHelper)(nil),
|
||||
Perl,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newAttr,
|
||||
|
||||
Name: "attr",
|
||||
Description: "Commands for Manipulating Filesystem Extended Attributes",
|
||||
Website: "https://savannah.nongnu.org/projects/attr/",
|
||||
|
||||
ID: 137,
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newACL() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.3.2"
|
||||
checksum = "-fY5nwH4K8ZHBCRXrzLdguPkqjKI6WIiGu4dBtrZ1o0t6AIU73w8wwJz_UyjIS0P"
|
||||
)
|
||||
return t.NewPackage("acl", version, newTar(
|
||||
"https://download.savannah.nongnu.org/releases/acl/"+
|
||||
"acl-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, &MakeHelper{
|
||||
// makes assumptions about uid_map/gid_map
|
||||
SkipCheck: true,
|
||||
},
|
||||
Attr,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newACL,
|
||||
|
||||
Name: "acl",
|
||||
Description: "Commands for Manipulating POSIX Access Control Lists",
|
||||
Website: "https://savannah.nongnu.org/projects/acl/",
|
||||
|
||||
Dependencies: P{
|
||||
Attr,
|
||||
},
|
||||
|
||||
ID: 16,
|
||||
})
|
||||
}
|
||||
36
internal/rosa/argp-standalone.go
Normal file
36
internal/rosa/argp-standalone.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newArgpStandalone() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.3"
|
||||
checksum = "vtW0VyO2pJ-hPyYmDI2zwSLS8QL0sPAUKC1t3zNYbwN2TmsaE-fADhaVtNd3eNFl"
|
||||
)
|
||||
return t.NewPackage("argp-standalone", version, newTar(
|
||||
"http://www.lysator.liu.se/~nisse/misc/"+
|
||||
"argp-standalone-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"CC=cc -std=gnu89 -fPIC",
|
||||
},
|
||||
}, &MakeHelper{
|
||||
Install: `
|
||||
install -D -m644 /usr/src/argp-standalone/argp.h /work/system/include/argp.h
|
||||
install -D -m755 libargp.a /work/system/lib/libargp.a
|
||||
`,
|
||||
},
|
||||
Diffutils,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newArgpStandalone,
|
||||
|
||||
Name: "argp-standalone",
|
||||
Description: "hierarchical argument parsing library broken out from glibc",
|
||||
Website: "http://www.lysator.liu.se/~nisse/misc/",
|
||||
})
|
||||
}
|
||||
@@ -209,7 +209,7 @@ func (p *parser) parseExpr() any {
|
||||
case '=':
|
||||
break
|
||||
|
||||
case '#':
|
||||
case '*':
|
||||
arg.R = true
|
||||
p.scanAs('=')
|
||||
|
||||
|
||||
@@ -5,13 +5,12 @@ import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"reflect"
|
||||
"slices"
|
||||
"unique"
|
||||
)
|
||||
|
||||
// Value are types supported by the language.
|
||||
type Value interface {
|
||||
bool | int64 | string | []string | []int64 | [][2]string
|
||||
bool | int64 | string | []string | [][2]string
|
||||
}
|
||||
|
||||
type (
|
||||
@@ -24,12 +23,9 @@ type (
|
||||
// FArgs are arguments passed to [F].
|
||||
FArgs []FArg
|
||||
|
||||
// PF implements the package declaration function.
|
||||
PF func(name Ident, args FArgs) (v any, set bool, err error)
|
||||
|
||||
// F is the implementation of a [Func].
|
||||
F struct {
|
||||
F func(args FArgs) (v any, set bool, err error)
|
||||
F func(isPackage bool, args FArgs) (v any, set bool, err error)
|
||||
V map[unique.Handle[Ident]]any
|
||||
}
|
||||
)
|
||||
@@ -81,20 +77,8 @@ func (e UndefinedError) Error() string {
|
||||
}
|
||||
|
||||
// evaluate is evaluateAny with a type parameter.
|
||||
func evaluate[T Value](d PF, s []Frame, expr any, rp *T) bool {
|
||||
return evaluateAny(d, s, expr, rp)
|
||||
}
|
||||
|
||||
// evaluateArray evaluates expr and returns its values as a slice.
|
||||
func evaluateArray[T Value](d PF, s []Frame, expr Array) []T {
|
||||
r := make([]T, 0, len(expr))
|
||||
for i := range expr {
|
||||
var _r T
|
||||
if evaluate(d, s, expr[i], &_r) {
|
||||
r = append(r, _r)
|
||||
}
|
||||
}
|
||||
return r
|
||||
func evaluate[T Value](s []Frame, expr any, rp *T) bool {
|
||||
return evaluateAny(s, expr, rp)
|
||||
}
|
||||
|
||||
// TypeError is an unexpected type during evaluation.
|
||||
@@ -103,7 +87,7 @@ type TypeError struct {
|
||||
}
|
||||
|
||||
func (e TypeError) Error() string {
|
||||
return fmt.Sprintf("expected %s, got %s", e.Asserted, e.Concrete)
|
||||
return "expected " + e.Asserted.String() + ", got " + e.Concrete.String()
|
||||
}
|
||||
|
||||
func (e TypeError) Is(err error) bool {
|
||||
@@ -148,25 +132,8 @@ func (e EvaluationError) Error() string {
|
||||
return fmt.Sprintf("expression %#v: %v", e.Expr, e.Err)
|
||||
}
|
||||
|
||||
var (
|
||||
// IdentInputs is a special array argument in a package declaration whose
|
||||
// values of [Ident] are kept as is when passed to a [PF].
|
||||
IdentInputs = unique.Make(Ident("inputs"))
|
||||
// IdentRuntime has the same semantics as [IdentInputs].
|
||||
IdentRuntime = unique.Make(Ident("runtime"))
|
||||
// IdentExtra has the same semantics as [IdentInputs].
|
||||
IdentExtra = unique.Make(Ident("extra"))
|
||||
// IdentSource is a special argument in a package declaration where an
|
||||
// assignment of a [Val] with a single [Ident] passes through the evaluator.
|
||||
IdentSource = unique.Make(Ident("source"))
|
||||
|
||||
// ErrInvalidSpecial is panicked for a special [PF] argument sharing its
|
||||
// value or set for R.
|
||||
ErrInvalidSpecial = errors.New("special must not be common or bound to scope")
|
||||
)
|
||||
|
||||
// evaluateAny implements [Evaluate].
|
||||
func evaluateAny(d PF, s []Frame, expr, rp any) bool {
|
||||
func evaluateAny(s []Frame, expr, rp any) bool {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
@@ -226,17 +193,17 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
|
||||
store(rp, false)
|
||||
return true
|
||||
default:
|
||||
return evaluateAny(d, s, v, rp)
|
||||
return evaluateAny(s, v, rp)
|
||||
}
|
||||
|
||||
default:
|
||||
return evaluateAny(d, s, e[0], rp)
|
||||
return evaluateAny(s, e[0], rp)
|
||||
}
|
||||
}
|
||||
var v string
|
||||
for i := range e {
|
||||
var _r string
|
||||
if evaluate(d, s, e[i], &_r) {
|
||||
if evaluate(s, e[i], &_r) {
|
||||
v += _r
|
||||
}
|
||||
}
|
||||
@@ -244,20 +211,21 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
|
||||
return true
|
||||
|
||||
case Array:
|
||||
if len(e) > 0 && len(e[0]) == 1 {
|
||||
if _, ok := e[0][0].(Int); ok {
|
||||
store(rp, evaluateArray[int64](d, s, e))
|
||||
return true
|
||||
r := make([]string, 0, len(e))
|
||||
for i := range e {
|
||||
var _r string
|
||||
if evaluate(s, e[i], &_r) {
|
||||
r = append(r, _r)
|
||||
}
|
||||
}
|
||||
store(rp, evaluateArray[string](d, s, e))
|
||||
store(rp, r)
|
||||
return true
|
||||
|
||||
case []KV:
|
||||
r := make([][2]string, 0, len(e))
|
||||
for i := range e {
|
||||
var _r string
|
||||
if e[i].V == nil || evaluate(d, s, e[i].V, &_r) {
|
||||
if e[i].V == nil || evaluate(s, e[i].V, &_r) {
|
||||
r = append(r, [2]string{string(e[i].K), _r})
|
||||
}
|
||||
}
|
||||
@@ -269,96 +237,44 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
|
||||
f F
|
||||
ok bool
|
||||
)
|
||||
if !e.Package {
|
||||
for i := range s {
|
||||
f, ok = s[len(s)-1-i].Func[unique.Make(e.Ident)]
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
panic(UndefinedError(e.Ident))
|
||||
for i := range s {
|
||||
f, ok = s[len(s)-1-i].Func[unique.Make(e.Ident)]
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
panic(UndefinedError(e.Ident))
|
||||
}
|
||||
|
||||
argc := len(e.Args)
|
||||
for _, arg := range e.Args {
|
||||
argc += len(arg.K) - 1
|
||||
}
|
||||
fargs := make([]FArg, 0, len(e.Args))
|
||||
s = append(s, Frame{})
|
||||
s = append(s, Frame{Val: maps.Clone(f.V)})
|
||||
fp := &s[len(s)-1]
|
||||
if !e.Package {
|
||||
fp.Val = maps.Clone(f.V)
|
||||
}
|
||||
|
||||
args:
|
||||
for _, arg := range e.Args {
|
||||
names := make([]unique.Handle[Ident], len(arg.K))
|
||||
for i, name := range arg.K {
|
||||
names[i] = unique.Make(name)
|
||||
}
|
||||
|
||||
farg := FArg{R: arg.R}
|
||||
if e.Package {
|
||||
for _, special := range [...]unique.Handle[Ident]{
|
||||
IdentInputs,
|
||||
IdentRuntime,
|
||||
IdentExtra,
|
||||
} {
|
||||
if slices.Contains(names, special) {
|
||||
if len(names) != 1 || len(arg.V) != 1 || arg.R {
|
||||
panic(ErrInvalidSpecial)
|
||||
}
|
||||
farg.K = names[0]
|
||||
if err := storeE(&farg.V, arg.V[0]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fargs = append(fargs, farg)
|
||||
continue args
|
||||
}
|
||||
}
|
||||
|
||||
if slices.Contains(names, IdentSource) {
|
||||
if len(names) != 1 || len(arg.V) != 1 || arg.R {
|
||||
panic(ErrInvalidSpecial)
|
||||
}
|
||||
if _, ok = arg.V[0].(Ident); ok {
|
||||
farg.K = names[0]
|
||||
if err := storeE(&farg.V, arg.V[0]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fargs = append(fargs, farg)
|
||||
continue args
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !evaluateAny(d, s, arg.V, &farg.V) {
|
||||
if !evaluateAny(s, arg.V, &farg.V) {
|
||||
farg.V = nil
|
||||
}
|
||||
for _, name := range names {
|
||||
farg.K = name
|
||||
for _, name := range arg.K {
|
||||
h := unique.Make(name)
|
||||
farg.K = h
|
||||
fargs = append(fargs, farg)
|
||||
|
||||
if arg.R && farg.V != nil {
|
||||
if fp.Val == nil {
|
||||
fp.Val = make(map[unique.Handle[Ident]]any)
|
||||
}
|
||||
(*fp).Val[name] = farg.V
|
||||
(*fp).Val[h] = farg.V
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
v any
|
||||
err error
|
||||
)
|
||||
if !e.Package {
|
||||
v, ok, err = f.F(fargs)
|
||||
} else {
|
||||
v, ok, err = d(e.Ident, fargs)
|
||||
}
|
||||
v, set, err := f.F(e.Package, fargs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
} else if v != nil {
|
||||
@@ -366,7 +282,7 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return ok
|
||||
return set
|
||||
|
||||
default:
|
||||
panic(UnsupportedExprError{expr})
|
||||
@@ -374,7 +290,7 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
|
||||
}
|
||||
|
||||
// Evaluate evaluates a statement and returns its value.
|
||||
func Evaluate[T any](d PF, s []Frame, expr any) (v T, set bool, err error) {
|
||||
func Evaluate[T Value](s []Frame, expr any) (v T, set bool, err error) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
@@ -387,6 +303,6 @@ func Evaluate[T any](d PF, s []Frame, expr any) (v T, set bool, err error) {
|
||||
}
|
||||
err = _err
|
||||
}()
|
||||
set = evaluateAny(d, s, expr, &v)
|
||||
set = evaluate[T](s, expr, &v)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -16,26 +16,19 @@ import (
|
||||
func makeStackCheck(check func(args FArgs) (any, error)) []Frame {
|
||||
return []Frame{{Func: map[unique.Handle[Ident]]F{
|
||||
unique.Make(Ident("f")): {F: func(
|
||||
isPackage bool,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
set = true
|
||||
v, err = check(args)
|
||||
if isPackage {
|
||||
err = errors.New("unexpected package")
|
||||
}
|
||||
return
|
||||
}},
|
||||
}}}
|
||||
}
|
||||
|
||||
// checkArgs is like makeStackCheck, but the resulting function asserts that its
|
||||
// args match the expected value.
|
||||
func checkArgs(want FArgs) []Frame {
|
||||
return makeStackCheck(func(args FArgs) (any, error) {
|
||||
if !reflect.DeepEqual(args, want) {
|
||||
return nil, fmt.Errorf("%#v, want %#v", args, want)
|
||||
}
|
||||
return "\xfd", nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestEvaluate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -43,7 +36,7 @@ func TestEvaluate(t *testing.T) {
|
||||
name string
|
||||
data string
|
||||
s []Frame
|
||||
want any
|
||||
want string
|
||||
err error
|
||||
}{
|
||||
{"apply unset", `f { v = unset; }`, makeStackCheck(func(
|
||||
@@ -85,7 +78,7 @@ func TestEvaluate(t *testing.T) {
|
||||
Err: UndefinedError("v"),
|
||||
}},
|
||||
|
||||
{"apply bound undefined", `f { _v# = "\x00"; v = _v; }`, makeStackCheck(func(
|
||||
{"apply bound undefined", `f { _v* = "\x00"; v = _v; }`, makeStackCheck(func(
|
||||
args FArgs,
|
||||
) (v any, err error) {
|
||||
v = "\xfd"
|
||||
@@ -108,78 +101,6 @@ func TestEvaluate(t *testing.T) {
|
||||
Expr: Ident("nil"),
|
||||
Err: UndefinedError("nil"),
|
||||
}},
|
||||
|
||||
{"common inputs", `package name { inputs, v = []; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{
|
||||
"inputs",
|
||||
"v",
|
||||
}, V: Val{Array(nil)}},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"bound inputs", `package name { inputs# = []; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"inputs"}, V: Val{Array(nil)}, R: true},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"bound runtime", `package name { runtime# = []; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"runtime"}, V: Val{Array(nil)}, R: true},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"concat inputs", `package name { inputs = ""+""; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"inputs"}, V: Val{String(""), String("")}},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"concat source", `package name { source = ""+""; }`, nil, "", EvaluationError{
|
||||
Expr: Func{
|
||||
Ident: Ident("name"),
|
||||
Package: true,
|
||||
|
||||
Args: []Arg{
|
||||
{K: []Ident{"source"}, V: Val{String(""), String("")}},
|
||||
},
|
||||
},
|
||||
Err: ErrInvalidSpecial,
|
||||
}},
|
||||
|
||||
{"source handle", `package name { source = name; }`, nil, FArgs{
|
||||
{K: unique.Make(Ident("source")), V: Ident("name")},
|
||||
}, nil},
|
||||
|
||||
{"integer array", `f { v = [ 0 ]; _v = [ 0, 9 ]; }`, checkArgs(FArgs{
|
||||
{K: unique.Make(Ident("v")), V: []int64{0}},
|
||||
{K: unique.Make(Ident("_v")), V: []int64{0, 9}},
|
||||
}), "\xfd", nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -193,23 +114,12 @@ func TestEvaluate(t *testing.T) {
|
||||
} else {
|
||||
expr = e[0].(Func)
|
||||
}
|
||||
const rPackage = "\xff\xff\xff\xff"
|
||||
r, set, err := Evaluate[string](func(
|
||||
name Ident,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
v = rPackage
|
||||
if !reflect.DeepEqual(args, tc.want) {
|
||||
err = fmt.Errorf("%#v, want %#v", args, tc.want)
|
||||
}
|
||||
set = true
|
||||
return
|
||||
}, tc.s, expr)
|
||||
r, set, err := Evaluate[string](tc.s, expr)
|
||||
if set != (err == nil) {
|
||||
t.Error("Evaluate: unexpected unset")
|
||||
}
|
||||
|
||||
if r != rPackage && r != tc.want {
|
||||
if r != tc.want {
|
||||
t.Errorf("Evaluate: %q, want %q", r, tc.want)
|
||||
}
|
||||
|
||||
@@ -237,19 +147,36 @@ func TestEvaluateGCC(t *testing.T) {
|
||||
}
|
||||
|
||||
var got [3]FArgs
|
||||
if r, set, err := Evaluate[string](func(
|
||||
name Ident,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
v = "\x00"
|
||||
set = true
|
||||
got[0] = args
|
||||
return
|
||||
}, []Frame{{
|
||||
if r, set, err := Evaluate[string]([]Frame{{
|
||||
Func: map[unique.Handle[Ident]]F{
|
||||
unique.Make(Ident("remoteTar")): {F: func(
|
||||
unique.Make(Ident("gcc")): {F: func(
|
||||
isPackage bool,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
v = "\x00"
|
||||
if !isPackage {
|
||||
err = errors.New("not a package")
|
||||
}
|
||||
set = true
|
||||
got[0] = args
|
||||
return
|
||||
}, V: map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("binutils")): "binutils",
|
||||
unique.Make(Ident("mpc")): "mpc",
|
||||
unique.Make(Ident("zlib")): "zlib",
|
||||
unique.Make(Ident("libucontext")): "libucontext",
|
||||
unique.Make(Ident("kernel-headers")): "kernel-headers",
|
||||
}},
|
||||
|
||||
unique.Make(Ident("remoteTar")): {F: func(
|
||||
isPackage bool,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
if isPackage {
|
||||
err = errors.New("unexpected package")
|
||||
return
|
||||
}
|
||||
|
||||
var url, checksum string
|
||||
var compress int
|
||||
if err = args.Apply(map[unique.Handle[Ident]]any{
|
||||
@@ -271,25 +198,37 @@ func TestEvaluateGCC(t *testing.T) {
|
||||
}},
|
||||
|
||||
unique.Make(Ident("make")): {F: func(
|
||||
isPackage bool,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
v = args
|
||||
if isPackage {
|
||||
err = errors.New("unexpected package")
|
||||
}
|
||||
set = true
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("arch")): {F: func(
|
||||
isPackage bool,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
set = false
|
||||
if isPackage {
|
||||
err = errors.New("unexpected package")
|
||||
}
|
||||
got[1] = args
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("noop")): {F: func(
|
||||
isPackage bool,
|
||||
args FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
set = false
|
||||
if isPackage {
|
||||
err = errors.New("unexpected package")
|
||||
}
|
||||
set = true
|
||||
got[2] = args
|
||||
return
|
||||
@@ -335,12 +274,12 @@ func TestEvaluateGCC(t *testing.T) {
|
||||
{K: unique.Make(Ident("skip-check")), V: true},
|
||||
}},
|
||||
|
||||
{K: unique.Make(Ident("inputs")), V: Array{
|
||||
{Ident("binutils")},
|
||||
{Ident("mpc")},
|
||||
{Ident("zlib")},
|
||||
{Ident("libucontext")},
|
||||
{Ident("kernel-headers")},
|
||||
{K: unique.Make(Ident("inputs")), V: []string{
|
||||
"binutils",
|
||||
"mpc",
|
||||
"zlib",
|
||||
"libucontext",
|
||||
"kernel-headers",
|
||||
}},
|
||||
},
|
||||
{
|
||||
@@ -365,7 +304,21 @@ func BenchmarkEvaluate(b *testing.B) {
|
||||
|
||||
s := []Frame{{
|
||||
Func: map[unique.Handle[Ident]]F{
|
||||
unique.Make(Ident("gcc")): {F: func(
|
||||
bool,
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}, V: map[unique.Handle[Ident]]any{
|
||||
unique.Make(Ident("binutils")): "binutils",
|
||||
unique.Make(Ident("mpc")): "mpc",
|
||||
unique.Make(Ident("zlib")): "zlib",
|
||||
unique.Make(Ident("libucontext")): "libucontext",
|
||||
unique.Make(Ident("kernel-headers")): "kernel-headers",
|
||||
}},
|
||||
|
||||
unique.Make(Ident("remoteTar")): {F: func(
|
||||
bool,
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
@@ -374,18 +327,21 @@ func BenchmarkEvaluate(b *testing.B) {
|
||||
}},
|
||||
|
||||
unique.Make(Ident("make")): {F: func(
|
||||
bool,
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("arch")): {F: func(
|
||||
bool,
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}},
|
||||
|
||||
unique.Make(Ident("noop")): {F: func(
|
||||
bool,
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
@@ -395,12 +351,7 @@ func BenchmarkEvaluate(b *testing.B) {
|
||||
},
|
||||
}}
|
||||
for b.Loop() {
|
||||
if _, _, err := Evaluate[string](func(
|
||||
Ident,
|
||||
FArgs,
|
||||
) (v any, set bool, err error) {
|
||||
return
|
||||
}, s, gcc); err != nil {
|
||||
if _, _, err := Evaluate[string](s, gcc); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
2
internal/rosa/azalea/testdata/gcc.az
vendored
2
internal/rosa/azalea/testdata/gcc.az
vendored
@@ -3,7 +3,7 @@ package gcc {
|
||||
website = "https://www.gnu.org/software/gcc";
|
||||
anitya = 6502;
|
||||
|
||||
version# = "16.1.0";
|
||||
version* = "16.1.0";
|
||||
source = remoteTar {
|
||||
url = "https://ftp.tsukuba.wide.ad.jp/software/gcc/releases/"+
|
||||
"gcc-"+version+"/gcc-"+version+".tar.gz";
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"path"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
const (
|
||||
// jobsE is expression for preferred job count set by [pkg].
|
||||
jobsE = `"$` + pkg.EnvJobs + `"`
|
||||
// jobsFlagE is expression for flag with preferred job count.
|
||||
jobsFlagE = `"-j$` + pkg.EnvJobs + `"`
|
||||
// jobsLE is expression for twice of preferred job count set by [pkg].
|
||||
jobsLE = `"$(expr ` + jobsE + ` '*' 2)"`
|
||||
// jobsLFlagE is expression for flag with double of preferred job count.
|
||||
jobsLFlagE = `"-j$(expr ` + jobsE + ` '*' 2)"`
|
||||
)
|
||||
|
||||
// newTar wraps [pkg.NewHTTPGetTar] with a simpler function signature.
|
||||
func newTar(url, checksum string, compression uint32) pkg.Artifact {
|
||||
return pkg.NewHTTPGetTar(nil, url, mustDecode(checksum), compression)
|
||||
}
|
||||
|
||||
// newFromCPAN is a helper for downloading release from CPAN.
|
||||
func newFromCPAN(author, name, version, checksum string) pkg.Artifact {
|
||||
return newTar(
|
||||
"https://cpan.metacpan.org/authors/id/"+
|
||||
author[:1]+"/"+author[:2]+"/"+author+"/"+
|
||||
name+"-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
)
|
||||
}
|
||||
|
||||
// newFromGitLab is a helper for downloading source from GitLab.
|
||||
func newFromGitLab(domain, suffix, ref, checksum string) pkg.Artifact {
|
||||
return newTar(
|
||||
"https://"+domain+"/"+suffix+"/-/archive/"+
|
||||
ref+"/"+path.Base(suffix)+"-"+
|
||||
strings.ReplaceAll(ref, "/", "-")+".tar.bz2",
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
)
|
||||
}
|
||||
|
||||
// newFromGitHub is a helper for downloading source from Microsoft Github.
|
||||
func newFromGitHub(suffix, tag, checksum string) pkg.Artifact {
|
||||
return newTar(
|
||||
"https://github.com/"+suffix+
|
||||
"/archive/refs/tags/"+tag+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
)
|
||||
}
|
||||
|
||||
// newFromGitHubRelease is a helper for downloading release tarball from
|
||||
// Microsoft Github.
|
||||
func newFromGitHubRelease(
|
||||
suffix, tag, name, checksum string,
|
||||
compression uint32,
|
||||
) pkg.Artifact {
|
||||
return newTar(
|
||||
"https://github.com/"+suffix+
|
||||
"/releases/download/"+tag+"/"+name,
|
||||
checksum,
|
||||
compression,
|
||||
)
|
||||
}
|
||||
|
||||
// skipGNUTests generates a string for skipping specific tests by number in a
|
||||
// GNU test suite. This is nontrivial because the test suite does not support
|
||||
// excluding tests in any way, so ranges for all but the skipped tests have to
|
||||
// be specified instead.
|
||||
//
|
||||
// For example, to skip test 764, ranges around the skipped test must be
|
||||
// specified:
|
||||
//
|
||||
// 1-763 765-
|
||||
//
|
||||
// Tests are numbered starting from 1. The resulting string is unquoted.
|
||||
func skipGNUTests(tests ...int64) string {
|
||||
tests = slices.Clone(tests)
|
||||
slices.Sort(tests)
|
||||
|
||||
var buf strings.Builder
|
||||
|
||||
if tests[0] != 1 {
|
||||
buf.WriteString("1-")
|
||||
}
|
||||
|
||||
for i, n := range tests {
|
||||
if n != 1 && (i == 0 || tests[i-1] != n-1) {
|
||||
buf.WriteString(strconv.Itoa(int(n - 1)))
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
if i == len(tests)-1 || tests[i+1] != n+1 {
|
||||
buf.WriteString(strconv.Itoa(int(n + 1)))
|
||||
buf.WriteString("-")
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
@@ -26,7 +26,7 @@ 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.FileArtifact].
|
||||
// Dependencies returns the underlying busybox [pkg.File].
|
||||
func (a busyboxBin) Dependencies() []pkg.Artifact {
|
||||
return []pkg.Artifact{a.bin}
|
||||
}
|
||||
|
||||
38
internal/rosa/bzip2.go
Normal file
38
internal/rosa/bzip2.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newBzip2() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.0.8"
|
||||
checksum = "cTLykcco7boom-s05H1JVsQi1AtChYL84nXkg_92Dm1Xt94Ob_qlMg_-NSguIK-c"
|
||||
)
|
||||
return t.NewPackage("bzip2", version, newTar(
|
||||
"https://sourceware.org/pub/bzip2/bzip2-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Writable: true,
|
||||
EnterSource: true,
|
||||
}, &MakeHelper{
|
||||
// uses source tree as scratch space
|
||||
SkipConfigure: true,
|
||||
SkipCheck: true,
|
||||
InPlace: true,
|
||||
Make: []string{
|
||||
"CC=cc",
|
||||
},
|
||||
Install: "make PREFIX=/work/system install",
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newBzip2,
|
||||
|
||||
Name: "bzip2",
|
||||
Description: "a freely available, patent free, high-quality data compressor",
|
||||
Website: "https://sourceware.org/bzip2/",
|
||||
|
||||
ID: 237,
|
||||
})
|
||||
}
|
||||
@@ -4,14 +4,120 @@ import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
var (
|
||||
_cmake = H("cmake")
|
||||
_ninja = H("ninja")
|
||||
)
|
||||
func (t Toolchain) newCMake() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "4.3.2"
|
||||
checksum = "6QylwRVKletndTSkZTV2YBRwgd_9rUVgav_QW23HpjUgV21AVYZOUOal8tdBDmO7"
|
||||
)
|
||||
return t.NewPackage("cmake", version, newFromGitHubRelease(
|
||||
"Kitware/CMake",
|
||||
"v"+version,
|
||||
"cmake-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
// test suite expects writable source tree
|
||||
Writable: true,
|
||||
|
||||
// CMakeHelper builds and tests a CMake project with specified CACHE entries.
|
||||
// expected to be writable in the copy made during bootstrap
|
||||
Chmod: true,
|
||||
|
||||
Patches: []KV{
|
||||
{"bootstrap-test-no-openssl", `diff --git a/Tests/BootstrapTest.cmake b/Tests/BootstrapTest.cmake
|
||||
index 137de78bc1..b4da52e664 100644
|
||||
--- a/Tests/BootstrapTest.cmake
|
||||
+++ b/Tests/BootstrapTest.cmake
|
||||
@@ -9,7 +9,7 @@ if(NOT nproc EQUAL 0)
|
||||
endif()
|
||||
message(STATUS "running bootstrap: ${bootstrap} ${ninja_arg} ${parallel_arg}")
|
||||
execute_process(
|
||||
- COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg}
|
||||
+ COMMAND ${bootstrap} ${ninja_arg} ${parallel_arg} -- -DCMAKE_USE_OPENSSL=OFF
|
||||
WORKING_DIRECTORY "${bin_dir}"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
`},
|
||||
|
||||
{"disable-broken-tests-musl", `diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
|
||||
index 2ead810437..f85cbb8b1c 100644
|
||||
--- a/Tests/CMakeLists.txt
|
||||
+++ b/Tests/CMakeLists.txt
|
||||
@@ -384,7 +384,6 @@ if(BUILD_TESTING)
|
||||
add_subdirectory(CMakeLib)
|
||||
endif()
|
||||
add_subdirectory(CMakeOnly)
|
||||
- add_subdirectory(RunCMake)
|
||||
|
||||
add_subdirectory(FindPackageModeMakefileTest)
|
||||
|
||||
@@ -528,9 +527,6 @@ if(BUILD_TESTING)
|
||||
-DCMake_TEST_CUDA:BOOL=${CMake_TEST_CUDA}
|
||||
-DCMake_INSTALL_NAME_TOOL_BUG:BOOL=${CMake_INSTALL_NAME_TOOL_BUG}
|
||||
)
|
||||
- ADD_TEST_MACRO(ExportImport ExportImport)
|
||||
- set_property(TEST ExportImport APPEND
|
||||
- PROPERTY LABELS "CUDA")
|
||||
ADD_TEST_MACRO(Unset Unset)
|
||||
ADD_TEST_MACRO(PolicyScope PolicyScope)
|
||||
ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
|
||||
@@ -624,7 +620,6 @@ if(BUILD_TESTING)
|
||||
# run test for BundleUtilities on supported platforms/compilers
|
||||
if((MSVC OR
|
||||
MINGW OR
|
||||
- CMAKE_SYSTEM_NAME MATCHES "Linux" OR
|
||||
CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
AND NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
|
||||
|
||||
@@ -3095,10 +3090,6 @@ if(BUILD_TESTING)
|
||||
"${CMake_SOURCE_DIR}/Tests/CTestTestFdSetSize/test.cmake.in"
|
||||
"${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake"
|
||||
@ONLY ESCAPE_QUOTES)
|
||||
- add_test(CTestTestFdSetSize ${CMAKE_CTEST_COMMAND}
|
||||
- -S "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/test.cmake" -j20 -V --timeout 120
|
||||
- --output-log "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/testOutput.log"
|
||||
- )
|
||||
|
||||
if(CMAKE_TESTS_CDASH_SERVER)
|
||||
set(regex "^([^:]+)://([^/]+)(.*)$")
|
||||
`},
|
||||
},
|
||||
}, &MakeHelper{
|
||||
OmitDefaults: true,
|
||||
|
||||
ConfigureName: "/usr/src/cmake/bootstrap",
|
||||
Configure: []KV{
|
||||
{"prefix", "/system"},
|
||||
{"parallel", jobsE},
|
||||
{"--"},
|
||||
{"-DCMAKE_USE_OPENSSL", "OFF"},
|
||||
{"-DCMake_TEST_NO_NETWORK", "ON"},
|
||||
},
|
||||
Check: []string{
|
||||
"CTEST_OUTPUT_ON_FAILURE=1",
|
||||
"CTEST_PARALLEL_LEVEL=128",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newCMake,
|
||||
|
||||
Name: "cmake",
|
||||
Description: "cross-platform, open-source build system",
|
||||
Website: "https://cmake.org/",
|
||||
|
||||
ID: 306,
|
||||
})
|
||||
}
|
||||
|
||||
// CMakeHelper is the [CMake] build system helper.
|
||||
type CMakeHelper struct {
|
||||
// Path elements joined with source.
|
||||
Append []string
|
||||
@@ -34,12 +140,12 @@ type CMakeHelper struct {
|
||||
|
||||
var _ Helper = new(CMakeHelper)
|
||||
|
||||
// extra returns the cmake handle alongside either ninja or make.
|
||||
// extra returns a hardcoded slice of [CMake] and [Ninja].
|
||||
func (attr *CMakeHelper) extra(int) P {
|
||||
if attr != nil && attr.Make {
|
||||
return P{_cmake, _make}
|
||||
return P{CMake, Make}
|
||||
}
|
||||
return P{_cmake, _ninja}
|
||||
return P{CMake, Ninja}
|
||||
}
|
||||
|
||||
// wantsChmod returns false.
|
||||
@@ -51,11 +157,14 @@ func (*CMakeHelper) wantsWrite() bool { return false }
|
||||
// scriptEarly returns the zero value.
|
||||
func (*CMakeHelper) scriptEarly() string { return "" }
|
||||
|
||||
// createDir returns true.
|
||||
func (*CMakeHelper) createDir() bool { return true }
|
||||
|
||||
// wantsDir returns a hardcoded, deterministic pathname.
|
||||
func (*CMakeHelper) wantsDir() (string, bool) { return "/cure/", true }
|
||||
func (*CMakeHelper) wantsDir() string { return "/cure/" }
|
||||
|
||||
// script generates the cure script.
|
||||
func (attr *CMakeHelper) script(t Toolchain, name string) string {
|
||||
func (attr *CMakeHelper) script(s *S, name string) string {
|
||||
if attr == nil {
|
||||
attr = new(CMakeHelper)
|
||||
}
|
||||
@@ -71,7 +180,7 @@ func (attr *CMakeHelper) script(t Toolchain, name string) string {
|
||||
}
|
||||
|
||||
script := attr.Script
|
||||
if !attr.SkipTest && t.opts&OptSkipCheck == 0 {
|
||||
if !attr.SkipTest && s.opts&OptSkipCheck == 0 {
|
||||
script += "\n" + test
|
||||
}
|
||||
|
||||
@@ -98,6 +207,6 @@ cmake -G ` + generate + ` \
|
||||
-DCMAKE_INSTALL_PREFIX=/system \
|
||||
'/usr/src/` + name + `/` + filepath.Join(attr.Append...) + `'
|
||||
cmake --build . --parallel=` + jobsE + `
|
||||
DESTDIR=/work cmake --install .
|
||||
cmake --install . --prefix=/work/system
|
||||
` + script
|
||||
}
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
musl does not implement res_ninit
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newConnman() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.0"
|
||||
checksum = "MhVTdJOhndnZn2SWd8URKo_Pj7Zvc14tntEbrVOf9L3yVWJvpb3v3Q6104tWJgtW"
|
||||
)
|
||||
return t.NewPackage("connman", version, newTar(
|
||||
"https://git.kernel.org/pub/scm/network/connman/connman.git/"+
|
||||
"snapshot/connman-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"alpine-musl-res", `musl does not implement res_ninit
|
||||
|
||||
--- a/gweb/gresolv.c
|
||||
+++ b/gweb/gresolv.c
|
||||
@@ -57,3 +73,37 @@ musl does not implement res_ninit
|
||||
}
|
||||
|
||||
if (!resolv->nameserver_list)
|
||||
`},
|
||||
},
|
||||
}, &MakeHelper{
|
||||
Generate: "./bootstrap",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
DBus,
|
||||
IPTables,
|
||||
GnuTLS,
|
||||
Readline,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newConnman,
|
||||
|
||||
Name: "connman",
|
||||
Description: "a daemon for managing Internet connections",
|
||||
Website: "https://git.kernel.org/pub/scm/network/connman/connman.git/",
|
||||
|
||||
Dependencies: P{
|
||||
DBus,
|
||||
IPTables,
|
||||
GnuTLS,
|
||||
Readline,
|
||||
},
|
||||
|
||||
ID: 337,
|
||||
})
|
||||
}
|
||||
56
internal/rosa/curl.go
Normal file
56
internal/rosa/curl.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newCurl() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "8.20.0"
|
||||
checksum = "xyHXwrngIRGMasuzhn-I5MSCOhktwINbsWt1f_LuR-5jRVvyx_g6U1EQfDLEbr9r"
|
||||
)
|
||||
return t.NewPackage("curl", version, newTar(
|
||||
"https://curl.se/download/curl-"+version+".tar.bz2",
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
), &PackageAttr{
|
||||
// remove broken test
|
||||
Writable: true,
|
||||
ScriptEarly: `
|
||||
chmod +w tests/data && rm -f tests/data/test459
|
||||
`,
|
||||
}, &MakeHelper{
|
||||
Configure: []KV{
|
||||
{"with-openssl"},
|
||||
{"with-ca-bundle", "/system/etc/ssl/certs/ca-bundle.crt"},
|
||||
|
||||
{"disable-smb"},
|
||||
},
|
||||
Check: []string{
|
||||
"TFLAGS=" + jobsLFlagE,
|
||||
"test-nonflaky",
|
||||
},
|
||||
},
|
||||
Perl,
|
||||
Python,
|
||||
PkgConfig,
|
||||
Diffutils,
|
||||
|
||||
Libpsl,
|
||||
OpenSSL,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newCurl,
|
||||
|
||||
Name: "curl",
|
||||
Description: "command line tool and library for transferring data with URLs",
|
||||
Website: "https://curl.se/",
|
||||
|
||||
Dependencies: P{
|
||||
Libpsl,
|
||||
OpenSSL,
|
||||
},
|
||||
|
||||
ID: 381,
|
||||
})
|
||||
}
|
||||
81
internal/rosa/dbus.go
Normal file
81
internal/rosa/dbus.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newDBus() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.16.2"
|
||||
checksum = "INwOuNdrDG7XW5ilW_vn8JSxEa444rRNc5ho97i84I1CNF09OmcFcV-gzbF4uCyg"
|
||||
)
|
||||
return t.NewPackage("dbus", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"dbus/dbus",
|
||||
"dbus-"+version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
// OSError: [Errno 30] Read-only file system: '/usr/src/dbus/subprojects/packagecache'
|
||||
Writable: true,
|
||||
// PermissionError: [Errno 13] Permission denied: '/usr/src/dbus/subprojects/packagecache'
|
||||
Chmod: true,
|
||||
}, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Depoll", "enabled"},
|
||||
{"Dinotify", "enabled"},
|
||||
{"Dx11_autolaunch", "disabled"},
|
||||
},
|
||||
},
|
||||
GLib,
|
||||
Libexpat,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newDBus,
|
||||
|
||||
Name: "dbus",
|
||||
Description: "a message bus system",
|
||||
Website: "https://www.freedesktop.org/wiki/Software/dbus/",
|
||||
|
||||
Dependencies: P{
|
||||
GLib,
|
||||
Libexpat,
|
||||
},
|
||||
|
||||
ID: 5356,
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newXDGDBusProxy() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.1.7"
|
||||
checksum = "UW5Pe-TP-XAaN-kTbxrkOQ7eYdmlAQlr2pdreLtPT0uwdAz-7rzDP8V_8PWuZBup"
|
||||
)
|
||||
return t.NewPackage("xdg-dbus-proxy", version, newFromGitHub(
|
||||
"flatpak/xdg-dbus-proxy",
|
||||
version,
|
||||
checksum,
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dman", "disabled"},
|
||||
},
|
||||
},
|
||||
DBus,
|
||||
|
||||
GLib,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newXDGDBusProxy,
|
||||
|
||||
Name: "xdg-dbus-proxy",
|
||||
Description: "a filtering proxy for D-Bus connections",
|
||||
Website: "https://github.com/flatpak/xdg-dbus-proxy",
|
||||
|
||||
Dependencies: P{
|
||||
GLib,
|
||||
},
|
||||
|
||||
ID: 58434,
|
||||
})
|
||||
}
|
||||
43
internal/rosa/dtc.go
Normal file
43
internal/rosa/dtc.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newDTC() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.7.2"
|
||||
checksum = "vUoiRynPyYRexTpS6USweT5p4SVHvvVJs8uqFkkVD-YnFjwf6v3elQ0-Etrh00Dt"
|
||||
)
|
||||
return t.NewPackage("dtc", version, newTar(
|
||||
"https://git.kernel.org/pub/scm/utils/dtc/dtc.git/snapshot/"+
|
||||
"dtc-v"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
// works around buggy test:
|
||||
// fdtdump-runtest.sh /usr/src/dtc/tests/fdtdump.dts
|
||||
Writable: true,
|
||||
Chmod: true,
|
||||
}, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dyaml", "disabled"},
|
||||
{"Dstatic-build", "true"},
|
||||
},
|
||||
},
|
||||
Flex,
|
||||
Bison,
|
||||
M4,
|
||||
Coreutils,
|
||||
Diffutils,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newDTC,
|
||||
|
||||
Name: "dtc",
|
||||
Description: "The Device Tree Compiler",
|
||||
Website: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git/",
|
||||
|
||||
ID: 16911,
|
||||
})
|
||||
}
|
||||
59
internal/rosa/elfutils.go
Normal file
59
internal/rosa/elfutils.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newElfutils() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.195"
|
||||
checksum = "JrGnBD38w8Mj0ZxDw3fKlRBFcLvRKu8rcYnX35R9yTlUSYnzTazyLboG-a2CsJlu"
|
||||
)
|
||||
return t.NewPackage("elfutils", version, newTar(
|
||||
"https://sourceware.org/elfutils/ftp/"+
|
||||
version+"/elfutils-"+version+".tar.bz2",
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"CC=cc" +
|
||||
// nonstandard glibc extension
|
||||
" -DFNM_EXTMATCH=0",
|
||||
},
|
||||
}, &MakeHelper{
|
||||
// nonstandard glibc extension
|
||||
SkipCheck: true,
|
||||
|
||||
Configure: []KV{
|
||||
{"enable-deterministic-archives"},
|
||||
},
|
||||
},
|
||||
M4,
|
||||
PkgConfig,
|
||||
|
||||
Zlib,
|
||||
Bzip2,
|
||||
Zstd,
|
||||
ArgpStandalone,
|
||||
MuslFts,
|
||||
MuslObstack,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newElfutils,
|
||||
|
||||
Name: "elfutils",
|
||||
Description: "utilities and libraries to handle ELF files and DWARF data",
|
||||
Website: "https://sourceware.org/elfutils/",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
Bzip2,
|
||||
Zstd,
|
||||
MuslFts,
|
||||
MuslObstack,
|
||||
},
|
||||
|
||||
ID: 5679,
|
||||
})
|
||||
}
|
||||
58
internal/rosa/fakeroot.go
Normal file
58
internal/rosa/fakeroot.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newFakeroot() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.37.2"
|
||||
checksum = "4ve-eDqVspzQ6VWDhPS0NjW3aSenBJcPAJq_BFT7OOFgUdrQzoTBxZWipDAGWxF8"
|
||||
)
|
||||
return t.NewPackage("fakeroot", version, newFromGitLab(
|
||||
"salsa.debian.org",
|
||||
"clint/fakeroot",
|
||||
"upstream/"+version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"remove-broken-docs", `diff --git a/doc/Makefile.am b/doc/Makefile.am
|
||||
index f135ad9..85c784c 100644
|
||||
--- a/doc/Makefile.am
|
||||
+++ b/doc/Makefile.am
|
||||
@@ -1,5 +1,4 @@
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
-SUBDIRS = de es fr nl pt ro sv
|
||||
|
||||
man_MANS = faked.1 fakeroot.1
|
||||
|
||||
`},
|
||||
},
|
||||
|
||||
Env: []string{
|
||||
"CONFIG_SHELL=/bin/sh",
|
||||
},
|
||||
}, &MakeHelper{
|
||||
Generate: "./bootstrap",
|
||||
|
||||
// makes assumptions about /etc/passwd
|
||||
SkipCheck: true,
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
Attr,
|
||||
Libcap,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newFakeroot,
|
||||
|
||||
Name: "fakeroot",
|
||||
Description: "tool for simulating superuser privileges",
|
||||
Website: "https://salsa.debian.org/clint/fakeroot",
|
||||
|
||||
ID: 12048,
|
||||
})
|
||||
}
|
||||
32
internal/rosa/flex.go
Normal file
32
internal/rosa/flex.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newFlex() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.6.4"
|
||||
checksum = "p9POjQU7VhgOf3x5iFro8fjhy0NOanvA7CTeuWS_veSNgCixIJshTrWVkc5XLZkB"
|
||||
)
|
||||
return t.NewPackage("flex", version, newFromGitHubRelease(
|
||||
"westes/flex",
|
||||
"v"+version,
|
||||
"flex-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
M4,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newFlex,
|
||||
|
||||
Name: "flex",
|
||||
Description: "scanner generator for lexing in C and C++",
|
||||
Website: "https://github.com/westes/flex/",
|
||||
|
||||
ID: 819,
|
||||
})
|
||||
}
|
||||
27
internal/rosa/freetype.go
Normal file
27
internal/rosa/freetype.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newFreetype() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.14.3"
|
||||
checksum = "-WfLv8fVJNyCHpP_lriiDzOcVbBL9ajdQ3tl8AzIIUa9-8sVpU9irxOmSMgRHWYz"
|
||||
)
|
||||
return t.NewPackage("freetype", version, newTar(
|
||||
"https://download.savannah.gnu.org/releases/freetype/"+
|
||||
"freetype-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newFreetype,
|
||||
|
||||
Name: "freetype",
|
||||
Description: "a freely available software library to render fonts",
|
||||
Website: "http://www.freetype.org/",
|
||||
|
||||
ID: 854,
|
||||
})
|
||||
}
|
||||
43
internal/rosa/fuse.go
Normal file
43
internal/rosa/fuse.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newFuse() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.18.2"
|
||||
checksum = "iL-7b7eUtmlVSf5cSq0dzow3UiqSjBmzV3cI_ENPs1tXcHdktkG45j1V12h-4jZe"
|
||||
)
|
||||
return t.NewPackage("fuse", version, newFromGitHubRelease(
|
||||
"libfuse/libfuse",
|
||||
"fuse-"+version,
|
||||
"fuse-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Ddefault_library", "both"},
|
||||
{"Dtests", "true"},
|
||||
{"Duseroot", "false"},
|
||||
{"Dinitscriptdir", "/system/etc"},
|
||||
},
|
||||
|
||||
ScriptCompiled: "python3 -m pytest test/",
|
||||
// this project uses pytest
|
||||
SkipTest: true,
|
||||
},
|
||||
PythonPyTest,
|
||||
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newFuse,
|
||||
|
||||
Name: "fuse",
|
||||
Description: "the reference implementation of the Linux FUSE interface",
|
||||
Website: "https://github.com/libfuse/libfuse/",
|
||||
|
||||
ID: 861,
|
||||
})
|
||||
}
|
||||
@@ -7,10 +7,103 @@ import (
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
var (
|
||||
_git = H("git")
|
||||
_nssCACert = H("nss-cacert")
|
||||
)
|
||||
func (t Toolchain) newGit() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.54.0"
|
||||
checksum = "7vGKtFOJGqY8DO4e8UMRax7dLgImXKQz5MMalec6MlgYrsarffSJjgOughwRFpSH"
|
||||
)
|
||||
return t.NewPackage("git", version, newTar(
|
||||
"https://www.kernel.org/pub/software/scm/git/"+
|
||||
"git-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
ScriptEarly: `
|
||||
ln -s ../../system/bin/perl /usr/bin/ || true
|
||||
|
||||
# test suite assumes apache
|
||||
rm -f /system/bin/httpd
|
||||
`,
|
||||
|
||||
// uses source tree as scratch space
|
||||
EnterSource: true,
|
||||
}, &MakeHelper{
|
||||
InPlace: true,
|
||||
Generate: "make configure",
|
||||
ScriptMakeEarly: `
|
||||
function disable_test {
|
||||
local test=$1 pattern=${2:-''}
|
||||
if [ $# -eq 1 ]; then
|
||||
rm "t/${test}.sh"
|
||||
else
|
||||
sed -i "t/${test}.sh" \
|
||||
-e "/^\s*test_expect_.*$pattern/,/^\s*' *\$/{s/^/: #/}"
|
||||
fi
|
||||
}
|
||||
|
||||
disable_test t1800-hook
|
||||
disable_test t5319-multi-pack-index
|
||||
disable_test t1305-config-include
|
||||
disable_test t3900-i18n-commit
|
||||
disable_test t3507-cherry-pick-conflict
|
||||
disable_test t4201-shortlog
|
||||
disable_test t5303-pack-corruption-resilience
|
||||
disable_test t4301-merge-tree-write-tree
|
||||
disable_test t8005-blame-i18n
|
||||
disable_test t9350-fast-export
|
||||
disable_test t9300-fast-import
|
||||
disable_test t0211-trace2-perf
|
||||
disable_test t1517-outside-repo
|
||||
disable_test t2200-add-update
|
||||
disable_test t0027-auto-crlf
|
||||
disable_test t7513-interpret-trailers
|
||||
disable_test t7703-repack-geometric
|
||||
disable_test t7002-mv-sparse-checkout
|
||||
disable_test t1451-fsck-buffer
|
||||
disable_test t4104-apply-boundary
|
||||
disable_test t4200-rerere
|
||||
disable_test t5515-fetch-merge-logic
|
||||
`,
|
||||
Check: []string{
|
||||
"-C t",
|
||||
`GIT_PROVE_OPTS="--jobs 32 --failures"`,
|
||||
"prove",
|
||||
},
|
||||
Install: `make \
|
||||
` + jobsFlagE + ` \
|
||||
DESTDIR=/work \
|
||||
NO_INSTALL_HARDLINKS=1 \
|
||||
install`,
|
||||
},
|
||||
// test suite hangs on mksh
|
||||
Bash,
|
||||
|
||||
Diffutils,
|
||||
Autoconf,
|
||||
Gettext,
|
||||
|
||||
Zlib,
|
||||
Curl,
|
||||
Libexpat,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newGit,
|
||||
|
||||
Name: "git",
|
||||
Description: "distributed version control system",
|
||||
Website: "https://www.git-scm.com/",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
Curl,
|
||||
Libexpat,
|
||||
},
|
||||
|
||||
ID: 5350,
|
||||
})
|
||||
}
|
||||
|
||||
// NewViaGit returns a [pkg.Artifact] for cloning a git repository.
|
||||
func (t Toolchain) NewViaGit(
|
||||
@@ -21,8 +114,8 @@ func (t Toolchain) NewViaGit(
|
||||
path.Base(url),
|
||||
".git",
|
||||
)+"-src-"+path.Base(rev), THostNet, t.Append(nil,
|
||||
_nssCACert,
|
||||
_git,
|
||||
NSSCACert,
|
||||
Git,
|
||||
), &checksum, nil, `
|
||||
git \
|
||||
-c advice.detachedHead=false \
|
||||
@@ -36,3 +129,8 @@ git \
|
||||
rm -rf /work/.git
|
||||
`, resolvconf())
|
||||
}
|
||||
|
||||
// newTagRemote is a helper around NewViaGit for a tag on a git remote.
|
||||
func (t Toolchain) newTagRemote(url, tag, checksum string) pkg.Artifact {
|
||||
return t.NewViaGit(url, "refs/tags/"+tag, mustDecode(checksum))
|
||||
}
|
||||
|
||||
248
internal/rosa/glslang.go
Normal file
248
internal/rosa/glslang.go
Normal file
@@ -0,0 +1,248 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.4.341.0"
|
||||
checksum = "0PL43-19Iaw4k7_D8J8BvoJ-iLgCVSYZ2ThgDPGfAJwIJFtre7l0cnQtLjcY-JvD"
|
||||
)
|
||||
return t.NewPackage("spirv-headers", version, newFromGitHub(
|
||||
"KhronosGroup/SPIRV-Headers",
|
||||
"vulkan-sdk-"+version,
|
||||
checksum,
|
||||
), nil, &CMakeHelper{
|
||||
// upstream has no tests
|
||||
SkipTest: true,
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newSPIRVHeaders,
|
||||
|
||||
Name: "spirv-headers",
|
||||
Description: "machine-readable files for the SPIR-V Registry",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-Headers",
|
||||
|
||||
ID: 230542,
|
||||
|
||||
// upstream changed version scheme, anitya incapable of filtering them
|
||||
latest: func(v *Versions) string {
|
||||
for _, s := range v.Stable {
|
||||
fields := strings.SplitN(s, ".", 4)
|
||||
if len(fields) != 4 {
|
||||
continue
|
||||
}
|
||||
if slices.ContainsFunc(fields, func(f string) bool {
|
||||
return slices.ContainsFunc([]byte(f), func(d byte) bool {
|
||||
return d < '0' || d > '9'
|
||||
})
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
return s
|
||||
}
|
||||
return v.Latest
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2026.1"
|
||||
checksum = "ZSQPQx8NltCDzQLk4qlaVxyWRWeI_JtsjEpeFt3kezTanl9DTHfLixSUCezMFBjv"
|
||||
)
|
||||
return t.NewPackage("spirv-tools", version, newFromGitHub(
|
||||
"KhronosGroup/SPIRV-Tools",
|
||||
"v"+version,
|
||||
checksum,
|
||||
), nil, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"SPIRV-Headers_SOURCE_DIR", "/system"},
|
||||
},
|
||||
},
|
||||
Python,
|
||||
|
||||
SPIRVHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newSPIRVTools,
|
||||
|
||||
Name: "spirv-tools",
|
||||
Description: "an API and commands for processing SPIR-V modules",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-Tools",
|
||||
|
||||
Dependencies: P{
|
||||
SPIRVHeaders,
|
||||
},
|
||||
|
||||
ID: 14894,
|
||||
|
||||
latest: (*Versions).getStable,
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "16.3.0"
|
||||
checksum = "xyqDf8k3-D0_BXHGi0uLgMglnJ05Rf3j73QgbDs3sGtKNdBIQhY8JfqX1NcNoJQN"
|
||||
)
|
||||
return t.NewPackage("glslang", version, newFromGitHub(
|
||||
"KhronosGroup/glslang",
|
||||
version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
// test suite writes to source
|
||||
Writable: true,
|
||||
Chmod: true,
|
||||
}, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"BUILD_SHARED_LIBS", "ON"},
|
||||
{"ALLOW_EXTERNAL_SPIRV_TOOLS", "ON"},
|
||||
},
|
||||
},
|
||||
Python,
|
||||
Bash,
|
||||
Diffutils,
|
||||
|
||||
SPIRVTools,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newGlslang,
|
||||
|
||||
Name: "glslang",
|
||||
Description: "reference front end for GLSL/ESSL",
|
||||
Website: "https://github.com/KhronosGroup/glslang",
|
||||
|
||||
ID: 205796,
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "22.1.2"
|
||||
checksum = "JZAaV5ewYcm-35YA_U2BM2IcsQouZtX1BLZR0zh2vSlfEXMsT5OCtY4Gh5RJkcGy"
|
||||
)
|
||||
skipChecks := []string{
|
||||
// error: line 13: OpTypeCooperativeMatrixKHR Scope is limited to Workgroup and Subgroup
|
||||
"cooperative_matrix_constant_null.spvasm",
|
||||
}
|
||||
|
||||
switch t.arch {
|
||||
case "arm64":
|
||||
skipChecks = append(skipChecks,
|
||||
// LLVM ERROR: unsupported calling convention
|
||||
"DebugInfo/COFF/no-cus.ll",
|
||||
"DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll",
|
||||
"DebugInfo/Generic/2009-11-10-CurrentFn.ll",
|
||||
"DebugInfo/Generic/2010-01-05-DbgScope.ll",
|
||||
"DebugInfo/Generic/2010-03-12-llc-crash.ll",
|
||||
"DebugInfo/Generic/2010-03-24-MemberFn.ll",
|
||||
"DebugInfo/Generic/2010-04-19-FramePtr.ll",
|
||||
"DebugInfo/Generic/2010-06-29-InlinedFnLocalVar.ll",
|
||||
"DebugInfo/Generic/2010-10-01-crash.ll",
|
||||
"DebugInfo/Generic/PR20038.ll",
|
||||
"DebugInfo/Generic/constant-pointers.ll",
|
||||
"DebugInfo/Generic/dead-argument-order.ll",
|
||||
"DebugInfo/Generic/debug-info-eis-option.ll",
|
||||
"DebugInfo/Generic/def-line.ll",
|
||||
"DebugInfo/Generic/discriminator.ll",
|
||||
"DebugInfo/Generic/dwarf-public-names.ll",
|
||||
"DebugInfo/Generic/enum.ll",
|
||||
"DebugInfo/Generic/func-using-decl.ll",
|
||||
"DebugInfo/Generic/global.ll",
|
||||
"DebugInfo/Generic/imported-name-inlined.ll",
|
||||
"DebugInfo/Generic/incorrect-variable-debugloc1.ll",
|
||||
"DebugInfo/Generic/inline-scopes.ll",
|
||||
"DebugInfo/Generic/inlined-arguments.ll",
|
||||
"DebugInfo/Generic/inlined-vars.ll",
|
||||
"DebugInfo/Generic/linear-dbg-value.ll",
|
||||
"DebugInfo/Generic/linkage-name-abstract.ll",
|
||||
"DebugInfo/Generic/member-order.ll",
|
||||
"DebugInfo/Generic/missing-abstract-variable.ll",
|
||||
"DebugInfo/Generic/multiline.ll",
|
||||
"DebugInfo/Generic/namespace_function_definition.ll",
|
||||
"DebugInfo/Generic/namespace_inline_function_definition.ll",
|
||||
"DebugInfo/Generic/noscopes.ll",
|
||||
"DebugInfo/Generic/ptrsize.ll",
|
||||
"DebugInfo/Generic/restrict.ll",
|
||||
"DebugInfo/Generic/two-cus-from-same-file.ll",
|
||||
"DebugInfo/Generic/version.ll",
|
||||
"DebugInfo/LocalAddressSpace.ll",
|
||||
"DebugInfo/UnknownBaseType.ll",
|
||||
"DebugInfo/expr-opcode.ll",
|
||||
)
|
||||
}
|
||||
|
||||
return t.NewPackage("spirv-llvm-translator", version, newFromGitHub(
|
||||
"KhronosGroup/SPIRV-LLVM-Translator",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"remove-early-prefix", `diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index c000a77e..f18f3fde 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -164,7 +164,7 @@ install(
|
||||
${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVOpts.h
|
||||
${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVExtensions.inc
|
||||
DESTINATION
|
||||
- ${CMAKE_INSTALL_PREFIX}/include/LLVMSPIRVLib
|
||||
+ include/LLVMSPIRVLib
|
||||
)
|
||||
|
||||
configure_file(LLVMSPIRVLib.pc.in ${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc @ONLY)
|
||||
@@ -172,5 +172,5 @@ install(
|
||||
FILES
|
||||
${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc
|
||||
DESTINATION
|
||||
- ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
+ lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
)
|
||||
;`},
|
||||
},
|
||||
|
||||
// litArgs emits shell syntax
|
||||
ScriptEarly: `
|
||||
export LIT_OPTS=` + litArgs(true, skipChecks...) + `
|
||||
`,
|
||||
}, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_SKIP_BUILD_RPATH", "ON"},
|
||||
{"BUILD_SHARED_LIBS", "ON"},
|
||||
{"LLVM_SPIRV_ENABLE_LIBSPIRV_DIS", "ON"},
|
||||
{"LLVM_EXTERNAL_SPIRV_HEADERS_SOURCE_DIR", "/system"},
|
||||
{"LLVM_EXTERNAL_LIT", "/system/bin/lit"},
|
||||
{"LLVM_INCLUDE_TESTS", "ON"},
|
||||
},
|
||||
},
|
||||
Bash,
|
||||
LIT,
|
||||
|
||||
SPIRVTools,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newSPIRVLLVMTranslator,
|
||||
|
||||
Name: "spirv-llvm-translator",
|
||||
Description: "bi-directional translation between SPIR-V and LLVM IR",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-LLVM-Translator",
|
||||
|
||||
Dependencies: P{
|
||||
SPIRVTools,
|
||||
},
|
||||
|
||||
ID: 227273,
|
||||
})
|
||||
}
|
||||
1366
internal/rosa/gnu.go
Normal file
1366
internal/rosa/gnu.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,18 +11,18 @@ func TestSkipGNUTests(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
tests []int64
|
||||
tests []int
|
||||
want string
|
||||
}{
|
||||
{[]int64{764}, "1-763 765-"},
|
||||
{[]int64{764, 0xcafe, 37, 9}, "1-8 10-36 38-763 765-51965 51967-"},
|
||||
{[]int64{1, 2, 0xbed}, "3-3052 3054-"},
|
||||
{[]int64{3, 4}, "1-2 5-"},
|
||||
{[]int{764}, "1-763 765-"},
|
||||
{[]int{764, 0xcafe, 37, 9}, "1-8 10-36 38-763 765-51965 51967-"},
|
||||
{[]int{1, 2, 0xbed}, "3-3052 3054-"},
|
||||
{[]int{3, 4}, "1-2 5-"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(strings.Join(slices.Collect(func(yield func(string) bool) {
|
||||
for _, n := range tc.tests {
|
||||
yield(strconv.Itoa(int(n)))
|
||||
yield(strconv.Itoa(n))
|
||||
}
|
||||
}), ","), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -6,111 +6,89 @@ import (
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
// newGoBootstrap returns the Go bootstrap toolchain.
|
||||
func (t Toolchain) newGoBootstrap() pkg.Artifact {
|
||||
const checksum = "8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23"
|
||||
return t.New("go1.4-bootstrap", 0, t.Append(nil,
|
||||
Bash,
|
||||
), nil, []string{
|
||||
"CGO_ENABLED=0",
|
||||
}, `
|
||||
mkdir -p /var/tmp/ /work/system/
|
||||
cp -r /usr/src/go /work/system/
|
||||
cd /work/system/go/src
|
||||
chmod -R +w ..
|
||||
|
||||
./make.bash
|
||||
`, pkg.Path(AbsUsrSrc.Append("go"), false, newTar(
|
||||
"https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
)))
|
||||
}
|
||||
|
||||
// newGo returns a specific version of the Go toolchain.
|
||||
func (t Toolchain) newGo(
|
||||
version, checksum string,
|
||||
env []string,
|
||||
script string,
|
||||
boot ...pkg.Artifact,
|
||||
extra ...pkg.Artifact,
|
||||
) pkg.Artifact {
|
||||
return t.NewPackage("go", version, newTar(
|
||||
"https://go.dev/dl/go"+version+".src.tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
EnterSource: true,
|
||||
Env: slices.Concat([]string{
|
||||
"CC=cc",
|
||||
"GOCACHE=/tmp/gocache",
|
||||
"GOROOT_BOOTSTRAP=/system/go",
|
||||
"TMPDIR=/dev/shm/go",
|
||||
}, env),
|
||||
|
||||
Extra: boot,
|
||||
}, &GenericHelper{
|
||||
InPlace: true,
|
||||
Build: `
|
||||
mkdir /work/system/ "${TMPDIR}"
|
||||
cp -r . /work/system/go
|
||||
cd /work/system/go/src/
|
||||
name := "all"
|
||||
if t.opts&OptSkipCheck != 0 {
|
||||
name = "make"
|
||||
}
|
||||
return t.New("go"+version, 0, t.Append(extra,
|
||||
Bash,
|
||||
), nil, slices.Concat([]string{
|
||||
"CC=cc",
|
||||
"GOCACHE=/tmp/gocache",
|
||||
"GOROOT_BOOTSTRAP=/system/go",
|
||||
"TMPDIR=/dev/shm/go",
|
||||
}, env), `
|
||||
mkdir /work/system "${TMPDIR}"
|
||||
cp -r /usr/src/go /work/system
|
||||
cd /work/system/go/src
|
||||
chmod -R +w ..
|
||||
` + script + `
|
||||
set +u
|
||||
. ./make.bash "$@" --no-banner
|
||||
set -u
|
||||
`,
|
||||
Check: "bash run.bash --no-rebuild\n",
|
||||
Install: `
|
||||
../bin/go tool dist banner # print build info
|
||||
`+script+`
|
||||
./`+name+`.bash
|
||||
|
||||
mkdir /work/system/bin
|
||||
ln -s \
|
||||
../go/bin/go \
|
||||
../go/bin/gofmt \
|
||||
/work/system/bin
|
||||
`,
|
||||
},
|
||||
_bash,
|
||||
)
|
||||
`, pkg.Path(AbsUsrSrc.Append("go"), false, newTar(
|
||||
"https://go.dev/dl/go"+version+".src.tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
)))
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "1.26.3"
|
||||
checksum = "lEiFocZFnN5fKvZzmwVdqc9pYUjAuhzqZGbuiOqxUP4XdcY8yECisKcqsQ_eNn1N"
|
||||
func (t Toolchain) newGoLatest() (pkg.Artifact, string) {
|
||||
var (
|
||||
bootstrapEnv []string
|
||||
bootstrapExtra []pkg.Artifact
|
||||
|
||||
finalEnv []string
|
||||
)
|
||||
meta := Metadata{
|
||||
Name: "go",
|
||||
Description: "the Go programming language toolchain",
|
||||
Website: "https://go.dev",
|
||||
Version: version,
|
||||
switch t.arch {
|
||||
case "amd64":
|
||||
bootstrapExtra = append(bootstrapExtra, t.newGoBootstrap())
|
||||
|
||||
ID: 1227,
|
||||
case "arm64", "riscv64":
|
||||
bootstrapEnv = append(bootstrapEnv, "GOROOT_BOOTSTRAP=/system")
|
||||
bootstrapExtra = t.Append(bootstrapExtra, gcc)
|
||||
finalEnv = append(finalEnv, "CGO_ENABLED=0")
|
||||
|
||||
default:
|
||||
panic("unsupported target " + t.arch)
|
||||
}
|
||||
native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
|
||||
var (
|
||||
bootstrapEnv []string
|
||||
bootstrapEarly []pkg.Artifact
|
||||
|
||||
finalEnv []string
|
||||
)
|
||||
switch t.arch {
|
||||
case "amd64":
|
||||
bootstrapEarly = []pkg.Artifact{t.NewPackage("go", "1.4-bootstrap", newTar(
|
||||
"https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz",
|
||||
"8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23",
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
EnterSource: true,
|
||||
Env: []string{
|
||||
"CGO_ENABLED=0",
|
||||
},
|
||||
}, &GenericHelper{
|
||||
InPlace: true,
|
||||
Build: `
|
||||
mkdir /work/system/
|
||||
cp -r . /work/system/go
|
||||
cd /work/system/go/src/
|
||||
mkdir -p /var/tmp/
|
||||
./make.bash
|
||||
`,
|
||||
},
|
||||
_bash,
|
||||
)}
|
||||
|
||||
case "arm64", "riscv64":
|
||||
bootstrapEnv = append(bootstrapEnv, "GOROOT_BOOTSTRAP=/system")
|
||||
bootstrapEarly = t.Append(bootstrapEarly, H("gcc"))
|
||||
finalEnv = append(finalEnv, "CGO_ENABLED=0")
|
||||
|
||||
default:
|
||||
panic("unsupported target " + t.arch)
|
||||
}
|
||||
|
||||
go119 := t.newGo(
|
||||
"1.19",
|
||||
"9_e0aFHsIkVxWVGsp9T2RvvjOc3p4n9o9S8tkNe9Cvgzk_zI2FhRQB7ioQkeAAro",
|
||||
append(bootstrapEnv, "CGO_ENABLED=0"), `
|
||||
go119 := t.newGo(
|
||||
"1.19",
|
||||
"9_e0aFHsIkVxWVGsp9T2RvvjOc3p4n9o9S8tkNe9Cvgzk_zI2FhRQB7ioQkeAAro",
|
||||
append(bootstrapEnv, "CGO_ENABLED=0"), `
|
||||
rm \
|
||||
crypto/tls/handshake_client_test.go \
|
||||
cmd/pprof/pprof_test.go \
|
||||
@@ -121,12 +99,12 @@ sed -i \
|
||||
echo \
|
||||
'type syscallDescriptor = int' >> \
|
||||
os/rawconn_test.go
|
||||
`, bootstrapEarly...)
|
||||
`, bootstrapExtra...)
|
||||
|
||||
go121 := t.newGo(
|
||||
"1.21.13",
|
||||
"YtrDka402BOAEwywx03Vz4QlVwoBiguJHzG7PuythMCPHXS8CVMLvzmvgEbu4Tzu",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
go121 := t.newGo(
|
||||
"1.21.13",
|
||||
"YtrDka402BOAEwywx03Vz4QlVwoBiguJHzG7PuythMCPHXS8CVMLvzmvgEbu4Tzu",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
@@ -139,22 +117,22 @@ echo \
|
||||
'type syscallDescriptor = int' >> \
|
||||
os/rawconn_test.go
|
||||
`, go119,
|
||||
)
|
||||
)
|
||||
|
||||
go123 := t.newGo(
|
||||
"1.23.12",
|
||||
"wcI32bl1tkqbgcelGtGWPI4RtlEddd-PTd76Eb-k7nXA5LbE9yTNdIL9QSOOxMOs",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
go123 := t.newGo(
|
||||
"1.23.12",
|
||||
"wcI32bl1tkqbgcelGtGWPI4RtlEddd-PTd76Eb-k7nXA5LbE9yTNdIL9QSOOxMOs",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
`, go121,
|
||||
)
|
||||
)
|
||||
|
||||
go125 := t.newGo(
|
||||
"1.25.10",
|
||||
"TwKwatkpwal-j9U2sDSRPEdM3YesI4Gm88YgGV59wtU-L85K9gA7UPy9SCxn6PMb",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
go125 := t.newGo(
|
||||
"1.25.10",
|
||||
"TwKwatkpwal-j9U2sDSRPEdM3YesI4Gm88YgGV59wtU-L85K9gA7UPy9SCxn6PMb",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
@@ -163,12 +141,16 @@ rm \
|
||||
os/root_unix_test.go \
|
||||
net/smtp/smtp_test.go
|
||||
`, go123,
|
||||
)
|
||||
)
|
||||
|
||||
return &meta, t.newGo(
|
||||
version,
|
||||
checksum,
|
||||
finalEnv, `
|
||||
const (
|
||||
version = "1.26.3"
|
||||
checksum = "lEiFocZFnN5fKvZzmwVdqc9pYUjAuhzqZGbuiOqxUP4XdcY8yECisKcqsQ_eNn1N"
|
||||
)
|
||||
return t.newGo(
|
||||
version,
|
||||
checksum,
|
||||
finalEnv, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+t.arch+`/obj.go
|
||||
@@ -181,7 +163,16 @@ rm \
|
||||
cmd/cgo/internal/testsanitizers/tsan_test.go \
|
||||
cmd/cgo/internal/testsanitizers/cshared_test.go
|
||||
`, go125,
|
||||
)
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newGoLatest,
|
||||
|
||||
Name: "go",
|
||||
Description: "the Go programming language toolchain",
|
||||
Website: "https://go.dev/",
|
||||
|
||||
ID: 1227,
|
||||
})
|
||||
}
|
||||
|
||||
60
internal/rosa/gtk.go
Normal file
60
internal/rosa/gtk.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"hakurei.app/fhs"
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newGLib() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.88.1"
|
||||
checksum = "Rkszn6W4RHjyspyqfXdVAVawdwDJCuS0Zu0f7qot7tbJhnw2fUDoUUJB40m-1MCX"
|
||||
)
|
||||
return t.NewPackage("glib", version, t.newTagRemote(
|
||||
"https://gitlab.gnome.org/GNOME/glib.git",
|
||||
version, checksum,
|
||||
), &PackageAttr{
|
||||
Paths: []pkg.ExecPath{
|
||||
pkg.Path(fhs.AbsEtc.Append(
|
||||
"machine-id",
|
||||
), false, pkg.NewFile(
|
||||
"glib-machine-id",
|
||||
[]byte("ffffffffffffffffffffffffffffffff\n"),
|
||||
)),
|
||||
pkg.Path(AbsSystem.Append(
|
||||
"var/lib/dbus/machine-id",
|
||||
), false, pkg.NewFile(
|
||||
"glib-machine-id",
|
||||
[]byte("fefefefefefefefefefefefefefefefe\n"),
|
||||
)),
|
||||
},
|
||||
}, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Ddefault_library", "both"},
|
||||
},
|
||||
},
|
||||
PythonPackaging,
|
||||
Bash,
|
||||
|
||||
PCRE2,
|
||||
Libffi,
|
||||
Zlib,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newGLib,
|
||||
|
||||
Name: "glib",
|
||||
Description: "the GNU library of miscellaneous stuff",
|
||||
Website: "https://developer.gnome.org/glib/",
|
||||
|
||||
Dependencies: P{
|
||||
PCRE2,
|
||||
Libffi,
|
||||
Zlib,
|
||||
},
|
||||
|
||||
ID: 10024,
|
||||
})
|
||||
}
|
||||
113
internal/rosa/hakurei.go
Normal file
113
internal/rosa/hakurei.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newHakurei(
|
||||
suffix, script string,
|
||||
withHostname bool,
|
||||
) pkg.Artifact {
|
||||
hostname := `
|
||||
echo 'Building test helper (hostname).'
|
||||
go build -o /bin/hostname /usr/src/hostname/main.go
|
||||
`
|
||||
if !withHostname {
|
||||
hostname = ""
|
||||
}
|
||||
|
||||
return t.New("hakurei"+suffix+"-"+hakureiVersion, 0, t.Append(nil,
|
||||
Go,
|
||||
PkgConfig,
|
||||
|
||||
// dist tarball
|
||||
Gzip,
|
||||
|
||||
// statically linked
|
||||
Libseccomp,
|
||||
ACL,
|
||||
Fuse,
|
||||
XCB,
|
||||
Wayland,
|
||||
WaylandProtocols,
|
||||
|
||||
KernelHeaders,
|
||||
), nil, []string{
|
||||
"CGO_ENABLED=1",
|
||||
"GOCACHE=/tmp/gocache",
|
||||
"CC=clang -O3 -Werror",
|
||||
}, hostname+`
|
||||
cd /usr/src/hakurei
|
||||
|
||||
HAKUREI_VERSION='v`+hakureiVersion+`'
|
||||
`+script, pkg.Path(AbsUsrSrc.Append("hakurei"), true, t.NewPatchedSource(
|
||||
"hakurei", hakureiVersion, hakureiSource, false, hakureiPatches...,
|
||||
)), pkg.Path(AbsUsrSrc.Append("hostname", "main.go"), false, pkg.NewFile(
|
||||
"hostname.go",
|
||||
[]byte(`
|
||||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
func main() {
|
||||
if name, err := os.Hostname(); err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
os.Stdout.WriteString(name)
|
||||
}
|
||||
}
|
||||
`),
|
||||
)))
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newHakurei("", `
|
||||
mkdir -p /work/system/libexec/hakurei/
|
||||
|
||||
echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)."
|
||||
go generate ./...
|
||||
go build -trimpath -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||
-buildid=
|
||||
-linkmode external
|
||||
-extldflags=-static
|
||||
-X hakurei.app/internal/info.buildVersion=${HAKUREI_VERSION}
|
||||
-X hakurei.app/internal/info.hakureiPath=/system/bin/hakurei
|
||||
-X hakurei.app/internal/info.hsuPath=/system/bin/hsu
|
||||
-X main.hakureiPath=/system/bin/hakurei
|
||||
" ./...
|
||||
echo
|
||||
|
||||
echo '##### Testing hakurei.'
|
||||
go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
|
||||
echo
|
||||
|
||||
mkdir -p /work/system/bin/
|
||||
(cd /work/system/libexec/hakurei && mv \
|
||||
hakurei \
|
||||
sharefs \
|
||||
../../bin/)
|
||||
`, true), hakureiVersion
|
||||
},
|
||||
|
||||
Name: "hakurei",
|
||||
Description: "low-level userspace tooling for Rosa OS",
|
||||
Website: "https://hakurei.app/",
|
||||
|
||||
ID: 388834,
|
||||
})
|
||||
native.MustRegister(&Artifact{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
name := "all"
|
||||
if t.opts&OptSkipCheck != 0 {
|
||||
name = "make"
|
||||
}
|
||||
return t.newHakurei("-dist", `
|
||||
export HAKUREI_VERSION
|
||||
DESTDIR=/work /usr/src/hakurei/`+name+`.sh
|
||||
`, true), hakureiVersion
|
||||
},
|
||||
|
||||
Name: "hakurei-dist",
|
||||
Description: "low-level userspace tooling for Rosa OS (distribution tarball)",
|
||||
Website: "https://hakurei.app/",
|
||||
})
|
||||
}
|
||||
26
internal/rosa/hakurei_current.go
Normal file
26
internal/rosa/hakurei_current.go
Normal file
@@ -0,0 +1,26 @@
|
||||
//go:build current
|
||||
|
||||
package rosa
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
const hakureiVersion = "1.0-current"
|
||||
|
||||
// hakureiSourceTarball is a compressed tarball of the hakurei source code.
|
||||
//
|
||||
//go:generate tar -zc -C ../.. --exclude .git --exclude *.tar.gz -f hakurei_current.tar.gz .
|
||||
//go:embed hakurei_current.tar.gz
|
||||
var hakureiSourceTarball []byte
|
||||
|
||||
// hakureiSource is the source code at the time this package is compiled.
|
||||
var hakureiSource = pkg.NewTar(pkg.NewFile(
|
||||
"hakurei-current.tar.gz",
|
||||
hakureiSourceTarball,
|
||||
), pkg.TarGzip)
|
||||
|
||||
// hakureiPatches are patches applied against the compile-time source tree.
|
||||
var hakureiPatches []KV
|
||||
18
internal/rosa/hakurei_release.go
Normal file
18
internal/rosa/hakurei_release.go
Normal file
@@ -0,0 +1,18 @@
|
||||
//go:build !current
|
||||
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
const hakureiVersion = "0.4.2"
|
||||
|
||||
// hakureiSource is the source code of a hakurei release.
|
||||
var hakureiSource = newTar(
|
||||
"https://git.gensokyo.uk/rosa/hakurei/archive/"+
|
||||
"v"+hakureiVersion+".tar.gz",
|
||||
"jadgaOrxv5ABGvzQ_Rk0aPGz7U8K-427TbMhQNQ32scSizEnlR44Pu7NoWYWVZWq",
|
||||
pkg.TarGzip,
|
||||
)
|
||||
|
||||
// hakureiPatches are patches applied against a hakurei release.
|
||||
var hakureiPatches []KV
|
||||
34
internal/rosa/hwdata.go
Normal file
34
internal/rosa/hwdata.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newHwdata() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.407"
|
||||
checksum = "6p1XD0CRuzt6hLfjv4ShKBW934BexmoPkRrmwxD4J63fBVCzVBRHyF8pVJdW_Xjm"
|
||||
)
|
||||
return t.NewPackage("hwdata", version, newFromGitHub(
|
||||
"vcrhonek/hwdata",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Writable: true,
|
||||
EnterSource: true,
|
||||
}, &MakeHelper{
|
||||
// awk: fatal: cannot open file `hwdata.spec' for reading: No such file or directory
|
||||
InPlace: true,
|
||||
|
||||
// lspci: Unknown option 'A' (see "lspci --help")
|
||||
SkipCheck: true,
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newHwdata,
|
||||
|
||||
Name: "hwdata",
|
||||
Description: "contains various hardware identification and configuration data",
|
||||
Website: "https://github.com/vcrhonek/hwdata",
|
||||
|
||||
ID: 5387,
|
||||
})
|
||||
}
|
||||
73
internal/rosa/images.go
Normal file
73
internal/rosa/images.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"hakurei.app/fhs"
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
Name: "earlyinit",
|
||||
Description: "Rosa OS initramfs init program",
|
||||
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.newHakurei("-early-init", `
|
||||
mkdir -p /work/system/libexec/hakurei/
|
||||
|
||||
echo '# Building earlyinit.'
|
||||
go build -trimpath -v -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||
-buildid=
|
||||
-linkmode external
|
||||
-extldflags=-static
|
||||
-X hakurei.app/internal/info.buildVersion=${HAKUREI_VERSION}
|
||||
" ./cmd/earlyinit
|
||||
echo
|
||||
`, false), Unversioned
|
||||
},
|
||||
})
|
||||
}
|
||||
func (t Toolchain) newImageSystem() (pkg.Artifact, string) {
|
||||
return t.New("system.img", TNoToolchain, t.Append(nil,
|
||||
SquashfsTools,
|
||||
), nil, nil, `
|
||||
mksquashfs /mnt/system /work/system.img
|
||||
`, pkg.Path(fhs.AbsRoot.Append("mnt"), false, t.Append(nil,
|
||||
Musl,
|
||||
Mksh,
|
||||
Toybox,
|
||||
|
||||
Kmod,
|
||||
Kernel,
|
||||
Firmware,
|
||||
)...)), Unversioned
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
Name: "system-image",
|
||||
Description: "Rosa OS system image",
|
||||
|
||||
f: Toolchain.newImageSystem,
|
||||
})
|
||||
}
|
||||
func (t Toolchain) newImageInitramfs() (pkg.Artifact, string) {
|
||||
return t.New("initramfs", TNoToolchain, t.Append(nil,
|
||||
Zstd,
|
||||
EarlyInit,
|
||||
GenInitCPIO,
|
||||
), nil, nil, `
|
||||
gen_init_cpio -t 4294967295 -c /usr/src/initramfs | zstd > /work/initramfs.zst
|
||||
`, pkg.Path(AbsUsrSrc.Append("initramfs"), false, pkg.NewFile("initramfs", []byte(`
|
||||
dir /dev 0755 0 0
|
||||
nod /dev/null 0666 0 0 c 1 3
|
||||
nod /dev/console 0600 0 0 c 5 1
|
||||
file /init /system/libexec/hakurei/earlyinit 0555 0 0
|
||||
`)))), Unversioned
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
Name: "initramfs-image",
|
||||
Description: "Rosa OS initramfs image",
|
||||
|
||||
f: Toolchain.newImageInitramfs,
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,118 @@
|
||||
From f54a91f5337cd918eb86cf600320d25b6cfd8209 Mon Sep 17 00:00:00 2001
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
const kernelVersion = "6.12.87"
|
||||
|
||||
var kernelSource = newTar(
|
||||
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
|
||||
"snapshot/linux-"+kernelVersion+".tar.gz",
|
||||
"QTl5teIy0K5KsOLYGHQ3FbnPCZNRH2bySXVzghiOoHDdM3zAcSPUkmdly85lMzHx",
|
||||
pkg.TarGzip,
|
||||
)
|
||||
|
||||
func (t Toolchain) newKernelSource() (pkg.Artifact, string) {
|
||||
return t.New("kernel-"+kernelVersion+"-src", 0, nil, nil, nil, `
|
||||
mkdir -p /work/usr/src/
|
||||
cp -r /usr/src/linux /work/usr/src/
|
||||
chmod -R +w /work/usr/src/linux/
|
||||
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newKernelSource,
|
||||
|
||||
Name: "kernel-source",
|
||||
Description: "a writable kernel source tree installed to /usr/src/linux",
|
||||
Website: "https://kernel.org/",
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newKernelHeaders() (pkg.Artifact, string) {
|
||||
checksum := perArch[string]{
|
||||
"amd64": "lCmBNcMeUmXifg0vecKOPy3GAaFcJSmOPnf3wit9xYTDSTsFADPt1xxUFfmTn1fD",
|
||||
"arm64": "PlRxp4JzZeMGx7CScRlT1NBzc2NVyJlb8Gm8sa3ofFght9ZT101ZJhcIXiCkHSHM",
|
||||
}
|
||||
return t.NewPackage("kernel-headers", kernelVersion, kernelSource, &PackageAttr{
|
||||
Flag: TEarly,
|
||||
KnownChecksum: new(mustDecode(checksum.unwrap(t.S))),
|
||||
|
||||
Paths: []pkg.ExecPath{
|
||||
// updated manually for API changes
|
||||
pkg.Path(AbsUsrSrc.Append("version.h"), false, pkg.NewFile(
|
||||
"version.h", []byte(`#define LINUX_VERSION_CODE 396372
|
||||
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
|
||||
#define LINUX_VERSION_MAJOR 6
|
||||
#define LINUX_VERSION_PATCHLEVEL 12
|
||||
#define LINUX_VERSION_SUBLEVEL 84
|
||||
`),
|
||||
)),
|
||||
},
|
||||
}, &MakeHelper{
|
||||
SkipConfigure: true,
|
||||
|
||||
SkipCheck: true,
|
||||
Make: []string{
|
||||
"-f /usr/src/kernel-headers/Makefile",
|
||||
"O=/tmp/kbuild",
|
||||
"LLVM=1",
|
||||
`HOSTLDFLAGS="${LDFLAGS:-''}"`,
|
||||
"INSTALL_HDR_PATH=/work/system",
|
||||
"headers_install",
|
||||
},
|
||||
Install: `
|
||||
cat \
|
||||
/usr/src/version.h > \
|
||||
/work/system/include/linux/version.h
|
||||
`,
|
||||
},
|
||||
Rsync,
|
||||
), kernelVersion
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newKernelHeaders,
|
||||
|
||||
Name: "kernel-headers",
|
||||
Description: "an installation of kernel headers",
|
||||
Website: "https://kernel.org/",
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newKernel() (pkg.Artifact, string) {
|
||||
return t.NewPackage("kernel", kernelVersion, kernelSource, &PackageAttr{
|
||||
Env: []string{
|
||||
"PATH=/system/sbin",
|
||||
},
|
||||
ScriptEarly: `
|
||||
install -Dm0400 \
|
||||
/usr/src/.config \
|
||||
/tmp/kbuild/.config
|
||||
install -Dm0500 \
|
||||
/usr/src/.installkernel \
|
||||
/sbin/installkernel
|
||||
`,
|
||||
|
||||
Paths: []pkg.ExecPath{
|
||||
pkg.Path(AbsUsrSrc.Append(
|
||||
".config",
|
||||
), false, pkg.NewFile(".config", kernelConfig)),
|
||||
pkg.Path(AbsUsrSrc.Append(
|
||||
".installkernel",
|
||||
), false, pkg.NewFile("installkernel", []byte(`#!/bin/sh -e
|
||||
echo "Installing linux $1..."
|
||||
cp -av "$2" "$4"
|
||||
cp -av "$3" "$4"
|
||||
`))),
|
||||
pkg.Path(AbsUsrSrc.Append(
|
||||
".depmod",
|
||||
), false, pkg.NewFile("depmod", []byte(`#!/bin/sh
|
||||
exec /system/sbin/depmod -m /lib/modules "$@"
|
||||
`))),
|
||||
},
|
||||
|
||||
Patches: []KV{
|
||||
{"f54a91f5337cd918eb86cf600320d25b6cfd8209", `From f54a91f5337cd918eb86cf600320d25b6cfd8209 Mon Sep 17 00:00:00 2001
|
||||
From: Nathan Chancellor <nathan@kernel.org>
|
||||
Date: Sat, 13 Dec 2025 19:58:10 +0900
|
||||
Subject: drm/amd/display: Reduce number of arguments of dcn30's
|
||||
@@ -604,3 +718,635 @@ index abe51cf3aab2..a244504cc1f2 100644
|
||||
for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) {
|
||||
--
|
||||
cgit 1.2.3-korg
|
||||
`},
|
||||
|
||||
{"6ce6fbfddc5b127e4f57c3b5bfdcf40239a4fc2f", `From 6ce6fbfddc5b127e4f57c3b5bfdcf40239a4fc2f Mon Sep 17 00:00:00 2001
|
||||
From: Nathan Chancellor <nathan@kernel.org>
|
||||
Date: Sat, 13 Dec 2025 19:58:11 +0900
|
||||
Subject: drm/amd/display: Reduce number of arguments of dcn30's
|
||||
CalculateWatermarksAndDRAMSpeedChangeSupport()
|
||||
|
||||
CalculateWatermarksAndDRAMSpeedChangeSupport() has a large number of
|
||||
parameters, which must be passed on the stack. Most of the parameters
|
||||
between the two callsites are the same, so they can be accessed through
|
||||
the existing mode_lib pointer, instead of being passed as explicit
|
||||
arguments. Doing this reduces the stack size of
|
||||
dml30_ModeSupportAndSystemConfigurationFull() from 1912 bytes to 1840
|
||||
bytes building for x86_64 with clang-22, helping stay under the 2048
|
||||
byte limit for display_mode_vba_30.c.
|
||||
|
||||
Additionally, now that there is a pointer to mode_lib->vba available,
|
||||
use 'v' consistently throughout the entire function.
|
||||
|
||||
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
|
||||
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
|
||||
(cherry picked from commit 563dfbefdf633c8d958398ddfa3955f9f40e47d9)
|
||||
---
|
||||
.../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 287 +++++----------------
|
||||
1 file changed, 66 insertions(+), 221 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
|
||||
index 2d19bb8de59c84..1df3412be3465d 100644
|
||||
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
|
||||
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
|
||||
@@ -265,62 +265,23 @@ static void CalculateDynamicMetadataParameters(
|
||||
static void CalculateWatermarksAndDRAMSpeedChangeSupport(
|
||||
struct display_mode_lib *mode_lib,
|
||||
unsigned int PrefetchMode,
|
||||
- unsigned int NumberOfActivePlanes,
|
||||
- unsigned int MaxLineBufferLines,
|
||||
- unsigned int LineBufferSize,
|
||||
- unsigned int DPPOutputBufferPixels,
|
||||
- unsigned int DETBufferSizeInKByte,
|
||||
- unsigned int WritebackInterfaceBufferSize,
|
||||
double DCFCLK,
|
||||
double ReturnBW,
|
||||
- bool GPUVMEnable,
|
||||
- unsigned int dpte_group_bytes[],
|
||||
- unsigned int MetaChunkSize,
|
||||
double UrgentLatency,
|
||||
double ExtraLatency,
|
||||
- double WritebackLatency,
|
||||
- double WritebackChunkSize,
|
||||
double SOCCLK,
|
||||
- double DRAMClockChangeLatency,
|
||||
- double SRExitTime,
|
||||
- double SREnterPlusExitTime,
|
||||
double DCFCLKDeepSleep,
|
||||
unsigned int DPPPerPlane[],
|
||||
- bool DCCEnable[],
|
||||
double DPPCLK[],
|
||||
unsigned int DETBufferSizeY[],
|
||||
unsigned int DETBufferSizeC[],
|
||||
unsigned int SwathHeightY[],
|
||||
unsigned int SwathHeightC[],
|
||||
- unsigned int LBBitPerPixel[],
|
||||
double SwathWidthY[],
|
||||
double SwathWidthC[],
|
||||
- double HRatio[],
|
||||
- double HRatioChroma[],
|
||||
- unsigned int vtaps[],
|
||||
- unsigned int VTAPsChroma[],
|
||||
- double VRatio[],
|
||||
- double VRatioChroma[],
|
||||
- unsigned int HTotal[],
|
||||
- double PixelClock[],
|
||||
- unsigned int BlendingAndTiming[],
|
||||
double BytePerPixelDETY[],
|
||||
double BytePerPixelDETC[],
|
||||
- double DSTXAfterScaler[],
|
||||
- double DSTYAfterScaler[],
|
||||
- bool WritebackEnable[],
|
||||
- enum source_format_class WritebackPixelFormat[],
|
||||
- double WritebackDestinationWidth[],
|
||||
- double WritebackDestinationHeight[],
|
||||
- double WritebackSourceHeight[],
|
||||
- enum clock_change_support *DRAMClockChangeSupport,
|
||||
- double *UrgentWatermark,
|
||||
- double *WritebackUrgentWatermark,
|
||||
- double *DRAMClockChangeWatermark,
|
||||
- double *WritebackDRAMClockChangeWatermark,
|
||||
- double *StutterExitWatermark,
|
||||
- double *StutterEnterPlusExitWatermark,
|
||||
- double *MinActiveDRAMClockChangeLatencySupported);
|
||||
+ enum clock_change_support *DRAMClockChangeSupport);
|
||||
static void CalculateDCFCLKDeepSleep(
|
||||
struct display_mode_lib *mode_lib,
|
||||
unsigned int NumberOfActivePlanes,
|
||||
@@ -2646,62 +2607,23 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
|
||||
CalculateWatermarksAndDRAMSpeedChangeSupport(
|
||||
mode_lib,
|
||||
PrefetchMode,
|
||||
- v->NumberOfActivePlanes,
|
||||
- v->MaxLineBufferLines,
|
||||
- v->LineBufferSize,
|
||||
- v->DPPOutputBufferPixels,
|
||||
- v->DETBufferSizeInKByte[0],
|
||||
- v->WritebackInterfaceBufferSize,
|
||||
v->DCFCLK,
|
||||
v->ReturnBW,
|
||||
- v->GPUVMEnable,
|
||||
- v->dpte_group_bytes,
|
||||
- v->MetaChunkSize,
|
||||
v->UrgentLatency,
|
||||
v->UrgentExtraLatency,
|
||||
- v->WritebackLatency,
|
||||
- v->WritebackChunkSize,
|
||||
v->SOCCLK,
|
||||
- v->FinalDRAMClockChangeLatency,
|
||||
- v->SRExitTime,
|
||||
- v->SREnterPlusExitTime,
|
||||
v->DCFCLKDeepSleep,
|
||||
v->DPPPerPlane,
|
||||
- v->DCCEnable,
|
||||
v->DPPCLK,
|
||||
v->DETBufferSizeY,
|
||||
v->DETBufferSizeC,
|
||||
v->SwathHeightY,
|
||||
v->SwathHeightC,
|
||||
- v->LBBitPerPixel,
|
||||
v->SwathWidthY,
|
||||
v->SwathWidthC,
|
||||
- v->HRatio,
|
||||
- v->HRatioChroma,
|
||||
- v->vtaps,
|
||||
- v->VTAPsChroma,
|
||||
- v->VRatio,
|
||||
- v->VRatioChroma,
|
||||
- v->HTotal,
|
||||
- v->PixelClock,
|
||||
- v->BlendingAndTiming,
|
||||
v->BytePerPixelDETY,
|
||||
v->BytePerPixelDETC,
|
||||
- v->DSTXAfterScaler,
|
||||
- v->DSTYAfterScaler,
|
||||
- v->WritebackEnable,
|
||||
- v->WritebackPixelFormat,
|
||||
- v->WritebackDestinationWidth,
|
||||
- v->WritebackDestinationHeight,
|
||||
- v->WritebackSourceHeight,
|
||||
- &DRAMClockChangeSupport,
|
||||
- &v->UrgentWatermark,
|
||||
- &v->WritebackUrgentWatermark,
|
||||
- &v->DRAMClockChangeWatermark,
|
||||
- &v->WritebackDRAMClockChangeWatermark,
|
||||
- &v->StutterExitWatermark,
|
||||
- &v->StutterEnterPlusExitWatermark,
|
||||
- &v->MinActiveDRAMClockChangeLatencySupported);
|
||||
+ &DRAMClockChangeSupport);
|
||||
|
||||
for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
if (v->WritebackEnable[k] == true) {
|
||||
@@ -4895,62 +4817,23 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
|
||||
CalculateWatermarksAndDRAMSpeedChangeSupport(
|
||||
mode_lib,
|
||||
v->PrefetchModePerState[i][j],
|
||||
- v->NumberOfActivePlanes,
|
||||
- v->MaxLineBufferLines,
|
||||
- v->LineBufferSize,
|
||||
- v->DPPOutputBufferPixels,
|
||||
- v->DETBufferSizeInKByte[0],
|
||||
- v->WritebackInterfaceBufferSize,
|
||||
v->DCFCLKState[i][j],
|
||||
v->ReturnBWPerState[i][j],
|
||||
- v->GPUVMEnable,
|
||||
- v->dpte_group_bytes,
|
||||
- v->MetaChunkSize,
|
||||
v->UrgLatency[i],
|
||||
v->ExtraLatency,
|
||||
- v->WritebackLatency,
|
||||
- v->WritebackChunkSize,
|
||||
v->SOCCLKPerState[i],
|
||||
- v->FinalDRAMClockChangeLatency,
|
||||
- v->SRExitTime,
|
||||
- v->SREnterPlusExitTime,
|
||||
v->ProjectedDCFCLKDeepSleep[i][j],
|
||||
v->NoOfDPPThisState,
|
||||
- v->DCCEnable,
|
||||
v->RequiredDPPCLKThisState,
|
||||
v->DETBufferSizeYThisState,
|
||||
v->DETBufferSizeCThisState,
|
||||
v->SwathHeightYThisState,
|
||||
v->SwathHeightCThisState,
|
||||
- v->LBBitPerPixel,
|
||||
v->SwathWidthYThisState,
|
||||
v->SwathWidthCThisState,
|
||||
- v->HRatio,
|
||||
- v->HRatioChroma,
|
||||
- v->vtaps,
|
||||
- v->VTAPsChroma,
|
||||
- v->VRatio,
|
||||
- v->VRatioChroma,
|
||||
- v->HTotal,
|
||||
- v->PixelClock,
|
||||
- v->BlendingAndTiming,
|
||||
v->BytePerPixelInDETY,
|
||||
v->BytePerPixelInDETC,
|
||||
- v->DSTXAfterScaler,
|
||||
- v->DSTYAfterScaler,
|
||||
- v->WritebackEnable,
|
||||
- v->WritebackPixelFormat,
|
||||
- v->WritebackDestinationWidth,
|
||||
- v->WritebackDestinationHeight,
|
||||
- v->WritebackSourceHeight,
|
||||
- &v->DRAMClockChangeSupport[i][j],
|
||||
- &v->UrgentWatermark,
|
||||
- &v->WritebackUrgentWatermark,
|
||||
- &v->DRAMClockChangeWatermark,
|
||||
- &v->WritebackDRAMClockChangeWatermark,
|
||||
- &v->StutterExitWatermark,
|
||||
- &v->StutterEnterPlusExitWatermark,
|
||||
- &v->MinActiveDRAMClockChangeLatencySupported);
|
||||
+ &v->DRAMClockChangeSupport[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5067,63 +4950,25 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
|
||||
static void CalculateWatermarksAndDRAMSpeedChangeSupport(
|
||||
struct display_mode_lib *mode_lib,
|
||||
unsigned int PrefetchMode,
|
||||
- unsigned int NumberOfActivePlanes,
|
||||
- unsigned int MaxLineBufferLines,
|
||||
- unsigned int LineBufferSize,
|
||||
- unsigned int DPPOutputBufferPixels,
|
||||
- unsigned int DETBufferSizeInKByte,
|
||||
- unsigned int WritebackInterfaceBufferSize,
|
||||
double DCFCLK,
|
||||
double ReturnBW,
|
||||
- bool GPUVMEnable,
|
||||
- unsigned int dpte_group_bytes[],
|
||||
- unsigned int MetaChunkSize,
|
||||
double UrgentLatency,
|
||||
double ExtraLatency,
|
||||
- double WritebackLatency,
|
||||
- double WritebackChunkSize,
|
||||
double SOCCLK,
|
||||
- double DRAMClockChangeLatency,
|
||||
- double SRExitTime,
|
||||
- double SREnterPlusExitTime,
|
||||
double DCFCLKDeepSleep,
|
||||
unsigned int DPPPerPlane[],
|
||||
- bool DCCEnable[],
|
||||
double DPPCLK[],
|
||||
unsigned int DETBufferSizeY[],
|
||||
unsigned int DETBufferSizeC[],
|
||||
unsigned int SwathHeightY[],
|
||||
unsigned int SwathHeightC[],
|
||||
- unsigned int LBBitPerPixel[],
|
||||
double SwathWidthY[],
|
||||
double SwathWidthC[],
|
||||
- double HRatio[],
|
||||
- double HRatioChroma[],
|
||||
- unsigned int vtaps[],
|
||||
- unsigned int VTAPsChroma[],
|
||||
- double VRatio[],
|
||||
- double VRatioChroma[],
|
||||
- unsigned int HTotal[],
|
||||
- double PixelClock[],
|
||||
- unsigned int BlendingAndTiming[],
|
||||
double BytePerPixelDETY[],
|
||||
double BytePerPixelDETC[],
|
||||
- double DSTXAfterScaler[],
|
||||
- double DSTYAfterScaler[],
|
||||
- bool WritebackEnable[],
|
||||
- enum source_format_class WritebackPixelFormat[],
|
||||
- double WritebackDestinationWidth[],
|
||||
- double WritebackDestinationHeight[],
|
||||
- double WritebackSourceHeight[],
|
||||
- enum clock_change_support *DRAMClockChangeSupport,
|
||||
- double *UrgentWatermark,
|
||||
- double *WritebackUrgentWatermark,
|
||||
- double *DRAMClockChangeWatermark,
|
||||
- double *WritebackDRAMClockChangeWatermark,
|
||||
- double *StutterExitWatermark,
|
||||
- double *StutterEnterPlusExitWatermark,
|
||||
- double *MinActiveDRAMClockChangeLatencySupported)
|
||||
+ enum clock_change_support *DRAMClockChangeSupport)
|
||||
{
|
||||
+ struct vba_vars_st *v = &mode_lib->vba;
|
||||
double EffectiveLBLatencyHidingY = 0;
|
||||
double EffectiveLBLatencyHidingC = 0;
|
||||
double LinesInDETY[DC__NUM_DPP__MAX] = { 0 };
|
||||
@@ -5142,101 +4987,101 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
|
||||
double WritebackDRAMClockChangeLatencyHiding = 0;
|
||||
unsigned int k, j;
|
||||
|
||||
- mode_lib->vba.TotalActiveDPP = 0;
|
||||
- mode_lib->vba.TotalDCCActiveDPP = 0;
|
||||
- for (k = 0; k < NumberOfActivePlanes; ++k) {
|
||||
- mode_lib->vba.TotalActiveDPP = mode_lib->vba.TotalActiveDPP + DPPPerPlane[k];
|
||||
- if (DCCEnable[k] == true) {
|
||||
- mode_lib->vba.TotalDCCActiveDPP = mode_lib->vba.TotalDCCActiveDPP + DPPPerPlane[k];
|
||||
+ v->TotalActiveDPP = 0;
|
||||
+ v->TotalDCCActiveDPP = 0;
|
||||
+ for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
+ v->TotalActiveDPP = v->TotalActiveDPP + DPPPerPlane[k];
|
||||
+ if (v->DCCEnable[k] == true) {
|
||||
+ v->TotalDCCActiveDPP = v->TotalDCCActiveDPP + DPPPerPlane[k];
|
||||
}
|
||||
}
|
||||
|
||||
- *UrgentWatermark = UrgentLatency + ExtraLatency;
|
||||
+ v->UrgentWatermark = UrgentLatency + ExtraLatency;
|
||||
|
||||
- *DRAMClockChangeWatermark = DRAMClockChangeLatency + *UrgentWatermark;
|
||||
+ v->DRAMClockChangeWatermark = v->FinalDRAMClockChangeLatency + v->UrgentWatermark;
|
||||
|
||||
- mode_lib->vba.TotalActiveWriteback = 0;
|
||||
- for (k = 0; k < NumberOfActivePlanes; ++k) {
|
||||
- if (WritebackEnable[k] == true) {
|
||||
- mode_lib->vba.TotalActiveWriteback = mode_lib->vba.TotalActiveWriteback + 1;
|
||||
+ v->TotalActiveWriteback = 0;
|
||||
+ for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
+ if (v->WritebackEnable[k] == true) {
|
||||
+ v->TotalActiveWriteback = v->TotalActiveWriteback + 1;
|
||||
}
|
||||
}
|
||||
|
||||
- if (mode_lib->vba.TotalActiveWriteback <= 1) {
|
||||
- *WritebackUrgentWatermark = WritebackLatency;
|
||||
+ if (v->TotalActiveWriteback <= 1) {
|
||||
+ v->WritebackUrgentWatermark = v->WritebackLatency;
|
||||
} else {
|
||||
- *WritebackUrgentWatermark = WritebackLatency + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
|
||||
+ v->WritebackUrgentWatermark = v->WritebackLatency + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
|
||||
}
|
||||
|
||||
- if (mode_lib->vba.TotalActiveWriteback <= 1) {
|
||||
- *WritebackDRAMClockChangeWatermark = DRAMClockChangeLatency + WritebackLatency;
|
||||
+ if (v->TotalActiveWriteback <= 1) {
|
||||
+ v->WritebackDRAMClockChangeWatermark = v->FinalDRAMClockChangeLatency + v->WritebackLatency;
|
||||
} else {
|
||||
- *WritebackDRAMClockChangeWatermark = DRAMClockChangeLatency + WritebackLatency + WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
|
||||
+ v->WritebackDRAMClockChangeWatermark = v->FinalDRAMClockChangeLatency + v->WritebackLatency + v->WritebackChunkSize * 1024.0 / 32.0 / SOCCLK;
|
||||
}
|
||||
|
||||
- for (k = 0; k < NumberOfActivePlanes; ++k) {
|
||||
+ for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
|
||||
- mode_lib->vba.LBLatencyHidingSourceLinesY = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(HRatio[k], 1.0)), 1)) - (vtaps[k] - 1);
|
||||
+ v->LBLatencyHidingSourceLinesY = dml_min((double) v->MaxLineBufferLines, dml_floor(v->LineBufferSize / v->LBBitPerPixel[k] / (SwathWidthY[k] / dml_max(v->HRatio[k], 1.0)), 1)) - (v->vtaps[k] - 1);
|
||||
|
||||
- mode_lib->vba.LBLatencyHidingSourceLinesC = dml_min((double) MaxLineBufferLines, dml_floor(LineBufferSize / LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(HRatioChroma[k], 1.0)), 1)) - (VTAPsChroma[k] - 1);
|
||||
+ v->LBLatencyHidingSourceLinesC = dml_min((double) v->MaxLineBufferLines, dml_floor(v->LineBufferSize / v->LBBitPerPixel[k] / (SwathWidthC[k] / dml_max(v->HRatioChroma[k], 1.0)), 1)) - (v->VTAPsChroma[k] - 1);
|
||||
|
||||
- EffectiveLBLatencyHidingY = mode_lib->vba.LBLatencyHidingSourceLinesY / VRatio[k] * (HTotal[k] / PixelClock[k]);
|
||||
+ EffectiveLBLatencyHidingY = v->LBLatencyHidingSourceLinesY / v->VRatio[k] * (v->HTotal[k] / v->PixelClock[k]);
|
||||
|
||||
- EffectiveLBLatencyHidingC = mode_lib->vba.LBLatencyHidingSourceLinesC / VRatioChroma[k] * (HTotal[k] / PixelClock[k]);
|
||||
+ EffectiveLBLatencyHidingC = v->LBLatencyHidingSourceLinesC / v->VRatioChroma[k] * (v->HTotal[k] / v->PixelClock[k]);
|
||||
|
||||
LinesInDETY[k] = (double) DETBufferSizeY[k] / BytePerPixelDETY[k] / SwathWidthY[k];
|
||||
LinesInDETYRoundedDownToSwath[k] = dml_floor(LinesInDETY[k], SwathHeightY[k]);
|
||||
- FullDETBufferingTimeY[k] = LinesInDETYRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatio[k];
|
||||
+ FullDETBufferingTimeY[k] = LinesInDETYRoundedDownToSwath[k] * (v->HTotal[k] / v->PixelClock[k]) / v->VRatio[k];
|
||||
if (BytePerPixelDETC[k] > 0) {
|
||||
- LinesInDETC = mode_lib->vba.DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k];
|
||||
+ LinesInDETC = v->DETBufferSizeC[k] / BytePerPixelDETC[k] / SwathWidthC[k];
|
||||
LinesInDETCRoundedDownToSwath = dml_floor(LinesInDETC, SwathHeightC[k]);
|
||||
- FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath * (HTotal[k] / PixelClock[k]) / VRatioChroma[k];
|
||||
+ FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath * (v->HTotal[k] / v->PixelClock[k]) / v->VRatioChroma[k];
|
||||
} else {
|
||||
LinesInDETC = 0;
|
||||
FullDETBufferingTimeC = 999999;
|
||||
}
|
||||
|
||||
- ActiveDRAMClockChangeLatencyMarginY = EffectiveLBLatencyHidingY + FullDETBufferingTimeY[k] - *UrgentWatermark - (HTotal[k] / PixelClock[k]) * (DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) - *DRAMClockChangeWatermark;
|
||||
+ ActiveDRAMClockChangeLatencyMarginY = EffectiveLBLatencyHidingY + FullDETBufferingTimeY[k] - v->UrgentWatermark - (v->HTotal[k] / v->PixelClock[k]) * (v->DSTXAfterScaler[k] / v->HTotal[k] + v->DSTYAfterScaler[k]) - v->DRAMClockChangeWatermark;
|
||||
|
||||
- if (NumberOfActivePlanes > 1) {
|
||||
- ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightY[k] * HTotal[k] / PixelClock[k] / VRatio[k];
|
||||
+ if (v->NumberOfActivePlanes > 1) {
|
||||
+ ActiveDRAMClockChangeLatencyMarginY = ActiveDRAMClockChangeLatencyMarginY - (1 - 1.0 / v->NumberOfActivePlanes) * SwathHeightY[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatio[k];
|
||||
}
|
||||
|
||||
if (BytePerPixelDETC[k] > 0) {
|
||||
- ActiveDRAMClockChangeLatencyMarginC = EffectiveLBLatencyHidingC + FullDETBufferingTimeC - *UrgentWatermark - (HTotal[k] / PixelClock[k]) * (DSTXAfterScaler[k] / HTotal[k] + DSTYAfterScaler[k]) - *DRAMClockChangeWatermark;
|
||||
+ ActiveDRAMClockChangeLatencyMarginC = EffectiveLBLatencyHidingC + FullDETBufferingTimeC - v->UrgentWatermark - (v->HTotal[k] / v->PixelClock[k]) * (v->DSTXAfterScaler[k] / v->HTotal[k] + v->DSTYAfterScaler[k]) - v->DRAMClockChangeWatermark;
|
||||
|
||||
- if (NumberOfActivePlanes > 1) {
|
||||
- ActiveDRAMClockChangeLatencyMarginC = ActiveDRAMClockChangeLatencyMarginC - (1 - 1.0 / NumberOfActivePlanes) * SwathHeightC[k] * HTotal[k] / PixelClock[k] / VRatioChroma[k];
|
||||
+ if (v->NumberOfActivePlanes > 1) {
|
||||
+ ActiveDRAMClockChangeLatencyMarginC = ActiveDRAMClockChangeLatencyMarginC - (1 - 1.0 / v->NumberOfActivePlanes) * SwathHeightC[k] * v->HTotal[k] / v->PixelClock[k] / v->VRatioChroma[k];
|
||||
}
|
||||
- mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, ActiveDRAMClockChangeLatencyMarginC);
|
||||
+ v->ActiveDRAMClockChangeLatencyMargin[k] = dml_min(ActiveDRAMClockChangeLatencyMarginY, ActiveDRAMClockChangeLatencyMarginC);
|
||||
} else {
|
||||
- mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = ActiveDRAMClockChangeLatencyMarginY;
|
||||
+ v->ActiveDRAMClockChangeLatencyMargin[k] = ActiveDRAMClockChangeLatencyMarginY;
|
||||
}
|
||||
|
||||
- if (WritebackEnable[k] == true) {
|
||||
+ if (v->WritebackEnable[k] == true) {
|
||||
|
||||
- WritebackDRAMClockChangeLatencyHiding = WritebackInterfaceBufferSize * 1024 / (WritebackDestinationWidth[k] * WritebackDestinationHeight[k] / (WritebackSourceHeight[k] * HTotal[k] / PixelClock[k]) * 4);
|
||||
- if (WritebackPixelFormat[k] == dm_444_64) {
|
||||
+ WritebackDRAMClockChangeLatencyHiding = v->WritebackInterfaceBufferSize * 1024 / (v->WritebackDestinationWidth[k] * v->WritebackDestinationHeight[k] / (v->WritebackSourceHeight[k] * v->HTotal[k] / v->PixelClock[k]) * 4);
|
||||
+ if (v->WritebackPixelFormat[k] == dm_444_64) {
|
||||
WritebackDRAMClockChangeLatencyHiding = WritebackDRAMClockChangeLatencyHiding / 2;
|
||||
}
|
||||
- if (mode_lib->vba.WritebackConfiguration == dm_whole_buffer_for_single_stream_interleave) {
|
||||
+ if (v->WritebackConfiguration == dm_whole_buffer_for_single_stream_interleave) {
|
||||
WritebackDRAMClockChangeLatencyHiding = WritebackDRAMClockChangeLatencyHiding * 2;
|
||||
}
|
||||
- WritebackDRAMClockChangeLatencyMargin = WritebackDRAMClockChangeLatencyHiding - mode_lib->vba.WritebackDRAMClockChangeWatermark;
|
||||
- mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] = dml_min(mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k], WritebackDRAMClockChangeLatencyMargin);
|
||||
+ WritebackDRAMClockChangeLatencyMargin = WritebackDRAMClockChangeLatencyHiding - v->WritebackDRAMClockChangeWatermark;
|
||||
+ v->ActiveDRAMClockChangeLatencyMargin[k] = dml_min(v->ActiveDRAMClockChangeLatencyMargin[k], WritebackDRAMClockChangeLatencyMargin);
|
||||
}
|
||||
}
|
||||
|
||||
- mode_lib->vba.MinActiveDRAMClockChangeMargin = 999999;
|
||||
+ v->MinActiveDRAMClockChangeMargin = 999999;
|
||||
PlaneWithMinActiveDRAMClockChangeMargin = 0;
|
||||
- for (k = 0; k < NumberOfActivePlanes; ++k) {
|
||||
- if (mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] < mode_lib->vba.MinActiveDRAMClockChangeMargin) {
|
||||
- mode_lib->vba.MinActiveDRAMClockChangeMargin = mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k];
|
||||
- if (BlendingAndTiming[k] == k) {
|
||||
+ for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
+ if (v->ActiveDRAMClockChangeLatencyMargin[k] < v->MinActiveDRAMClockChangeMargin) {
|
||||
+ v->MinActiveDRAMClockChangeMargin = v->ActiveDRAMClockChangeLatencyMargin[k];
|
||||
+ if (v->BlendingAndTiming[k] == k) {
|
||||
PlaneWithMinActiveDRAMClockChangeMargin = k;
|
||||
} else {
|
||||
- for (j = 0; j < NumberOfActivePlanes; ++j) {
|
||||
- if (BlendingAndTiming[k] == j) {
|
||||
+ for (j = 0; j < v->NumberOfActivePlanes; ++j) {
|
||||
+ if (v->BlendingAndTiming[k] == j) {
|
||||
PlaneWithMinActiveDRAMClockChangeMargin = j;
|
||||
}
|
||||
}
|
||||
@@ -5244,40 +5089,40 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
|
||||
}
|
||||
}
|
||||
|
||||
- *MinActiveDRAMClockChangeLatencySupported = mode_lib->vba.MinActiveDRAMClockChangeMargin + DRAMClockChangeLatency;
|
||||
+ v->MinActiveDRAMClockChangeLatencySupported = v->MinActiveDRAMClockChangeMargin + v->FinalDRAMClockChangeLatency;
|
||||
|
||||
SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = 999999;
|
||||
- for (k = 0; k < NumberOfActivePlanes; ++k) {
|
||||
- if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (BlendingAndTiming[k] == k)) && !(BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin) && mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k] < SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank) {
|
||||
- SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k];
|
||||
+ for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
+ if (!((k == PlaneWithMinActiveDRAMClockChangeMargin) && (v->BlendingAndTiming[k] == k)) && !(v->BlendingAndTiming[k] == PlaneWithMinActiveDRAMClockChangeMargin) && v->ActiveDRAMClockChangeLatencyMargin[k] < SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank) {
|
||||
+ SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank = v->ActiveDRAMClockChangeLatencyMargin[k];
|
||||
}
|
||||
}
|
||||
|
||||
- mode_lib->vba.TotalNumberOfActiveOTG = 0;
|
||||
- for (k = 0; k < NumberOfActivePlanes; ++k) {
|
||||
- if (BlendingAndTiming[k] == k) {
|
||||
- mode_lib->vba.TotalNumberOfActiveOTG = mode_lib->vba.TotalNumberOfActiveOTG + 1;
|
||||
+ v->TotalNumberOfActiveOTG = 0;
|
||||
+ for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
+ if (v->BlendingAndTiming[k] == k) {
|
||||
+ v->TotalNumberOfActiveOTG = v->TotalNumberOfActiveOTG + 1;
|
||||
}
|
||||
}
|
||||
|
||||
- if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) {
|
||||
+ if (v->MinActiveDRAMClockChangeMargin > 0) {
|
||||
*DRAMClockChangeSupport = dm_dram_clock_change_vactive;
|
||||
- } else if (((mode_lib->vba.SynchronizedVBlank == true || mode_lib->vba.TotalNumberOfActiveOTG == 1 || SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0) && PrefetchMode == 0)) {
|
||||
+ } else if (((v->SynchronizedVBlank == true || v->TotalNumberOfActiveOTG == 1 || SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0) && PrefetchMode == 0)) {
|
||||
*DRAMClockChangeSupport = dm_dram_clock_change_vblank;
|
||||
} else {
|
||||
*DRAMClockChangeSupport = dm_dram_clock_change_unsupported;
|
||||
}
|
||||
|
||||
FullDETBufferingTimeYStutterCriticalPlane = FullDETBufferingTimeY[0];
|
||||
- for (k = 0; k < NumberOfActivePlanes; ++k) {
|
||||
+ for (k = 0; k < v->NumberOfActivePlanes; ++k) {
|
||||
if (FullDETBufferingTimeY[k] <= FullDETBufferingTimeYStutterCriticalPlane) {
|
||||
FullDETBufferingTimeYStutterCriticalPlane = FullDETBufferingTimeY[k];
|
||||
- TimeToFinishSwathTransferStutterCriticalPlane = (SwathHeightY[k] - (LinesInDETY[k] - LinesInDETYRoundedDownToSwath[k])) * (HTotal[k] / PixelClock[k]) / VRatio[k];
|
||||
+ TimeToFinishSwathTransferStutterCriticalPlane = (SwathHeightY[k] - (LinesInDETY[k] - LinesInDETYRoundedDownToSwath[k])) * (v->HTotal[k] / v->PixelClock[k]) / v->VRatio[k];
|
||||
}
|
||||
}
|
||||
|
||||
- *StutterExitWatermark = SRExitTime + ExtraLatency + 10 / DCFCLKDeepSleep;
|
||||
- *StutterEnterPlusExitWatermark = dml_max(SREnterPlusExitTime + ExtraLatency + 10 / DCFCLKDeepSleep, TimeToFinishSwathTransferStutterCriticalPlane);
|
||||
+ v->StutterExitWatermark = v->SRExitTime + ExtraLatency + 10 / DCFCLKDeepSleep;
|
||||
+ v->StutterEnterPlusExitWatermark = dml_max(v->SREnterPlusExitTime + ExtraLatency + 10 / DCFCLKDeepSleep, TimeToFinishSwathTransferStutterCriticalPlane);
|
||||
|
||||
}
|
||||
|
||||
--
|
||||
cgit 1.2.3-korg
|
||||
`},
|
||||
},
|
||||
|
||||
Flag: TExclusive,
|
||||
}, &MakeHelper{
|
||||
OmitDefaults: true,
|
||||
SkipConfigure: true,
|
||||
|
||||
// Build, install, and boot kernel before running kselftest on it.
|
||||
SkipCheck: true,
|
||||
|
||||
Make: []string{
|
||||
"-f /usr/src/kernel/Makefile",
|
||||
"O=/tmp/kbuild",
|
||||
|
||||
"LLVM=1",
|
||||
"KBUILD_BUILD_VERSION='1-Rosa'",
|
||||
"KBUILD_BUILD_TIMESTAMP='2106-02-07 06:28:15 UTC'",
|
||||
"KBUILD_BUILD_USER=kbuild",
|
||||
"KBUILD_BUILD_HOST=localhost",
|
||||
"all",
|
||||
},
|
||||
Install: `
|
||||
# kernel is not aware of kmod moduledir
|
||||
install -Dm0500 \
|
||||
/usr/src/.depmod \
|
||||
/sbin/depmod
|
||||
|
||||
make \
|
||||
` + jobsFlagE + ` \
|
||||
-f /usr/src/kernel/Makefile \
|
||||
O=/tmp/kbuild \
|
||||
LLVM=1 \
|
||||
INSTALL_PATH=/work \
|
||||
install \
|
||||
INSTALL_MOD_PATH=/work/system \
|
||||
DEPMOD=/sbin/depmod \
|
||||
modules_install
|
||||
rm -v /work/system/lib/modules/` + kernelVersion + `/build
|
||||
`,
|
||||
},
|
||||
Flex,
|
||||
Bison,
|
||||
M4,
|
||||
Tar,
|
||||
Perl,
|
||||
BC,
|
||||
Sed,
|
||||
Gawk,
|
||||
Coreutils,
|
||||
Diffutils,
|
||||
Python,
|
||||
|
||||
XZ,
|
||||
Gzip,
|
||||
Kmod,
|
||||
Elfutils,
|
||||
UtilLinux,
|
||||
KernelHeaders,
|
||||
), kernelVersion
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newKernel,
|
||||
|
||||
Name: "kernel",
|
||||
Description: "the generic Rosa OS linux kernel",
|
||||
Website: "https://kernel.org/",
|
||||
|
||||
ID: 375621,
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newGenInitCPIO() (pkg.Artifact, string) {
|
||||
return t.New("gen_init_cpio-"+kernelVersion, 0, nil, nil, nil, `
|
||||
mkdir -p /work/system/bin/
|
||||
cc -o /work/system/bin/gen_init_cpio /usr/src/linux/usr/gen_init_cpio.c
|
||||
`, pkg.Path(AbsUsrSrc.Append("linux"), false, kernelSource)), kernelVersion
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newGenInitCPIO,
|
||||
|
||||
Name: "gen_init_cpio",
|
||||
Description: "a program in the kernel source tree for creating initramfs archive",
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newFirmware() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "20260410"
|
||||
checksum = "J8PdQlGqwrivpskPzbL6xacqR6mlKtXpe5RpzFfVzKPAgG81ZRXsc3qrxwdGJbil"
|
||||
)
|
||||
return t.NewPackage("firmware", version, newFromGitLab(
|
||||
"gitlab.com",
|
||||
"kernel-firmware/linux-firmware",
|
||||
version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
// dedup creates temporary file
|
||||
Writable: true,
|
||||
// does not use configure
|
||||
EnterSource: true,
|
||||
|
||||
Env: []string{
|
||||
"HOME=/proc/nonexistent",
|
||||
},
|
||||
}, &MakeHelper{
|
||||
OmitDefaults: true,
|
||||
SkipConfigure: true,
|
||||
InPlace: true,
|
||||
|
||||
Make: []string{
|
||||
"DESTDIR=/work/system",
|
||||
"install-zst",
|
||||
},
|
||||
SkipCheck: true, // requires pre-commit
|
||||
Install: "make " + jobsFlagE + " DESTDIR=/work/system dedup",
|
||||
},
|
||||
Parallel,
|
||||
Rdfind,
|
||||
Zstd,
|
||||
Findutils,
|
||||
Coreutils,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newFirmware,
|
||||
|
||||
Name: "firmware",
|
||||
Description: "firmware blobs for use with the Linux kernel",
|
||||
Website: "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/",
|
||||
|
||||
ID: 141464,
|
||||
})
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/x86 6.12.90 Kernel Configuration
|
||||
# Linux/x86 6.12.84 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.6"
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.4"
|
||||
CONFIG_GCC_VERSION=0
|
||||
CONFIG_CC_IS_CLANG=y
|
||||
CONFIG_CLANG_VERSION=220106
|
||||
CONFIG_CLANG_VERSION=220104
|
||||
CONFIG_AS_IS_LLVM=y
|
||||
CONFIG_AS_VERSION=220106
|
||||
CONFIG_AS_VERSION=220104
|
||||
CONFIG_LD_VERSION=0
|
||||
CONFIG_LD_IS_LLD=y
|
||||
CONFIG_LLD_VERSION=220106
|
||||
CONFIG_LLD_VERSION=220104
|
||||
CONFIG_RUSTC_VERSION=0
|
||||
CONFIG_RUSTC_LLVM_VERSION=0
|
||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||
@@ -12137,9 +12137,7 @@ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_NONE is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
|
||||
# CONFIG_DEBUG_INFO_SPLIT is not set
|
||||
# CONFIG_GDB_SCRIPTS is not set
|
||||
CONFIG_FRAME_WARN=2048
|
||||
8
internal/rosa/kernel_amd64.go
Normal file
8
internal/rosa/kernel_amd64.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package rosa
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed kernel_amd64.config
|
||||
var kernelConfig []byte
|
||||
|
||||
const kernelName = "bzImage"
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/arm64 6.12.90 Kernel Configuration
|
||||
# Linux/arm64 6.12.83 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.6"
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.4"
|
||||
CONFIG_GCC_VERSION=0
|
||||
CONFIG_CC_IS_CLANG=y
|
||||
CONFIG_CLANG_VERSION=220106
|
||||
CONFIG_CLANG_VERSION=220104
|
||||
CONFIG_AS_IS_LLVM=y
|
||||
CONFIG_AS_VERSION=220106
|
||||
CONFIG_AS_VERSION=220104
|
||||
CONFIG_LD_VERSION=0
|
||||
CONFIG_LD_IS_LLD=y
|
||||
CONFIG_LLD_VERSION=220106
|
||||
CONFIG_LLD_VERSION=220104
|
||||
CONFIG_RUSTC_VERSION=0
|
||||
CONFIG_RUSTC_LLVM_VERSION=0
|
||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||
@@ -13858,9 +13858,7 @@ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_NONE is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
|
||||
# CONFIG_DEBUG_INFO_SPLIT is not set
|
||||
# CONFIG_GDB_SCRIPTS is not set
|
||||
CONFIG_FRAME_WARN=2048
|
||||
8
internal/rosa/kernel_arm64.go
Normal file
8
internal/rosa/kernel_arm64.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package rosa
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed kernel_arm64.config
|
||||
var kernelConfig []byte
|
||||
|
||||
const kernelName = "vmlinuz.efi"
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/riscv 6.12.90 Kernel Configuration
|
||||
# Linux/riscv 6.12.80 Kernel Configuration
|
||||
#
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.6"
|
||||
CONFIG_CC_VERSION_TEXT="clang version 22.1.2"
|
||||
CONFIG_GCC_VERSION=0
|
||||
CONFIG_CC_IS_CLANG=y
|
||||
CONFIG_CLANG_VERSION=220106
|
||||
CONFIG_CLANG_VERSION=220102
|
||||
CONFIG_AS_IS_LLVM=y
|
||||
CONFIG_AS_VERSION=220106
|
||||
CONFIG_AS_VERSION=220102
|
||||
CONFIG_LD_VERSION=0
|
||||
CONFIG_LD_IS_LLD=y
|
||||
CONFIG_LLD_VERSION=220106
|
||||
CONFIG_LLD_VERSION=220102
|
||||
CONFIG_RUSTC_VERSION=0
|
||||
CONFIG_RUSTC_LLVM_VERSION=0
|
||||
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
|
||||
@@ -11123,9 +11123,7 @@ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
# CONFIG_DEBUG_INFO_DWARF4 is not set
|
||||
# CONFIG_DEBUG_INFO_DWARF5 is not set
|
||||
# CONFIG_DEBUG_INFO_REDUCED is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_NONE is not set
|
||||
# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_ZSTD=y
|
||||
CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
|
||||
# CONFIG_GDB_SCRIPTS is not set
|
||||
CONFIG_FRAME_WARN=2048
|
||||
# CONFIG_STRIP_ASM_SYMS is not set
|
||||
8
internal/rosa/kernel_riscv64.go
Normal file
8
internal/rosa/kernel_riscv64.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package rosa
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed kernel_riscv64.config
|
||||
var kernelConfig []byte
|
||||
|
||||
const kernelName = "bzImage"
|
||||
50
internal/rosa/kmod.go
Normal file
50
internal/rosa/kmod.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newKmod() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "34.2"
|
||||
checksum = "0K7POeTKxMhExsaTsnKAC6LUNsRSfe6sSZxWONPbOu-GI_pXOw3toU_BIoqfBhJV"
|
||||
)
|
||||
return t.NewPackage("kmod", version, newTar(
|
||||
"https://www.kernel.org/pub/linux/utils/kernel/"+
|
||||
"kmod/kmod-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dmoduledir", "/system/lib/modules"},
|
||||
{"Dsysconfdir", "/system/etc"},
|
||||
{"Dbashcompletiondir", "no"},
|
||||
{"Dfishcompletiondir", "no"},
|
||||
{"Dxz", "disabled"},
|
||||
{"Dmanpages", "false"},
|
||||
},
|
||||
|
||||
// makes assumptions about the running kernel
|
||||
SkipTest: true,
|
||||
},
|
||||
Zlib,
|
||||
Zstd,
|
||||
OpenSSL,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newKmod,
|
||||
|
||||
Name: "kmod",
|
||||
Description: "a set of tools to handle common tasks with Linux kernel modules",
|
||||
Website: "https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
Zstd,
|
||||
OpenSSL,
|
||||
},
|
||||
|
||||
ID: 1517,
|
||||
})
|
||||
}
|
||||
@@ -1,3 +1,20 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibarchive() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.8.7"
|
||||
checksum = "CUJK4MDQmZmATClgQBH2Wt-7Ts4iiSUlg1J_TVb6-5IK3rVUgVLIMc5k-bnWB9w3"
|
||||
)
|
||||
return t.NewPackage("libarchive", version, newFromGitHub(
|
||||
"libarchive/libarchive",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Paths: []pkg.ExecPath{
|
||||
pkg.Path(AbsUsrSrc.Append(
|
||||
"CTestCustom.cmake",
|
||||
), false, pkg.NewFile("CTestCustom.cmake", []byte(`
|
||||
list(APPEND CTEST_CUSTOM_TESTS_IGNORE
|
||||
"libarchive_test_archive_string_conversion_fail_c"
|
||||
"libarchive_test_archive_string_conversion_fail_latin1"
|
||||
@@ -61,3 +78,23 @@ list(APPEND CTEST_CUSTOM_TESTS_IGNORE
|
||||
"libarchive_test_read_format_ustar_filename"
|
||||
"libarchive_test_read_append_wrong_filter"
|
||||
)
|
||||
`))),
|
||||
},
|
||||
|
||||
Writable: true,
|
||||
ScriptEarly: `
|
||||
install -Dv /usr/src/CTestCustom.cmake /cure/
|
||||
`,
|
||||
}, (*CMakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibarchive,
|
||||
|
||||
Name: "libarchive",
|
||||
Description: "multi-format archive and compression library",
|
||||
Website: "https://www.libarchive.org/",
|
||||
|
||||
ID: 1558,
|
||||
})
|
||||
}
|
||||
62
internal/rosa/libbsd.go
Normal file
62
internal/rosa/libbsd.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibmd() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.2.0"
|
||||
checksum = "1rJ6joAO0wwMZvSfnRNkc1MOhywyAq7SM8VmF92NvDtv7Qdl1LRbjm5fg_DFFtGj"
|
||||
)
|
||||
return t.NewPackage("libmd", version, t.newTagRemote(
|
||||
"https://git.hadrons.org/git/libmd.git",
|
||||
version, checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "echo '" + version + "' > .dist-version && ./autogen",
|
||||
ScriptMakeEarly: `
|
||||
install -D /usr/src/libmd/src/helper.c src/helper.c
|
||||
`,
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibmd,
|
||||
|
||||
Name: "libmd",
|
||||
Description: "Message Digest functions from BSD systems",
|
||||
Website: "https://www.hadrons.org/software/libmd/",
|
||||
|
||||
ID: 15525,
|
||||
})
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibbsd() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.12.2"
|
||||
checksum = "NVS0xFLTwSP8JiElEftsZ-e1_C-IgJhHrHE77RwKt5178M7r087waO-zYx2_dfGX"
|
||||
)
|
||||
return t.NewPackage("libbsd", version, t.newTagRemote(
|
||||
"https://gitlab.freedesktop.org/libbsd/libbsd.git",
|
||||
version, checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "echo '" + version + "' > .dist-version && ./autogen",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
|
||||
Libmd,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibbsd,
|
||||
|
||||
Name: "libbsd",
|
||||
Description: "provides useful functions commonly found on BSD systems",
|
||||
Website: "https://libbsd.freedesktop.org/",
|
||||
|
||||
ID: 1567,
|
||||
})
|
||||
}
|
||||
54
internal/rosa/libcap.go
Normal file
54
internal/rosa/libcap.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibcap() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.78"
|
||||
checksum = "wFdUkBhFMD9InPnrBZyegWrlPSAg_9JiTBC-eSFyWWlmbzL2qjh2mKxr9Kx2a8ut"
|
||||
)
|
||||
return t.NewPackage("libcap", version, newTar(
|
||||
"https://git.kernel.org/pub/scm/libs/libcap/libcap.git/"+
|
||||
"snapshot/libcap-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
// uses source tree as scratch space
|
||||
Writable: true,
|
||||
Chmod: true,
|
||||
|
||||
Env: []string{
|
||||
"prefix=/system",
|
||||
"lib=lib",
|
||||
},
|
||||
ScriptEarly: `
|
||||
ln -s ../system/bin/bash /bin/
|
||||
`,
|
||||
}, &MakeHelper{
|
||||
SkipConfigure: true,
|
||||
InPlace: true,
|
||||
|
||||
Make: []string{
|
||||
"CC=cc",
|
||||
"all",
|
||||
},
|
||||
Check: []string{
|
||||
"CC=cc",
|
||||
"test",
|
||||
},
|
||||
},
|
||||
Bash,
|
||||
Diffutils,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibcap,
|
||||
|
||||
Name: "libcap",
|
||||
Description: "a library for getting and setting POSIX.1e draft 15 capabilities",
|
||||
Website: "https://sites.google.com/site/fullycapable/",
|
||||
|
||||
ID: 1569,
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,19 @@
|
||||
diff --git a/tests/tests.c b/tests/tests.c
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibconfig() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.8.2"
|
||||
checksum = "fD32hjeAZuTz98g6WYHRwsxphrgrEFqxi5Z1jlJemPckPBfxpS3i5HgshAuA6vmT"
|
||||
)
|
||||
return t.NewPackage("libconfig", version, newFromGitHub(
|
||||
"hyperrealm/libconfig",
|
||||
"v"+version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"disable-broken-tests", `diff --git a/tests/tests.c b/tests/tests.c
|
||||
index eba7eae..f916d2e 100644
|
||||
--- a/tests/tests.c
|
||||
+++ b/tests/tests.c
|
||||
@@ -18,3 +33,18 @@ index eba7eae..f916d2e 100644
|
||||
TT_SUITE_RUN(LibConfigTests);
|
||||
failures = TT_SUITE_NUM_FAILURES(LibConfigTests);
|
||||
TT_SUITE_END(LibConfigTests);
|
||||
`},
|
||||
},
|
||||
}, (*CMakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibconfig,
|
||||
|
||||
Name: "libconfig",
|
||||
Description: "a simple library for processing structured configuration files",
|
||||
Website: "https://hyperrealm.github.io/libconfig/",
|
||||
|
||||
ID: 1580,
|
||||
})
|
||||
}
|
||||
30
internal/rosa/libdisplay-info.go
Normal file
30
internal/rosa/libdisplay-info.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibdisplayInfo() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.3.0"
|
||||
checksum = "yjOqPUHHYgRtpqGw5RI1n2Q1_hO5j0LiFNMbjcRWV4Nf71XwwoC9fZMlKBDeLchT"
|
||||
)
|
||||
return t.NewPackage("libdisplay-info", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"emersion/libdisplay-info",
|
||||
version, checksum,
|
||||
), nil, (*MesonHelper)(nil),
|
||||
Diffutils,
|
||||
|
||||
Hwdata,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibdisplayInfo,
|
||||
|
||||
Name: "libdisplay-info",
|
||||
Description: "EDID and DisplayID library",
|
||||
Website: "https://gitlab.freedesktop.org/emersion/libdisplay-info",
|
||||
|
||||
ID: 326668,
|
||||
})
|
||||
}
|
||||
33
internal/rosa/libepoxy.go
Normal file
33
internal/rosa/libepoxy.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibepoxy() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.5.10"
|
||||
checksum = "OHI8wshrlGw6BMGrmSyejJtwzM2gPhyFJrTsKxULyKMmYrfgcOe7Iw2ibVoUND_Q"
|
||||
)
|
||||
return t.NewPackage("libepoxy", version, newFromGitHub(
|
||||
"anholt/libepoxy",
|
||||
version,
|
||||
checksum,
|
||||
), nil, &MesonHelper{
|
||||
Setup: []KV{
|
||||
{"Dglx", "no"},
|
||||
{"Degl", "no"},
|
||||
},
|
||||
},
|
||||
LibX11,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibepoxy,
|
||||
|
||||
Name: "libepoxy",
|
||||
Description: "a library for handling OpenGL function pointer management",
|
||||
Website: "https://github.com/anholt/libepoxy",
|
||||
|
||||
ID: 6090,
|
||||
})
|
||||
}
|
||||
26
internal/rosa/libev.go
Normal file
26
internal/rosa/libev.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibev() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "4.33"
|
||||
checksum = "774eSXV_4k8PySRprUDChbEwsw-kzjIFnJ3MpNOl5zDpamBRvC3BqPyRxvkwcL6_"
|
||||
)
|
||||
return t.NewPackage("libev", version, newTar(
|
||||
"https://dist.schmorp.de/libev/Attic/libev-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibev,
|
||||
|
||||
Name: "libev",
|
||||
Description: "a full-featured and high-performance event loop",
|
||||
Website: "http://libev.schmorp.de/",
|
||||
|
||||
ID: 1605,
|
||||
})
|
||||
}
|
||||
34
internal/rosa/libexpat.go
Normal file
34
internal/rosa/libexpat.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newLibexpat() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.8.1"
|
||||
checksum = "iMEtbOJhQfGof2GxSlxffQSI1va_NDDQ9VIuqcPbNZ0291Dr8wttD5QecYyjIQap"
|
||||
)
|
||||
return t.NewPackage("libexpat", version, newFromGitHubRelease(
|
||||
"libexpat/libexpat",
|
||||
"R_"+strings.ReplaceAll(version, ".", "_"),
|
||||
"expat-"+version+".tar.bz2",
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Bash,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibexpat,
|
||||
|
||||
Name: "libexpat",
|
||||
Description: "a stream-oriented XML parser library",
|
||||
Website: "https://libexpat.github.io/",
|
||||
|
||||
ID: 770,
|
||||
})
|
||||
}
|
||||
30
internal/rosa/libffi.go
Normal file
30
internal/rosa/libffi.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibffi() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.5.2"
|
||||
checksum = "2_Q-ZNBBbVhltfL5zEr0wljxPegUimTK4VeMSiwJEGksls3n4gj3lV0Ly3vviSFH"
|
||||
)
|
||||
return t.NewPackage("libffi", version, newFromGitHubRelease(
|
||||
"libffi/libffi",
|
||||
"v"+version,
|
||||
"libffi-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibffi,
|
||||
|
||||
Name: "libffi",
|
||||
Description: "a portable, high level programming interface to various calling conventions",
|
||||
Website: "https://sourceware.org/libffi/",
|
||||
|
||||
ID: 1611,
|
||||
})
|
||||
}
|
||||
40
internal/rosa/libgd.go
Normal file
40
internal/rosa/libgd.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibgd() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2.3.3"
|
||||
checksum = "8T-sh1_FJT9K9aajgxzh8ot6vWIF-xxjcKAHvTak9MgGUcsFfzP8cAvvv44u2r36"
|
||||
)
|
||||
return t.NewPackage("libgd", version, newFromGitHubRelease(
|
||||
"libgd/libgd",
|
||||
"gd-"+version,
|
||||
"libgd-"+version+".tar.gz", checksum,
|
||||
pkg.TarGzip,
|
||||
), &PackageAttr{
|
||||
Env: []string{
|
||||
"TMPDIR=/dev/shm/gd",
|
||||
},
|
||||
ScriptEarly: `
|
||||
mkdir /dev/shm/gd
|
||||
`,
|
||||
}, (*MakeHelper)(nil),
|
||||
Zlib,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
native.MustRegister(&Artifact{
|
||||
f: Toolchain.newLibgd,
|
||||
|
||||
Name: "libgd",
|
||||
Description: "an open source code library for the dynamic creation of images",
|
||||
Website: "https://libgd.github.io/",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
},
|
||||
|
||||
ID: 880,
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user